diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2014-09-10 15:29:58 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-09-26 12:01:56 -0400 |
commit | 0aa525d11859c1a4d5b78fdc704148e2ae03ae13 (patch) | |
tree | 716c43ede261700ea3e278b708ff2564ece41425 /drivers/tty | |
parent | d74d5d1b7288ff9d4439c8c7e0e314cde9743467 (diff) |
tty: serial: 8250_core: read only RX if there is something in the FIFO
The serial8250_do_startup() function unconditionally clears the
interrupts and for that it reads from the RX-FIFO without checking if
there is a byte in the FIFO or not. This works fine on OMAP4+ HW like
AM335x or DRA7.
OMAP3630 ES1.1 (which means probably all OMAP3 and earlier) does not like
this:
|Unhandled fault: external abort on non-linefetch (0x1028) at 0xfb020000
|Internal error: : 1028 [#1] ARM
|Modules linked in:
|CPU: 0 PID: 1 Comm: swapper Not tainted 3.16.0-00022-g7edcb57-dirty #1213
|task: de0572c0 ti: de058000 task.ti: de058000
|PC is at mem32_serial_in+0xc/0x1c
|LR is at serial8250_do_startup+0x220/0x85c
|Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
|Control: 10c5387d Table: 80004019 DAC: 00000015
|[<c03051d4>] (mem32_serial_in) from [<c0307fe8>] (serial8250_do_startup+0x220/0x85c)
|[<c0307fe8>] (serial8250_do_startup) from [<c0309e00>] (omap_8250_startup+0x5c/0xe0)
|[<c0309e00>] (omap_8250_startup) from [<c030863c>] (serial8250_startup+0x18/0x2c)
|[<c030863c>] (serial8250_startup) from [<c030394c>] (uart_startup+0x78/0x1d8)
|[<c030394c>] (uart_startup) from [<c0304678>] (uart_open+0xe8/0x114)
|[<c0304678>] (uart_open) from [<c02e9e10>] (tty_open+0x1a8/0x5a4)
Reviewed-by: Tony Lindgren <tony@atomide.com>
Tested-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/serial/8250/8250_core.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 3cf5c98013e4..547afde9fdda 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c | |||
@@ -2088,8 +2088,8 @@ int serial8250_do_startup(struct uart_port *port) | |||
2088 | /* | 2088 | /* |
2089 | * Clear the interrupt registers. | 2089 | * Clear the interrupt registers. |
2090 | */ | 2090 | */ |
2091 | serial_port_in(port, UART_LSR); | 2091 | if (serial_port_in(port, UART_LSR) & UART_LSR_DR) |
2092 | serial_port_in(port, UART_RX); | 2092 | serial_port_in(port, UART_RX); |
2093 | serial_port_in(port, UART_IIR); | 2093 | serial_port_in(port, UART_IIR); |
2094 | serial_port_in(port, UART_MSR); | 2094 | serial_port_in(port, UART_MSR); |
2095 | 2095 | ||
@@ -2250,8 +2250,8 @@ dont_test_tx_en: | |||
2250 | * saved flags to avoid getting false values from polling | 2250 | * saved flags to avoid getting false values from polling |
2251 | * routines or the previous session. | 2251 | * routines or the previous session. |
2252 | */ | 2252 | */ |
2253 | serial_port_in(port, UART_LSR); | 2253 | if (serial_port_in(port, UART_LSR) & UART_LSR_DR) |
2254 | serial_port_in(port, UART_RX); | 2254 | serial_port_in(port, UART_RX); |
2255 | serial_port_in(port, UART_IIR); | 2255 | serial_port_in(port, UART_IIR); |
2256 | serial_port_in(port, UART_MSR); | 2256 | serial_port_in(port, UART_MSR); |
2257 | up->lsr_saved_flags = 0; | 2257 | up->lsr_saved_flags = 0; |
@@ -2344,7 +2344,8 @@ void serial8250_do_shutdown(struct uart_port *port) | |||
2344 | * Read data port to reset things, and then unlink from | 2344 | * Read data port to reset things, and then unlink from |
2345 | * the IRQ chain. | 2345 | * the IRQ chain. |
2346 | */ | 2346 | */ |
2347 | serial_port_in(port, UART_RX); | 2347 | if (serial_port_in(port, UART_LSR) & UART_LSR_DR) |
2348 | serial_port_in(port, UART_RX); | ||
2348 | serial8250_rpm_put(up); | 2349 | serial8250_rpm_put(up); |
2349 | 2350 | ||
2350 | del_timer_sync(&up->timer); | 2351 | del_timer_sync(&up->timer); |