aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/cns3xxx/patches-2.6.31/210-cns3xxx_smp_serial_fix.patch
blob: a9b45aefe561f1e34305107decf94134e20d5a70 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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);