]> git.neil.brown.name Git - history.git/commitdiff
[SERIAL] serial driver fixes
authorRussell King <rmk@flint.arm.linux.org.uk>
Sat, 13 Nov 2004 18:12:03 +0000 (18:12 +0000)
committerRussell King <rmk@flint.arm.linux.org.uk>
Sat, 13 Nov 2004 18:12:03 +0000 (18:12 +0000)
Patch from Alan Cox, expanded to cover ARM drivers by Russell King.

- define SUPPORT_SYSRQ early
- ensure consistent include ordering
- use proper helper functions for flip buffer handling
- remove deadlock on overrun

12 files changed:
drivers/serial/21285.c
drivers/serial/8250.c
drivers/serial/amba-pl010.c
drivers/serial/amba-pl011.c
drivers/serial/clps711x.c
drivers/serial/dz.c
drivers/serial/imx.c
drivers/serial/pxa.c
drivers/serial/s3c2410.c
drivers/serial/sa1100.c
drivers/serial/serial_lh7a40x.c
drivers/serial/uart00.c

index 511a40b0f8539f6dfeccdb31e0759478dc75d87e..759addd51854745dd7fe5118c84b58ba79324a38 100644 (file)
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/console.h>
+#include <linux/device.h>
+#include <linux/tty_flip.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
-#include <linux/device.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/mach-types.h>
 #include <asm/hardware/dec21285.h>
 #include <asm/hardware.h>
 
@@ -90,22 +92,21 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r
 {
        struct uart_port *port = dev_id;
        struct tty_struct *tty = port->info->tty;
-       unsigned int status, ch, rxs, max_count = 256;
+       unsigned int status, ch, flag, rxs, max_count = 256;
 
        status = *CSR_UARTFLG;
        while (!(status & 0x10) && max_count--) {
                if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-                       tty->flip.work.func((void *)tty);
-                       if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-                               printk(KERN_WARNING "TTY_DONT_FLIP set\n");
-                               goto out;
-                       }
+                       if (tty->low_latency)
+                               tty_flip_buffer_push(tty);
+                       /*
+                        * If this failed then we will throw away the
+                        * bytes but must do so to clear interrupts
+                        */
                }
 
                ch = *CSR_UARTDR;
-
-               *tty->flip.char_buf_ptr = ch;
-               *tty->flip.flag_buf_ptr = TTY_NORMAL;
+               flag = TTY_NORMAL;
                port->icount.rx++;
 
                rxs = *CSR_RXSTAT | RXSTAT_DUMMY_READ;
@@ -120,15 +121,13 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r
                        rxs &= port->read_status_mask;
 
                        if (rxs & RXSTAT_PARITY)
-                               *tty->flip.flag_buf_ptr = TTY_PARITY;
+                               flag = TTY_PARITY;
                        else if (rxs & RXSTAT_FRAME)
-                               *tty->flip.flag_buf_ptr = TTY_FRAME;
+                               flag = TTY_FRAME;
                }
 
                if ((rxs & port->ignore_status_mask) == 0) {
-                       tty->flip.flag_buf_ptr++;
-                       tty->flip.char_buf_ptr++;
-                       tty->flip.count++;
+                       tty_insert_flip_char(tty, ch, flag);
                }
                if ((rxs & RXSTAT_OVERRUN) &&
                    tty->flip.count < TTY_FLIPBUF_SIZE) {
@@ -137,9 +136,7 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r
                         * immediately, and doesn't affect the current
                         * character.
                         */
-                       *tty->flip.char_buf_ptr++ = 0;
-                       *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
-                       tty->flip.count++;
+                       tty_insert_flip_char(tty, 0, TTY_OVERRUN);
                }
                status = *CSR_UARTFLG;
        }
index 5dcf0e64faf49dcd844ffedba4930c96c84205c5..8b8dc2f23a9541c47822abd454fe03a4f3dbe7fc 100644 (file)
  *  membase is an 'ioremapped' cookie.
  */
 #include <linux/config.h>
+
+#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/tty.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
 #include <linux/serial_reg.h>
+#include <linux/serial_core.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/device.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
 #include "8250.h"
 
 /*
@@ -979,16 +980,19 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
        struct tty_struct *tty = up->port.info->tty;
        unsigned char ch, lsr = *status;
        int max_count = 256;
+       char flag;
 
        do {
+               /* The following is not allowed by the tty layer and
+                  unsafe. It should be fixed ASAP */
                if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-                       tty->flip.work.func((void *)tty);
-                       if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-                               return; // if TTY_DONT_FLIP is set
+                       if(tty->low_latency)
+                               tty_flip_buffer_push(tty);
+                       /* If this failed then we will throw away the
+                          bytes but must do so to clear interrupts */
                }
                ch = serial_inp(up, UART_RX);
-               *tty->flip.char_buf_ptr = ch;
-               *tty->flip.flag_buf_ptr = TTY_NORMAL;
+               flag = TTY_NORMAL;
                up->port.icount.rx++;
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
@@ -1031,18 +1035,16 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
 
                        if (lsr & UART_LSR_BI) {
                                DEBUG_INTR("handling break....");
-                               *tty->flip.flag_buf_ptr = TTY_BREAK;
+                               flag = TTY_BREAK;
                        } else if (lsr & UART_LSR_PE)
-                               *tty->flip.flag_buf_ptr = TTY_PARITY;
+                               flag = TTY_PARITY;
                        else if (lsr & UART_LSR_FE)
-                               *tty->flip.flag_buf_ptr = TTY_FRAME;
+                               flag = TTY_FRAME;
                }
                if (uart_handle_sysrq_char(&up->port, ch, regs))
                        goto ignore_char;
                if ((lsr & up->port.ignore_status_mask) == 0) {
-                       tty->flip.flag_buf_ptr++;
-                       tty->flip.char_buf_ptr++;
-                       tty->flip.count++;
+                       tty_insert_flip_char(tty, ch, flag);
                }
                if ((lsr & UART_LSR_OE) &&
                    tty->flip.count < TTY_FLIPBUF_SIZE) {
@@ -1051,10 +1053,7 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
                         * immediately, and doesn't affect the current
                         * character.
                         */
-                       *tty->flip.flag_buf_ptr = TTY_OVERRUN;
-                       tty->flip.flag_buf_ptr++;
-                       tty->flip.char_buf_ptr++;
-                       tty->flip.count++;
+                       tty_insert_flip_char(tty, 0, TTY_OVERRUN);
                }
        ignore_char:
                lsr = serial_inp(up, UART_LSR);
index b88c00b37e7378d953aac64e798772cf9d87f178..0cee4b9460e9ee0abacb2b1920a61bed6fdacfef 100644 (file)
  * and hooked into this driver.
  */
 #include <linux/config.h>
+
+#if defined(CONFIG_SERIAL_AMBA_PL010_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
 #include <linux/module.h>
-#include <linux/tty.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
-#include <linux/serial.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
 #include <linux/device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/hardware/amba.h>
-
-#if defined(CONFIG_SERIAL_AMBA_PL010_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-
 #include <asm/hardware/amba_serial.h>
 
 #define UART_NR                2
@@ -149,22 +149,22 @@ pl010_rx_chars(struct uart_port *port)
 #endif
 {
        struct tty_struct *tty = port->info->tty;
-       unsigned int status, ch, rsr, max_count = 256;
+       unsigned int status, ch, flag, rsr, max_count = 256;
 
        status = UART_GET_FR(port);
        while (UART_RX_DATA(status) && max_count--) {
                if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-                       tty->flip.work.func((void *)tty);
-                       if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-                               printk(KERN_WARNING "TTY_DONT_FLIP set\n");
-                               return;
-                       }
+                       if (tty->low_latency)
+                               tty_flip_buffer_push(tty);
+                       /*
+                        * If this failed then we will throw away the
+                        * bytes but must do so to clear interrupts.
+                        */
                }
 
                ch = UART_GET_CHAR(port);
+               flag = TTY_NORMAL;
 
-               *tty->flip.char_buf_ptr = ch;
-               *tty->flip.flag_buf_ptr = TTY_NORMAL;
                port->icount.rx++;
 
                /*
@@ -188,20 +188,18 @@ pl010_rx_chars(struct uart_port *port)
                        rsr &= port->read_status_mask;
 
                        if (rsr & UART01x_RSR_BE)
-                               *tty->flip.flag_buf_ptr = TTY_BREAK;
+                               flag = TTY_BREAK;
                        else if (rsr & UART01x_RSR_PE)
-                               *tty->flip.flag_buf_ptr = TTY_PARITY;
+                               flag = TTY_PARITY;
                        else if (rsr & UART01x_RSR_FE)
-                               *tty->flip.flag_buf_ptr = TTY_FRAME;
+                               flag = TTY_FRAME;
                }
 
                if (uart_handle_sysrq_char(port, ch, regs))
                        goto ignore_char;
 
                if ((rsr & port->ignore_status_mask) == 0) {
-                       tty->flip.flag_buf_ptr++;
-                       tty->flip.char_buf_ptr++;
-                       tty->flip.count++;
+                       tty_insert_flip_char(tty, ch, flag);
                }
                if ((rsr & UART01x_RSR_OE) &&
                    tty->flip.count < TTY_FLIPBUF_SIZE) {
@@ -210,9 +208,7 @@ pl010_rx_chars(struct uart_port *port)
                         * immediately, and doesn't affect the current
                         * character
                         */
-                       *tty->flip.char_buf_ptr++ = 0;
-                       *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
-                       tty->flip.count++;
+                       tty_insert_flip_char(tty, 0, TTY_OVERRUN);
                }
        ignore_char:
                status = UART_GET_FR(port);
index 54d1a72cf9f4f56bf0b2c6e66549e0940a284479..ff658a830f3401ea9c0f3932abc2ed12599acb5e 100644 (file)
  * and hooked into this driver.
  */
 #include <linux/config.h>
+
+#if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
 #include <linux/module.h>
-#include <linux/tty.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
-#include <linux/serial.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
 #include <linux/device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/hardware/amba.h>
 #include <asm/hardware/clock.h>
-
-#if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-
 #include <asm/hardware/amba_serial.h>
 
 #define UART_NR                        14
@@ -115,22 +115,21 @@ pl011_rx_chars(struct uart_amba_port *uap)
 #endif
 {
        struct tty_struct *tty = uap->port.info->tty;
-       unsigned int status, ch, rsr, max_count = 256;
+       unsigned int status, ch, flag, rsr, max_count = 256;
 
        status = readw(uap->port.membase + UART01x_FR);
        while ((status & UART01x_FR_RXFE) == 0 && max_count--) {
                if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-                       tty->flip.work.func((void *)tty);
-                       if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-                               printk(KERN_WARNING "TTY_DONT_FLIP set\n");
-                               return;
-                       }
+                       if (tty->low_latency)
+                               tty_flip_buffer_push(tty);
+                       /*
+                        * If this failed then we will throw away the
+                        * bytes but must do so to clear interrupts
+                        */
                }
 
                ch = readw(uap->port.membase + UART01x_DR);
-
-               *tty->flip.char_buf_ptr = ch;
-               *tty->flip.flag_buf_ptr = TTY_NORMAL;
+               flag = TTY_NORMAL;
                uap->port.icount.rx++;
 
                /*
@@ -154,20 +153,18 @@ pl011_rx_chars(struct uart_amba_port *uap)
                        rsr &= uap->port.read_status_mask;
 
                        if (rsr & UART01x_RSR_BE)
-                               *tty->flip.flag_buf_ptr = TTY_BREAK;
+                               flag = TTY_BREAK;
                        else if (rsr & UART01x_RSR_PE)
-                               *tty->flip.flag_buf_ptr = TTY_PARITY;
+                               flag = TTY_PARITY;
                        else if (rsr & UART01x_RSR_FE)
-                               *tty->flip.flag_buf_ptr = TTY_FRAME;
+                               flag = TTY_FRAME;
                }
 
                if (uart_handle_sysrq_char(&uap->port, ch, regs))
                        goto ignore_char;
 
                if ((rsr & uap->port.ignore_status_mask) == 0) {
-                       tty->flip.flag_buf_ptr++;
-                       tty->flip.char_buf_ptr++;
-                       tty->flip.count++;
+                       tty_insert_flip_char(tty, ch, flag);
                }
                if ((rsr & UART01x_RSR_OE) &&
                    tty->flip.count < TTY_FLIPBUF_SIZE) {
@@ -176,9 +173,7 @@ pl011_rx_chars(struct uart_amba_port *uap)
                         * immediately, and doesn't affect the current
                         * character
                         */
-                       *tty->flip.char_buf_ptr++ = 0;
-                       *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
-                       tty->flip.count++;
+                       tty_insert_flip_char(tty, 0, TTY_OVERRUN);
                }
        ignore_char:
                status = readw(uap->port.membase + UART01x_FR);
index 4aaef99d120b54c7e154e1ae7391f0b18c0ff298..16592fae47f3c5e9a06d00b038f074c7f328ca5c 100644 (file)
  *
  */
 #include <linux/config.h>
+
+#if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
 #include <linux/module.h>
-#include <linux/tty.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
-#include <linux/serial.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
 #include <linux/spinlock.h>
 #include <linux/device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-
-#if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-
 #include <asm/hardware/clps7111.h>
 
 #define UART_NR                2
@@ -123,9 +123,7 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re
                        goto ignore_char;
 
        error_return:
-               *tty->flip.flag_buf_ptr++ = flg;
-               *tty->flip.char_buf_ptr++ = ch;
-               tty->flip.count++;
+               tty_insert_flip_char(tty, ch, flg);
        ignore_char:
                status = clps_readl(SYSFLG(port));
        }
@@ -158,11 +156,7 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re
                 * CHECK: does overrun affect the current character?
                 * ASSUMPTION: it does not.
                 */
-               *tty->flip.flag_buf_ptr++ = flg;
-               *tty->flip.char_buf_ptr++ = ch;
-               tty->flip.count++;
-               if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-                       goto ignore_char;
+               tty_insert_flip_char(tty, ch, flg);
                ch = 0;
                flg = TTY_OVERRUN;
        }
index 293d17234bffd5b10ba9462b3781c2e5e607ca0f..97824eeeafae51bdeb93cda017b21e223b7c8c9e 100644 (file)
 
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/tty.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/console.h>
-#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
 #include <linux/serial_core.h>
+#include <linux/serial.h>
 
 #include <asm/bootinfo.h>
 #include <asm/dec/interrupts.h>
@@ -186,7 +187,7 @@ static inline void dz_receive_chars(struct dz_port *dport)
        struct uart_icount *icount;
        int ignore = 0;
        unsigned short status, tmp;
-       unsigned char ch;
+       unsigned char ch, flag;
 
        /* this code is going to be a problem...
           the call to tty_flip_buffer is going to need
@@ -201,6 +202,7 @@ static inline void dz_receive_chars(struct dz_port *dport)
 
 
                ch = UCHAR(status);     /* grab the char */
+               flag = TTY_NORMAL;
 
 #if 0
                if (info->is_console) {
@@ -217,8 +219,6 @@ static inline void dz_receive_chars(struct dz_port *dport)
                if (tty->flip.count >= TTY_FLIPBUF_SIZE)
                        break;
 
-               *tty->flip.char_buf_ptr = ch;
-               *tty->flip.flag_buf_ptr = 0;
                icount->rx++;
 
                /* keep track of the statistics */
@@ -243,12 +243,12 @@ static inline void dz_receive_chars(struct dz_port *dport)
                        tmp = status & dport->port.read_status_mask;
 
                        if (tmp & DZ_PERR) {
-                               *tty->flip.flag_buf_ptr = TTY_PARITY;
+                               flag = TTY_PARITY;
 #ifdef DEBUG_DZ
                                debug_console("PERR\n", 5);
 #endif
                        } else if (tmp & DZ_FERR) {
-                               *tty->flip.flag_buf_ptr = TTY_FRAME;
+                               flag = TTY_FRAME;
 #ifdef DEBUG_DZ
                                debug_console("FERR\n", 5);
 #endif
@@ -257,17 +257,12 @@ static inline void dz_receive_chars(struct dz_port *dport)
 #ifdef DEBUG_DZ
                                debug_console("OERR\n", 5);
 #endif
-                               if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-                                       tty->flip.count++;
-                                       tty->flip.flag_buf_ptr++;
-                                       tty->flip.char_buf_ptr++;
-                                       *tty->flip.flag_buf_ptr = TTY_OVERRUN;
-                               }
+                               tty_insert_flip_char(tty, ch, flag);
+                               ch = 0;
+                               flag = TTY_OVERRUN;
                        }
                }
-               tty->flip.flag_buf_ptr++;
-               tty->flip.char_buf_ptr++;
-               tty->flip.count++;
+               tty_insert_flip_char(tty, ch, flag);
              ignore_char:
        } while (status & DZ_DVAL);
 
index c52fd3928882fdd7d860775771f4ca6d18d1b741..89726fa4048f5df99dc5500b91ce9c971ccfa018 100644 (file)
  *
  */
 #include <linux/config.h>
+
+#if defined(CONFIG_SERIAL_IMX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
 #include <linux/module.h>
-#include <linux/tty.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
-#include <linux/serial.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
 #include <linux/device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/arch/serial.h>
 #include <asm/mach-types.h>
 
-#if defined(CONFIG_SERIAL_IMX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-
 /* We've been assigned a range on the "Low-density serial ports" major */
 #define SERIAL_IMX_MAJOR       204
 #define MINOR_START            41
@@ -237,9 +238,7 @@ static irqreturn_t imx_rxint(int irq, void *dev_id, struct pt_regs *regs)
                        goto handle_error;
 
        error_return:
-               *tty->flip.flag_buf_ptr++ = flg;
-               *tty->flip.char_buf_ptr++ = (unsigned char)rx;
-               tty->flip.count++;
+               tty_insert_flip_char(tty, rx, flg);
 
                if (tty->flip.count >= TTY_FLIPBUF_SIZE)
                        goto out;
index 3a7ab51d20cedbfa8b0811fa0a0532c741c771ff..68b25b2c26b1c5746c5fe055b3bc2fbed9c67d5d 100644 (file)
  */
 
 #include <linux/config.h>
+
+#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
 #include <linux/module.h>
-#include <linux/tty.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
 
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/irq.h>
 #include <asm/arch/pxa-regs.h>
 
-#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-
 
 struct uart_pxa_port {
        struct uart_port        port;
@@ -102,25 +103,20 @@ static inline void
 receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs)
 {
        struct tty_struct *tty = up->port.info->tty;
-       unsigned char ch;
+       unsigned int ch, flag;
        int max_count = 256;
 
        do {
                if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
+                       if (tty->low_latency)
+                               tty_flip_buffer_push(tty);
                        /*
-                        * FIXME: Deadlock can happen here if we're a
-                        * low-latency port.  We're holding the per-port
-                        * spinlock, and we call flush_to_ldisc->
-                        * n_tty_receive_buf->n_tty_receive_char->
-                        * opost->uart_put_char.
+                        * If this failed then we will throw away the
+                        * bytes but must do so to clear interrupts
                         */
-                       tty->flip.work.func((void *)tty);
-                       if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-                               return; // if TTY_DONT_FLIP is set
                }
                ch = serial_in(up, UART_RX);
-               *tty->flip.char_buf_ptr = ch;
-               *tty->flip.flag_buf_ptr = TTY_NORMAL;
+               flag = TTY_NORMAL;
                up->port.icount.rx++;
 
                if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
@@ -159,18 +155,16 @@ receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs)
                        }
 #endif
                        if (*status & UART_LSR_BI) {
-                               *tty->flip.flag_buf_ptr = TTY_BREAK;
+                               flag = TTY_BREAK;
                        } else if (*status & UART_LSR_PE)
-                               *tty->flip.flag_buf_ptr = TTY_PARITY;
+                               flag = TTY_PARITY;
                        else if (*status & UART_LSR_FE)
-                               *tty->flip.flag_buf_ptr = TTY_FRAME;
+                               flag = TTY_FRAME;
                }
                if (uart_handle_sysrq_char(&up->port, ch, regs))
                        goto ignore_char;
                if ((*status & up->port.ignore_status_mask) == 0) {
-                       tty->flip.flag_buf_ptr++;
-                       tty->flip.char_buf_ptr++;
-                       tty->flip.count++;
+                       tty_insert_flip_char(tty, ch, flag);
                }
                if ((*status & UART_LSR_OE) &&
                    tty->flip.count < TTY_FLIPBUF_SIZE) {
@@ -179,10 +173,7 @@ receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs)
                         * immediately, and doesn't affect the current
                         * character.
                         */
-                       *tty->flip.flag_buf_ptr = TTY_OVERRUN;
-                       tty->flip.flag_buf_ptr++;
-                       tty->flip.char_buf_ptr++;
-                       tty->flip.count++;
+                       tty_insert_flip_char(tty, 0, TTY_OVERRUN);
                }
        ignore_char:
                *status = serial_in(up, UART_LSR);
index 70d2f833318e1240d83311fd796115961443716a..baa480f065430535e36a4eb974a2e2932c30216d 100644 (file)
  */
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/tty.h>
 #include <linux/ioport.h>
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/console.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
 
@@ -111,7 +112,7 @@ serial_s3c2410_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct uart_port *port = dev_id;
        struct tty_struct *tty = port->info->tty;
-       unsigned int ufcon, ch, rxs, ufstat;
+       unsigned int ufcon, ch, flag, rxs, ufstat;
        int max_count = 256;
 
        while (max_count-- > 0) {
@@ -122,17 +123,16 @@ serial_s3c2410_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
                        break;
 
                if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-                       tty->flip.work.func((void *)tty);
-                       if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-                               printk(KERN_WARNING "TTY_DONT_FLIP set\n");
-                               goto out;
-                       }
+                       if (tty->low_latency)
+                               tty_flip_buffer_push(tty);
+                       /*
+                        * If this failed then we will throw away the
+                        * bytes but must do so to clear interrupts
+                        */
                }
 
                ch = rd_regb(port, S3C2410_URXH);
-
-               *tty->flip.char_buf_ptr = ch;
-               *tty->flip.flag_buf_ptr = TTY_NORMAL;
+               flag = TTY_NORMAL;
                port->icount.rx++;
 
                rxs = rd_regb(port, S3C2410_UERSTAT) | RXSTAT_DUMMY_READ;
@@ -146,15 +146,13 @@ serial_s3c2410_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
                        rxs &= port->read_status_mask;
 
                        if (rxs & S3C2410_UERSTAT_PARITY)
-                               *tty->flip.flag_buf_ptr = TTY_PARITY;
+                               flag = TTY_PARITY;
                        else if (rxs & ( S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_OVERRUN))
-                               *tty->flip.flag_buf_ptr = TTY_FRAME;
+                               flag = TTY_FRAME;
                }
 
                if ((rxs & port->ignore_status_mask) == 0) {
-                       tty->flip.flag_buf_ptr++;
-                       tty->flip.char_buf_ptr++;
-                       tty->flip.count++;
+                       tty_insert_flip_char(tty, ch, flag);
                }
 
                if ((rxs & S3C2410_UERSTAT_OVERRUN) &&
@@ -164,9 +162,7 @@ serial_s3c2410_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
                         * immediately, and doesn't affect the current
                         * character.
                         */
-                       *tty->flip.char_buf_ptr++ = 0;
-                       *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
-                       tty->flip.count++;
+                       tty_insert_flip_char(tty, 0, TTY_OVERRUN);
                }
        }
        tty_flip_buffer_push(tty);
index b60c5b60484c7ec0fb3496ae9e39906ac5f32131..91d208755a6ad5722eca243bf2e4d0ac9690f0f6 100644 (file)
  *
  */
 #include <linux/config.h>
+
+#if defined(CONFIG_SERIAL_SA1100_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
 #include <linux/module.h>
-#include <linux/tty.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
-#include <linux/serial.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
 #include <linux/device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/hardware.h>
 #include <asm/mach/serial_sa1100.h>
 
-#if defined(CONFIG_SERIAL_SA1100_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-
 /* We've been assigned a range on the "Low-density serial ports" major */
 #define SERIAL_SA1100_MAJOR    204
 #define MINOR_START            5
@@ -220,9 +221,7 @@ sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
                        goto ignore_char;
 
        error_return:
-               *tty->flip.flag_buf_ptr++ = flg;
-               *tty->flip.char_buf_ptr++ = ch;
-               tty->flip.count++;
+               tty_insert_flip_char(tty, ch, flg);
        ignore_char:
                status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
                         UTSR0_TO_SM(UART_GET_UTSR0(sport));
@@ -257,11 +256,7 @@ sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
                 * overrun does *not* affect the character
                 * we read from the FIFO
                 */
-               *tty->flip.flag_buf_ptr++ = flg;
-               *tty->flip.char_buf_ptr++ = ch;
-               tty->flip.count++;
-               if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-                       goto ignore_char;
+               tty_insert_flip_char(tty, ch, flg);
                ch = 0;
                flg = TTY_OVERRUN;
        }
index 8aa264f4cb42cf931aadc35c7a84ce4e7939b4ee..4ce3a41f16116478d5b8664274ebbff00e763bda 100644 (file)
  */
 
 #include <linux/config.h>
+
+#if defined(CONFIG_SERIAL_LH7A40X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
 #include <linux/module.h>
-#include <linux/tty.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
-#include <linux/serial.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#if defined(CONFIG_SERIAL_LH7A40X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-
 #define DEV_MAJOR      204
 #define DEV_MINOR      16
 #define DEV_NR         3
@@ -145,21 +146,20 @@ lh7a40xuart_rx_chars (struct uart_port* port)
 {
        struct tty_struct* tty = port->info->tty;
        int cbRxMax = 256;      /* (Gross) limit on receive */
-       unsigned int data;      /* Received data and status */
+       unsigned int data, flag;/* Received data and status */
 
        while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) {
                if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-                       tty->flip.work.func((void*)tty);
-                       if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-                               printk(KERN_WARNING "TTY_DONT_FLIP set\n");
-                               return;
-                       }
+                       if (tty->low_latency)
+                               tty_flip_buffer_push(tty);
+                       /*
+                        * If this failed then we will throw away the
+                        * bytes but must do so to clear interrupts
+                        */
                }
 
                data = UR (port, UART_R_DATA);
-
-               *tty->flip.char_buf_ptr = (unsigned char) data;
-               *tty->flip.flag_buf_ptr = TTY_NORMAL;
+               flag = TTY_NORMAL;
                ++port->icount.rx;
 
                if (data & RxError) {   /* Quick check, short-circuit */
@@ -180,20 +180,18 @@ lh7a40xuart_rx_chars (struct uart_port* port)
                        data &= port->read_status_mask | 0xff;
 
                        if (data & RxBreak)
-                               *tty->flip.flag_buf_ptr = TTY_BREAK;
+                               flag = TTY_BREAK;
                        else if (data & RxParityError)
-                               *tty->flip.flag_buf_ptr = TTY_PARITY;
+                               flag = TTY_PARITY;
                        else if (data & RxFramingError)
-                               *tty->flip.flag_buf_ptr = TTY_FRAME;
+                               flag = TTY_FRAME;
                }
 
                if (uart_handle_sysrq_char (port, (unsigned char) data, regs))
                        continue;
 
                if ((data & port->ignore_status_mask) == 0) {
-                       ++tty->flip.flag_buf_ptr;
-                       ++tty->flip.char_buf_ptr;
-                       ++tty->flip.count;
+                       tty_insert_flip_char(tty, data, flag);
                }
                if ((data & RxOverrunError)
                    && tty->flip.count < TTY_FLIPBUF_SIZE) {
@@ -202,9 +200,7 @@ lh7a40xuart_rx_chars (struct uart_port* port)
                         * immediately, and doesn't affect the current
                         * character
                         */
-                       *tty->flip.char_buf_ptr++ = 0;
-                       *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
-                       ++tty->flip.count;
+                       tty_insert_flip_char(tty, 0, TTY_OVERRUN);
                }
        }
        tty_flip_buffer_push (tty);
index caaa89a8d14a999187a6197c4296824679ef1e98..186f1300cead9524a54e54bf7823c42492bd2dc3 100644 (file)
  *
  */
 #include <linux/config.h>
+
+#if defined(CONFIG_SERIAL_UART00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
 #include <linux/module.h>
-#include <linux/tty.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
-#include <linux/serial.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/sizes.h>
 
-#if defined(CONFIG_SERIAL_UART00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
 #include <asm/arch/excalibur.h>
 #define UART00_TYPE (volatile unsigned int*)
 #include <asm/arch/uart00.h>
@@ -132,9 +134,8 @@ uart00_rx_chars(struct uart_port *port, struct pt_regs *regs)
                        goto ignore_char;
 
        error_return:
-               *tty->flip.flag_buf_ptr++ = flg;
-               *tty->flip.char_buf_ptr++ = ch;
-               tty->flip.count++;
+               tty_insert_flip_char(tty, ch, flg);
+
        ignore_char:
                status = UART_GET_RSR(port);
        }
@@ -174,11 +175,7 @@ uart00_rx_chars(struct uart_port *port, struct pt_regs *regs)
                 * CHECK: does overrun affect the current character?
                 * ASSUMPTION: it does not.
                 */
-               *tty->flip.flag_buf_ptr++ = flg;
-               *tty->flip.char_buf_ptr++ = ch;
-               tty->flip.count++;
-               if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-                       goto ignore_char;
+               tty_insert_flip_char(tty, ch, flg);
                ch = 0;
                flg = TTY_OVERRUN;
        }