debuggers.hg
diff xen/drivers/char/ns16550.c @ 20955:12fc55dffb6b
Handle bogus serial ports that appear normal, but don't generate
interrupts e.g. the "remote serial console" on Blades.
Authored-by: Gary Grebus <Gary.Grebus@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
interrupts e.g. the "remote serial console" on Blades.
Authored-by: Gary Grebus <Gary.Grebus@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Mon Feb 08 08:49:19 2010 +0000 (2010-02-08) |
parents | 5a224e101cb3 |
children | 8cb6e7eff2ba |
line diff
1.1 --- a/xen/drivers/char/ns16550.c Mon Feb 08 08:48:40 2010 +0000 1.2 +++ b/xen/drivers/char/ns16550.c Mon Feb 08 08:49:19 2010 +0000 1.3 @@ -39,6 +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 + int probing, intr_works; 1.8 } ns16550_com[2] = { { 0 } }; 1.9 1.10 /* Register offsets */ 1.11 @@ -127,6 +128,13 @@ static void ns16550_interrupt( 1.12 struct serial_port *port = dev_id; 1.13 struct ns16550 *uart = port->uart; 1.14 1.15 + if (uart->intr_works == 0) 1.16 + { 1.17 + uart->probing = 0; 1.18 + uart->intr_works = 1; 1.19 + stop_timer(&uart->timer); 1.20 + } 1.21 + 1.22 while ( !(ns_read_reg(uart, IIR) & IIR_NOINT) ) 1.23 { 1.24 char lsr = ns_read_reg(uart, LSR); 1.25 @@ -143,6 +151,15 @@ static void ns16550_poll(void *data) 1.26 struct ns16550 *uart = port->uart; 1.27 struct cpu_user_regs *regs = guest_cpu_user_regs(); 1.28 1.29 + if ( uart->intr_works ) 1.30 + return; /* Interrupts work - no more polling */ 1.31 + 1.32 + if ( uart->probing ) { 1.33 + uart->probing = 0; 1.34 + if ( (ns_read_reg(uart, LSR) & 0xff) == 0xff ) 1.35 + return; /* All bits set - probably no UART present */ 1.36 + } 1.37 + 1.38 while ( ns_read_reg(uart, LSR) & LSR_DR ) 1.39 serial_rx_interrupt(port, regs); 1.40 1.41 @@ -230,15 +247,14 @@ static void __devinit ns16550_init_posti 1.42 1.43 serial_async_transmit(port); 1.44 1.45 + init_timer(&uart->timer, ns16550_poll, port, 0); 1.46 + /* Calculate time to fill RX FIFO and/or empty TX FIFO for polling. */ 1.47 + bits = uart->data_bits + uart->stop_bits + !!uart->parity; 1.48 + uart->timeout_ms = max_t( 1.49 + unsigned int, 1, (bits * port->tx_fifo_size * 1000) / uart->baud); 1.50 + 1.51 if ( uart->irq == 0 ) 1.52 - { 1.53 - /* Polled mode. Calculate time to fill RX FIFO and/or empty TX FIFO. */ 1.54 - bits = uart->data_bits + uart->stop_bits + !!uart->parity; 1.55 - uart->timeout_ms = max_t( 1.56 - unsigned int, 1, (bits * port->tx_fifo_size * 1000) / uart->baud); 1.57 - init_timer(&uart->timer, ns16550_poll, port, 0); 1.58 set_timer(&uart->timer, NOW() + MILLISECS(uart->timeout_ms)); 1.59 - } 1.60 else 1.61 { 1.62 uart->irqaction.handler = ns16550_interrupt; 1.63 @@ -252,6 +268,12 @@ static void __devinit ns16550_init_posti 1.64 1.65 /* Enable receive and transmit interrupts. */ 1.66 ns_write_reg(uart, IER, IER_ERDAI | IER_ETHREI); 1.67 + 1.68 + /* Do a timed write to make sure we are getting interrupts. */ 1.69 + uart->probing = 1; 1.70 + uart->intr_works = 0; 1.71 + ns_write_reg(uart, THR, 0xff); 1.72 + set_timer(&uart->timer, NOW() + MILLISECS(uart->timeout_ms)); 1.73 } 1.74 } 1.75