Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

serial: owl: Use uart_prepare_sysrq_char() to handle sysrq.

The port lock is a spinlock_t which is becomes a sleeping lock on PREEMPT_RT.
The driver splits the locking function into two parts: local_irq_save() and
uart_port_lock() and this breaks PREEMPT_RT.

Handle sysrq requests sysrq once the port lock is dropped.
Remove the special case in the console write routine an always use the
complete locking function.

Cc: Andreas Färber <afaerber@suse.de>
Cc: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-actions@lists.infradead.org
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Link: https://lore.kernel.org/r/20240301215246.891055-11-bigeasy@linutronix.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Sebastian Andrzej Siewior and committed by
Greg Kroah-Hartman
2af52148 6ba52968

+12 -18
+12 -18
drivers/tty/serial/owl-uart.c
··· 199 199 stat = owl_uart_read(port, OWL_UART_STAT); 200 200 while (!(stat & OWL_UART_STAT_RFEM)) { 201 201 char flag = TTY_NORMAL; 202 + bool sysrq; 202 203 203 204 if (stat & OWL_UART_STAT_RXER) 204 205 port->icount.overrun++; ··· 218 217 val = owl_uart_read(port, OWL_UART_RXDAT); 219 218 val &= 0xff; 220 219 221 - if ((stat & port->ignore_status_mask) == 0) 220 + sysrq = uart_prepare_sysrq_char(port, val); 221 + 222 + if (!sysrq && (stat & port->ignore_status_mask) == 0) 222 223 tty_insert_flip_char(&port->state->port, val, flag); 223 224 224 225 stat = owl_uart_read(port, OWL_UART_STAT); ··· 232 229 static irqreturn_t owl_uart_irq(int irq, void *dev_id) 233 230 { 234 231 struct uart_port *port = dev_id; 235 - unsigned long flags; 236 232 u32 stat; 237 233 238 - uart_port_lock_irqsave(port, &flags); 234 + uart_port_lock(port); 239 235 240 236 stat = owl_uart_read(port, OWL_UART_STAT); 241 237 ··· 248 246 stat |= OWL_UART_STAT_RIP | OWL_UART_STAT_TIP; 249 247 owl_uart_write(port, stat, OWL_UART_STAT); 250 248 251 - uart_port_unlock_irqrestore(port, flags); 249 + uart_unlock_and_check_sysrq(port); 252 250 253 251 return IRQ_HANDLED; 254 252 } ··· 510 508 { 511 509 u32 old_ctl, val; 512 510 unsigned long flags; 513 - int locked; 511 + int locked = 1; 514 512 515 - local_irq_save(flags); 516 - 517 - if (port->sysrq) 518 - locked = 0; 519 - else if (oops_in_progress) 520 - locked = uart_port_trylock(port); 521 - else { 522 - uart_port_lock(port); 523 - locked = 1; 524 - } 513 + if (oops_in_progress) 514 + locked = uart_port_trylock_irqsave(port, &flags); 515 + else 516 + uart_port_lock_irqsave(port, &flags); 525 517 526 518 old_ctl = owl_uart_read(port, OWL_UART_CTL); 527 519 val = old_ctl | OWL_UART_CTL_TRFS_TX; ··· 537 541 owl_uart_write(port, old_ctl, OWL_UART_CTL); 538 542 539 543 if (locked) 540 - uart_port_unlock(port); 541 - 542 - local_irq_restore(flags); 544 + uart_port_unlock_irqrestore(port, flags); 543 545 } 544 546 545 547 static void owl_uart_console_write(struct console *co, const char *s,