diff options
author | Fugang Duan <fugang.duan@nxp.com> | 2020-11-11 10:51:36 +0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-11-24 13:29:20 +0100 |
commit | 772ff2c77cce7a84f3dc69d5dcb848cb02227352 (patch) | |
tree | 5f70fb65aec6d1dfe4c96dc2c301654e01b93d45 /drivers/tty | |
parent | 663f70f1f5e733867a7f8cf7afef73abebd9576d (diff) | |
download | linux-stable-772ff2c77cce7a84f3dc69d5dcb848cb02227352.tar.gz linux-stable-772ff2c77cce7a84f3dc69d5dcb848cb02227352.tar.bz2 linux-stable-772ff2c77cce7a84f3dc69d5dcb848cb02227352.zip |
tty: serial: imx: keep console clocks always on
commit e67c139c488e84e7eae6c333231e791f0e89b3fb upstream.
For below code, there has chance to cause deadlock in SMP system:
Thread 1:
clk_enable_lock();
pr_info("debug message");
clk_enable_unlock();
Thread 2:
imx_uart_console_write()
clk_enable()
clk_enable_lock();
Thread 1:
Acuired clk enable_lock -> printk -> console_trylock_spinning
Thread 2:
console_unlock() -> imx_uart_console_write -> clk_disable -> Acquite clk enable_lock
So the patch is to keep console port clocks always on like
other console drivers.
Fixes: 1cf93e0d5488 ("serial: imx: remove the uart_console() check")
Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
Link: https://lore.kernel.org/r/20201111025136.29818-1-fugang.duan@nxp.com
Cc: stable <stable@vger.kernel.org>
[fix up build warning - gregkh]
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/serial/imx.c | 20 |
1 files changed, 3 insertions, 17 deletions
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index f7e80ad4de1b..e5ed4ab2b08d 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1942,16 +1942,6 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count) unsigned int ucr1; unsigned long flags = 0; int locked = 1; - int retval; - - retval = clk_enable(sport->clk_per); - if (retval) - return; - retval = clk_enable(sport->clk_ipg); - if (retval) { - clk_disable(sport->clk_per); - return; - } if (sport->port.sysrq) locked = 0; @@ -1987,9 +1977,6 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count) if (locked) spin_unlock_irqrestore(&sport->port.lock, flags); - - clk_disable(sport->clk_ipg); - clk_disable(sport->clk_per); } /* @@ -2090,15 +2077,14 @@ imx_uart_console_setup(struct console *co, char *options) retval = uart_set_options(&sport->port, co, baud, parity, bits, flow); - clk_disable(sport->clk_ipg); if (retval) { - clk_unprepare(sport->clk_ipg); + clk_disable_unprepare(sport->clk_ipg); goto error_console; } - retval = clk_prepare(sport->clk_per); + retval = clk_prepare_enable(sport->clk_per); if (retval) - clk_unprepare(sport->clk_ipg); + clk_disable_unprepare(sport->clk_ipg); error_console: return retval; |