Skip to content

Commit 33f1685

Browse files
Sam Nobsgregkh
authored andcommitted
tty: serial: imx: fix potential deadlock
Enabling the lock dependency validator has revealed that the way spinlocks are used in the IMX serial port could result in a deadlock. Specifically, imx_uart_int() acquires a spinlock without disabling the interrupts, meaning that another interrupt could come along and try to acquire the same spinlock, potentially causing the two to wait for each other indefinitely. Use spin_lock_irqsave() instead to disable interrupts upon acquisition of the spinlock. Fixes: c974991 ("tty:serial:imx: use spin_lock instead of spin_lock_irqsave in isr") Reviewed-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Signed-off-by: Sam Nobs <samuel.nobs@taitradio.com> Link: https://lore.kernel.org/r/1604955006-9363-1-git-send-email-samuel.nobs@taitradio.com Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent f8394f2 commit 33f1685

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

drivers/tty/serial/imx.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -942,8 +942,14 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id)
942942
struct imx_port *sport = dev_id;
943943
unsigned int usr1, usr2, ucr1, ucr2, ucr3, ucr4;
944944
irqreturn_t ret = IRQ_NONE;
945+
unsigned long flags = 0;
945946

946-
spin_lock(&sport->port.lock);
947+
/*
948+
* IRQs might not be disabled upon entering this interrupt handler,
949+
* e.g. when interrupt handlers are forced to be threaded. To support
950+
* this scenario as well, disable IRQs when acquiring the spinlock.
951+
*/
952+
spin_lock_irqsave(&sport->port.lock, flags);
947953

948954
usr1 = imx_uart_readl(sport, USR1);
949955
usr2 = imx_uart_readl(sport, USR2);
@@ -1013,7 +1019,7 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id)
10131019
ret = IRQ_HANDLED;
10141020
}
10151021

1016-
spin_unlock(&sport->port.lock);
1022+
spin_unlock_irqrestore(&sport->port.lock, flags);
10171023

10181024
return ret;
10191025
}

0 commit comments

Comments
 (0)