Skip to content
/ linux Public

Commit 0e16f46

Browse files
ij-intelgregkh
authored andcommitted
serial: 8250: Add late synchronize_irq() to shutdown to handle DW UART BUSY
commit e0a368a upstream. When DW UART is !uart_16550_compatible, it can indicate BUSY at any point (when under constant Rx pressure) unless a complex sequence of steps is performed. Any LCR write can run a foul with the condition that prevents writing LCR while the UART is BUSY, which triggers BUSY_DETECT interrupt that seems unmaskable using IER bits. Normal flow is that dw8250_handle_irq() handles BUSY_DETECT condition by reading USR register. This BUSY feature, however, breaks the assumptions made in serial8250_do_shutdown(), which runs synchronize_irq() after clearing IER and assumes no interrupts can occur after that point but then proceeds to update LCR, which on DW UART can trigger an interrupt. If serial8250_do_shutdown() releases the interrupt handler before the handler has run and processed the BUSY_DETECT condition by read the USR register, the IRQ is not deasserted resulting in interrupt storm that triggers "irq x: nobody cared" warning leading to disabling the IRQ. Add late synchronize_irq() into serial8250_do_shutdown() to ensure BUSY_DETECT from DW UART is handled before port's interrupt handler is released. Alternative would be to add DW UART specific shutdown function but it would mostly duplicate the generic code and the extra synchronize_irq() seems pretty harmless in serial8250_do_shutdown(). Fixes: 7d4008e ("tty: add a DesignWare 8250 driver") Cc: stable <stable@kernel.org> Reported-by: Bandal, Shankar <shankar.bandal@intel.com> Tested-by: Bandal, Shankar <shankar.bandal@intel.com> Tested-by: Murthy, Shanth <shanth.murthy@intel.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Link: https://patch.msgid.link/20260203171049.4353-7-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 5dfd8c7 commit 0e16f46

File tree

1 file changed

+6
-0
lines changed

1 file changed

+6
-0
lines changed

drivers/tty/serial/8250/8250_port.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2399,6 +2399,12 @@ void serial8250_do_shutdown(struct uart_port *port)
23992399
* the IRQ chain.
24002400
*/
24012401
serial_port_in(port, UART_RX);
2402+
/*
2403+
* LCR writes on DW UART can trigger late (unmaskable) IRQs.
2404+
* Handle them before releasing the handler.
2405+
*/
2406+
synchronize_irq(port->irq);
2407+
24022408
serial8250_rpm_put(up);
24032409

24042410
up->ops->release_irq(up);

0 commit comments

Comments
 (0)