dect
/
linux-2.6
Archived
13
0
Fork 0

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>
This commit is contained in:
Alexander Shiyan 2012-10-14 11:05:30 +04:00 committed by Greg Kroah-Hartman
parent ec335526b4
commit f27de95c2a
1 changed files with 29 additions and 30 deletions

View File

@ -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;
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;
}