1
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>
hifive-unleashed-5.1
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 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;
} }