On Thu, Oct 29, 2026 at 8:18 AM Andy Shevchenko
[off-list ref] wrote:
On Thu, Oct 29, 2026 at 01:36:58AM -0600, James Hilliard wrote:
quoted
uart_write_wakeup() expects the UART port lock to be held. Several worker,
DMA completion and interrupt paths call it without that lock, including
indirect calls from uart_handle_cts_change() and the transmit helpers.
Take the port lock around these notifications or their transmit helper.
Keep sleeping SPI and regmap accesses outside the locked region, and keep
the FSL LPUART completion lock held through its wakeup. Acquire the port
lock after releasing private channel locks to preserve the ordering used
by UART callbacks. In the MUX timer, publish available FIFO space under
the port lock and keep the hardware FIFO-drain wait outside it.
Use IRQ-safe locking in the Atmel RX and TX tasklets and SB1250 termios
path, since their interrupt handlers now acquire the same port lock.
Preserve the caller's interrupt state when releasing those locks.
On SB1250, lock modem-state updates after reading and filtering the change
status, and wake modem-status waiters after unlocking. Take the TX lock
inside its service routine so RX-only interrupts need no acquisition.
Keep that lock across x_char handling, FIFO consumption and the decision
to mask TX interrupts: a writer must not enqueue data and enable TX between
the empty-FIFO check and the interrupt-mask write. Each TX invocation sends
at most one character.
Serialize CLPS711x TX servicing and its interrupt-enable state with the
port lock. Disable TX interrupts without waiting in stop_tx(), since a
threaded handler may need that same lock. Have an already queued handler
leave stopped output untouched, and drain it outside the lock during
shutdown before the transmit FIFO can be released.
SCCNXP handles interrupts under a controller lock which its UART callbacks
acquire with the port lock already held. Collect the ports needing wakeups
in an unsigned long bitmap while servicing the controller, then release
that lock before visiting the set bits, taking each port lock and
rechecking the wakeup threshold. Removal drains the IRQ or timer before
unregistering the ports.
This serializes write notifications with port-locked serial-core state
changes, allowing readiness and transmit-storage reservations to gate the
notification without a check-versus-shutdown race.
Cover DZ TX servicing and JSM Classic modem notifications as well. On
DECstation ZS, acquire the port lock before the SCC lock and notify writers
after releasing the SCC lock. Defer normal TX restart after console output
to a worker, since console output can already run under the port lock.
Check transmitter readiness before consuming another character and drain
the restart worker during shutdown and removal. Release Lantiq's hardware
lock through the transmit helper's completion hook before notifying the
line discipline.
...
quoted
static irqreturn_t serial21285_tx_chars(int irq, void *dev_id)
quoted
struct uart_port *port = dev_id;
u8 ch;
+ guard(uart_port_lock_irqsave)(port);
Why _irqsave?
For serial21285_tx_chars(), a plain uart_port_lock guard is sufficient.
It is only registered as an IRQ handler; saving and restoring the IRQ
state adds no protection on the hard-IRQ path. The necessary change
here is acquiring the port lock.
quoted
uart_port_tx_limited(port, ch, 256,
!(*CSR_UARTFLG & 0x20),
*CSR_UARTDR = ch,
...
Same Q everywhere (it might be legit in some cases,
it might be too strong in others).
The other sites have different calling contexts. Workers and tasklets
can share the lock with a hard IRQ, and some helpers have callers with
different incoming IRQ states. Those need different treatment from
hard-IRQ-only handlers.
--
With Best Regards,
Andy Shevchenko