Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2119

kernel-2.6.18-238.el5.src.rpm

From: Brian Maly <bmaly@redhat.com>
Date: Thu, 19 Jun 2008 17:52:27 -0400
Subject: [misc] ttyS1 lost interrupt, stops transmitting v2
Message-id: 485AD51B.7070307@redhat.com
O-Subject: [RHEL5.3 patch] Stratus 5.3: ttyS1 lost interrupt and it stops transmitting
Bugzilla: 451157
RH-Acked-by: Alan Cox <alan@redhat.com>

resolves BZ's  440121, 451157

This is a follow up patch on behalf of Stratus. There was a previous
patch for this issue already posted (by Stratus) and committed into
RHEL5 (BZ 440121). This patch caused a regression (BZ 451157) which was
a lockdep warning "circular locking dependency detected". I have been
asked to take over this issue on behalf of Stratus, so I am posting this
follow up patch so as to resolve the regression the initial patch
caused. The history of this issue is somewhat confusing and there has
been much discussion on how to correctly solve this issue. I believe the
patch Im attaching was the final patch agreed on by all as acceptable.
This new patch has locking re-ordered to prevent deadlock. This patch
has been tested (on HP and IBM blades) and has been confirmed to resolve
the issue.

Brian

 drivers/serial/8250.c |   18 ++++++++++--------
 1 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 85d29a1..96eec5c 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -1762,7 +1762,11 @@ static int serial8250_startup(struct uart_port *port)
 	 */
 	serial_outp(up, UART_LCR, UART_LCR_WLEN8);
 
-	spin_lock_irqsave(&up->port.lock, flags);
+	if (is_real_interrupt(up->port.irq)) {
+		spin_lock_irqsave(&irq_lists[up->port.irq].lock, flags);
+		spin_lock(&up->port.lock);
+	} else
+		spin_lock_irqsave(&up->port.lock, flags);
 	if (up->port.flags & UPF_FOURPORT) {
 		if (!is_real_interrupt(up->port.irq))
 			up->port.mctrl |= TIOCM_OUT1;
@@ -1779,17 +1783,11 @@ static int serial8250_startup(struct uart_port *port)
 	 * Do a quick test to see if we receive an
 	 * interrupt when we enable the TX irq.
 	 */
-	if (is_real_interrupt(up->port.irq))
-		spin_lock(&irq_lists[up->port.irq].lock);
-
 	serial_outp(up, UART_IER, UART_IER_THRI);
 	lsr = serial_in(up, UART_LSR);
 	iir = serial_in(up, UART_IIR);
 	serial_outp(up, UART_IER, 0);
 
-	if (is_real_interrupt(up->port.irq))
-		spin_unlock(&irq_lists[up->port.irq].lock);
-
 	if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
 		if (!(up->bugs & UART_BUG_TXEN)) {
 			up->bugs |= UART_BUG_TXEN;
@@ -1800,7 +1798,11 @@ static int serial8250_startup(struct uart_port *port)
 		up->bugs &= ~UART_BUG_TXEN;
 	}
 
-	spin_unlock_irqrestore(&up->port.lock, flags);
+	if (is_real_interrupt(up->port.irq)) {
+		spin_unlock(&up->port.lock);
+		spin_unlock_irqrestore(&irq_lists[up->port.irq].lock, flags);
+	} else
+		spin_unlock_irqrestore(&up->port.lock, flags);
 
 	/*
 	 * Finally, enable interrupts.  Note: Modem status interrupts