On Tue, Jan 16, 2024 at 08:49:14AM +0100, Jiri Slaby wrote: > On 16. 01. 24, 8:32, 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. > > > > 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. > > Hmm, that appears incorrect to me. > > Perhaps we need a raw spin lock? Or maybe I am totally off, as my RT > knowledge is close to zero. If we have a raw_spin_lock_irqsave() here, it would hurt RT by a lot since disabling interrupts is usually bad at the RT kernel, and serial console can be used a lot. > > This needs advices from RT folks... Agree. All help is welcome in this case! Thanks! Leo > > > 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); > > -- > js > suse labs >