diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2006-01-04 11:55:09 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-01-04 11:55:09 -0500 |
commit | 2af7cd68f1ed20e2e72c91988c3d4f457fa29ebc (patch) | |
tree | a242ce0d1ecd154ef6bfa7aaf910a003bed3abdd /drivers/serial | |
parent | 88026842b0a760145aa71d69e74fbc9ec118ca44 (diff) |
[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>
Diffstat (limited to 'drivers/serial')
-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 d2bcd1f87cd6..076bf848e4d1 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) | |||
1255 | __stop_tx(up); | 1255 | __stop_tx(up); |
1256 | } | 1256 | } |
1257 | 1257 | ||
1258 | static _INLINE_ void check_modem_status(struct uart_8250_port *up) | 1258 | static unsigned int check_modem_status(struct uart_8250_port *up) |
1259 | { | 1259 | { |
1260 | int status; | 1260 | unsigned int status = serial_in(up, UART_MSR); |
1261 | 1261 | ||
1262 | status = serial_in(up, UART_MSR); | 1262 | if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI) { |
1263 | if (status & UART_MSR_TERI) | ||
1264 | up->port.icount.rng++; | ||
1265 | if (status & UART_MSR_DDSR) | ||
1266 | up->port.icount.dsr++; | ||
1267 | if (status & UART_MSR_DDCD) | ||
1268 | uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); | ||
1269 | if (status & UART_MSR_DCTS) | ||
1270 | uart_handle_cts_change(&up->port, status & UART_MSR_CTS); | ||
1263 | 1271 | ||
1264 | if ((status & UART_MSR_ANY_DELTA) == 0) | 1272 | wake_up_interruptible(&up->port.info->delta_msr_wait); |
1265 | return; | 1273 | } |
1266 | |||
1267 | if (status & UART_MSR_TERI) | ||
1268 | up->port.icount.rng++; | ||
1269 | if (status & UART_MSR_DDSR) | ||
1270 | up->port.icount.dsr++; | ||
1271 | if (status & UART_MSR_DDCD) | ||
1272 | uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); | ||
1273 | if (status & UART_MSR_DCTS) | ||
1274 | uart_handle_cts_change(&up->port, status & UART_MSR_CTS); | ||
1275 | 1274 | ||
1276 | wake_up_interruptible(&up->port.info->delta_msr_wait); | 1275 | return status; |
1277 | } | 1276 | } |
1278 | 1277 | ||
1279 | /* | 1278 | /* |
@@ -1454,10 +1453,10 @@ static unsigned int serial8250_tx_empty(struct uart_port *port) | |||
1454 | static unsigned int serial8250_get_mctrl(struct uart_port *port) | 1453 | static unsigned int serial8250_get_mctrl(struct uart_port *port) |
1455 | { | 1454 | { |
1456 | struct uart_8250_port *up = (struct uart_8250_port *)port; | 1455 | struct uart_8250_port *up = (struct uart_8250_port *)port; |
1457 | unsigned char status; | 1456 | unsigned int status; |
1458 | unsigned int ret; | 1457 | unsigned int ret; |
1459 | 1458 | ||
1460 | status = serial_in(up, UART_MSR); | 1459 | status = check_modem_status(up); |
1461 | 1460 | ||
1462 | ret = 0; | 1461 | ret = 0; |
1463 | if (status & UART_MSR_DCD) | 1462 | if (status & UART_MSR_DCD) |