serial deadlock with SMP
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
linux (Ubuntu) |
Fix Released
|
High
|
Unassigned | ||
Hardy |
Fix Released
|
High
|
Andy Whitcroft |
Bug Description
Binary package hint: linux-image-
Upon switching from Dapper to Hardy, I noticed one of my systems kept getting serial timeouts. Upon further investigation, it seems that there is a serial deadlock issue in kernels < 2.6.27, where machines with multiple processors and multiple serial devices can call the serial interrupt handler at the same time and become deadlocked. This was fixed in 2.6.27 with 4 lines of code. I have created a patch with the same four line based on the linux-source-
The original discussion of this bug and the patch (by the usual kernel programmers) is at:
http://
Note, that the final fix in 2.6.27 keeps the lock and unlock lines as they were (the original discussion at the thread above changed them). My patch does not change them (as in the final 2.6.27 patch for this problem).
===
SRU Justification
Justification: Systems with multiple serial ports on the will deadlock losing serial output.
Impact: Systems may lose serial output including console output, particularly serious on servers.
Fix Description: Cherry-picked the upstream fixes for this, which introduces proper locking.
Patch:
http://
http://
Risks: This has been tested by the affected users to good effect. Risk should be low for normal use.
TEST CASE: See bug report.
description: | updated |
description: | updated |
Changed in linux: | |
assignee: | nobody → apw |
status: | Triaged → In Progress |
description: | updated |
Changed in linux: | |
status: | In Progress → Fix Committed |
Hi pbeeson,
Thanks for the report. I'll go ahead and open a Hardy nomination. I'm also including the git commit id's whose final patch result is what you have attached:
commit 768aec0b5bccbd4 60bcf6e9131f19b 5a26f3862d
Author: Anton Vorontsov <email address hidden>
serial: 8250: fix shared interrupts issues with SMP and RT kernels
diff --git a/drivers/ serial/ 8250.c b/drivers/ serial/ 8250.c serial/ 8250.c serial/ 8250.c startup( struct uart_port *port) irqsave( &up->port. lock, flags); &up->port. lock); irq_nosync( up->port. irq);
index ce948b6..27f34a9 100644
--- a/drivers/
+++ b/drivers/
@@ -1874,7 +1874,9 @@ static int serial8250_
* the interrupt is enabled. Delays are necessary to
* allow register changes to become visible.
*/
- spin_lock_
+ spin_lock(
+ if (up->port.flags & UPF_SHARE_IRQ)
+ disable_
@@ -1886,7 +1888,9 @@ static int serial8250_
iir = serial_in(up, UART_IIR);
- spin_unlock_ irqrestore( &up->port. lock, flags); irq(up- >port.irq) ; &up->port. lock);
+ if (up->port.flags & UPF_SHARE_IRQ)
+ enable_
+ spin_unlock(
/*
* If the interrupt is not reasserted, setup a timer to
commit c389d27b5e643d7 45f55ffb939b142 6060ba63d4
Author: Borislav Petkov <email address hidden>
8250.c: port.lock is irq-safe
diff --git a/drivers/ serial/ 8250.c b/drivers/ serial/ 8250.c serial/ 8250.c serial/ 8250.c startup( struct uart_port *port) &up->port. lock); irqsave( &up->port. lock, flags);
disable_ irq_nosync( up->port. irq);
index a97f1ae..342e12f 100644
--- a/drivers/
+++ b/drivers/
@@ -1885,7 +1885,7 @@ static int serial8250_
* the interrupt is enabled. Delays are necessary to
* allow register changes to become visible.
*/
- spin_lock(
+ spin_lock_
if (up->port.flags & UPF_SHARE_IRQ)
@@ -1901,7 +1901,7 @@ static int serial8250_ startup( struct uart_port *port)
if (up->port.flags & UPF_SHARE_IRQ)
enable_ irq(up- >port.irq) ; &up->port. lock); irqrestore( &up->port. lock, flags);
- spin_unlock(
+ spin_unlock_
/*
* If the interrupt is not reasserted, setup a timer to