aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVineet Gupta <Vineet.Gupta1@synopsys.com>2013-08-02 00:49:19 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-08-01 23:54:12 -0400
commit5284eba7b37dfeffe75bfdf81a13e9efebe0480a (patch)
tree488245e42b7e58d5e813cfd3de6f56c04c53c8a1
parentcb50e5235b8ae5aa0fe422eaaa8e444024c5bd98 (diff)
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>
-rw-r--r--drivers/tty/serial/arc_uart.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index 2f195f0d7a11..e296c892df61 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -209,9 +209,9 @@ static void arc_serial_start_tx(struct uart_port *port)
209 arc_serial_tx_chars(uart); 209 arc_serial_tx_chars(uart);
210} 210}
211 211
212static void arc_serial_rx_chars(struct arc_uart_port *uart) 212static 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 * UART has 4 deep RX-FIFO. Driver's recongnition of this fact 217 * UART has 4 deep RX-FIFO. Driver's recongnition of this fact
@@ -222,11 +222,11 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart)
222 * before RX-EMPTY=0, implies some sort of buffering going on in the 222 * before RX-EMPTY=0, implies some sort of buffering going on in the
223 * controller, which is indeed the Rx-FIFO. 223 * controller, which is indeed the Rx-FIFO.
224 */ 224 */
225 while (!((status = UART_GET_STATUS(uart)) & RXEMPTY)) { 225 do {
226 226 /*
227 ch = UART_GET_DATA(uart); 227 * This could be an Rx Intr for err (no data),
228 uart->port.icount.rx++; 228 * so check err and clear that Intr first
229 229 */
230 if (unlikely(status & (RXOERR | RXFERR))) { 230 if (unlikely(status & (RXOERR | RXFERR))) {
231 if (status & RXOERR) { 231 if (status & RXOERR) {
232 uart->port.icount.overrun++; 232 uart->port.icount.overrun++;
@@ -242,6 +242,12 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart)
242 } else 242 } else
243 flg = TTY_NORMAL; 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 if (unlikely(uart_handle_sysrq_char(&uart->port, ch))) 251 if (unlikely(uart_handle_sysrq_char(&uart->port, ch)))
246 goto done; 252 goto done;
247 253
@@ -249,7 +255,7 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart)
249 255
250done: 256done:
251 tty_flip_buffer_push(&uart->port.state->port); 257 tty_flip_buffer_push(&uart->port.state->port);
252 } 258 } while (!((status = UART_GET_STATUS(uart)) & RXEMPTY));
253} 259}
254 260
255/* 261/*
@@ -292,11 +298,11 @@ static irqreturn_t arc_serial_isr(int irq, void *dev_id)
292 * notifications from the UART Controller. 298 * notifications from the UART Controller.
293 * To demultiplex between the two, we check the relevant bits 299 * To demultiplex between the two, we check the relevant bits
294 */ 300 */
295 if ((status & RXIENB) && !(status & RXEMPTY)) { 301 if (status & RXIENB) {
296 302
297 /* already in ISR, no need of xx_irqsave */ 303 /* already in ISR, no need of xx_irqsave */
298 spin_lock(&uart->port.lock); 304 spin_lock(&uart->port.lock);
299 arc_serial_rx_chars(uart); 305 arc_serial_rx_chars(uart, status);
300 spin_unlock(&uart->port.lock); 306 spin_unlock(&uart->port.lock);
301 } 307 }
302 308