summaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorMatteo Facchinetti <matteo.facchinetti@sirius-es.it>2013-06-12 09:21:42 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-06-17 21:49:43 +0200
commit8a29dfb8b67fbea03e084370d93fc99cbf375535 (patch)
treed099b48f3e5841de25770c4180a059df4323d6f9 /drivers/tty
parentserial: mfd: Add sysrq support (diff)
downloadlinux-8a29dfb8b67fbea03e084370d93fc99cbf375535.tar.xz
linux-8a29dfb8b67fbea03e084370d93fc99cbf375535.zip
serial/mpc52xx_uart: fix kernel panic when system reboot
This bug appear when a second PSC based driver appends an interrupt routine to the FIFO controller shared interrupt (like spi-mpc512x-psc). When reboot, uart_shutdown() remove the serial console interrupt handler while spi-mpc512x-psc isr is still activate and cause the following kernel panic: The system is going down for reboot NOW!rpc (ttyPSC0) (Mon Jun 10 12:26:07 20 INIT: Sending processirq 40: nobody cared (try booting with the "irqpoll" option) CPU: 0 PID: 0 Comm: swapper Not tainted 3.10.0-rc4-next-20130607-00001-ga0bceb3-dirty #5 Call Trace: [cfff9f00] [c0007910] show_stack+0x48/0x150 (unreliable) [cfff9f40] [c005ae60] __report_bad_irq.isra.6+0x34/0xe0 [cfff9f60] [c005b194] note_interrupt+0x214/0x26c [cfff9f90] [c00590fc] handle_irq_event_percpu+0xd0/0x1bc [cfff9fd0] [c005921c] handle_irq_event+0x34/0x54 [cfff9fe0] [c005b8f4] handle_level_irq+0x90/0xf4 [cfff9ff0] [c000cb98] call_handle_irq+0x18/0x28 [c050dd60] [c000575c] do_IRQ+0xcc/0x124 [c050dd90] [c000eb04] ret_from_except+0x0/0x14 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/serial/mpc52xx_uart.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 9ba194590a80..e1280a20b7a2 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -1058,6 +1058,9 @@ mpc52xx_uart_shutdown(struct uart_port *port)
if (psc_ops->clock)
psc_ops->clock(port, 0);
+ /* Disable interrupt */
+ psc_ops->cw_disable_ints(port);
+
/* Release interrupt */
free_irq(port->irq, port);
}