aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorImre Kaloz <kaloz@openwrt.org>2010-08-09 11:27:14 +0000
committerImre Kaloz <kaloz@openwrt.org>2010-08-09 11:27:14 +0000
commit16478f7dd6f30eb6580470e026ab32fdd572e2af (patch)
tree567f408ee5be92378e092d4f8346853b816241a7
parent0f5d0f69ab14d9817c16147cef0a1a537a1cc8c4 (diff)
downloadupstream-16478f7dd6f30eb6580470e026ab32fdd572e2af.tar.gz
upstream-16478f7dd6f30eb6580470e026ab32fdd572e2af.tar.bz2
upstream-16478f7dd6f30eb6580470e026ab32fdd572e2af.zip
workaround serial hang with SMP enabled
SVN-Revision: 22557
-rw-r--r--target/linux/cns3xxx/patches-2.6.31/210-cns3xxx_smp_serial_fix.patch39
1 files changed, 39 insertions, 0 deletions
diff --git a/target/linux/cns3xxx/patches-2.6.31/210-cns3xxx_smp_serial_fix.patch b/target/linux/cns3xxx/patches-2.6.31/210-cns3xxx_smp_serial_fix.patch
new file mode 100644
index 0000000000..a9b45aefe5
--- /dev/null
+++ b/target/linux/cns3xxx/patches-2.6.31/210-cns3xxx_smp_serial_fix.patch
@@ -0,0 +1,39 @@
+--- a/drivers/serial/8250.c
++++ b/drivers/serial/8250.c
+@@ -1743,6 +1743,7 @@ static void serial8250_backup_timeout(un
+ unsigned int iir, ier = 0, lsr;
+ unsigned long flags;
+
++ spin_lock_irqsave(&up->port.lock, flags);
+ /*
+ * Must disable interrupts or else we risk racing with the interrupt
+ * based handler.
+@@ -1760,10 +1761,8 @@ static void serial8250_backup_timeout(un
+ * the "Diva" UART used on the management processor on many HP
+ * ia64 and parisc boxes.
+ */
+- spin_lock_irqsave(&up->port.lock, flags);
+ lsr = serial_in(up, UART_LSR);
+ up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+- spin_unlock_irqrestore(&up->port.lock, flags);
+ if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
+ (!uart_circ_empty(&up->port.info->xmit) || up->port.x_char) &&
+ (lsr & UART_LSR_THRE)) {
+@@ -1771,12 +1770,14 @@ static void serial8250_backup_timeout(un
+ iir |= UART_IIR_THRI;
+ }
+
+- if (!(iir & UART_IIR_NO_INT))
+- serial8250_handle_port(up);
+-
+ if (is_real_interrupt(up->port.irq))
+ serial_out(up, UART_IER, ier);
+
++ spin_unlock_irqrestore(&up->port.lock, flags);
++
++ if (!(iir & UART_IIR_NO_INT))
++ serial8250_handle_port(up);
++
+ /* Standard timer interval plus 0.2s to keep the port running */
+ mod_timer(&up->timer,
+ jiffies + poll_timeout(up->port.timeout) + HZ / 5);