diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2006-01-04 16:55:09 +0000 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-01-04 16:55:09 +0000 |
commit | 2af7cd68f1ed20e2e72c91988c3d4f457fa29ebc (patch) | |
tree | a242ce0d1ecd154ef6bfa7aaf910a003bed3abdd | |
parent | 88026842b0a760145aa71d69e74fbc9ec118ca44 (diff) | |
download | op-kernel-dev-2af7cd68f1ed20e2e72c91988c3d4f457fa29ebc.zip op-kernel-dev-2af7cd68f1ed20e2e72c91988c3d4f457fa29ebc.tar.gz |
[Serial] Don't miss modem status changes
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>
-rw-r--r-- | drivers/serial/8250.c | 33 |
1 files changed, 16 insertions, 17 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index d2bcd1f..076bf84 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -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) |