6.18-stable review patch. If anyone has any objections, please let me know. ------------------ From: Nicolai Buchwitz [ Upstream commit 8a9750209596be35d109de5aa89623b049855c67 ] While the driver waits out delay_rts_before_send, another write calls pl011_start_tx() again. pl011_rs485_tx_start() then switches straight to SEND, and the data goes out before the delay has passed. Leave the start to the trigger_start_tx timer while it is pending. Fixes: 2c1fd53af21b ("serial: amba-pl011: Fix RTS handling in RS485 mode") Cc: stable@vger.kernel.org Signed-off-by: Nicolai Buchwitz Link: https://patch.msgid.link/20261011-fix-pl011-rs485-rts-delay-v1-1-5078e61bc408@tipi-net.de Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/tty/serial/amba-pl011.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 4b213d0c61336..3e777e4d13f20 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1355,10 +1355,6 @@ static void pl011_rs485_tx_start(struct uart_amba_port *uap) struct uart_port *port = &uap->port; u32 cr; - if (uap->rs485_tx_state == WAIT_AFTER_RTS) { - uap->rs485_tx_state = SEND; - return; - } if (uap->rs485_tx_state == WAIT_AFTER_SEND || uap->rs485_tx_state == WAIT_AFTER_SEND_DELAY) { hrtimer_try_to_cancel(&uap->trigger_stop_tx); @@ -1397,6 +1393,10 @@ static void pl011_start_tx(struct uart_port *port) if ((uap->port.rs485.flags & SER_RS485_ENABLED) && uap->rs485_tx_state != SEND) { + /* trigger_start_tx starts TX once delay_rts_before_send passed */ + if (uap->rs485_tx_state == WAIT_AFTER_RTS) + return; + pl011_rs485_tx_start(uap); if (uap->rs485_tx_state == WAIT_AFTER_RTS) return; @@ -1413,8 +1413,10 @@ static enum hrtimer_restart pl011_trigger_start_tx(struct hrtimer *t) unsigned long flags; uart_port_lock_irqsave(&uap->port, &flags); - if (uap->rs485_tx_state == WAIT_AFTER_RTS) + if (uap->rs485_tx_state == WAIT_AFTER_RTS) { + uap->rs485_tx_state = SEND; pl011_start_tx(&uap->port); + } uart_port_unlock_irqrestore(&uap->port, flags); return HRTIMER_NORESTART; -- 2.53.0