Merge 3.13-rc4 into tty-next
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 17 Dec 2013 00:36:37 +0000 (16:36 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 17 Dec 2013 00:36:37 +0000 (16:36 -0800)
We want the fixes in here as well.

23 files changed:
drivers/input/serio/serport.c
drivers/parport/parport_serial.c
drivers/staging/fwserial/Kconfig
drivers/staging/fwserial/fwserial.c
drivers/staging/fwserial/fwserial.h
drivers/tty/n_gsm.c
drivers/tty/n_r3964.c
drivers/tty/n_tty.c
drivers/tty/rocket.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/amba-pl010.c
drivers/tty/serial/amba-pl011.c
drivers/tty/serial/imx.c
drivers/tty/serial/mxs-auart.c
drivers/tty/serial/pch_uart.c
drivers/tty/serial/rp2.c
drivers/tty/serial/serial_core.c
drivers/tty/tty_buffer.c
include/linux/amba/serial.h
include/linux/init.h
include/linux/tty.h
include/linux/tty_flip.h
include/linux/tty_ldisc.h

index 8755f5f3ad37c2218de60b96782c0863615a705e..0cb7ef59071b792a350a914e88f4e9be7da34efc 100644 (file)
@@ -124,7 +124,7 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c
 {
        struct serport *serport = (struct serport*) tty->disc_data;
        unsigned long flags;
-       unsigned int ch_flags;
+       unsigned int ch_flags = 0;
        int i;
 
        spin_lock_irqsave(&serport->lock, flags);
@@ -133,18 +133,20 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c
                goto out;
 
        for (i = 0; i < count; i++) {
-               switch (fp[i]) {
-               case TTY_FRAME:
-                       ch_flags = SERIO_FRAME;
-                       break;
-
-               case TTY_PARITY:
-                       ch_flags = SERIO_PARITY;
-                       break;
-
-               default:
-                       ch_flags = 0;
-                       break;
+               if (fp) {
+                       switch (fp[i]) {
+                       case TTY_FRAME:
+                               ch_flags = SERIO_FRAME;
+                               break;
+
+                       case TTY_PARITY:
+                               ch_flags = SERIO_PARITY;
+                               break;
+
+                       default:
+                               ch_flags = 0;
+                               break;
+                       }
                }
 
                serio_interrupt(serport->serio, cp[i], ch_flags);
index 1b8bdb7e9bf40a6549c5739e6d8a50a732bc9cd9..ff53314100f684ed9dcb86a9a89ea3f12b6a24e6 100644 (file)
@@ -596,13 +596,11 @@ static int parport_serial_pci_probe(struct pci_dev *dev,
 
        err = pci_enable_device (dev);
        if (err) {
-               pci_set_drvdata (dev, NULL);
                kfree (priv);
                return err;
        }
 
        if (parport_register (dev, id)) {
-               pci_set_drvdata (dev, NULL);
                kfree (priv);
                return -ENODEV;
        }
@@ -611,7 +609,6 @@ static int parport_serial_pci_probe(struct pci_dev *dev,
                int i;
                for (i = 0; i < priv->num_par; i++)
                        parport_pc_unregister_port (priv->port[i]);
-               pci_set_drvdata (dev, NULL);
                kfree (priv);
                return -ENODEV;
        }
@@ -624,8 +621,6 @@ static void parport_serial_pci_remove(struct pci_dev *dev)
        struct parport_serial_private *priv = pci_get_drvdata (dev);
        int i;
 
-       pci_set_drvdata(dev, NULL);
-
        // Serial ports
        if (priv->serial)
                pciserial_remove_ports(priv->serial);
index a0812d99136f5e171c277e88f637579cfea4c71c..9c7c9267d52cb3a62dd80452930ad33269bf2951 100644 (file)
@@ -9,3 +9,23 @@ config FIREWIRE_SERIAL
 
          To compile this driver as a module, say M here:  the module will
          be called firewire-serial.
+
+if FIREWIRE_SERIAL
+
+config FWTTY_MAX_TOTAL_PORTS
+       int "Maximum number of serial ports supported"
+       default "64"
+       help
+          Set this to the maximum number of serial ports you want the
+         firewire-serial driver to support.
+
+config FWTTY_MAX_CARD_PORTS
+       int "Maximum number of serial ports supported per adapter"
+       range 0 FWTTY_MAX_TOTAL_PORTS
+       default "32"
+       help
+          Set this to the maximum number of serial ports each firewire
+         adapter supports. The actual number of serial ports registered
+         is set with the module parameter "ttys".
+
+endif
index 62df009e5ac7c8e9bcd5779bf57e9b8c1d2c309d..8af136e9c9dc16e1ab5f5f5cecf7dfe1579c528b 100644 (file)
@@ -136,14 +136,14 @@ static struct fwtty_peer *__fwserial_peer_by_node_id(struct fw_card *card,
 
 #ifdef FWTTY_PROFILING
 
-static void profile_fifo_avail(struct fwtty_port *port, unsigned *stat)
+static void fwtty_profile_fifo(struct fwtty_port *port, unsigned *stat)
 {
        spin_lock_bh(&port->lock);
-       profile_size_distrib(stat, dma_fifo_avail(&port->tx_fifo));
+       fwtty_profile_data(stat, dma_fifo_avail(&port->tx_fifo));
        spin_unlock_bh(&port->lock);
 }
 
-static void dump_profile(struct seq_file *m, struct stats *stats)
+static void fwtty_dump_profile(struct seq_file *m, struct stats *stats)
 {
        /* for each stat, print sum of 0 to 2^k, then individually */
        int k = 4;
@@ -183,8 +183,8 @@ static void dump_profile(struct seq_file *m, struct stats *stats)
 }
 
 #else
-#define profile_fifo_avail(port, stat)
-#define dump_profile(m, stats)
+#define fwtty_profile_fifo(port, stat)
+#define fwtty_dump_profile(m, stats)
 #endif
 
 /*
@@ -456,16 +456,27 @@ static int fwtty_write_port_status(struct fwtty_port *port)
        return err;
 }
 
-static void __fwtty_throttle(struct fwtty_port *port, struct tty_struct *tty)
+static void fwtty_throttle_port(struct fwtty_port *port)
 {
+       struct tty_struct *tty;
        unsigned old;
 
+       tty = tty_port_tty_get(&port->port);
+       if (!tty)
+               return;
+
+       spin_lock_bh(&port->lock);
+
        old = port->mctrl;
        port->mctrl |= OOB_RX_THROTTLE;
        if (C_CRTSCTS(tty))
                port->mctrl &= ~TIOCM_RTS;
        if (~old & OOB_RX_THROTTLE)
                __fwtty_write_port_status(port);
+
+       spin_unlock_bh(&port->lock);
+
+       tty_kref_put(tty);
 }
 
 /**
@@ -532,80 +543,14 @@ static void fwtty_emit_breaks(struct work_struct *work)
        port->icount.brk += brk;
 }
 
-static void fwtty_pushrx(struct work_struct *work)
-{
-       struct fwtty_port *port = to_port(work, push);
-       struct tty_struct *tty;
-       struct buffered_rx *buf, *next;
-       int n, c = 0;
-
-       spin_lock_bh(&port->lock);
-       list_for_each_entry_safe(buf, next, &port->buf_list, list) {
-               n = tty_insert_flip_string_fixed_flag(&port->port, buf->data,
-                                                     TTY_NORMAL, buf->n);
-               c += n;
-               port->buffered -= n;
-               if (n < buf->n) {
-                       if (n > 0) {
-                               memmove(buf->data, buf->data + n, buf->n - n);
-                               buf->n -= n;
-                       }
-                       tty = tty_port_tty_get(&port->port);
-                       if (tty) {
-                               __fwtty_throttle(port, tty);
-                               tty_kref_put(tty);
-                       }
-                       break;
-               } else {
-                       list_del(&buf->list);
-                       kfree(buf);
-               }
-       }
-       if (c > 0)
-               tty_flip_buffer_push(&port->port);
-
-       if (list_empty(&port->buf_list))
-               clear_bit(BUFFERING_RX, &port->flags);
-       spin_unlock_bh(&port->lock);
-}
-
-static int fwtty_buffer_rx(struct fwtty_port *port, unsigned char *d, size_t n)
-{
-       struct buffered_rx *buf;
-       size_t size = (n + sizeof(struct buffered_rx) + 0xFF) & ~0xFF;
-
-       if (port->buffered + n > HIGH_WATERMARK) {
-               fwtty_err_ratelimited(port, "overflowed rx buffer: buffered: %d new: %zu wtrmk: %d\n",
-                                     port->buffered, n, HIGH_WATERMARK);
-               return 0;
-       }
-       buf = kmalloc(size, GFP_ATOMIC);
-       if (!buf)
-               return 0;
-       INIT_LIST_HEAD(&buf->list);
-       buf->n = n;
-       memcpy(buf->data, d, n);
-
-       spin_lock_bh(&port->lock);
-       list_add_tail(&buf->list, &port->buf_list);
-       port->buffered += n;
-       if (port->buffered > port->stats.watermark)
-               port->stats.watermark = port->buffered;
-       set_bit(BUFFERING_RX, &port->flags);
-       spin_unlock_bh(&port->lock);
-
-       return n;
-}
-
 static int fwtty_rx(struct fwtty_port *port, unsigned char *data, size_t len)
 {
-       struct tty_struct *tty;
        int c, n = len;
        unsigned lsr;
        int err = 0;
 
        fwtty_dbg(port, "%d\n", n);
-       profile_size_distrib(port->stats.reads, n);
+       fwtty_profile_data(port->stats.reads, n);
 
        if (port->write_only) {
                n = 0;
@@ -636,31 +581,24 @@ static int fwtty_rx(struct fwtty_port *port, unsigned char *data, size_t len)
                goto out;
        }
 
-       if (!test_bit(BUFFERING_RX, &port->flags)) {
-               c = tty_insert_flip_string_fixed_flag(&port->port, data,
-                               TTY_NORMAL, n);
-               if (c > 0)
-                       tty_flip_buffer_push(&port->port);
-               n -= c;
-
-               if (n) {
-                       /* start buffering and throttling */
-                       n -= fwtty_buffer_rx(port, &data[c], n);
-
-                       tty = tty_port_tty_get(&port->port);
-                       if (tty) {
-                               spin_lock_bh(&port->lock);
-                               __fwtty_throttle(port, tty);
-                               spin_unlock_bh(&port->lock);
-                               tty_kref_put(tty);
-                       }
-               }
-       } else
-               n -= fwtty_buffer_rx(port, data, n);
+       c = tty_insert_flip_string_fixed_flag(&port->port, data, TTY_NORMAL, n);
+       if (c > 0)
+               tty_flip_buffer_push(&port->port);
+       n -= c;
 
        if (n) {
                port->overrun = true;
                err = -EIO;
+               fwtty_err_ratelimited(port, "flip buffer overrun\n");
+
+       } else {
+               /* throttle the sender if remaining flip buffer space has
+                * reached high watermark to avoid losing data which may be
+                * in-flight. Since the AR request context is 32k, that much
+                * data may have _already_ been acked.
+                */
+               if (tty_buffer_space_avail(&port->port) < HIGH_WATERMARK)
+                       fwtty_throttle_port(port);
        }
 
 out:
@@ -821,7 +759,7 @@ static int fwtty_tx(struct fwtty_port *port, bool drain)
                        if (n == -EAGAIN)
                                ++port->stats.tx_stall;
                        else if (n == -ENODATA)
-                               profile_size_distrib(port->stats.txns, 0);
+                               fwtty_profile_data(port->stats.txns, 0);
                        else {
                                ++port->stats.fifo_errs;
                                fwtty_err_ratelimited(port, "fifo err: %d\n",
@@ -830,7 +768,7 @@ static int fwtty_tx(struct fwtty_port *port, bool drain)
                        break;
                }
 
-               profile_size_distrib(port->stats.txns, txn->dma_pended.len);
+               fwtty_profile_data(port->stats.txns, txn->dma_pended.len);
 
                fwtty_send_txn_async(peer, txn, TCODE_WRITE_BLOCK_REQUEST,
                                     peer->fifo_addr, txn->dma_pended.data,
@@ -1101,20 +1039,13 @@ static int fwtty_port_activate(struct tty_port *tty_port,
 static void fwtty_port_shutdown(struct tty_port *tty_port)
 {
        struct fwtty_port *port = to_port(tty_port, port);
-       struct buffered_rx *buf, *next;
 
        /* TODO: cancel outstanding transactions */
 
        cancel_delayed_work_sync(&port->emit_breaks);
        cancel_delayed_work_sync(&port->drain);
-       cancel_work_sync(&port->push);
 
        spin_lock_bh(&port->lock);
-       list_for_each_entry_safe(buf, next, &port->buf_list, list) {
-               list_del(&buf->list);
-               kfree(buf);
-       }
-       port->buffered = 0;
        port->flags = 0;
        port->break_ctl = 0;
        port->overrun = 0;
@@ -1184,7 +1115,7 @@ static int fwtty_write(struct tty_struct *tty, const unsigned char *buf, int c)
        int n, len;
 
        fwtty_dbg(port, "%d\n", c);
-       profile_size_distrib(port->stats.writes, c);
+       fwtty_profile_data(port->stats.writes, c);
 
        spin_lock_bh(&port->lock);
        n = dma_fifo_in(&port->tx_fifo, buf, c);
@@ -1262,9 +1193,7 @@ static void fwtty_unthrottle(struct tty_struct *tty)
 
        fwtty_dbg(port, "CRTSCTS: %d\n", (C_CRTSCTS(tty) != 0));
 
-       profile_fifo_avail(port, port->stats.unthrottle);
-
-       schedule_work(&port->push);
+       fwtty_profile_fifo(port, port->stats.unthrottle);
 
        spin_lock_bh(&port->lock);
        port->mctrl &= ~OOB_RX_THROTTLE;
@@ -1523,15 +1452,14 @@ static void fwtty_debugfs_show_port(struct seq_file *m, struct fwtty_port *port)
 
        seq_printf(m, " dr:%d st:%d err:%d lost:%d", stats.dropped,
                   stats.tx_stall, stats.fifo_errs, stats.lost);
-       seq_printf(m, " pkts:%d thr:%d wtrmk:%d", stats.sent, stats.throttled,
-                  stats.watermark);
+       seq_printf(m, " pkts:%d thr:%d", stats.sent, stats.throttled);
 
        if (port->port.console) {
                seq_puts(m, "\n    ");
                (*port->fwcon_ops->proc_show)(m, port->con_data);
        }
 
-       dump_profile(m, &port->stats);
+       fwtty_dump_profile(m, &port->stats);
 }
 
 static void fwtty_debugfs_show_peer(struct seq_file *m, struct fwtty_peer *peer)
@@ -2297,13 +2225,12 @@ static int fwserial_create(struct fw_unit *unit)
                port->index = FWTTY_INVALID_INDEX;
                port->port.ops = &fwtty_port_ops;
                port->serial = serial;
+               tty_buffer_set_limit(&port->port, 128 * 1024);
 
                spin_lock_init(&port->lock);
                INIT_DELAYED_WORK(&port->drain, fwtty_drain_tx);
                INIT_DELAYED_WORK(&port->emit_breaks, fwtty_emit_breaks);
                INIT_WORK(&port->hangup, fwtty_do_hangup);
-               INIT_WORK(&port->push, fwtty_pushrx);
-               INIT_LIST_HEAD(&port->buf_list);
                init_waitqueue_head(&port->wait_tx);
                port->max_payload = link_speed_to_max_payload(SCODE_100);
                dma_fifo_init(&port->tx_fifo);
index 24635014a2acdad232634248794e41eff2450ffa..54f7f9b9b2123a120a48595a878723b5d89d465e 100644 (file)
 #ifdef FWTTY_PROFILING
 #define DISTRIBUTION_MAX_SIZE     8192
 #define DISTRIBUTION_MAX_INDEX    (ilog2(DISTRIBUTION_MAX_SIZE) + 1)
-static inline void profile_size_distrib(unsigned stat[], unsigned val)
+static inline void fwtty_profile_data(unsigned stat[], unsigned val)
 {
        int n = (val) ? min(ilog2(val) + 1, DISTRIBUTION_MAX_INDEX) : 0;
        ++stat[n];
 }
 #else
 #define DISTRIBUTION_MAX_INDEX    0
-#define profile_size_distrib(st, n)
+#define fwtty_profile_data(st, n)
 #endif
 
 /* Parameters for both VIRT_CABLE_PLUG & VIRT_CABLE_PLUG_RSP mgmt codes */
@@ -166,7 +166,6 @@ struct stats {
        unsigned        sent;
        unsigned        lost;
        unsigned        throttled;
-       unsigned        watermark;
        unsigned        reads[DISTRIBUTION_MAX_INDEX + 1];
        unsigned        writes[DISTRIBUTION_MAX_INDEX + 1];
        unsigned        txns[DISTRIBUTION_MAX_INDEX + 1];
@@ -183,12 +182,6 @@ struct fwconsole_ops {
 #define FWCON_NOTIFY_ATTACH            1
 #define FWCON_NOTIFY_DETACH            2
 
-struct buffered_rx {
-       struct list_head        list;
-       size_t                  n;
-       unsigned char           data[0];
-};
-
 /**
  * fwtty_port: structure used to track/represent underlying tty_port
  * @port: underlying tty_port
@@ -223,11 +216,6 @@ struct buffered_rx {
  *         The work can race with the writer but concurrent sending is
  *         prevented with the IN_TX flag. Scheduled under lock to
  *         limit scheduling when fifo has just been drained.
- * @push: work responsible for pushing buffered rx to the ldisc.
- *       rx can become buffered if the tty buffer is filled before the
- *       ldisc throttles the sender.
- * @buf_list: list of buffered rx yet to be sent to ldisc
- * @buffered: byte count of buffered rx
  * @tx_fifo: fifo used to store & block-up writes for dma to remote
  * @max_payload: max bytes transmissable per dma (based on peer's max_payload)
  * @status_mask: UART_LSR_* bitmask significant to rx (based on termios)
@@ -267,9 +255,6 @@ struct fwtty_port {
        spinlock_t                 lock;
        unsigned                   mctrl;
        struct delayed_work        drain;
-       struct work_struct         push;
-       struct list_head           buf_list;
-       int                        buffered;
        struct dma_fifo            tx_fifo;
        int                        max_payload;
        unsigned                   status_mask;
@@ -291,7 +276,6 @@ struct fwtty_port {
 /* bit #s for flags field */
 #define IN_TX                      0
 #define STOP_TX                    1
-#define BUFFERING_RX              2
 
 /* bitmasks for special mctrl/mstatus bits */
 #define OOB_RX_THROTTLE   0x00010000
@@ -307,8 +291,8 @@ struct fwtty_port {
 #define FREQ_BREAKS        (HZ / 50)
 
 /* Ports are allocated in blocks of num_ports for each fw_card */
-#define MAX_CARD_PORTS           32    /* max # of ports per card */
-#define MAX_TOTAL_PORTS          64    /* max # of ports total    */
+#define MAX_CARD_PORTS           CONFIG_FWTTY_MAX_CARD_PORTS
+#define MAX_TOTAL_PORTS          CONFIG_FWTTY_MAX_TOTAL_PORTS
 
 /* tuning parameters */
 #define FWTTY_PORT_TXFIFO_LEN  4096
index c0f76da553042db2f3eadb91cfb9ff08bc60e43d..679294b37653f684473733ebf9ccf69edfea2f3f 100644 (file)
@@ -194,6 +194,7 @@ struct gsm_control {
 struct gsm_mux {
        struct tty_struct *tty;         /* The tty our ldisc is bound to */
        spinlock_t lock;
+       struct mutex mutex;
        unsigned int num;
        struct kref ref;
 
@@ -2054,9 +2055,11 @@ void gsm_cleanup_mux(struct gsm_mux *gsm)
                                        dlci->state == DLCI_CLOSED);
        }
        /* Free up any link layer users */
+       mutex_lock(&gsm->mutex);
        for (i = 0; i < NUM_DLCI; i++)
                if (gsm->dlci[i])
                        gsm_dlci_release(gsm->dlci[i]);
+       mutex_unlock(&gsm->mutex);
        /* Now wipe the queues */
        list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list)
                kfree(txq);
@@ -2170,6 +2173,7 @@ struct gsm_mux *gsm_alloc_mux(void)
                return NULL;
        }
        spin_lock_init(&gsm->lock);
+       mutex_init(&gsm->mutex);
        kref_init(&gsm->ref);
        INIT_LIST_HEAD(&gsm->tx_list);
 
@@ -2269,14 +2273,15 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
        char *f;
        int i;
        char buf[64];
-       char flags;
+       char flags = TTY_NORMAL;
 
        if (debug & 4)
                print_hex_dump_bytes("gsmld_receive: ", DUMP_PREFIX_OFFSET,
                                     cp, count);
 
        for (i = count, dp = cp, f = fp; i; i--, dp++) {
-               flags = *f++;
+               if (f)
+                       flags = *f++;
                switch (flags) {
                case TTY_NORMAL:
                        gsm->receive(gsm, *dp);
@@ -2909,23 +2914,33 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty)
        This is ok from a locking
        perspective as we don't have to worry about this
        if DLCI0 is lost */
-       if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN)
+       mutex_lock(&gsm->mutex);
+       if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN) {
+               mutex_unlock(&gsm->mutex);
                return -EL2NSYNC;
+       }
        dlci = gsm->dlci[line];
        if (dlci == NULL) {
                alloc = true;
                dlci = gsm_dlci_alloc(gsm, line);
        }
-       if (dlci == NULL)
+       if (dlci == NULL) {
+               mutex_unlock(&gsm->mutex);
                return -ENOMEM;
+       }
        ret = tty_port_install(&dlci->port, driver, tty);
        if (ret) {
                if (alloc)
                        dlci_put(dlci);
+               mutex_unlock(&gsm->mutex);
                return ret;
        }
 
+       dlci_get(dlci);
+       dlci_get(gsm->dlci[0]);
+       mux_get(gsm);
        tty->driver_data = dlci;
+       mutex_unlock(&gsm->mutex);
 
        return 0;
 }
@@ -2936,9 +2951,6 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)
        struct tty_port *port = &dlci->port;
 
        port->count++;
-       dlci_get(dlci);
-       dlci_get(dlci->gsm->dlci[0]);
-       mux_get(dlci->gsm);
        tty_port_tty_set(port, tty);
 
        dlci->modem_rx = 0;
@@ -2965,7 +2977,7 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp)
        mutex_unlock(&dlci->mutex);
        gsm = dlci->gsm;
        if (tty_port_close_start(&dlci->port, tty, filp) == 0)
-               goto out;
+               return;
        gsm_dlci_begin_close(dlci);
        if (test_bit(ASYNCB_INITIALIZED, &dlci->port.flags)) {
                if (C_HUPCL(tty))
@@ -2973,10 +2985,7 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp)
        }
        tty_port_close_end(&dlci->port, tty);
        tty_port_tty_set(&dlci->port, NULL);
-out:
-       dlci_put(dlci);
-       dlci_put(gsm->dlci[0]);
-       mux_put(gsm);
+       return;
 }
 
 static void gsmtty_hangup(struct tty_struct *tty)
@@ -3153,6 +3162,16 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state)
        return gsmtty_modem_update(dlci, encode);
 }
 
+static void gsmtty_remove(struct tty_driver *driver, struct tty_struct *tty)
+{
+       struct gsm_dlci *dlci = tty->driver_data;
+       struct gsm_mux *gsm = dlci->gsm;
+
+       dlci_put(dlci);
+       dlci_put(gsm->dlci[0]);
+       mux_put(gsm);
+       driver->ttys[tty->index] = NULL;
+}
 
 /* Virtual ttys for the demux */
 static const struct tty_operations gsmtty_ops = {
@@ -3172,6 +3191,7 @@ static const struct tty_operations gsmtty_ops = {
        .tiocmget               = gsmtty_tiocmget,
        .tiocmset               = gsmtty_tiocmset,
        .break_ctl              = gsmtty_break_ctl,
+       .remove                 = gsmtty_remove,
 };
 
 
index 1e6405070ce649e356b24d272a824e9eda737159..8b157d68a03e97aa2089d9b3c4d98fdb0b109719 100644 (file)
@@ -1244,7 +1244,7 @@ static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 {
        struct r3964_info *pInfo = tty->disc_data;
        const unsigned char *p;
-       char *f, flags = 0;
+       char *f, flags = TTY_NORMAL;
        int i;
 
        for (i = count, p = cp, f = fp; i; i--, p++) {
index 268b62768f2b41eab5f7db4d4c5c8b9111f248b6..fdc2ecde5ac2049c8c1877364e293412d330d9ac 100644 (file)
@@ -274,7 +274,8 @@ static void n_tty_check_unthrottle(struct tty_struct *tty)
                        return;
                n_tty_set_room(tty);
                n_tty_write_wakeup(tty->link);
-               wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT);
+               if (waitqueue_active(&tty->link->write_wait))
+                       wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT);
                return;
        }
 
@@ -349,7 +350,8 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty)
        spin_lock_irqsave(&tty->ctrl_lock, flags);
        if (tty->link->packet) {
                tty->ctrl_status |= TIOCPKT_FLUSHREAD;
-               wake_up_interruptible(&tty->link->read_wait);
+               if (waitqueue_active(&tty->link->read_wait))
+                       wake_up_interruptible(&tty->link->read_wait);
        }
        spin_unlock_irqrestore(&tty->ctrl_lock, flags);
 }
@@ -1157,7 +1159,8 @@ static void n_tty_receive_break(struct tty_struct *tty)
                put_tty_queue('\0', ldata);
        }
        put_tty_queue('\0', ldata);
-       wake_up_interruptible(&tty->read_wait);
+       if (waitqueue_active(&tty->read_wait))
+               wake_up_interruptible(&tty->read_wait);
 }
 
 /**
@@ -1215,7 +1218,8 @@ static void n_tty_receive_parity_error(struct tty_struct *tty, unsigned char c)
                put_tty_queue('\0', ldata);
        else
                put_tty_queue(c, ldata);
-       wake_up_interruptible(&tty->read_wait);
+       if (waitqueue_active(&tty->read_wait))
+               wake_up_interruptible(&tty->read_wait);
 }
 
 static void
@@ -1259,7 +1263,6 @@ static int
 n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
 {
        struct n_tty_data *ldata = tty->disc_data;
-       int parmrk;
 
        if (I_IXON(tty)) {
                if (c == START_CHAR(tty)) {
@@ -1344,8 +1347,6 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
                }
                if ((c == EOL_CHAR(tty)) ||
                    (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) {
-                       parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty))
-                                ? 1 : 0;
                        /*
                         * XXX are EOL_CHAR and EOL2_CHAR echoed?!?
                         */
@@ -1360,7 +1361,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
                         * XXX does PARMRK doubling happen for
                         * EOL_CHAR and EOL2_CHAR?
                         */
-                       if (parmrk)
+                       if (c == (unsigned char) '\377' && I_PARMRK(tty))
                                put_tty_queue(c, ldata);
 
 handle_newline:
@@ -1374,7 +1375,6 @@ handle_newline:
                }
        }
 
-       parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
        if (L_ECHO(tty)) {
                finish_erasing(ldata);
                if (c == '\n')
@@ -1388,7 +1388,8 @@ handle_newline:
                commit_echoes(tty);
        }
 
-       if (parmrk)
+       /* PARMRK doubling check */
+       if (c == (unsigned char) '\377' && I_PARMRK(tty))
                put_tty_queue(c, ldata);
 
        put_tty_queue(c, ldata);
@@ -1399,7 +1400,6 @@ static inline void
 n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c)
 {
        struct n_tty_data *ldata = tty->disc_data;
-       int parmrk;
 
        if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) {
                start_tty(tty);
@@ -1413,13 +1413,13 @@ n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c)
                echo_char(c, tty);
                commit_echoes(tty);
        }
-       parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
-       if (parmrk)
+       /* PARMRK doubling check */
+       if (c == (unsigned char) '\377' && I_PARMRK(tty))
                put_tty_queue(c, ldata);
        put_tty_queue(c, ldata);
 }
 
-static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
+static void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
 {
        n_tty_receive_char_inline(tty, c);
 }
@@ -1444,8 +1444,7 @@ n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c)
        put_tty_queue(c, ldata);
 }
 
-static inline void
-n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c)
+static void n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c)
 {
        if (I_ISTRIP(tty))
                c &= 0x7f;
@@ -1676,32 +1675,9 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp,
        }
 }
 
-static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
-                             char *fp, int count)
-{
-       int room, n;
-
-       down_read(&tty->termios_rwsem);
-
-       while (1) {
-               room = receive_room(tty);
-               n = min(count, room);
-               if (!n)
-                       break;
-               __receive_buf(tty, cp, fp, n);
-               cp += n;
-               if (fp)
-                       fp += n;
-               count -= n;
-       }
-
-       tty->receive_room = room;
-       n_tty_check_throttle(tty);
-       up_read(&tty->termios_rwsem);
-}
-
-static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp,
-                             char *fp, int count)
+static int
+n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp,
+                        char *fp, int count, int flow)
 {
        struct n_tty_data *ldata = tty->disc_data;
        int room, n, rcvd = 0;
@@ -1712,7 +1688,7 @@ static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp,
                room = receive_room(tty);
                n = min(count, room);
                if (!n) {
-                       if (!room)
+                       if (flow && !room)
                                ldata->no_room = 1;
                        break;
                }
@@ -1731,6 +1707,18 @@ static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp,
        return rcvd;
 }
 
+static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
+                             char *fp, int count)
+{
+       n_tty_receive_buf_common(tty, cp, fp, count, 0);
+}
+
+static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp,
+                             char *fp, int count)
+{
+       return n_tty_receive_buf_common(tty, cp, fp, count, 1);
+}
+
 int is_ignored(int sig)
 {
        return (sigismember(&current->blocked, sig) ||
@@ -1820,8 +1808,10 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
                start_tty(tty);
 
        /* The termios change make the tty ready for I/O */
-       wake_up_interruptible(&tty->write_wait);
-       wake_up_interruptible(&tty->read_wait);
+       if (waitqueue_active(&tty->write_wait))
+               wake_up_interruptible(&tty->write_wait);
+       if (waitqueue_active(&tty->read_wait))
+               wake_up_interruptible(&tty->read_wait);
 }
 
 /**
@@ -1887,14 +1877,15 @@ err:
        return -ENOMEM;
 }
 
-static inline int input_available_p(struct tty_struct *tty, int amt)
+static inline int input_available_p(struct tty_struct *tty, int poll)
 {
        struct n_tty_data *ldata = tty->disc_data;
+       int amt = poll && !TIME_CHAR(tty) ? MIN_CHAR(tty) : 1;
 
        if (ldata->icanon && !L_EXTPROC(tty)) {
                if (ldata->canon_head != ldata->read_tail)
                        return 1;
-       } else if (read_cnt(ldata) >= (amt ? amt : 1))
+       } else if (read_cnt(ldata) >= amt)
                return 1;
 
        return 0;
@@ -2393,7 +2384,7 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file,
 
        poll_wait(file, &tty->read_wait, wait);
        poll_wait(file, &tty->write_wait, wait);
-       if (input_available_p(tty, TIME_CHAR(tty) ? 0 : MIN_CHAR(tty)))
+       if (input_available_p(tty, 1))
                mask |= POLLIN | POLLRDNORM;
        if (tty->packet && tty->link->ctrl_status)
                mask |= POLLPRI | POLLIN | POLLRDNORM;
index 354564ea47c504446ba5aeab1153d48edc4acc48..383c4c796637713e12bede50677803a0d639a855 100644 (file)
@@ -1744,7 +1744,7 @@ static void rp_flush_buffer(struct tty_struct *tty)
 
 #ifdef CONFIG_PCI
 
-static DEFINE_PCI_DEVICE_TABLE(rocket_pci_ids) = {
+static const struct pci_device_id rocket_pci_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP4QUAD) },
        { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP8OCTA) },
        { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_URP8OCTA) },
index 4658e3e0ec4256d9b2e31f890ea72822abf47f93..816ec88a0d7f536aa0dac8d4ce9eb1a86682039c 100644 (file)
@@ -272,7 +272,6 @@ static int dw8250_probe_of(struct uart_port *p,
        return 0;
 }
 
-#ifdef CONFIG_ACPI
 static int dw8250_probe_acpi(struct uart_8250_port *up,
                             struct dw8250_data *data)
 {
@@ -300,13 +299,6 @@ static int dw8250_probe_acpi(struct uart_8250_port *up,
 
        return 0;
 }
-#else
-static inline int dw8250_probe_acpi(struct uart_8250_port *up,
-                                   struct dw8250_data *data)
-{
-       return -ENODEV;
-}
-#endif /* CONFIG_ACPI */
 
 static int dw8250_probe(struct platform_device *pdev)
 {
index 33bd8606be6272d93f82e8aa6279cc00f6da87f0..01c9e72433e192bc85423d4235ec8704c9409990 100644 (file)
@@ -756,9 +756,10 @@ static int pl010_remove(struct amba_device *dev)
        return 0;
 }
 
-static int pl010_suspend(struct amba_device *dev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int pl010_suspend(struct device *dev)
 {
-       struct uart_amba_port *uap = amba_get_drvdata(dev);
+       struct uart_amba_port *uap = dev_get_drvdata(dev);
 
        if (uap)
                uart_suspend_port(&amba_reg, &uap->port);
@@ -766,15 +767,18 @@ static int pl010_suspend(struct amba_device *dev, pm_message_t state)
        return 0;
 }
 
-static int pl010_resume(struct amba_device *dev)
+static int pl010_resume(struct device *dev)
 {
-       struct uart_amba_port *uap = amba_get_drvdata(dev);
+       struct uart_amba_port *uap = dev_get_drvdata(dev);
 
        if (uap)
                uart_resume_port(&amba_reg, &uap->port);
 
        return 0;
 }
+#endif
+
+static SIMPLE_DEV_PM_OPS(pl010_dev_pm_ops, pl010_suspend, pl010_resume);
 
 static struct amba_id pl010_ids[] = {
        {
@@ -789,12 +793,11 @@ MODULE_DEVICE_TABLE(amba, pl010_ids);
 static struct amba_driver pl010_driver = {
        .drv = {
                .name   = "uart-pl010",
+               .pm     = &pl010_dev_pm_ops,
        },
        .id_table       = pl010_ids,
        .probe          = pl010_probe,
        .remove         = pl010_remove,
-       .suspend        = pl010_suspend,
-       .resume         = pl010_resume,
 };
 
 static int __init pl010_init(void)
index 7203864992a523509ee0f0f42f47c36714a886aa..c8cc8f02b092b2e481096b3bc00260648ed24ebc 100644 (file)
@@ -112,8 +112,6 @@ static struct vendor_data vendor_st = {
        .get_fifosize           = get_fifosize_st,
 };
 
-static struct uart_amba_port *amba_ports[UART_NR];
-
 /* Deals with DMA transactions */
 
 struct pl011_sgbuf {
@@ -327,7 +325,7 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *
                dmaengine_slave_config(chan, &rx_conf);
                uap->dmarx.chan = chan;
 
-               if (plat && plat->dma_rx_poll_enable) {
+               if (plat) {
                        /* Set poll rate if specified. */
                        if (plat->dma_rx_poll_rate) {
                                uap->dmarx.auto_poll_rate = false;
@@ -2169,10 +2167,10 @@ static int pl011_remove(struct amba_device *dev)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int pl011_suspend(struct amba_device *dev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int pl011_suspend(struct device *dev)
 {
-       struct uart_amba_port *uap = amba_get_drvdata(dev);
+       struct uart_amba_port *uap = dev_get_drvdata(dev);
 
        if (!uap)
                return -EINVAL;
@@ -2180,9 +2178,9 @@ static int pl011_suspend(struct amba_device *dev, pm_message_t state)
        return uart_suspend_port(&amba_reg, &uap->port);
 }
 
-static int pl011_resume(struct amba_device *dev)
+static int pl011_resume(struct device *dev)
 {
-       struct uart_amba_port *uap = amba_get_drvdata(dev);
+       struct uart_amba_port *uap = dev_get_drvdata(dev);
 
        if (!uap)
                return -EINVAL;
@@ -2191,6 +2189,8 @@ static int pl011_resume(struct amba_device *dev)
 }
 #endif
 
+static SIMPLE_DEV_PM_OPS(pl011_dev_pm_ops, pl011_suspend, pl011_resume);
+
 static struct amba_id pl011_ids[] = {
        {
                .id     = 0x00041011,
@@ -2210,14 +2210,11 @@ MODULE_DEVICE_TABLE(amba, pl011_ids);
 static struct amba_driver pl011_driver = {
        .drv = {
                .name   = "uart-pl011",
+               .pm     = &pl011_dev_pm_ops,
        },
        .id_table       = pl011_ids,
        .probe          = pl011_probe,
        .remove         = pl011_remove,
-#ifdef CONFIG_PM
-       .suspend        = pl011_suspend,
-       .resume         = pl011_resume,
-#endif
 };
 
 static int __init pl011_init(void)
index b2cfdb661947ec2690fc4840e089688151749a68..d799140e53b6a649b51ace8129b8846ed695a824 100644 (file)
@@ -806,6 +806,9 @@ static unsigned int imx_get_mctrl(struct uart_port *port)
        if (readl(sport->port.membase + UCR2) & UCR2_CTS)
                tmp |= TIOCM_RTS;
 
+       if (readl(sport->port.membase + uts_reg(sport)) & UTS_LOOP)
+               tmp |= TIOCM_LOOP;
+
        return tmp;
 }
 
@@ -821,6 +824,11 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
                        temp |= UCR2_CTS;
 
        writel(temp, sport->port.membase + UCR2);
+
+       temp = readl(sport->port.membase + uts_reg(sport)) & ~UTS_LOOP;
+       if (mctrl & TIOCM_LOOP)
+               temp |= UTS_LOOP;
+       writel(temp, sport->port.membase + uts_reg(sport));
 }
 
 /*
index d8b6fee77a039220ae8d7d8f08a9ff8e08c7066f..aa97fd845b4d8123102c6026ed9a79e53d61e45f 100644 (file)
@@ -734,9 +734,12 @@ static void mxs_auart_reset(struct uart_port *u)
 
 static int mxs_auart_startup(struct uart_port *u)
 {
+       int ret;
        struct mxs_auart_port *s = to_auart_port(u);
 
-       clk_prepare_enable(s->clk);
+       ret = clk_prepare_enable(s->clk);
+       if (ret)
+               return ret;
 
        writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
 
@@ -957,7 +960,9 @@ auart_console_setup(struct console *co, char *options)
        if (!s)
                return -ENODEV;
 
-       clk_prepare_enable(s->clk);
+       ret = clk_prepare_enable(s->clk);
+       if (ret)
+               return ret;
 
        if (options)
                uart_parse_options(options, &baud, &parity, &bits, &flow);
index 0aa2b528ef3d76363c3cd9dcc4ebd96adee850a8..9cbd3acaf37fca13a55ea6b9a854e259790d1758 100644 (file)
@@ -1853,7 +1853,6 @@ static void pch_uart_exit_port(struct eg20t_port *priv)
                debugfs_remove(priv->debugfs);
 #endif
        uart_remove_one_port(&pch_uart_driver, &priv->port);
-       pci_set_drvdata(priv->pdev, NULL);
        free_page((unsigned long)priv->rxbuf.buf);
 }
 
@@ -1907,7 +1906,7 @@ static int pch_uart_pci_resume(struct pci_dev *pdev)
 #define pch_uart_pci_resume NULL
 #endif
 
-static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = {
+static const struct pci_device_id pch_uart_pci_id[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8811),
         .driver_data = pch_et20t_uart0},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8812),
index 328d6deb6b0899b490684b3735800970625cea85..056f91b3a4ca564d4a04d47183979014922f2cc3 100644 (file)
@@ -810,7 +810,7 @@ static void rp2_remove(struct pci_dev *pdev)
        rp2_remove_ports(card);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(rp2_pci_tbl) = {
+static const struct pci_device_id rp2_pci_tbl[] = {
 
        /* RocketPort INFINITY cards */
 
index 0f02351c9239b2221dbc3820b7896388a83a71a8..ece2049bd27016487aef8327eee7fb040ee346db 100644 (file)
@@ -1830,9 +1830,13 @@ uart_set_options(struct uart_port *port, struct console *co,
        /*
         * Ensure that the serial console lock is initialised
         * early.
+        * If this port is a console, then the spinlock is already
+        * initialised.
         */
-       spin_lock_init(&port->lock);
-       lockdep_set_class(&port->lock, &port_lock_key);
+       if (!(uart_console(port) && (port->cons->flags & CON_ENABLED))) {
+               spin_lock_init(&port->lock);
+               lockdep_set_class(&port->lock, &port_lock_key);
+       }
 
        memset(&termios, 0, sizeof(struct ktermios));
 
index c043136fbe5198cf0a7a8704254fc28763ecd0b9..3002e20e10d7d1d227d6f0dcf82ae03959d7a6f1 100644 (file)
@@ -26,7 +26,7 @@
  * Byte threshold to limit memory consumption for flip buffers.
  * The actual memory limit is > 2x this amount.
  */
-#define TTYB_MEM_LIMIT 65536
+#define TTYB_DEFAULT_MEM_LIMIT 65536
 
 /*
  * We default to dicing tty buffer allocations to this many characters
@@ -89,9 +89,10 @@ void tty_buffer_unlock_exclusive(struct tty_port *port)
 
 int tty_buffer_space_avail(struct tty_port *port)
 {
-       int space = TTYB_MEM_LIMIT - atomic_read(&port->buf.memory_used);
+       int space = port->buf.mem_limit - atomic_read(&port->buf.mem_used);
        return max(space, 0);
 }
+EXPORT_SYMBOL_GPL(tty_buffer_space_avail);
 
 static void tty_buffer_reset(struct tty_buffer *p, size_t size)
 {
@@ -100,6 +101,7 @@ static void tty_buffer_reset(struct tty_buffer *p, size_t size)
        p->next = NULL;
        p->commit = 0;
        p->read = 0;
+       p->flags = 0;
 }
 
 /**
@@ -129,7 +131,7 @@ void tty_buffer_free_all(struct tty_port *port)
        buf->head = &buf->sentinel;
        buf->tail = &buf->sentinel;
 
-       atomic_set(&buf->memory_used, 0);
+       atomic_set(&buf->mem_used, 0);
 }
 
 /**
@@ -162,7 +164,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size)
 
        /* Should possibly check if this fails for the largest buffer we
           have queued and recycle that ? */
-       if (atomic_read(&port->buf.memory_used) > TTYB_MEM_LIMIT)
+       if (atomic_read(&port->buf.mem_used) > port->buf.mem_limit)
                return NULL;
        p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
        if (p == NULL)
@@ -170,7 +172,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size)
 
 found:
        tty_buffer_reset(p, size);
-       atomic_add(size, &port->buf.memory_used);
+       atomic_add(size, &port->buf.mem_used);
        return p;
 }
 
@@ -188,7 +190,7 @@ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b)
        struct tty_bufhead *buf = &port->buf;
 
        /* Dumb strategy for now - should keep some stats */
-       WARN_ON(atomic_sub_return(b->size, &buf->memory_used) < 0);
+       WARN_ON(atomic_sub_return(b->size, &buf->mem_used) < 0);
 
        if (b->size > MIN_TTYB_SIZE)
                kfree(b);
@@ -200,9 +202,7 @@ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b)
  *     tty_buffer_flush                -       flush full tty buffers
  *     @tty: tty to flush
  *
- *     flush all the buffers containing receive data. If the buffer is
- *     being processed by flush_to_ldisc then we defer the processing
- *     to that function
+ *     flush all the buffers containing receive data.
  *
  *     Locking: takes buffer lock to ensure single-threaded flip buffer
  *              'consumer'
@@ -230,31 +230,49 @@ void tty_buffer_flush(struct tty_struct *tty)
  *     tty_buffer_request_room         -       grow tty buffer if needed
  *     @tty: tty structure
  *     @size: size desired
+ *     @flags: buffer flags if new buffer allocated (default = 0)
  *
  *     Make at least size bytes of linear space available for the tty
  *     buffer. If we fail return the size we managed to find.
+ *
+ *     Will change over to a new buffer if the current buffer is encoded as
+ *     TTY_NORMAL (so has no flags buffer) and the new buffer requires
+ *     a flags buffer.
  */
-int tty_buffer_request_room(struct tty_port *port, size_t size)
+static int __tty_buffer_request_room(struct tty_port *port, size_t size,
+                                    int flags)
 {
        struct tty_bufhead *buf = &port->buf;
        struct tty_buffer *b, *n;
-       int left;
+       int left, change;
 
        b = buf->tail;
-       left = b->size - b->used;
+       if (b->flags & TTYB_NORMAL)
+               left = 2 * b->size - b->used;
+       else
+               left = b->size - b->used;
 
-       if (left < size) {
+       change = (b->flags & TTYB_NORMAL) && (~flags & TTYB_NORMAL);
+       if (change || left < size) {
                /* This is the slow path - looking for new buffers to use */
                if ((n = tty_buffer_alloc(port, size)) != NULL) {
+                       n->flags = flags;
                        buf->tail = n;
                        b->commit = b->used;
                        smp_mb();
                        b->next = n;
-               } else
+               } else if (change)
+                       size = 0;
+               else
                        size = left;
        }
        return size;
 }
+
+int tty_buffer_request_room(struct tty_port *port, size_t size)
+{
+       return __tty_buffer_request_room(port, size, 0);
+}
 EXPORT_SYMBOL_GPL(tty_buffer_request_room);
 
 /**
@@ -274,12 +292,14 @@ int tty_insert_flip_string_fixed_flag(struct tty_port *port,
        int copied = 0;
        do {
                int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
-               int space = tty_buffer_request_room(port, goal);
+               int flags = (flag == TTY_NORMAL) ? TTYB_NORMAL : 0;
+               int space = __tty_buffer_request_room(port, goal, flags);
                struct tty_buffer *tb = port->buf.tail;
                if (unlikely(space == 0))
                        break;
                memcpy(char_buf_ptr(tb, tb->used), chars, space);
-               memset(flag_buf_ptr(tb, tb->used), flag, space);
+               if (~tb->flags & TTYB_NORMAL)
+                       memset(flag_buf_ptr(tb, tb->used), flag, space);
                tb->used += space;
                copied += space;
                chars += space;
@@ -362,52 +382,28 @@ EXPORT_SYMBOL(tty_schedule_flip);
 int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars,
                size_t size)
 {
-       int space = tty_buffer_request_room(port, size);
+       int space = __tty_buffer_request_room(port, size, TTYB_NORMAL);
        if (likely(space)) {
                struct tty_buffer *tb = port->buf.tail;
                *chars = char_buf_ptr(tb, tb->used);
-               memset(flag_buf_ptr(tb, tb->used), TTY_NORMAL, space);
+               if (~tb->flags & TTYB_NORMAL)
+                       memset(flag_buf_ptr(tb, tb->used), TTY_NORMAL, space);
                tb->used += space;
        }
        return space;
 }
 EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
 
-/**
- *     tty_prepare_flip_string_flags   -       make room for characters
- *     @port: tty port
- *     @chars: return pointer for character write area
- *     @flags: return pointer for status flag write area
- *     @size: desired size
- *
- *     Prepare a block of space in the buffer for data. Returns the length
- *     available and buffer pointer to the space which is now allocated and
- *     accounted for as ready for characters. This is used for drivers
- *     that need their own block copy routines into the buffer. There is no
- *     guarantee the buffer is a DMA target!
- */
-
-int tty_prepare_flip_string_flags(struct tty_port *port,
-                       unsigned char **chars, char **flags, size_t size)
-{
-       int space = tty_buffer_request_room(port, size);
-       if (likely(space)) {
-               struct tty_buffer *tb = port->buf.tail;
-               *chars = char_buf_ptr(tb, tb->used);
-               *flags = flag_buf_ptr(tb, tb->used);
-               tb->used += space;
-       }
-       return space;
-}
-EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
-
 
 static int
 receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count)
 {
        struct tty_ldisc *disc = tty->ldisc;
        unsigned char *p = char_buf_ptr(head, head->read);
-       char          *f = flag_buf_ptr(head, head->read);
+       char          *f = NULL;
+
+       if (~head->flags & TTYB_NORMAL)
+               f = flag_buf_ptr(head, head->read);
 
        if (disc->ops->receive_buf2)
                count = disc->ops->receive_buf2(tty, p, f, count);
@@ -533,7 +529,25 @@ void tty_buffer_init(struct tty_port *port)
        buf->head = &buf->sentinel;
        buf->tail = &buf->sentinel;
        init_llist_head(&buf->free);
-       atomic_set(&buf->memory_used, 0);
+       atomic_set(&buf->mem_used, 0);
        atomic_set(&buf->priority, 0);
        INIT_WORK(&buf->work, flush_to_ldisc);
+       buf->mem_limit = TTYB_DEFAULT_MEM_LIMIT;
+}
+
+/**
+ *     tty_buffer_set_limit    -       change the tty buffer memory limit
+ *     @port: tty port to change
+ *
+ *     Change the tty buffer memory limit.
+ *     Must be called before the other tty buffer functions are used.
+ */
+
+int tty_buffer_set_limit(struct tty_port *port, int limit)
+{
+       if (limit < MIN_TTYB_SIZE)
+               return -EINVAL;
+       port->buf.mem_limit = limit;
+       return 0;
 }
+EXPORT_SYMBOL_GPL(tty_buffer_set_limit);
index 0ddb5c02ad8b6c279047c4c8c9c90e5516327ca7..0891ea0458f64d19f8e4bc04adff6617131999b9 100644 (file)
@@ -203,7 +203,6 @@ struct amba_pl011_data {
        bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
        void *dma_rx_param;
        void *dma_tx_param;
-       bool dma_rx_poll_enable;
        unsigned int dma_rx_poll_rate;
        unsigned int dma_rx_poll_timeout;
         void (*init) (void);
index 8e68a64bfe00b8f151300cc240acedb3820d37dd..e1688802964f3ccb6aebc0738a98f9b838a6d02d 100644 (file)
@@ -286,9 +286,11 @@ void __init parse_early_options(char *cmdline);
 #define arch_initcall(fn)              module_init(fn)
 #define subsys_initcall(fn)            module_init(fn)
 #define fs_initcall(fn)                        module_init(fn)
+#define rootfs_initcall(fn)            module_init(fn)
 #define device_initcall(fn)            module_init(fn)
 #define late_initcall(fn)              module_init(fn)
 
+#define console_initcall(fn)           module_init(fn)
 #define security_initcall(fn)          module_init(fn)
 
 /* Each module must use one module_init(). */
index 97d660ed70c1901407dac9ea49bd1036840e649c..ad98b437696846a0f81914ef1252fff778ec623f 100644 (file)
@@ -39,10 +39,14 @@ struct tty_buffer {
        int size;
        int commit;
        int read;
+       int flags;
        /* Data points here */
        unsigned long data[0];
 };
 
+/* Values for .flags field of tty_buffer */
+#define TTYB_NORMAL    1       /* buffer has no flags buffer */
+
 static inline unsigned char *char_buf_ptr(struct tty_buffer *b, int ofs)
 {
        return ((unsigned char *)b->data) + ofs;
@@ -60,7 +64,8 @@ struct tty_bufhead {
        atomic_t           priority;
        struct tty_buffer sentinel;
        struct llist_head free;         /* Free queue head */
-       atomic_t           memory_used; /* In-use buffers excluding free list */
+       atomic_t           mem_used;    /* In-use buffers excluding free list */
+       int                mem_limit;
        struct tty_buffer *tail;        /* Active buffer */
 };
 /*
index 21ddd7d9ea1fe0303e5910b7de3019b9851e8bda..c28dd523f96e655fcd89dd4bcb4ab200255cbb54 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _LINUX_TTY_FLIP_H
 #define _LINUX_TTY_FLIP_H
 
+extern int tty_buffer_set_limit(struct tty_port *port, int limit);
 extern int tty_buffer_space_avail(struct tty_port *port);
 extern int tty_buffer_request_room(struct tty_port *port, size_t size);
 extern int tty_insert_flip_string_flags(struct tty_port *port,
@@ -9,8 +10,6 @@ extern int tty_insert_flip_string_fixed_flag(struct tty_port *port,
                const unsigned char *chars, char flag, size_t size);
 extern int tty_prepare_flip_string(struct tty_port *port,
                unsigned char **chars, size_t size);
-extern int tty_prepare_flip_string_flags(struct tty_port *port,
-               unsigned char **chars, char **flags, size_t size);
 extern void tty_flip_buffer_push(struct tty_port *port);
 void tty_schedule_flip(struct tty_port *port);
 
@@ -18,8 +17,12 @@ static inline int tty_insert_flip_char(struct tty_port *port,
                                        unsigned char ch, char flag)
 {
        struct tty_buffer *tb = port->buf.tail;
-       if (tb && tb->used < tb->size) {
-               *flag_buf_ptr(tb, tb->used) = flag;
+       int change;
+
+       change = (tb->flags & TTYB_NORMAL) && (flag != TTY_NORMAL);
+       if (!change && tb->used < tb->size) {
+               if (~tb->flags & TTYB_NORMAL)
+                       *flag_buf_ptr(tb, tb->used) = flag;
                *char_buf_ptr(tb, tb->used++) = ch;
                return 1;
        }
index f15c898ff462006fb0bec91d5922ecbf24267d8c..b8347c207cb845d940ed163cb89776e0bacaf252 100644 (file)
@@ -84,7 +84,8 @@
  *     processing.  <cp> is a pointer to the buffer of input
  *     character received by the device.  <fp> is a pointer to a
  *     pointer of flag bytes which indicate whether a character was
- *     received with a parity error, etc.
+ *     received with a parity error, etc. <fp> may be NULL to indicate
+ *     all data received is TTY_NORMAL.
  *
  * void        (*write_wakeup)(struct tty_struct *);
  *
  *     processing.  <cp> is a pointer to the buffer of input
  *     character received by the device.  <fp> is a pointer to a
  *     pointer of flag bytes which indicate whether a character was
- *     received with a parity error, etc.
+ *     received with a parity error, etc. <fp> may be NULL to indicate
+ *     all data received is TTY_NORMAL.
  *     If assigned, prefer this function for automatic flow control.
  */
 
This page took 0.068136 seconds and 5 git commands to generate.