From: Fugang Duan fugang.duan@nxp.com
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 --- drivers/tty/serial/imx.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-)
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 4066cb2b79cb..7a6e26b12bf6 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1915,16 +1915,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; @@ -1960,9 +1950,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); }
/* @@ -2063,15 +2050,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;