Linux Serial subsystem development
 help / color / mirror / Atom feed
* [PATCH v2] serial: amba-pl011: keep transmitter enabled when disabling RS485
@ 2026-10-12 14:23 Nicolai Buchwitz
  2026-10-12 14:34 ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: Nicolai Buchwitz @ 2026-10-12 14:23 UTC (permalink / raw)
  To: Russell King, Greg Kroah-Hartman, Jiri Slaby, Lino Sanfilippo
  Cc: linux-kernel, linux-serial, stable, Nicolai Buchwitz

Disabling RS485 on an open port calls pl011_rs485_tx_stop(), which
turns off the transmitter. Only the RS485 TX path turns it back on, so
any later output stays queued and tcdrain() hangs until the port is
closed.

pl011_rs485_tx_stop() also checks only the hardware FIFO. If a DMA
transfer has started but has not filled the FIFO yet, the transmitter
is turned off under the transfer and the DMA channel never recovers.

When leaving RS485 mode, cancel pending deferred starts and stops, leave
the transmitter enabled and start any TX that was still waiting for
delay_rts_before_send.

Fixes: 8d479237727c ("serial: amba-pl011: add RS485 support")
Cc: stable@vger.kernel.org
Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
---
Noticed while implementing a DMX master on a CM5 with its PL011.
Userspace turns RS485 mode off to send the break, and the port then
stopped transmitting.

Tested on that board with an RS485 transceiver at 9600, 115200 and
250000 baud.
---
Changes in v2:
- Start TX that was still waiting for delay_rts_before_send instead of
  dropping it (sashiko)
- Link to v1: https://patch.msgid.link/20261011-fix-pl011-rs485-txe-v1-1-302b6c034b7f@tipi-net.de

To: Russell King <linux@armlinux.org.uk>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: Jiri Slaby <jirislaby@kernel.org>
To: Lino Sanfilippo <LinoSanfilippo@gmx.de>
Cc: linux-kernel@vger.kernel.org
Cc: linux-serial@vger.kernel.org
---
 drivers/tty/serial/amba-pl011.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index c4824c201e1c..2ad6ccfdb52c 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -2397,8 +2397,31 @@ static int pl011_rs485_config(struct uart_port *port, struct ktermios *termios,
 	struct uart_amba_port *uap =
 		container_of(port, struct uart_amba_port, port);
 
-	if (port->rs485.flags & SER_RS485_ENABLED)
+	if ((port->rs485.flags & SER_RS485_ENABLED) &&
+	    !(rs485->flags & SER_RS485_ENABLED)) {
+		bool tx_pending = uap->rs485_tx_state == WAIT_AFTER_RTS;
+		u32 cr = pl011_read(uap, REG_CR);
+
+		/*
+		 * Leaving RS485 mode, which only enables the transmitter while
+		 * sending. Don't stop it, as that stalls a DMA transfer still
+		 * in flight. Drop pending deferred starts and stops and keep
+		 * it enabled.
+		 */
+		hrtimer_try_to_cancel(&uap->trigger_start_tx);
+		hrtimer_try_to_cancel(&uap->trigger_stop_tx);
+		uap->rs485_tx_state = OFF;
+
+		cr |= UART011_CR_TXE | UART011_CR_RXE;
+		pl011_write(cr, uap, REG_CR);
+
+		/* Start TX that was still waiting for delay_rts_before_send */
+		if (tx_pending && !uart_tx_stopped(port) &&
+		    !pl011_dma_tx_start(uap))
+			pl011_start_tx_pio(uap);
+	} else if (port->rs485.flags & SER_RS485_ENABLED) {
 		pl011_rs485_tx_stop(uap);
+	}
 
 	/* Make sure auto RTS is disabled */
 	if (rs485->flags & SER_RS485_ENABLED) {

---
base-commit: a90ee4305c4a5df72c11b31dacfdc76e00fcf78a
change-id: 20261011-fix-pl011-rs485-txe-f61e1c969f9a

Best regards,
--  
Nicolai Buchwitz <nb@tipi-net.de>


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v2] serial: amba-pl011: keep transmitter enabled when disabling RS485
  2026-10-12 14:23 [PATCH v2] serial: amba-pl011: keep transmitter enabled when disabling RS485 Nicolai Buchwitz
@ 2026-10-12 14:34 ` sashiko-bot
  0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-10-12 14:34 UTC (permalink / raw)
  To: Nicolai Buchwitz; +Cc: linux-serial

> Disabling RS485 on an open port calls pl011_rs485_tx_stop(), which
> turns off the transmitter. Only the RS485 TX path turns it back on, so
> any later output stays queued and tcdrain() hangs until the port is
> closed.
> 
> pl011_rs485_tx_stop() also checks only the hardware FIFO. If a DMA
> transfer has started but has not filled the FIFO yet, the transmitter
> is turned off under the transfer and the DMA channel never recovers.
> 
> When leaving RS485 mode, cancel pending deferred starts and stops, leave
> the transmitter enabled and start any TX that was still waiting for
> delay_rts_before_send.
> 
> Fixes: 8d479237727c ("serial: amba-pl011: add RS485 support")
> Cc: stable@vger.kernel.org
> Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261012-fix-pl011-rs485-txe-v2-1-e9bf7d218389@tipi-net.de?part=1


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-12 14:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-12 14:23 [PATCH v2] serial: amba-pl011: keep transmitter enabled when disabling RS485 Nicolai Buchwitz
2026-10-12 14:34 ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox