Skip to content

Commit

Permalink
serial: clps711x: Check for valid TTY in RX-interrupt
Browse files Browse the repository at this point in the history
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Alexander Shiyan authored and Greg Kroah-Hartman committed Oct 24, 2012
1 parent ec33552 commit f27de95
Showing 1 changed file with 29 additions and 30 deletions.
59 changes: 29 additions & 30 deletions drivers/tty/serial/clps711x.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit f27de95

Please sign in to comment.