On Tue, 16 Jan 2024, Leonardo Bras wrote: > With PREEMPT_RT enabled, a spin_lock_irqsave() becomes a possibly sleeping > spin_lock(), without preempt_disable() or irq_disable(). > > This allows a task T1 to get preempted or interrupted while holding the > port->lock. If the preempting task T2 need the lock, spin_lock() code > will schedule T1 back until it finishes using the lock, and then go back to > T2. > > There is an issue if a T1 holding port->lock is interrupted by an > IRQ, and this IRQ handler needs to get port->lock for writting (printk): > spin_lock() code will try to reschedule the interrupt handler, which is in > atomic context, causing a BUG() for trying to reschedule/sleep in atomic > context. I thought that the printk side was supposed to be become aware when it's not safe to write to serial side so the printing can be deferred... Has that plan changed? -- i. > So for the case (PREEMPT_RT && in_atomic()) try to get the lock, and if it > fails proceed anyway, just like it's done in oops_in_progress case. > > Signed-off-by: Leonardo Bras <leobras@xxxxxxxxxx> > --- > drivers/tty/serial/8250/8250_port.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c > index 8ca061d3bbb92..8480832846319 100644 > --- a/drivers/tty/serial/8250/8250_port.c > +++ b/drivers/tty/serial/8250/8250_port.c > @@ -3397,7 +3397,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, > > touch_nmi_watchdog(); > > - if (oops_in_progress) > + if (oops_in_progress || (IS_ENABLED(CONFIG_PREEMPT_RT) && in_atomic()) > locked = uart_port_trylock_irqsave(port, &flags); > else > uart_port_lock_irqsave(port, &flags); >