[PATCH] clocksource/drivers/timer-atmel-pit: Fix mck reference leak in error paths
From: Wentao Liang
Date: Tue Sep 15 2026 - 01:00:53 EST
at91sam926x_pit_dt_init() obtains the mck clock with of_clk_get() but the
exit label only frees the pit_data, leaking the clock reference on every
error path that reaches it. Once the clock has been prepared and enabled,
later failures leave it enabled as well, and the clk_prepare_enable()
failure path leaks the reference even though the clock was never enabled.
Add disable_clk and put_clk labels so the mck reference is always
released on error: clk_put() when prepare+enable fails, and
clk_disable_unprepare() followed by clk_put() when aborting after the
clock has been enabled. Error paths before the clock is obtained keep
jumping to exit, and the success path keeps the clock enabled for the
lifetime of the timer.
Fixes: a17686c46244 ("clocksource/drivers/timer-atmel-pit: Drop at91sam926x_pit_common_init")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Wentao Liang <vulab@xxxxxxxxxxx>
---
drivers/clocksource/timer-atmel-pit.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c
index 888b06731e54..794b4ce4d700 100644
--- a/drivers/clocksource/timer-atmel-pit.c
+++ b/drivers/clocksource/timer-atmel-pit.c
@@ -191,7 +191,7 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
ret = clk_prepare_enable(data->mck);
if (ret) {
pr_err("Unable to enable mck\n");
- goto exit;
+ goto put_clk;
}
/* Get the interrupts property */
@@ -199,7 +199,7 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
if (!data->irq) {
pr_err("Unable to get IRQ from DT\n");
ret = -EINVAL;
- goto exit;
+ goto disable_clk;
}
/*
@@ -227,7 +227,7 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
ret = clocksource_register_hz(&data->clksrc, pit_rate);
if (ret) {
pr_err("Failed to register clocksource\n");
- goto exit;
+ goto disable_clk;
}
/* Set up irq handler */
@@ -237,7 +237,7 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
if (ret) {
pr_err("Unable to setup IRQ\n");
clocksource_unregister(&data->clksrc);
- goto exit;
+ goto disable_clk;
}
/* Set up and register clockevents */
@@ -256,6 +256,10 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
return 0;
+disable_clk:
+ clk_disable_unprepare(data->mck);
+put_clk:
+ clk_put(data->mck);
exit:
kfree(data);
return ret;
--
2.34.1