diff options
author | Keir Fraser <keir@xen.org> | 2012-03-07 09:30:42 +0000 |
---|---|---|
committer | Keir Fraser <keir@xen.org> | 2012-03-07 09:30:42 +0000 |
commit | 3ebbff13b667f9923e65a808e639740898774180 (patch) | |
tree | 1d0d2d87a16faeb91795a0ae456617fd04656354 | |
parent | b1aff7cfd4ad96ee868dfeb392b41aab2e65e136 (diff) | |
download | xen-3ebbff13b667f9923e65a808e639740898774180.tar.gz xen-3ebbff13b667f9923e65a808e639740898774180.tar.bz2 xen-3ebbff13b667f9923e65a808e639740898774180.zip |
ns16550: Simplify UART and UART-interrupt probing logic.
1. No need to check for UART existence in the polling routine. We
already check for UART existence during boot-time initialisation (see
check_existence() function).
2. No obvious need to send a dummy character. The poll routine will
run until a character is eventually sent, but for the most common use
of serial ports (console logging) that will happen almost immediately.
Signed-off-by: Keir Fraser <keir@xen.org>
xen-unstable changeset: 23811:f1349a968a5a
xen-unstable date: Fri Sep 02 14:56:26 2011 +0100
Revert part of 23811:f1349a968a5a "ns16550: Simplify UART..."
The change to poll LSR.THRE in a loop from __ns16550_poll is a bug.
We can loop indefinitely if there are no chars to transmit.
Thanks to Jan for spotting it.
Signed-off-by: Keir Fraser <keir@xen.org>
xen-unstable changeset: 23948:dcb2bd283dca
xen-unstable date: Wed Oct 12 17:11:28 2011 +0100
-rw-r--r-- | xen/drivers/char/ns16550.c | 25 |
1 files changed, 5 insertions, 20 deletions
diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c index 46ae7bd6c8..cea45300d6 100644 --- a/xen/drivers/char/ns16550.c +++ b/xen/drivers/char/ns16550.c @@ -39,7 +39,7 @@ static struct ns16550 { /* UART with no IRQ line: periodically-polled I/O. */ struct timer timer; unsigned int timeout_ms; - bool_t probing, intr_works; + bool_t intr_works; /* PCI card parameters. */ unsigned int pb_bdf[3]; /* pci bridge BDF */ unsigned int ps_bdf[3]; /* pci serial port BDF */ @@ -133,12 +133,7 @@ static void ns16550_interrupt( struct serial_port *port = dev_id; struct ns16550 *uart = port->uart; - if (uart->intr_works == 0) - { - uart->probing = 0; - uart->intr_works = 1; - stop_timer(&uart->timer); - } + uart->intr_works = 1; while ( !(ns_read_reg(uart, IIR) & IIR_NOINT) ) { @@ -150,7 +145,7 @@ static void ns16550_interrupt( } } -/* Safe: ns16550_poll() runs in softirq context so not reentrant on a given CPU. */ +/* Safe: ns16550_poll() runs as softirq so not reentrant on a given CPU. */ static DEFINE_PER_CPU(struct serial_port *, poll_port); static void __ns16550_poll(struct cpu_user_regs *regs) @@ -161,12 +156,6 @@ static void __ns16550_poll(struct cpu_user_regs *regs) if ( uart->intr_works ) return; /* Interrupts work - no more polling */ - if ( uart->probing ) { - uart->probing = 0; - if ( (ns_read_reg(uart, LSR) & 0xff) == 0xff ) - return; /* All bits set - probably no UART present */ - } - while ( ns_read_reg(uart, LSR) & LSR_DR ) serial_rx_interrupt(port, regs); @@ -230,6 +219,8 @@ static void __devinit ns16550_init_preirq(struct serial_port *port) unsigned char lcr; unsigned int divisor; + uart->intr_works = 0; + pci_serial_early_init(uart); /* I/O ports are distinguished by their size (16 bits). */ @@ -304,12 +295,6 @@ static void __devinit ns16550_init_postirq(struct serial_port *port) /* Enable receive and transmit interrupts. */ ns_write_reg(uart, IER, IER_ERDAI | IER_ETHREI); - - /* Do a timed write to make sure we are getting interrupts. */ - uart->probing = 1; - uart->intr_works = 0; - ns_write_reg(uart, THR, 0xff); - set_timer(&uart->timer, NOW() + MILLISECS(uart->timeout_ms)); } } |