summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSherry Sun <sherry.sun@nxp.com>2023-02-23 17:39:41 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-03-22 13:33:55 +0100
commitd72ebe4855eb097c370d383e3b2b953f303c6b18 (patch)
treeb13f56e3e8712e7ca9fec12694eedc93de22df8e /drivers
parent4d2304d8f77974209f7dc82f6fc50d94599bf1fe (diff)
downloadlinux-d72ebe4855eb097c370d383e3b2b953f303c6b18.tar.gz
linux-d72ebe4855eb097c370d383e3b2b953f303c6b18.tar.bz2
linux-d72ebe4855eb097c370d383e3b2b953f303c6b18.zip
tty: serial: fsl_lpuart: skip waiting for transmission complete when UARTCTRL_SBK is asserted
commit 2411fd94ceaa6e11326e95d6ebf876cbfed28d23 upstream. According to LPUART RM, Transmission Complete Flag becomes 0 if queuing a break character by writing 1 to CTRL[SBK], so here need to skip waiting for transmission complete when UARTCTRL_SBK is asserted, otherwise the kernel may stuck here. And actually set_termios() adds transmission completion waiting to avoid data loss or data breakage when changing the baud rate, but we don't need to worry about this when queuing break characters. Signed-off-by: Sherry Sun <sherry.sun@nxp.com> Cc: stable <stable@kernel.org> Link: https://lore.kernel.org/r/20230223093941.31790-1-sherry.sun@nxp.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/tty/serial/fsl_lpuart.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index f9d667ce1619..c51883f34ac2 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -2184,9 +2184,15 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
/* update the per-port timeout */
uart_update_timeout(port, termios->c_cflag, baud);
- /* wait transmit engin complete */
- lpuart32_write(&sport->port, 0, UARTMODIR);
- lpuart32_wait_bit_set(&sport->port, UARTSTAT, UARTSTAT_TC);
+ /*
+ * LPUART Transmission Complete Flag may never be set while queuing a break
+ * character, so skip waiting for transmission complete when UARTCTRL_SBK is
+ * asserted.
+ */
+ if (!(old_ctrl & UARTCTRL_SBK)) {
+ lpuart32_write(&sport->port, 0, UARTMODIR);
+ lpuart32_wait_bit_set(&sport->port, UARTSTAT, UARTSTAT_TC);
+ }
/* disable transmit and receive */
lpuart32_write(&sport->port, old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE),