8250.c: port.lock is irq-safe
authorBorislav Petkov <petkovbb@googlemail.com>
Wed, 30 Jul 2008 05:33:32 +0000 (22:33 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 30 Jul 2008 16:41:45 +0000 (09:41 -0700)
serial8250_startup() doesn't disable interrupts while taking the &up->port.lock
which might race against the interrupt handler serial8250_interrupt(), which
when entered, will deadlock waiting for the lock to be released.

Signed-off-by: Borislav Petkov <petkovbb@gmail.com>
Tested-by: Ingo Molnar <mingo@elte.hu>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/serial/8250.c

index a97f1ae11f786c5c81205fac0e12db6d45537d55..342e12fb1c2525f74bb15d0e21ca4e473962ecd1 100644 (file)
@@ -1885,7 +1885,7 @@ static int serial8250_startup(struct uart_port *port)
                 * the interrupt is enabled.  Delays are necessary to
                 * allow register changes to become visible.
                 */
-               spin_lock(&up->port.lock);
+               spin_lock_irqsave(&up->port.lock, flags);
                if (up->port.flags & UPF_SHARE_IRQ)
                        disable_irq_nosync(up->port.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);
-               spin_unlock(&up->port.lock);
+               spin_unlock_irqrestore(&up->port.lock, flags);
 
                /*
                 * If the interrupt is not reasserted, setup a timer to