]> err.no Git - linux-2.6/commitdiff
[Serial] Don't miss modem status changes
authorRussell King <rmk@dyn-67.arm.linux.org.uk>
Wed, 4 Jan 2006 16:55:09 +0000 (16:55 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Wed, 4 Jan 2006 16:55:09 +0000 (16:55 +0000)
Reading the MSR register on 8250-compatible UARTs results in any
modem status interrupts being cleared.  To avoid missing any
status changes, arrange for get_mctrl() to read the current
status via check_modem_status(), which will process any pending
state changes for us.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
drivers/serial/8250.c

index d2bcd1f87cd61b10349d715c1795d2d5cf5761e5..076bf848e4d170d176f376ed1d392b9f7c9dc517 100644 (file)
@@ -1255,25 +1255,24 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up)
                __stop_tx(up);
 }
 
-static _INLINE_ void check_modem_status(struct uart_8250_port *up)
+static unsigned int check_modem_status(struct uart_8250_port *up)
 {
-       int status;
+       unsigned int status = serial_in(up, UART_MSR);
 
-       status = serial_in(up, UART_MSR);
+       if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI) {
+               if (status & UART_MSR_TERI)
+                       up->port.icount.rng++;
+               if (status & UART_MSR_DDSR)
+                       up->port.icount.dsr++;
+               if (status & UART_MSR_DDCD)
+                       uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
+               if (status & UART_MSR_DCTS)
+                       uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
 
-       if ((status & UART_MSR_ANY_DELTA) == 0)
-               return;
-
-       if (status & UART_MSR_TERI)
-               up->port.icount.rng++;
-       if (status & UART_MSR_DDSR)
-               up->port.icount.dsr++;
-       if (status & UART_MSR_DDCD)
-               uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-       if (status & UART_MSR_DCTS)
-               uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
+               wake_up_interruptible(&up->port.info->delta_msr_wait);
+       }
 
-       wake_up_interruptible(&up->port.info->delta_msr_wait);
+       return status;
 }
 
 /*
@@ -1454,10 +1453,10 @@ static unsigned int serial8250_tx_empty(struct uart_port *port)
 static unsigned int serial8250_get_mctrl(struct uart_port *port)
 {
        struct uart_8250_port *up = (struct uart_8250_port *)port;
-       unsigned char status;
+       unsigned int status;
        unsigned int ret;
 
-       status = serial_in(up, UART_MSR);
+       status = check_modem_status(up);
 
        ret = 0;
        if (status & UART_MSR_DCD)