Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

serial/arc-uart: Handle Rx Error Interrupts w/o any data

Currently, Rx error handling only triggers if there is some Rx data.
Fix that by checking for error - before the data handling.

Reported-by: Mischa Jonker <mjonker@synopsys.com>
Tested-by: Mischa Jonker <mjonker@synopsys.com>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Vineet Gupta and committed by
Greg Kroah-Hartman
5284eba7 cb50e523

+16 -10
+16 -10
drivers/tty/serial/arc_uart.c
··· 209 209 arc_serial_tx_chars(uart); 210 210 } 211 211 212 - static void arc_serial_rx_chars(struct arc_uart_port *uart) 212 + static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status) 213 213 { 214 - unsigned int status, ch, flg = 0; 214 + unsigned int ch, flg = 0; 215 215 216 216 /* 217 217 * UART has 4 deep RX-FIFO. Driver's recongnition of this fact ··· 222 222 * before RX-EMPTY=0, implies some sort of buffering going on in the 223 223 * controller, which is indeed the Rx-FIFO. 224 224 */ 225 - while (!((status = UART_GET_STATUS(uart)) & RXEMPTY)) { 226 - 227 - ch = UART_GET_DATA(uart); 228 - uart->port.icount.rx++; 229 - 225 + do { 226 + /* 227 + * This could be an Rx Intr for err (no data), 228 + * so check err and clear that Intr first 229 + */ 230 230 if (unlikely(status & (RXOERR | RXFERR))) { 231 231 if (status & RXOERR) { 232 232 uart->port.icount.overrun++; ··· 242 242 } else 243 243 flg = TTY_NORMAL; 244 244 245 + if (status & RXEMPTY) 246 + continue; 247 + 248 + ch = UART_GET_DATA(uart); 249 + uart->port.icount.rx++; 250 + 245 251 if (unlikely(uart_handle_sysrq_char(&uart->port, ch))) 246 252 goto done; 247 253 ··· 255 249 256 250 done: 257 251 tty_flip_buffer_push(&uart->port.state->port); 258 - } 252 + } while (!((status = UART_GET_STATUS(uart)) & RXEMPTY)); 259 253 } 260 254 261 255 /* ··· 298 292 * notifications from the UART Controller. 299 293 * To demultiplex between the two, we check the relevant bits 300 294 */ 301 - if ((status & RXIENB) && !(status & RXEMPTY)) { 295 + if (status & RXIENB) { 302 296 303 297 /* already in ISR, no need of xx_irqsave */ 304 298 spin_lock(&uart->port.lock); 305 - arc_serial_rx_chars(uart); 299 + arc_serial_rx_chars(uart, status); 306 300 spin_unlock(&uart->port.lock); 307 301 } 308 302