diff options
author | Pekka Enberg <penberg@kernel.org> | 2010-10-24 19:57:05 +0300 |
---|---|---|
committer | Pekka Enberg <penberg@kernel.org> | 2010-10-24 19:57:05 +0300 |
commit | 6d4121f6c20a0e86231d52f535f1c82423b3326f (patch) | |
tree | 5c235cac699ca86b504850aa663ddadde0455a61 /drivers/serial/8250.c | |
parent | 92a5bbc11ff2442a54b2f1d313088c245828ef4e (diff) | |
parent | 35da7a307c535f9c2929cae277f3df425c9f9b1e (diff) |
Merge branch 'master' into for-linus
Conflicts:
include/linux/percpu.h
mm/percpu.c
Diffstat (limited to 'drivers/serial/8250.c')
-rw-r--r-- | drivers/serial/8250.c | 69 |
1 files changed, 44 insertions, 25 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 24110f6f61e..167c4a6ccbc 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -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 { @@ -1606,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); @@ -1722,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 @@ -1742,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) @@ -1787,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) @@ -1867,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) { @@ -2069,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); } /* @@ -2079,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) @@ -2440,16 +2431,24 @@ serial8250_set_ldisc(struct uart_port *port, int new) 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) @@ -2674,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; @@ -2719,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); + } } @@ -3010,6 +3022,7 @@ static int __devinit serial8250_probe(struct platform_device *dev) 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); @@ -3176,6 +3189,12 @@ int serial8250_register_port(struct uart_port *port) /* 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) |