serial8250: ratelimit "too much work" error
[pandora-kernel.git] / drivers / serial / 8250.c
index 09ef570..167c4a6 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/tty.h>
+#include <linux/ratelimit.h>
 #include <linux/tty_flip.h>
 #include <linux/serial_reg.h>
 #include <linux/serial_core.h>
@@ -154,12 +155,6 @@ struct uart_8250_port {
        unsigned char           lsr_saved_flags;
 #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
        unsigned char           msr_saved_flags;
-
-       /*
-        * We provide a per-port pm hook.
-        */
-       void                    (*pm)(struct uart_port *port,
-                                     unsigned int state, unsigned int old);
 };
 
 struct irq_info {
@@ -241,7 +236,7 @@ static const struct serial8250_config uart_config[] = {
                .fifo_size      = 128,
                .tx_loadsz      = 128,
                .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO,
+               .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
        },
        [PORT_16654] = {
                .name           = "ST16654",
@@ -300,6 +295,13 @@ static const struct serial8250_config uart_config[] = {
                .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
                .flags          = UART_CAP_FIFO | UART_CAP_AFE,
        },
+       [PORT_U6_16550A] = {
+               .name           = "U6_16550A",
+               .fifo_size      = 64,
+               .tx_loadsz      = 64,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
+       },
 };
 
 #if defined(CONFIG_MIPS_ALCHEMY)
@@ -1070,6 +1072,15 @@ static void autoconfig_16550a(struct uart_8250_port *up)
                DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
        }
        serial_outp(up, UART_IER, iersave);
+
+       /*
+        * We distinguish between 16550A and U6 16550A by counting
+        * how many bytes are in the FIFO.
+        */
+       if (up->port.type == PORT_16550A && size_fifo(up) == 64) {
+               up->port.type = PORT_U6_16550A;
+               up->capabilities |= UART_CAP_AFE;
+       }
 }
 
 /*
@@ -1590,8 +1601,8 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
 
                if (l == i->head && pass_counter++ > PASS_LIMIT) {
                        /* If we hit this, we're dead. */
-                       printk(KERN_ERR "serial8250: too much work for "
-                               "irq%d\n", irq);
+                       printk_ratelimited(KERN_ERR
+                               "serial8250: too much work for irq%d\n", irq);
                        break;
                }
        } while (l != end);
@@ -1706,12 +1717,6 @@ static void serial_unlink_irq_chain(struct uart_8250_port *up)
        mutex_unlock(&hash_mutex);
 }
 
-/* Base timer interval for polling */
-static inline int poll_timeout(int timeout)
-{
-       return timeout > 6 ? (timeout / 2 - 2) : 1;
-}
-
 /*
  * This function is used to handle ports that do not have an
  * interrupt.  This doesn't work very well for 16450's, but gives
@@ -1726,7 +1731,7 @@ static void serial8250_timeout(unsigned long data)
        iir = serial_in(up, UART_IIR);
        if (!(iir & UART_IIR_NO_INT))
                serial8250_handle_port(up);
-       mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
+       mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port));
 }
 
 static void serial8250_backup_timeout(unsigned long data)
@@ -1771,7 +1776,7 @@ static void serial8250_backup_timeout(unsigned long data)
 
        /* Standard timer interval plus 0.2s to keep the port running */
        mod_timer(&up->timer,
-               jiffies + poll_timeout(up->port.timeout) + HZ / 5);
+               jiffies + uart_poll_timeout(&up->port) + HZ / 5);
 }
 
 static unsigned int serial8250_tx_empty(struct uart_port *port)
@@ -1851,15 +1856,17 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits)
        unsigned int status, tmout = 10000;
 
        /* Wait up to 10ms for the character(s) to be sent. */
-       do {
+       for (;;) {
                status = serial_in(up, UART_LSR);
 
                up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
 
+               if ((status & bits) == bits)
+                       break;
                if (--tmout == 0)
                        break;
                udelay(1);
-       } while ((status & bits) != bits);
+       }
 
        /* Wait up to 1s for flow control if necessary */
        if (up->port.flags & UPF_CONS_FLOW) {
@@ -2053,7 +2060,7 @@ static int serial8250_startup(struct uart_port *port)
                up->timer.function = serial8250_backup_timeout;
                up->timer.data = (unsigned long)up;
                mod_timer(&up->timer, jiffies +
-                         poll_timeout(up->port.timeout) + HZ / 5);
+                       uart_poll_timeout(port) + HZ / 5);
        }
 
        /*
@@ -2063,7 +2070,7 @@ static int serial8250_startup(struct uart_port *port)
         */
        if (!is_real_interrupt(up->port.irq)) {
                up->timer.data = (unsigned long)up;
-               mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
+               mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
        } else {
                retval = serial_link_irq_chain(up);
                if (retval)
@@ -2224,9 +2231,9 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int
        return quot;
 }
 
-static void
-serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
-                      struct ktermios *old)
+void
+serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+                         struct ktermios *old)
 {
        struct uart_8250_port *up = (struct uart_8250_port *)port;
        unsigned char cval, fcr = 0;
@@ -2402,32 +2409,46 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
        if (tty_termios_baud_rate(termios))
                tty_termios_encode_baud_rate(termios, baud, baud);
 }
+EXPORT_SYMBOL(serial8250_do_set_termios);
 
 static void
-serial8250_set_ldisc(struct uart_port *port)
+serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
+                      struct ktermios *old)
 {
-       int line = port->line;
-
-       if (line >= port->state->port.tty->driver->num)
-               return;
+       if (port->set_termios)
+               port->set_termios(port, termios, old);
+       else
+               serial8250_do_set_termios(port, termios, old);
+}
 
-       if (port->state->port.tty->ldisc->ops->num == N_PPS) {
+static void
+serial8250_set_ldisc(struct uart_port *port, int new)
+{
+       if (new == N_PPS) {
                port->flags |= UPF_HARDPPS_CD;
                serial8250_enable_ms(port);
        } else
                port->flags &= ~UPF_HARDPPS_CD;
 }
 
-static void
-serial8250_pm(struct uart_port *port, unsigned int state,
-             unsigned int oldstate)
+
+void serial8250_do_pm(struct uart_port *port, unsigned int state,
+                     unsigned int oldstate)
 {
        struct uart_8250_port *p = (struct uart_8250_port *)port;
 
        serial8250_set_sleep(p, state != 0);
+}
+EXPORT_SYMBOL(serial8250_do_pm);
 
-       if (p->pm)
-               p->pm(port, state, oldstate);
+static void
+serial8250_pm(struct uart_port *port, unsigned int state,
+             unsigned int oldstate)
+{
+       if (port->pm)
+               port->pm(port, state, oldstate);
+       else
+               serial8250_do_pm(port, state, oldstate);
 }
 
 static unsigned int serial8250_port_size(struct uart_8250_port *pt)
@@ -2652,6 +2673,16 @@ static struct uart_ops serial8250_pops = {
 
 static struct uart_8250_port serial8250_ports[UART_NR];
 
+static void (*serial8250_isa_config)(int port, struct uart_port *up,
+       unsigned short *capabilities);
+
+void serial8250_set_isa_configurator(
+       void (*v)(int port, struct uart_port *up, unsigned short *capabilities))
+{
+       serial8250_isa_config = v;
+}
+EXPORT_SYMBOL(serial8250_set_isa_configurator);
+
 static void __init serial8250_isa_init_ports(void)
 {
        struct uart_8250_port *up;
@@ -2697,6 +2728,9 @@ static void __init serial8250_isa_init_ports(void)
                up->port.regshift = old_serial_port[i].iomem_reg_shift;
                set_io_from_upio(&up->port);
                up->port.irqflags |= irqflag;
+               if (serial8250_isa_config != NULL)
+                       serial8250_isa_config(i, &up->port, &up->capabilities);
+
        }
 }
 
@@ -2987,6 +3021,8 @@ static int __devinit serial8250_probe(struct platform_device *dev)
                port.type               = p->type;
                port.serial_in          = p->serial_in;
                port.serial_out         = p->serial_out;
+               port.set_termios        = p->set_termios;
+               port.pm                 = p->pm;
                port.dev                = &dev->dev;
                port.irqflags           |= irqflag;
                ret = serial8250_register_port(&port);
@@ -3150,6 +3186,15 @@ int serial8250_register_port(struct uart_port *port)
                        uart->port.serial_in = port->serial_in;
                if (port->serial_out)
                        uart->port.serial_out = port->serial_out;
+               /*  Possibly override set_termios call */
+               if (port->set_termios)
+                       uart->port.set_termios = port->set_termios;
+               if (port->pm)
+                       uart->port.pm = port->pm;
+
+               if (serial8250_isa_config != NULL)
+                       serial8250_isa_config(0, &uart->port,
+                                       &uart->capabilities);
 
                ret = uart_add_one_port(&serial8250_reg, &uart->port);
                if (ret == 0)