aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorZeng Zhaoming <b32542@freescale.com>2011-08-04 09:07:32 +0800
committerZeng Zhaoming <b32542@freescale.com>2011-08-04 09:34:09 +0800
commitb3448d7dba355334ace56f951bbe841010f22269 (patch)
tree286f86cf7d6499ca88af9b866da0fe8615bef029 /drivers
parent4bef2dd07584d2902ca7ea23a5c7455b79ad40a3 (diff)
ENGR00154346 UART: fix uart deadlock
UART hold the following locks in order of: imx_set_termios(): --> spin_lock_irqsave(&sport->port.lock, flags) del_timer_sync(&sport->timer); --> spin_lock(timer->base->lock); --> spin_unlock(timer->base->lock); spin_unlock_irqrestore(&sport->port.lock); while when imx_timeout() may invoked in following stack: run_timer_softirq(): --> spin_lock_irqsave(timer->base->lock, flags); imx_timeout(); --> spin_lock_irqsave(&sport->port.lock, flags); ...; --> spin_unlock_irqrestore(&sport->port.lock, flags); spin_unlock_irqrestore(timer->base->lock, flags); the above two cases hold lock with revert order, may deadlock in SMP platform. Signed-off-by: Zeng Zhaoming <b32542@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/tty/serial/imx.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 995a3dceb81..21516c8fa03 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -852,6 +852,8 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
quot = uart_get_divisor(port, baud);
+ del_timer_sync(&sport->timer);
+
spin_lock_irqsave(&sport->port.lock, flags);
sport->port.read_status_mask = 0;
@@ -876,8 +878,6 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
sport->port.ignore_status_mask |= URXD_OVRRUN;
}
- del_timer_sync(&sport->timer);
-
/*
* Update the per-port timeout.
*/
@@ -941,10 +941,10 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
/* set the parity, stop bits and data size */
writel(ucr2 | old_txrxen, sport->port.membase + UCR2);
+ spin_unlock_irqrestore(&sport->port.lock, flags);
+
if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
imx_enable_ms(&sport->port);
-
- spin_unlock_irqrestore(&sport->port.lock, flags);
}
static const char *imx_type(struct uart_port *port)