[PATCH] pinctrl: stm32: Fix reset control leak in stm32_pctl_probe() error paths

From: Xiangwu Lai

Date: Tue Nov 10 2026 - 02:05:52 EST


stm32_pctl_probe() acquires an exclusive reset control for every GPIO
bank with of_reset_control_get_exclusive(), but none of the error
paths release them again: the bank loop returns directly on
-EPROBE_DEFER and on a failed clock lookup, and the
clk_bulk_prepare_enable() failure and the err_register path also
leave the already acquired reset controls behind.

On success the reset controls are kept for the lifetime of the device
and are never released either (the driver has no .remove), but that
is harmless. On a failed probe, and in particular when the probe is
retried after -EPROBE_DEFER, every attempt leaks another set of
reset control references.

Release the acquired reset controls on all error paths.

Fixes: bb949ed9b16b ("pinctrl: stm32: Switch to use for_each_gpiochip_node() helper")
Signed-off-by: laixiangwu <laixiangwu@xxxxxxxxxxxxxxxxxxxx>
---
drivers/pinctrl/stm32/pinctrl-stm32.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index 98cf9c6f4..49a8dcc9e 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -1966,15 +1966,17 @@ int stm32_pctl_probe(struct platform_device *pdev)
bank->rstc = of_reset_control_get_exclusive(np, NULL);
if (PTR_ERR(bank->rstc) == -EPROBE_DEFER) {
fwnode_handle_put(child);
- return -EPROBE_DEFER;
+ ret = -EPROBE_DEFER;
+ goto err_put_rstcs;
}

pctl->clks[i].clk = of_clk_get_by_name(np, NULL);
if (IS_ERR(pctl->clks[i].clk)) {
fwnode_handle_put(child);
clk_bulk_put(i, pctl->clks);
- return dev_err_probe(dev, PTR_ERR(pctl->clks[i].clk),
- "failed to get clk\n");
+ ret = dev_err_probe(dev, PTR_ERR(pctl->clks[i].clk),
+ "failed to get clk\n");
+ goto err_put_rstcs;
}
pctl->clks[i].id = "pctl";
i++;
@@ -1984,7 +1986,7 @@ int stm32_pctl_probe(struct platform_device *pdev)
if (ret) {
dev_err(dev, "failed to prepare_enable clk (%d)\n", ret);
clk_bulk_put(banks, pctl->clks);
- return ret;
+ goto err_put_rstcs;
}

for_each_gpiochip_node(dev, child) {
@@ -2009,6 +2011,10 @@ int stm32_pctl_probe(struct platform_device *pdev)

clk_bulk_disable_unprepare(banks, pctl->clks);
clk_bulk_put(banks, pctl->clks);
+err_put_rstcs:
+ for (i = 0; i < banks; i++)
+ if (!IS_ERR_OR_NULL(pctl->banks[i].rstc))
+ reset_control_put(pctl->banks[i].rstc);
return ret;
}
EXPORT_SYMBOL(stm32_pctl_probe);