From c3ad42ccd303113a08bd0b441fb5b3380f29c5bf Mon Sep 17 00:00:00 2001 From: Tapio Reijonen Date: Thu, 8 Oct 2026 09:48:28 +0000 Subject: [PATCH] serial: max310x: don't power down the port mid-transmission on close max310x_shutdown() powers the port down regardless of what the transmitter is doing. The power-off stops the UART clock mid-character, truncating the final frame, and on the auto-RTS path it freezes the RTS output at its current level: a close() with data still queued leaves the RS485 transceiver asserted until the next open, which also emits the interrupted character corrupted. Waiting for the data to drain is no better: the tty layer's wait-until-sent is bounded by closing_wait, configurable to none, and a hangup arrives with no wait at all, so draining a full FIFO blocks close() in uninterruptible sleep for seconds at low baud rates - and forever when CTS flow control blocks the FIFO. Instead, set MODE1 TxDisabl: the character in flight completes and the transmitter ceases with TX_ at idle. Give that character one character time (the chip has no transmitter-idle status), then reset the FIFOs so the auto-RTS engine sees the transmitter empty and releases RTS within the configured after-send hold; wait that hold plus one bit time before powering off. Abandoned data was explicitly not waited for, and startup() resets the FIFOs and TxDisabl on open anyway. Measured on a MAX14830: a truncating close() at 50 baud takes 0.23 s, RTS releases one character plus the hold after the last stop bit on both polarities, and the reopen corruption is gone. Fixes: f65444187a66 ("serial: New serial driver MAX310X") Assisted-by: Claude:claude-fable-5 Signed-off-by: Tapio Reijonen Link: https://patch.msgid.link/20261008-max310x-rs485-sw-delay-v8-5-6ba881f81e1f@vaisala.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/max310x.c | 44 ++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index c57d6dde7fe3..86400092a901 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -300,6 +300,7 @@ struct max310x_one { struct work_struct md_work; struct work_struct rs_work; struct regmap *regmap; + unsigned int char_time_us; unsigned int baud; bool tx_break; /* break_ctl() owns the transceiver */ @@ -1010,6 +1011,7 @@ static void max310x_set_termios(struct uart_port *port, struct ktermios *termios, const struct ktermios *old) { + unsigned int frame_bits = tty_get_frame_size(termios->c_cflag); unsigned int lcr = 0, flow = 0; int baud; @@ -1122,10 +1124,13 @@ static void max310x_set_termios(struct uart_port *port, uart_update_timeout(port, termios->c_cflag, baud); /* - * Cache the new baud rate and reprogram the RS485 RTS delays, whose - * millisecond-to-bit-time conversion depends on it. + * Cache the new baud rate and the time it takes to clock out one + * character before reprogramming the RS485 RTS delays: the + * millisecond-to-bit-time conversion divides by the baud rate. */ to_max310x_port(port)->baud = baud; + to_max310x_port(port)->char_time_us = + DIV_ROUND_UP(USEC_PER_SEC * frame_bits, baud); max310x_set_rts_ctl_params(to_max310x_port(port)); } @@ -1182,9 +1187,10 @@ static int max310x_startup(struct uart_port *port) one->tx_break = false; max310x_port_update(port, MAX310X_LCR_REG, MAX310X_LCR_TXBREAK_BIT, 0); - /* Configure MODE1 register */ + /* Configure MODE1: re-enable the transmitter shutdown() stopped */ max310x_port_update(port, MAX310X_MODE1_REG, - MAX310X_MODE1_TRNSCVCTRL_BIT, 0); + MAX310X_MODE1_TRNSCVCTRL_BIT | + MAX310X_MODE1_TXDIS_BIT, 0); /* Configure MODE2 register & Reset FIFOs*/ val = MAX310X_MODE2_RXEMPTINV_BIT | MAX310X_MODE2_FIFORST_BIT; @@ -1221,9 +1227,39 @@ static int max310x_startup(struct uart_port *port) static void max310x_shutdown(struct uart_port *port) { + struct max310x_one *one = to_max310x_port(port); + /* Disable all interrupts */ max310x_port_write(port, MAX310X_IRQEN_REG, 0); + /* + * Stop the transmitter: the character in flight completes, data + * still queued is abandoned (the next startup() resets the FIFOs). + */ + max310x_port_update(port, MAX310X_MODE1_REG, + MAX310X_MODE1_TXDIS_BIT, MAX310X_MODE1_TXDIS_BIT); + + /* + * Let the character in flight finish (the chip has no + * transmitter-idle status), then empty the FIFO: auto-RTS releases + * only once the transmitter is empty, and the power-off below + * would freeze an asserted pin until the next open. + */ + fsleep(one->char_time_us); + max310x_port_update(port, MAX310X_MODE2_REG, + MAX310X_MODE2_FIFORST_BIT, + MAX310X_MODE2_FIFORST_BIT); + max310x_port_update(port, MAX310X_MODE2_REG, + MAX310X_MODE2_FIFORST_BIT, 0); + if (port->rs485.flags & SER_RS485_ENABLED && one->baud) { + unsigned int hold = DIV_ROUND_UP(one->baud * + port->rs485.delay_rts_after_send, + MSEC_PER_SEC); + + fsleep(max(DIV_ROUND_UP((hold + 1) * USEC_PER_SEC, + one->baud), 100U)); + } + max310x_power(port, 0); }