diff options
author | Sherry Sun <sherry.sun@nxp.com> | 2023-02-23 17:39:41 +0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2023-03-09 17:06:28 +0100 |
commit | 2411fd94ceaa6e11326e95d6ebf876cbfed28d23 (patch) | |
tree | 7c822a0ee2ac5d6e2e4aad318a1e96d004421dc8 /drivers/tty/serial/fsl_lpuart.c | |
parent | 2d638be71155b2e036aca1966b6129e2d661e91f (diff) | |
download | linux-stable-2411fd94ceaa6e11326e95d6ebf876cbfed28d23.tar.gz linux-stable-2411fd94ceaa6e11326e95d6ebf876cbfed28d23.tar.bz2 linux-stable-2411fd94ceaa6e11326e95d6ebf876cbfed28d23.zip |
tty: serial: fsl_lpuart: skip waiting for transmission complete when UARTCTRL_SBK is asserted
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/tty/serial/fsl_lpuart.c')
-rw-r--r-- | drivers/tty/serial/fsl_lpuart.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index e945f41b93d4..f9e164abf920 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -2240,9 +2240,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), |