xcp-1.6-updates/xen-4.1.hg

changeset 23253:f1b85192dbd8

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
author Keir Fraser <keir@xen.org>
date Wed Mar 07 09:30:42 2012 +0000 (2012-03-07)
parents 6c3a6fb7013d
children 1c0f76eea67d
files xen/drivers/char/ns16550.c
line diff
     1.1 --- a/xen/drivers/char/ns16550.c	Wed Mar 07 09:25:34 2012 +0000
     1.2 +++ b/xen/drivers/char/ns16550.c	Wed Mar 07 09:30:42 2012 +0000
     1.3 @@ -39,7 +39,7 @@ static struct ns16550 {
     1.4      /* UART with no IRQ line: periodically-polled I/O. */
     1.5      struct timer timer;
     1.6      unsigned int timeout_ms;
     1.7 -    bool_t probing, intr_works;
     1.8 +    bool_t intr_works;
     1.9      /* PCI card parameters. */
    1.10      unsigned int pb_bdf[3]; /* pci bridge BDF */
    1.11      unsigned int ps_bdf[3]; /* pci serial port BDF */
    1.12 @@ -133,12 +133,7 @@ static void ns16550_interrupt(
    1.13      struct serial_port *port = dev_id;
    1.14      struct ns16550 *uart = port->uart;
    1.15  
    1.16 -    if (uart->intr_works == 0)
    1.17 -    {
    1.18 -        uart->probing = 0;
    1.19 -        uart->intr_works = 1;
    1.20 -        stop_timer(&uart->timer);
    1.21 -    }
    1.22 +    uart->intr_works = 1;
    1.23  
    1.24      while ( !(ns_read_reg(uart, IIR) & IIR_NOINT) )
    1.25      {
    1.26 @@ -150,7 +145,7 @@ static void ns16550_interrupt(
    1.27      }
    1.28  }
    1.29  
    1.30 -/* Safe: ns16550_poll() runs in softirq context so not reentrant on a given CPU. */
    1.31 +/* Safe: ns16550_poll() runs as softirq so not reentrant on a given CPU. */
    1.32  static DEFINE_PER_CPU(struct serial_port *, poll_port);
    1.33  
    1.34  static void __ns16550_poll(struct cpu_user_regs *regs)
    1.35 @@ -161,12 +156,6 @@ static void __ns16550_poll(struct cpu_us
    1.36      if ( uart->intr_works )
    1.37          return;     /* Interrupts work - no more polling */
    1.38  
    1.39 -    if ( uart->probing ) {
    1.40 -        uart->probing = 0;
    1.41 -        if ( (ns_read_reg(uart, LSR) & 0xff) == 0xff )
    1.42 -            return;     /* All bits set - probably no UART present */
    1.43 -    }
    1.44 -
    1.45      while ( ns_read_reg(uart, LSR) & LSR_DR )
    1.46          serial_rx_interrupt(port, regs);
    1.47  
    1.48 @@ -230,6 +219,8 @@ static void __devinit ns16550_init_preir
    1.49      unsigned char lcr;
    1.50      unsigned int  divisor;
    1.51  
    1.52 +    uart->intr_works = 0;
    1.53 +
    1.54      pci_serial_early_init(uart);
    1.55  
    1.56      /* I/O ports are distinguished by their size (16 bits). */
    1.57 @@ -304,12 +295,6 @@ static void __devinit ns16550_init_posti
    1.58  
    1.59          /* Enable receive and transmit interrupts. */
    1.60          ns_write_reg(uart, IER, IER_ERDAI | IER_ETHREI);
    1.61 -
    1.62 -        /* Do a timed write to make sure we are getting interrupts. */
    1.63 -        uart->probing = 1;
    1.64 -        uart->intr_works = 0;
    1.65 -        ns_write_reg(uart, THR, 0xff);
    1.66 -        set_timer(&uart->timer, NOW() + MILLISECS(uart->timeout_ms));
    1.67      }
    1.68  }
    1.69