diff options
author | Michael Walle <michael@walle.cc> | 2021-05-12 16:12:51 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-05-13 16:08:26 +0200 |
commit | 5541a9bacfe54fb2038531fb276724fcec6c29c4 (patch) | |
tree | b76602d56db9ed0bcd83eb1dc8b021779efc4faa /drivers/tty/serial/fsl_lpuart.c | |
parent | 5697df7322fe0a95e56393f63ca8e0f256be92f9 (diff) | |
download | linux-stable-5541a9bacfe54fb2038531fb276724fcec6c29c4.tar.gz linux-stable-5541a9bacfe54fb2038531fb276724fcec6c29c4.tar.bz2 linux-stable-5541a9bacfe54fb2038531fb276724fcec6c29c4.zip |
serial: fsl_lpuart: handle break and make sysrq work
Although there is already sysrq characters handling, a break condition
was never detected. Add support for it.
The LPUART can't distinguish between a framing error and a break
condition. We assume it is a break if the received data is all zero.
Signed-off-by: Michael Walle <michael@walle.cc>
Link: https://lore.kernel.org/r/20210512141255.18277-6-michael@walle.cc
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/fsl_lpuart.c')
-rw-r--r-- | drivers/tty/serial/fsl_lpuart.c | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 72caa7a193a8..baa96e61ab14 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -910,6 +910,7 @@ static void lpuart32_rxint(struct lpuart_port *sport) unsigned int flg, ignored = 0; struct tty_port *port = &sport->port.state->port; unsigned long rx, sr; + bool is_break; spin_lock(&sport->port.lock); @@ -924,14 +925,27 @@ static void lpuart32_rxint(struct lpuart_port *sport) rx = lpuart32_read(&sport->port, UARTDATA); rx &= UARTDATA_MASK; + /* + * The LPUART can't distinguish between a break and a framing error, + * thus we assume it is a break if the received data is zero. + */ + is_break = (sr & UARTSTAT_FE) && !rx; + + if (is_break && uart_handle_break(&sport->port)) + continue; + if (uart_prepare_sysrq_char(&sport->port, rx)) continue; if (sr & (UARTSTAT_PE | UARTSTAT_OR | UARTSTAT_FE)) { - if (sr & UARTSTAT_PE) - sport->port.icount.parity++; - else if (sr & UARTSTAT_FE) + if (sr & UARTSTAT_PE) { + if (is_break) + sport->port.icount.brk++; + else + sport->port.icount.parity++; + } else if (sr & UARTSTAT_FE) { sport->port.icount.frame++; + } if (sr & UARTSTAT_OR) sport->port.icount.overrun++; @@ -944,15 +958,17 @@ static void lpuart32_rxint(struct lpuart_port *sport) sr &= sport->port.read_status_mask; - if (sr & UARTSTAT_PE) - flg = TTY_PARITY; - else if (sr & UARTSTAT_FE) + if (sr & UARTSTAT_PE) { + if (is_break) + flg = TTY_BREAK; + else + flg = TTY_PARITY; + } else if (sr & UARTSTAT_FE) { flg = TTY_FRAME; + } if (sr & UARTSTAT_OR) flg = TTY_OVERRUN; - - sport->port.sysrq = 0; } tty_insert_flip_char(port, rx, flg); |