diff options
author | Mark Brown <broonie@sirena.org.uk> | 2009-04-14 06:06:49 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-04-15 05:01:02 -0400 |
commit | 41609ff43005de11dadfb0ccadb344f0e2966829 (patch) | |
tree | a84bf697eb3f1d2535c9f243e71308caa53939e6 /drivers/serial | |
parent | 9fa264d0d327a67db4913b400bcfb174d929054c (diff) |
[ARM] 5449/1: S3C: Use disable_irq_nosync() to fix boot lockups
With 2.6.30-rc1 on SMDK6410 I experience a soft lockup on bootup when
the Samsung serial driver attempts to disable the transmit interrupt
from within the transmit interrupt handler: it calls disable_irq()
which locks up due to attempting to synchronise with the running handler.
Fix this by using disable_irq_nosync().
Also make the same change in the recieve path.
Backtrace:
[<c002a914>] (__irq_svc+0x34/0x80) from [<c00696c0>] (synchr)
[<c00696c0>] (synchronize_irq+0xc/0xcc) from [<c018d434>] (s)
[<c018d434>] (s3c24xx_serial_stop_tx+0x1c/0x3c) from [<c018d)
[<c018d54c>] (s3c24xx_serial_tx_chars+0xf8/0x104) from [<c00)
[<c0068bcc>] (handle_IRQ_event+0x74/0x118) from [<c006ab04>])
[<c006ab04>] (handle_level_irq+0x100/0x118) from [<c00349c4>)
[<c00349c4>] (s3c_irq_demux_uart+0x94/0xc4) from [<c002a050>)
[<c002a050>] (_text+0x50/0x6c) from [<c002a914>] (__irq_svc+)
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/samsung.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c index 41ac94872b8d..e06686ae858b 100644 --- a/drivers/serial/samsung.c +++ b/drivers/serial/samsung.c | |||
@@ -127,7 +127,7 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port) | |||
127 | struct s3c24xx_uart_port *ourport = to_ourport(port); | 127 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
128 | 128 | ||
129 | if (tx_enabled(port)) { | 129 | if (tx_enabled(port)) { |
130 | disable_irq(ourport->tx_irq); | 130 | disable_irq_nosync(ourport->tx_irq); |
131 | tx_enabled(port) = 0; | 131 | tx_enabled(port) = 0; |
132 | if (port->flags & UPF_CONS_FLOW) | 132 | if (port->flags & UPF_CONS_FLOW) |
133 | s3c24xx_serial_rx_enable(port); | 133 | s3c24xx_serial_rx_enable(port); |
@@ -154,7 +154,7 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port) | |||
154 | 154 | ||
155 | if (rx_enabled(port)) { | 155 | if (rx_enabled(port)) { |
156 | dbg("s3c24xx_serial_stop_rx: port=%p\n", port); | 156 | dbg("s3c24xx_serial_stop_rx: port=%p\n", port); |
157 | disable_irq(ourport->rx_irq); | 157 | disable_irq_nosync(ourport->rx_irq); |
158 | rx_enabled(port) = 0; | 158 | rx_enabled(port) = 0; |
159 | } | 159 | } |
160 | } | 160 | } |