[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Handle bogus serial ports that appear normal, but don't generate



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1265618959 0
# Node ID 12fc55dffb6bbd78864092eed705cec8192ed461
# Parent  a06e9def02bb54b1231be027cce1ce9a44a4d248
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@xxxxxxxxxx>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
---
 xen/drivers/char/ns16550.c |   36 +++++++++++++++++++++++++++++-------
 1 files changed, 29 insertions(+), 7 deletions(-)

diff -r a06e9def02bb -r 12fc55dffb6b xen/drivers/char/ns16550.c
--- a/xen/drivers/char/ns16550.c        Mon Feb 08 08:48:40 2010 +0000
+++ b/xen/drivers/char/ns16550.c        Mon Feb 08 08:49:19 2010 +0000
@@ -39,6 +39,7 @@ static struct ns16550 {
     /* UART with no IRQ line: periodically-polled I/O. */
     struct timer timer;
     unsigned int timeout_ms;
+    int probing, intr_works;
 } ns16550_com[2] = { { 0 } };
 
 /* Register offsets */
@@ -127,6 +128,13 @@ 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);
+    }
+
     while ( !(ns_read_reg(uart, IIR) & IIR_NOINT) )
     {
         char lsr = ns_read_reg(uart, LSR);
@@ -143,6 +151,15 @@ static void ns16550_poll(void *data)
     struct ns16550 *uart = port->uart;
     struct cpu_user_regs *regs = guest_cpu_user_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,15 +247,14 @@ static void __devinit ns16550_init_posti
 
     serial_async_transmit(port);
 
+    init_timer(&uart->timer, ns16550_poll, port, 0);
+    /* Calculate time to fill RX FIFO and/or empty TX FIFO for polling. */
+    bits = uart->data_bits + uart->stop_bits + !!uart->parity;
+    uart->timeout_ms = max_t(
+        unsigned int, 1, (bits * port->tx_fifo_size * 1000) / uart->baud);
+
     if ( uart->irq == 0 )
-    {
-        /* Polled mode. Calculate time to fill RX FIFO and/or empty TX FIFO. */
-        bits = uart->data_bits + uart->stop_bits + !!uart->parity;
-        uart->timeout_ms = max_t(
-            unsigned int, 1, (bits * port->tx_fifo_size * 1000) / uart->baud);
-        init_timer(&uart->timer, ns16550_poll, port, 0);
         set_timer(&uart->timer, NOW() + MILLISECS(uart->timeout_ms));
-    }
     else
     {
         uart->irqaction.handler = ns16550_interrupt;
@@ -252,6 +268,12 @@ static void __devinit ns16550_init_posti
 
         /* 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));
     }
 }
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.