summaryrefslogtreecommitdiff
path: root/tools/lib/python
diff options
context:
space:
mode:
authorTapio Reijonen <tapio.reijonen@vaisala.com>2026-10-08 09:48:32 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-10-13 15:19:41 +0200
commitae588038e31c9dbd6836cb12bbdd82af0271c373 (patch)
treeb69a59fc2b254e448a0d20774eb66db71407406c /tools/lib/python
parent33632215e1bbc6109173b761e0c9bc5c4fcdbeee (diff)
serial: max310x: don't transmit while an RS485 reconfigure is pending
TIOCSRS485 applies its register changes asynchronously: rs485_config() stores the new configuration and schedules rs_work, which programs HDPIXDELAY, MODE1.TRNSCVCTRL and the RTS path. A write() issued right after the ioctl therefore transmits against the old, half-switched state. On a single core the ordering is even deterministic: start_tx() picks the stale path first, then rs_work reprograms the chip, then tx_work pumps the data - with the transceiver already released. A TIOCSRS485 switching from the hardware to the software RTS path followed immediately by a write puts the whole transfer on the wire with the transceiver disabled: nothing reaches the bus and no error is reported anywhere. The inverse direction is as old as the asynchronous reconfigure itself: enabling RS485 and writing immediately shifts the first bytes out before rs_work has enabled the chip's auto-RTS. Defer instead: rs485_config() marks the reconfigure pending under port->lock, start_tx() leaves the data in the kfifo while the mark is set, and rs_work restarts the transmission itself once the new configuration is fully applied. The rs485-disable path's direct tx_work kick is replaced by the same mechanism, which also orders that flush after the reconfigure instead of before it. The restart kick also checks port->x_char: uart_send_xchar() reaches start_tx() too, and a lone x_char deferred by the pending gate leaves the kfifo empty, so the kick would otherwise skip it and nothing else would ever send it - an idle chip FIFO raises no TXEMPTY interrupt. And start_tx() re-checks the pending mark after the hrtimer_try_to_cancel(-1) path retakes the dropped lock, mirroring the tx_teardown re-check there: a TIOCSRS485 posted inside that window would otherwise let the transmission proceed on the stale path. rs_work takes port->lock for that restart through uart_port_lock_irqsave(): start_tx() may drop and retake the lock through the uart_port API on its hrtimer_try_to_cancel(-1) path, and a raw spinlock guard around the call would unbalance the nbcon console handling underneath. The restart also rewinds a send state adopted for the deferred write itself: set_rts_ctl_params() cannot tell data the pending gate deferred apart from an in-flight transfer's refill by the xmit buffer alone, and a deferred write pumped in the adopted send phase would skip the configured before-send delay. With the chip FIFO empty the adopted state can only be the deferred write: rewind it and let the restart run the full envelope. The chip-FIFO check for that rewind is deliberately lock-free, so a TX-empty refill can land between the read and the lock and the rewind can hit a live envelope. The consequence is bounded: the rewind runs under port->lock in a state the RTS worker reads as asserted, so the envelope pauses one before-send delay with the transceiver held - the same pause the unconditional rewind produced before patch 8's guard. Fixes: 5bdb48b501e8 ("serial: max310x: Fix RS485 handling") Assisted-by: Claude:claude-fable-5 Signed-off-by: Tapio Reijonen <tapio.reijonen@vaisala.com> Link: https://patch.msgid.link/20261008-max310x-rs485-sw-delay-v8-9-6ba881f81e1f@vaisala.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'tools/lib/python')
0 files changed, 0 insertions, 0 deletions