workaround serial hang with SMP enabled
[openwrt/staging/chunkeey.git] / target / linux / cns3xxx / patches-2.6.31 / 210-cns3xxx_smp_serial_fix.patch
1 --- a/drivers/serial/8250.c
2 +++ b/drivers/serial/8250.c
3 @@ -1743,6 +1743,7 @@ static void serial8250_backup_timeout(un
4 unsigned int iir, ier = 0, lsr;
5 unsigned long flags;
6
7 + spin_lock_irqsave(&up->port.lock, flags);
8 /*
9 * Must disable interrupts or else we risk racing with the interrupt
10 * based handler.
11 @@ -1760,10 +1761,8 @@ static void serial8250_backup_timeout(un
12 * the "Diva" UART used on the management processor on many HP
13 * ia64 and parisc boxes.
14 */
15 - spin_lock_irqsave(&up->port.lock, flags);
16 lsr = serial_in(up, UART_LSR);
17 up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
18 - spin_unlock_irqrestore(&up->port.lock, flags);
19 if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
20 (!uart_circ_empty(&up->port.info->xmit) || up->port.x_char) &&
21 (lsr & UART_LSR_THRE)) {
22 @@ -1771,12 +1770,14 @@ static void serial8250_backup_timeout(un
23 iir |= UART_IIR_THRI;
24 }
25
26 - if (!(iir & UART_IIR_NO_INT))
27 - serial8250_handle_port(up);
28 -
29 if (is_real_interrupt(up->port.irq))
30 serial_out(up, UART_IER, ier);
31
32 + spin_unlock_irqrestore(&up->port.lock, flags);
33 +
34 + if (!(iir & UART_IIR_NO_INT))
35 + serial8250_handle_port(up);
36 +
37 /* Standard timer interval plus 0.2s to keep the port running */
38 mod_timer(&up->timer,
39 jiffies + poll_timeout(up->port.timeout) + HZ / 5);