drivers/serial/sunsu.c: Correct use after free
[safe/jmp/linux-2.6] / drivers / serial / 21285.c
index f8504b0..8681f13 100644 (file)
@@ -1,13 +1,10 @@
 /*
- * linux/drivers/char/21285.c
+ * linux/drivers/serial/21285.c
  *
  * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
  *
  * Based on drivers/char/serial.c
- *
- *  $Id: 21285.c,v 1.37 2002/07/28 10:03:27 rmk Exp $
  */
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/tty.h>
 #include <linux/ioport.h>
 #include <linux/tty_flip.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
+#include <linux/io.h>
 
-#include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 #include <asm/hardware/dec21285.h>
-#include <asm/hardware.h>
+#include <mach/hardware.h>
 
 #define BAUD_BASE              (mem_fclk_21285/64)
 
@@ -58,17 +55,15 @@ static const char serial21285_name[] = "Footbridge UART";
  *  int((BAUD_BASE - (baud >> 1)) / baud)
  */
 
-static void
-serial21285_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void serial21285_stop_tx(struct uart_port *port)
 {
        if (tx_enabled(port)) {
-               disable_irq(IRQ_CONTX);
+               disable_irq_nosync(IRQ_CONTX);
                tx_enabled(port) = 0;
        }
 }
 
-static void
-serial21285_start_tx(struct uart_port *port, unsigned int tty_start)
+static void serial21285_start_tx(struct uart_port *port)
 {
        if (!tx_enabled(port)) {
                enable_irq(IRQ_CONTX);
@@ -79,7 +74,7 @@ serial21285_start_tx(struct uart_port *port, unsigned int tty_start)
 static void serial21285_stop_rx(struct uart_port *port)
 {
        if (rx_enabled(port)) {
-               disable_irq(IRQ_CONRX);
+               disable_irq_nosync(IRQ_CONRX);
                rx_enabled(port) = 0;
        }
 }
@@ -88,29 +83,20 @@ static void serial21285_enable_ms(struct uart_port *port)
 {
 }
 
-static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t serial21285_rx_chars(int irq, void *dev_id)
 {
        struct uart_port *port = dev_id;
-       struct tty_struct *tty = port->info->tty;
+       struct tty_struct *tty = port->state->port.tty;
        unsigned int status, ch, flag, rxs, max_count = 256;
 
        status = *CSR_UARTFLG;
        while (!(status & 0x10) && max_count--) {
-               if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-                       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;
                flag = TTY_NORMAL;
                port->icount.rx++;
 
                rxs = *CSR_RXSTAT | RXSTAT_DUMMY_READ;
-               if (rxs & RXSTAT_ANYERR) {
+               if (unlikely(rxs & RXSTAT_ANYERR)) {
                        if (rxs & RXSTAT_PARITY)
                                port->icount.parity++;
                        else if (rxs & RXSTAT_FRAME)
@@ -126,18 +112,8 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r
                                flag = TTY_FRAME;
                }
 
-               if ((rxs & port->ignore_status_mask) == 0) {
-                       tty_insert_flip_char(tty, ch, flag);
-               }
-               if ((rxs & RXSTAT_OVERRUN) &&
-                   tty->flip.count < TTY_FLIPBUF_SIZE) {
-                       /*
-                        * Overrun is special, since it's reported
-                        * immediately, and doesn't affect the current
-                        * character.
-                        */
-                       tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-               }
+               uart_insert_char(port, rxs, RXSTAT_OVERRUN, ch, flag);
+
                status = *CSR_UARTFLG;
        }
        tty_flip_buffer_push(tty);
@@ -145,10 +121,10 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r
        return IRQ_HANDLED;
 }
 
-static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t serial21285_tx_chars(int irq, void *dev_id)
 {
        struct uart_port *port = dev_id;
-       struct circ_buf *xmit = &port->info->xmit;
+       struct circ_buf *xmit = &port->state->xmit;
        int count = 256;
 
        if (port->x_char) {
@@ -158,7 +134,7 @@ static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *r
                goto out;
        }
        if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-               serial21285_stop_tx(port, 0);
+               serial21285_stop_tx(port);
                goto out;
        }
 
@@ -174,7 +150,7 @@ static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *r
                uart_write_wakeup(port);
 
        if (uart_circ_empty(xmit))
-               serial21285_stop_tx(port, 0);
+               serial21285_stop_tx(port);
 
  out:
        return IRQ_HANDLED;
@@ -236,8 +212,8 @@ static void serial21285_shutdown(struct uart_port *port)
 }
 
 static void
-serial21285_set_termios(struct uart_port *port, struct termios *termios,
-                       struct termios *old)
+serial21285_set_termios(struct uart_port *port, struct ktermios *termios,
+                       struct ktermios *old)
 {
        unsigned long flags;
        unsigned int baud, quot, h_lcr;
@@ -259,6 +235,12 @@ serial21285_set_termios(struct uart_port *port, struct termios *termios,
        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
        quot = uart_get_divisor(port, baud);
 
+       if (port->state && port->state->port.tty) {
+               struct tty_struct *tty = port->state->port.tty;
+               unsigned int b = port->uartclk / (16 * quot);
+               tty_encode_baud_rate(tty, b, b);
+       }
+
        switch (termios->c_cflag & CSIZE) {
        case CS5:
                h_lcr = 0x00;
@@ -383,11 +365,11 @@ static struct uart_ops serial21285_ops = {
 
 static struct uart_port serial21285_port = {
        .mapbase        = 0x42000160,
-       .iotype         = SERIAL_IO_MEM,
+       .iotype         = UPIO_MEM,
        .irq            = NO_IRQ,
        .fifosize       = 16,
        .ops            = &serial21285_ops,
-       .flags          = ASYNC_BOOT_AUTOCONF,
+       .flags          = UPF_BOOT_AUTOCONF,
 };
 
 static void serial21285_setup_ports(void)
@@ -396,23 +378,18 @@ static void serial21285_setup_ports(void)
 }
 
 #ifdef CONFIG_SERIAL_21285_CONSOLE
+static void serial21285_console_putchar(struct uart_port *port, int ch)
+{
+       while (*CSR_UARTFLG & 0x20)
+               barrier();
+       *CSR_UARTDR = ch;
+}
 
 static void
 serial21285_console_write(struct console *co, const char *s,
                          unsigned int count)
 {
-       int i;
-
-       for (i = 0; i < count; i++) {
-               while (*CSR_UARTFLG & 0x20)
-                       barrier();
-               *CSR_UARTDR = s[i];
-               if (s[i] == '\n') {
-                       while (*CSR_UARTFLG & 0x20)
-                               barrier();
-                       *CSR_UARTDR = '\r';
-               }
-       }
+       uart_console_write(&serial21285_port, s, count, serial21285_console_putchar);
 }
 
 static void __init
@@ -475,7 +452,7 @@ static int __init serial21285_console_setup(struct console *co, char *options)
        return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
-extern struct uart_driver serial21285_reg;
+static struct uart_driver serial21285_reg;
 
 static struct console serial21285_console =
 {
@@ -505,7 +482,6 @@ static struct uart_driver serial21285_reg = {
        .owner                  = THIS_MODULE,
        .driver_name            = "ttyFB",
        .dev_name               = "ttyFB",
-       .devfs_name             = "ttyFB",
        .major                  = SERIAL_21285_MAJOR,
        .minor                  = SERIAL_21285_MINOR,
        .nr                     = 1,
@@ -516,7 +492,7 @@ static int __init serial21285_init(void)
 {
        int ret;
 
-       printk(KERN_INFO "Serial: 21285 driver $Revision: 1.37 $\n");
+       printk(KERN_INFO "Serial: 21285 driver\n");
 
        serial21285_setup_ports();
 
@@ -537,5 +513,5 @@ module_init(serial21285_init);
 module_exit(serial21285_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver $Revision: 1.37 $");
+MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver");
 MODULE_ALIAS_CHARDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);