| From e67c139c488e84e7eae6c333231e791f0e89b3fb Mon Sep 17 00:00:00 2001 |
| From: Fugang Duan <fugang.duan@nxp.com> |
| Date: Wed, 11 Nov 2020 10:51:36 +0800 |
| Subject: tty: serial: imx: keep console clocks always on |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| 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(-) |
| |
| --- a/drivers/tty/serial/imx.c |
| +++ b/drivers/tty/serial/imx.c |
| @@ -1915,16 +1915,6 @@ imx_uart_console_write(struct console *c |
| 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 *c |
| |
| 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 *c |
| |
| 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; |