Commit d6e1935819db ("serial: core: Allow processing sysrq at port unlock time") worked around a circular locking dependency by adding helpers used to defer sysrq processing to when the port lock was released. A later commit unfortunately converted these inline helpers to exported functions despite the fact that the unlock helper was restoring irq flags, something which needs to be done in the same function that saved them (e.g. on SPARC). Fixes: 8e20fc391711 ("serial_core: Move sysrq functions from header file") Cc: stable <stable@xxxxxxxxxxxxxxx> # 5.6 Cc: Dmitry Safonov <0x7f454c46@xxxxxxxxx> Signed-off-by: Johan Hovold <johan@xxxxxxxxxx> --- drivers/tty/serial/serial_core.c | 19 ------------------- include/linux/serial_core.h | 21 +++++++++++++++++++-- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index edfb7bc14bbf..f6cf9cc4ce69 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -3239,25 +3239,6 @@ int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch) } EXPORT_SYMBOL_GPL(uart_prepare_sysrq_char); -void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags) -{ - int sysrq_ch; - - if (!port->has_sysrq) { - spin_unlock_irqrestore(&port->lock, irqflags); - return; - } - - sysrq_ch = port->sysrq_ch; - port->sysrq_ch = 0; - - spin_unlock_irqrestore(&port->lock, irqflags); - - if (sysrq_ch) - handle_sysrq(sysrq_ch); -} -EXPORT_SYMBOL_GPL(uart_unlock_and_check_sysrq); - /* * We do the SysRQ and SAK checking like this... */ diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 1f4443db5474..858c5dd926ad 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -462,8 +462,25 @@ extern void uart_insert_char(struct uart_port *port, unsigned int status, extern int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch); extern int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch); -extern void uart_unlock_and_check_sysrq(struct uart_port *port, - unsigned long irqflags); + +static inline void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags) +{ + int sysrq_ch; + + if (!port->has_sysrq) { + spin_unlock_irqrestore(&port->lock, irqflags); + return; + } + + sysrq_ch = port->sysrq_ch; + port->sysrq_ch = 0; + + spin_unlock_irqrestore(&port->lock, irqflags); + + if (sysrq_ch) + handle_sysrq(sysrq_ch); +} + extern int uart_handle_break(struct uart_port *port); /* -- 2.26.2