diff options
author | Alexander Shiyan <shc_work@mail.ru> | 2012-10-14 11:05:30 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-10-24 11:39:48 -0700 |
commit | f27de95c2a2120526c8cb051d741b7eb09e78cc9 (patch) | |
tree | a77a16711ea877bdce3cdd8877e81902883194e0 /drivers/tty/serial | |
parent | ec335526b4bce21f6777d3917d6d67c16009ec63 (diff) |
serial: clps711x: Check for valid TTY in RX-interrupt
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial')
-rw-r--r-- | drivers/tty/serial/clps711x.c | 59 |
1 files changed, 29 insertions, 30 deletions
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c index 73505c1edc7..6039ebe349c 100644 --- a/drivers/tty/serial/clps711x.c +++ b/drivers/tty/serial/clps711x.c @@ -55,8 +55,6 @@ #define TX_IRQ(port) ((port)->line ? IRQ_UTXINT2 : IRQ_UTXINT1) #define RX_IRQ(port) ((port)->line ? IRQ_URXINT2 : IRQ_URXINT1) -#define UART_ANY_ERR (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR) - struct clps711x_port { struct uart_driver uart; struct clk *uart_clk; @@ -99,54 +97,55 @@ static void clps711xuart_enable_ms(struct uart_port *port) static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id) { struct uart_port *port = dev_id; - struct tty_struct *tty = port->state->port.tty; + struct tty_struct *tty = tty_port_tty_get(&port->state->port); unsigned int status, ch, flg; - status = clps_readl(SYSFLG(port)); - while (!(status & SYSFLG_URXFE)) { - ch = clps_readl(UARTDR(port)); + if (!tty) + return IRQ_HANDLED; - port->icount.rx++; + for (;;) { + status = clps_readl(SYSFLG(port)); + if (status & SYSFLG_URXFE) + break; + ch = clps_readw(UARTDR(port)); + status = ch & (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR); + ch &= 0xff; + + port->icount.rx++; flg = TTY_NORMAL; - /* - * Note that the error handling code is - * out of the main execution path - */ - if (unlikely(ch & UART_ANY_ERR)) { - if (ch & UARTDR_PARERR) + if (unlikely(status)) { + if (status & UARTDR_PARERR) port->icount.parity++; - else if (ch & UARTDR_FRMERR) + else if (status & UARTDR_FRMERR) port->icount.frame++; - if (ch & UARTDR_OVERR) + else if (status & UARTDR_OVERR) port->icount.overrun++; - ch &= port->read_status_mask; + status &= port->read_status_mask; - if (ch & UARTDR_PARERR) + if (status & UARTDR_PARERR) flg = TTY_PARITY; - else if (ch & UARTDR_FRMERR) + else if (status & UARTDR_FRMERR) flg = TTY_FRAME; - -#ifdef SUPPORT_SYSRQ - port->sysrq = 0; -#endif + else if (status & UARTDR_OVERR) + flg = TTY_OVERRUN; } if (uart_handle_sysrq_char(port, ch)) - goto ignore_char; + continue; - /* - * CHECK: does overrun affect the current character? - * ASSUMPTION: it does not. - */ - uart_insert_char(port, ch, UARTDR_OVERR, ch, flg); + if (status & port->ignore_status_mask) + continue; - ignore_char: - status = clps_readl(SYSFLG(port)); + uart_insert_char(port, status, UARTDR_OVERR, ch, flg); } + tty_flip_buffer_push(tty); + + tty_kref_put(tty); + return IRQ_HANDLED; } |