diff options
author | Zeng Zhaoming <b32542@freescale.com> | 2011-08-04 09:07:32 +0800 |
---|---|---|
committer | Zeng Zhaoming <b32542@freescale.com> | 2011-08-04 09:34:09 +0800 |
commit | b3448d7dba355334ace56f951bbe841010f22269 (patch) | |
tree | 286f86cf7d6499ca88af9b866da0fe8615bef029 /drivers | |
parent | 4bef2dd07584d2902ca7ea23a5c7455b79ad40a3 (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.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 995a3dceb811..21516c8fa031 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) |