If owl_port->clk was enabled in owl_uart_probe(), it must be disabled in all error paths to ensure proper cleanup. However, if uart_add_one_port() returns an error in owl_uart_probe(), the owl_port->clk clock will not be disabled.
Use the devm_clk_get_enabled() helper function to ensure proper call balance for owl_port->clk.
Found by Linux Verification Center (linuxtesting.org) with Klever.
Fixes: abf42d2f333b ("tty: serial: owl: add "much needed" clk_prepare_enable()") Cc: stable@vger.kernel.org Signed-off-by: Vitalii Mordan mordan@ispras.ru --- drivers/tty/serial/owl-uart.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-)
diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c index 0542882cfbbe..64446820437c 100644 --- a/drivers/tty/serial/owl-uart.c +++ b/drivers/tty/serial/owl-uart.c @@ -680,18 +680,12 @@ static int owl_uart_probe(struct platform_device *pdev) if (!owl_port) return -ENOMEM;
- owl_port->clk = devm_clk_get(&pdev->dev, NULL); + owl_port->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(owl_port->clk)) { - dev_err(&pdev->dev, "could not get clk\n"); + dev_err(&pdev->dev, "could not get and enable clk\n"); return PTR_ERR(owl_port->clk); }
- ret = clk_prepare_enable(owl_port->clk); - if (ret) { - dev_err(&pdev->dev, "could not enable clk\n"); - return ret; - } - owl_port->port.dev = &pdev->dev; owl_port->port.line = pdev->id; owl_port->port.type = PORT_OWL; @@ -701,7 +695,6 @@ static int owl_uart_probe(struct platform_device *pdev) owl_port->port.uartclk = clk_get_rate(owl_port->clk); if (owl_port->port.uartclk == 0) { dev_err(&pdev->dev, "clock rate is zero\n"); - clk_disable_unprepare(owl_port->clk); return -EINVAL; } owl_port->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_LOW_LATENCY; @@ -725,7 +718,6 @@ static void owl_uart_remove(struct platform_device *pdev)
uart_remove_one_port(&owl_uart_driver, &owl_port->port); owl_uart_ports[pdev->id] = NULL; - clk_disable_unprepare(owl_port->clk); }
static struct platform_driver owl_uart_platform_driver = {
On Thu, Feb 13, 2025 at 02:24:16PM +0300, Vitalii Mordan wrote:
If owl_port->clk was enabled in owl_uart_probe(), it must be disabled in all error paths to ensure proper cleanup. However, if uart_add_one_port() returns an error in owl_uart_probe(), the owl_port->clk clock will not be disabled.
Use the devm_clk_get_enabled() helper function to ensure proper call balance for owl_port->clk.
Do not use newly introduced APIs to fix old bugs. The bug should be fixed separately to allow backporting and the conversion should be done on top.
- Mani
Found by Linux Verification Center (linuxtesting.org) with Klever.
Fixes: abf42d2f333b ("tty: serial: owl: add "much needed" clk_prepare_enable()") Cc: stable@vger.kernel.org Signed-off-by: Vitalii Mordan mordan@ispras.ru
drivers/tty/serial/owl-uart.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-)
diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c index 0542882cfbbe..64446820437c 100644 --- a/drivers/tty/serial/owl-uart.c +++ b/drivers/tty/serial/owl-uart.c @@ -680,18 +680,12 @@ static int owl_uart_probe(struct platform_device *pdev) if (!owl_port) return -ENOMEM;
- owl_port->clk = devm_clk_get(&pdev->dev, NULL);
- owl_port->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(owl_port->clk)) {
dev_err(&pdev->dev, "could not get clk\n");
return PTR_ERR(owl_port->clk); }dev_err(&pdev->dev, "could not get and enable clk\n");
- ret = clk_prepare_enable(owl_port->clk);
- if (ret) {
dev_err(&pdev->dev, "could not enable clk\n");
return ret;
- }
- owl_port->port.dev = &pdev->dev; owl_port->port.line = pdev->id; owl_port->port.type = PORT_OWL;
@@ -701,7 +695,6 @@ static int owl_uart_probe(struct platform_device *pdev) owl_port->port.uartclk = clk_get_rate(owl_port->clk); if (owl_port->port.uartclk == 0) { dev_err(&pdev->dev, "clock rate is zero\n");
return -EINVAL; } owl_port->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_LOW_LATENCY;clk_disable_unprepare(owl_port->clk);
@@ -725,7 +718,6 @@ static void owl_uart_remove(struct platform_device *pdev) uart_remove_one_port(&owl_uart_driver, &owl_port->port); owl_uart_ports[pdev->id] = NULL;
- clk_disable_unprepare(owl_port->clk);
} static struct platform_driver owl_uart_platform_driver = { -- 2.25.1
On Fri, 14. Feb 22:44, Manivannan Sadhasivam wrote:
On Thu, Feb 13, 2025 at 02:24:16PM +0300, Vitalii Mordan wrote:
If owl_port->clk was enabled in owl_uart_probe(), it must be disabled in all error paths to ensure proper cleanup. However, if uart_add_one_port() returns an error in owl_uart_probe(), the owl_port->clk clock will not be disabled.
Use the devm_clk_get_enabled() helper function to ensure proper call balance for owl_port->clk.
Do not use newly introduced APIs to fix old bugs. The bug should be fixed separately to allow backporting and the conversion should be done on top.
These relatively new helpers are already available in all currently supported stable kernels including 5.4.y.
Commit 7ef9651e9792 ("clk: Provide new devm_clk helpers for prepared and enabled clocks") was conveniently backported there as a dependency for the similar bug fixes.
On Fri, Feb 14, 2025 at 09:39:09PM +0300, Fedor Pchelkin wrote:
On Fri, 14. Feb 22:44, Manivannan Sadhasivam wrote:
On Thu, Feb 13, 2025 at 02:24:16PM +0300, Vitalii Mordan wrote:
If owl_port->clk was enabled in owl_uart_probe(), it must be disabled in all error paths to ensure proper cleanup. However, if uart_add_one_port() returns an error in owl_uart_probe(), the owl_port->clk clock will not be disabled.
Use the devm_clk_get_enabled() helper function to ensure proper call balance for owl_port->clk.
Do not use newly introduced APIs to fix old bugs. The bug should be fixed separately to allow backporting and the conversion should be done on top.
These relatively new helpers are already available in all currently supported stable kernels including 5.4.y.
Commit 7ef9651e9792 ("clk: Provide new devm_clk helpers for prepared and enabled clocks") was conveniently backported there as a dependency for the similar bug fixes.
Ah, then fine with me.
- Mani
On Thu, Feb 13, 2025 at 02:24:16PM +0300, Vitalii Mordan wrote:
If owl_port->clk was enabled in owl_uart_probe(), it must be disabled in all error paths to ensure proper cleanup. However, if uart_add_one_port() returns an error in owl_uart_probe(), the owl_port->clk clock will not be disabled.
Use the devm_clk_get_enabled() helper function to ensure proper call balance for owl_port->clk.
Found by Linux Verification Center (linuxtesting.org) with Klever.
Fixes: abf42d2f333b ("tty: serial: owl: add "much needed" clk_prepare_enable()") Cc: stable@vger.kernel.org Signed-off-by: Vitalii Mordan mordan@ispras.ru
Reviewed-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org
- Mani
drivers/tty/serial/owl-uart.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-)
diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c index 0542882cfbbe..64446820437c 100644 --- a/drivers/tty/serial/owl-uart.c +++ b/drivers/tty/serial/owl-uart.c @@ -680,18 +680,12 @@ static int owl_uart_probe(struct platform_device *pdev) if (!owl_port) return -ENOMEM;
- owl_port->clk = devm_clk_get(&pdev->dev, NULL);
- owl_port->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(owl_port->clk)) {
dev_err(&pdev->dev, "could not get clk\n");
return PTR_ERR(owl_port->clk); }dev_err(&pdev->dev, "could not get and enable clk\n");
- ret = clk_prepare_enable(owl_port->clk);
- if (ret) {
dev_err(&pdev->dev, "could not enable clk\n");
return ret;
- }
- owl_port->port.dev = &pdev->dev; owl_port->port.line = pdev->id; owl_port->port.type = PORT_OWL;
@@ -701,7 +695,6 @@ static int owl_uart_probe(struct platform_device *pdev) owl_port->port.uartclk = clk_get_rate(owl_port->clk); if (owl_port->port.uartclk == 0) { dev_err(&pdev->dev, "clock rate is zero\n");
return -EINVAL; } owl_port->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_LOW_LATENCY;clk_disable_unprepare(owl_port->clk);
@@ -725,7 +718,6 @@ static void owl_uart_remove(struct platform_device *pdev) uart_remove_one_port(&owl_uart_driver, &owl_port->port); owl_uart_ports[pdev->id] = NULL;
- clk_disable_unprepare(owl_port->clk);
} static struct platform_driver owl_uart_platform_driver = { -- 2.25.1
linux-stable-mirror@lists.linaro.org