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:
parent
ec335526b4
commit
f27de95c2a
1 changed files with 29 additions and 30 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue