From 8a9750209596be35d109de5aa89623b049855c67 Mon Sep 17 00:00:00 2001 From: Nicolai Buchwitz Date: Sun, 11 Oct 2026 22:23:44 +0200 Subject: [PATCH] serial: amba-pl011: honour delay_rts_before_send for every write 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 --- 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 fcfa9f00aec6..cd8cbc967281 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1419,10 +1419,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); @@ -1461,6 +1457,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; @@ -1477,8 +1477,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;