DORMANTno replies

[PATCH 2/6] clocksource/drivers/mxs_timer: Fix clock reference leak in mxs_timer_init

From: Wentao Liang <hidden>
Date: 2026-09-15 05:17:56
Also in: imx, lkml, stable
Subsystem: clocksource, clockevent drivers, the rest · Maintainers: Daniel Lezcano, Thomas Gleixner, Linus Torvalds

mxs_timer_init() looks up the timer clock with of_clk_get(), which takes
a reference on the clock, but no clk_put() exists anywhere in the
driver. The reference is leaked on every return path after the clock
has been obtained:

- clk_prepare_enable() failure,
- mxs_clocksource_init() failure,
- mxs_clockevent_init() failure,
- irq_of_parse_and_map() failure,
- request_irq() failure,
- and on success, where the clock is intentionally left enabled for the
  timer but the local timer_clk pointer is lost.

Add proper error unwinding: on failure of clk_prepare_enable() only the
reference is dropped, on the later error paths the clock is disabled and
unprepared before the reference is dropped, and on success the reference
is dropped while keeping the clock enabled.

Fixes: 2efb950465e9 ("ARM: mxs: look up timrot clock from device tree")
Cc: stable@vger.kernel.org
Signed-off-by: Wentao Liang <redacted>
---
 drivers/clocksource/mxs_timer.c | 30 +++++++++++++++++++++++-------
 1 file changed, 23 insertions(+), 7 deletions(-)
diff --git a/drivers/clocksource/mxs_timer.c b/drivers/clocksource/mxs_timer.c
index e52e12d27d2a..dd58d7505797 100644
--- a/drivers/clocksource/mxs_timer.c
+++ b/drivers/clocksource/mxs_timer.c
@@ -215,8 +215,10 @@ static int __init mxs_timer_init(struct device_node *np)
 	}
 
 	ret = clk_prepare_enable(timer_clk);
-	if (ret)
+	if (ret) {
+		clk_put(timer_clk);
 		return ret;
+	}
 
 	/*
 	 * Initialize timers to a known state
@@ -256,18 +258,32 @@ static int __init mxs_timer_init(struct device_node *np)
 	/* init and register the timer to the framework */
 	ret = mxs_clocksource_init(timer_clk);
 	if (ret)
-		return ret;
+		goto err_clk_disable;
 
 	ret = mxs_clockevent_init(timer_clk);
 	if (ret)
-		return ret;
+		goto err_clk_disable;
 
 	/* Make irqs happen */
 	irq = irq_of_parse_and_map(np, 0);
-	if (irq <= 0)
-		return -EINVAL;
+	if (irq <= 0) {
+		ret = -EINVAL;
+		goto err_clk_disable;
+	}
+
+	ret = request_irq(irq, mxs_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL,
+			  "MXS Timer Tick", &mxs_clockevent_device);
+	if (ret)
+		goto err_clk_disable;
+
+	clk_put(timer_clk);
+
+	return 0;
+
+err_clk_disable:
+	clk_disable_unprepare(timer_clk);
+	clk_put(timer_clk);
 
-	return request_irq(irq, mxs_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL,
-			   "MXS Timer Tick", &mxs_clockevent_device);
+	return ret;
 }
 TIMER_OF_DECLARE(mxs, "fsl,timrot", mxs_timer_init);
-- 
2.34.1

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help