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
|
@ -55,8 +55,6 @@
|
||||||
#define TX_IRQ(port) ((port)->line ? IRQ_UTXINT2 : IRQ_UTXINT1)
|
#define TX_IRQ(port) ((port)->line ? IRQ_UTXINT2 : IRQ_UTXINT1)
|
||||||
#define RX_IRQ(port) ((port)->line ? IRQ_URXINT2 : IRQ_URXINT1)
|
#define RX_IRQ(port) ((port)->line ? IRQ_URXINT2 : IRQ_URXINT1)
|
||||||
|
|
||||||
#define UART_ANY_ERR (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR)
|
|
||||||
|
|
||||||
struct clps711x_port {
|
struct clps711x_port {
|
||||||
struct uart_driver uart;
|
struct uart_driver uart;
|
||||||
struct clk *uart_clk;
|
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)
|
static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct uart_port *port = 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;
|
unsigned int status, ch, flg;
|
||||||
|
|
||||||
status = clps_readl(SYSFLG(port));
|
if (!tty)
|
||||||
while (!(status & SYSFLG_URXFE)) {
|
return IRQ_HANDLED;
|
||||||
ch = clps_readl(UARTDR(port));
|
|
||||||
|
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++;
|
port->icount.rx++;
|
||||||
|
|
||||||
flg = TTY_NORMAL;
|
flg = TTY_NORMAL;
|
||||||
|
|
||||||
/*
|
if (unlikely(status)) {
|
||||||
* Note that the error handling code is
|
if (status & UARTDR_PARERR)
|
||||||
* out of the main execution path
|
|
||||||
*/
|
|
||||||
if (unlikely(ch & UART_ANY_ERR)) {
|
|
||||||
if (ch & UARTDR_PARERR)
|
|
||||||
port->icount.parity++;
|
port->icount.parity++;
|
||||||
else if (ch & UARTDR_FRMERR)
|
else if (status & UARTDR_FRMERR)
|
||||||
port->icount.frame++;
|
port->icount.frame++;
|
||||||
if (ch & UARTDR_OVERR)
|
else if (status & UARTDR_OVERR)
|
||||||
port->icount.overrun++;
|
port->icount.overrun++;
|
||||||
|
|
||||||
ch &= port->read_status_mask;
|
status &= port->read_status_mask;
|
||||||
|
|
||||||
if (ch & UARTDR_PARERR)
|
if (status & UARTDR_PARERR)
|
||||||
flg = TTY_PARITY;
|
flg = TTY_PARITY;
|
||||||
else if (ch & UARTDR_FRMERR)
|
else if (status & UARTDR_FRMERR)
|
||||||
flg = TTY_FRAME;
|
flg = TTY_FRAME;
|
||||||
|
else if (status & UARTDR_OVERR)
|
||||||
#ifdef SUPPORT_SYSRQ
|
flg = TTY_OVERRUN;
|
||||||
port->sysrq = 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uart_handle_sysrq_char(port, ch))
|
if (uart_handle_sysrq_char(port, ch))
|
||||||
goto ignore_char;
|
continue;
|
||||||
|
|
||||||
/*
|
if (status & port->ignore_status_mask)
|
||||||
* CHECK: does overrun affect the current character?
|
continue;
|
||||||
* ASSUMPTION: it does not.
|
|
||||||
*/
|
|
||||||
uart_insert_char(port, ch, UARTDR_OVERR, ch, flg);
|
|
||||||
|
|
||||||
ignore_char:
|
uart_insert_char(port, status, UARTDR_OVERR, ch, flg);
|
||||||
status = clps_readl(SYSFLG(port));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tty_flip_buffer_push(tty);
|
tty_flip_buffer_push(tty);
|
||||||
|
|
||||||
|
tty_kref_put(tty);
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue