Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f27de95c authored by Alexander Shiyan's avatar Alexander Shiyan Committed by Greg Kroah-Hartman
Browse files

serial: clps711x: Check for valid TTY in RX-interrupt

parent ec335526
Loading
Loading
Loading
Loading
+29 −30
Original line number Diff line number Diff line
@@ -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;

	if (!tty)
		return IRQ_HANDLED;

	for (;;) {
		status = clps_readl(SYSFLG(port));
	while (!(status & SYSFLG_URXFE)) {
		ch = clps_readl(UARTDR(port));
		if (status & SYSFLG_URXFE)
			break;

		port->icount.rx++;
		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;
}