serial: 8250: fix handle_irq locking
The 8250 handle_irq callback is not just called from the interrupt
handler but also from a timer callback when polling (e.g. for ports
without an interrupt line). Consequently the callback must explicitly
disable interrupts to avoid a potential deadlock with another interrupt
in polled mode.
Add back an irqrestore-version of the sysrq port-unlock helper and use
it in the 8250 callbacks that need it.
Fixes: 75f4e830fa ("serial: do not restore interrupt state in sysrq helper")
Cc: stable@vger.kernel.org # 5.13
Cc: Joel Stanley <joel@jms.id.au>
Cc: Andrew Jeffery <andrew@aj.id.au>
Reported-by: kernel test robot <oliver.sang@intel.com>
Signed-off-by: Johan Hovold <johan@kernel.org>
Link: https://lore.kernel.org/r/20210714080427.28164-1-johan@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
cc9ca4d958
commit
853a9ae29e
4 changed files with 33 additions and 6 deletions
|
|
@ -518,6 +518,25 @@ static inline void uart_unlock_and_check_sysrq(struct uart_port *port)
|
|||
if (sysrq_ch)
|
||||
handle_sysrq(sysrq_ch);
|
||||
}
|
||||
|
||||
static inline void uart_unlock_and_check_sysrq_irqrestore(struct uart_port *port,
|
||||
unsigned long flags)
|
||||
{
|
||||
int sysrq_ch;
|
||||
|
||||
if (!port->has_sysrq) {
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
sysrq_ch = port->sysrq_ch;
|
||||
port->sysrq_ch = 0;
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
if (sysrq_ch)
|
||||
handle_sysrq(sysrq_ch);
|
||||
}
|
||||
#else /* CONFIG_MAGIC_SYSRQ_SERIAL */
|
||||
static inline int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
|
||||
{
|
||||
|
|
@ -531,6 +550,11 @@ static inline void uart_unlock_and_check_sysrq(struct uart_port *port)
|
|||
{
|
||||
spin_unlock(&port->lock);
|
||||
}
|
||||
static inline void uart_unlock_and_check_sysrq_irqrestore(struct uart_port *port,
|
||||
unsigned long flags)
|
||||
{
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
#endif /* CONFIG_MAGIC_SYSRQ_SERIAL */
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue