Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / serial / clps711x.c
index 4aaef99..2691112 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
@@ -69,8 +69,7 @@
 
 #define tx_enabled(port)       ((port)->unused[0])
 
-static void
-clps711xuart_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void clps711xuart_stop_tx(struct uart_port *port)
 {
        if (tx_enabled(port)) {
                disable_irq(TX_IRQ(port));
@@ -78,8 +77,7 @@ clps711xuart_stop_tx(struct uart_port *port, unsigned int tty_stop)
        }
 }
 
-static void
-clps711xuart_start_tx(struct uart_port *port, unsigned int tty_start)
+static void clps711xuart_start_tx(struct uart_port *port)
 {
        if (!tx_enabled(port)) {
                enable_irq(TX_IRQ(port));
@@ -100,14 +98,12 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re
 {
        struct uart_port *port = dev_id;
        struct tty_struct *tty = port->info->tty;
-       unsigned int status, ch, flg, ignored = 0;
+       unsigned int status, ch, flg;
 
        status = clps_readl(SYSFLG(port));
        while (!(status & SYSFLG_URXFE)) {
                ch = clps_readl(UARTDR(port));
 
-               if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-                       goto ignore_char;
                port->icount.rx++;
 
                flg = TTY_NORMAL;
@@ -116,60 +112,40 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re
                 * Note that the error handling code is
                 * out of the main execution path
                 */
-               if (ch & UART_ANY_ERR)
-                       goto handle_error;
+               if (unlikely(ch & UART_ANY_ERR)) {
+                       if (ch & UARTDR_PARERR)
+                               port->icount.parity++;
+                       else if (ch & UARTDR_FRMERR)
+                               port->icount.frame++;
+                       if (ch & UARTDR_OVERR)
+                               port->icount.overrun++;
 
-               if (uart_handle_sysrq_char(port, ch, regs))
-                       goto ignore_char;
+                       ch &= port->read_status_mask;
 
-       error_return:
-               *tty->flip.flag_buf_ptr++ = flg;
-               *tty->flip.char_buf_ptr++ = ch;
-               tty->flip.count++;
-       ignore_char:
-               status = clps_readl(SYSFLG(port));
-       }
- out:
-       tty_flip_buffer_push(tty);
-       return IRQ_HANDLED;
+                       if (ch & UARTDR_PARERR)
+                               flg = TTY_PARITY;
+                       else if (ch & UARTDR_FRMERR)
+                               flg = TTY_FRAME;
 
- handle_error:
-       if (ch & UARTDR_PARERR)
-               port->icount.parity++;
-       else if (ch & UARTDR_FRMERR)
-               port->icount.frame++;
-       if (ch & UARTDR_OVERR)
-               port->icount.overrun++;
-
-       if (ch & port->ignore_status_mask) {
-               if (++ignored > 100)
-                       goto out;
-               goto ignore_char;
-       }
-       ch &= port->read_status_mask;
+#ifdef SUPPORT_SYSRQ
+                       port->sysrq = 0;
+#endif
+               }
 
-       if (ch & UARTDR_PARERR)
-               flg = TTY_PARITY;
-       else if (ch & UARTDR_FRMERR)
-               flg = TTY_FRAME;
+               if (uart_handle_sysrq_char(port, ch, regs))
+                       goto ignore_char;
 
-       if (ch & UARTDR_OVERR) {
                /*
                 * 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;
-               ch = 0;
-               flg = TTY_OVERRUN;
+               uart_insert_char(port, ch, UARTDR_OVERR, ch, flg);
+
+       ignore_char:
+               status = clps_readl(SYSFLG(port));
        }
-#ifdef SUPPORT_SYSRQ
-       port->sysrq = 0;
-#endif
-       goto error_return;
+       tty_flip_buffer_push(tty);
+       return IRQ_HANDLED;
 }
 
 static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *regs)
@@ -185,7 +161,7 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *re
                return IRQ_HANDLED;
        }
        if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-               clps711xuart_stop_tx(port, 0);
+               clps711xuart_stop_tx(port);
                return IRQ_HANDLED;
        }
 
@@ -202,7 +178,7 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *re
                uart_write_wakeup(port);
 
        if (uart_circ_empty(xmit))
-               clps711xuart_stop_tx(port, 0);
+               clps711xuart_stop_tx(port);
 
        return IRQ_HANDLED;
 }
@@ -434,7 +410,7 @@ static struct uart_port clps711x_ports[UART_NR] = {
                .fifosize       = 16,
                .ops            = &clps711x_pops,
                .line           = 0,
-               .flags          = ASYNC_BOOT_AUTOCONF,
+               .flags          = UPF_BOOT_AUTOCONF,
        },
        {
                .iobase         = SYSCON2,
@@ -443,11 +419,18 @@ static struct uart_port clps711x_ports[UART_NR] = {
                .fifosize       = 16,
                .ops            = &clps711x_pops,
                .line           = 1,
-               .flags          = ASYNC_BOOT_AUTOCONF,
+               .flags          = UPF_BOOT_AUTOCONF,
        }
 };
 
 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
+static void clps711xuart_console_putchar(struct uart_port *port, int ch)
+{
+       while (clps_readl(SYSFLG(port)) & SYSFLG_UTXFF)
+               barrier();
+       clps_writel(ch, UARTDR(port));
+}
+
 /*
  *     Print a string to the serial port trying not to disturb
  *     any possible real use of the port...
@@ -462,7 +445,6 @@ clps711xuart_console_write(struct console *co, const char *s,
 {
        struct uart_port *port = clps711x_ports + co->index;
        unsigned int status, syscon;
-       int i;
 
        /*
         *      Ensure that the port is enabled.
@@ -470,21 +452,7 @@ clps711xuart_console_write(struct console *co, const char *s,
        syscon = clps_readl(SYSCON(port));
        clps_writel(syscon | SYSCON_UARTEN, SYSCON(port));
 
-       /*
-        *      Now, do each character
-        */
-       for (i = 0; i < count; i++) {
-               do {
-                       status = clps_readl(SYSFLG(port));
-               } while (status & SYSFLG_UTXFF);
-               clps_writel(s[i], UARTDR(port));
-               if (s[i] == '\n') {
-                       do {
-                               status = clps_readl(SYSFLG(port));
-                       } while (status & SYSFLG_UTXFF);
-                       clps_writel('\r', UARTDR(port));
-               }
-       }
+       uart_console_write(port, s, count, clps711xuart_console_putchar);
 
        /*
         *      Finally, wait for transmitter to become empty
@@ -547,7 +515,7 @@ static int __init clps711xuart_console_setup(struct console *co, char *options)
        return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
-extern struct uart_driver clps711x_reg;
+static struct uart_driver clps711x_reg;
 static struct console clps711x_console = {
        .name           = "ttyCL",
        .write          = clps711xuart_console_write,