[PATCH 2/2] gpio: rockchip: fix teardown bugs and resource leaks
Marco Scardovi (scardracs)
scardracs at disroot.org
Mon May 25 09:39:39 PDT 2026
This commit addresses several teardown issues and resource leaks in the
driver's remove path and error handling:
1. Debounce clock reference leak: The debounce clock (bank->db_clk) was
obtained using of_clk_get() which increments the clock's reference
count, but clk_put() was never called. A devm action is now registered
to cleanly release it on unbind. Note that of_clk_get(..., 1) remains
necessary over devm_clk_get() because the DT binding does not define
clock-names, precluding name-based lookup.
2. Unregistered chained IRQ handler: The chained IRQ handler was not
disconnected in remove(). If a stray interrupt fired after the driver
was removed, the kernel would attempt to execute a stale handler,
leading to a panic. This is fixed by clearing the handler in remove().
3. IRQ domain leak: The linear IRQ domain and its generic chips were
allocated manually during probe but never removed. The IRQ domain is
now removed during driver teardown to free the associated generic chips
and mappings.
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Marco Scardovi <scardracs at disroot.org>
---
drivers/gpio/gpio-rockchip.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
index 33580093a4e7..c804f970d823 100644
--- a/drivers/gpio/gpio-rockchip.c
+++ b/drivers/gpio/gpio-rockchip.c
@@ -638,10 +638,17 @@ static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank)
return ret;
}
+static void rockchip_clk_put(void *data)
+{
+ struct clk *clk = data;
+
+ clk_put(clk);
+}
+
static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
{
struct resource res;
- int id = 0;
+ int id = 0, ret;
if (of_address_to_resource(bank->of_node, 0, &res)) {
dev_err(bank->dev, "cannot find IO resource for bank\n");
@@ -673,6 +680,13 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
dev_err(bank->dev, "cannot find debounce clk\n");
return -EINVAL;
}
+
+ ret = devm_add_action_or_reset(bank->dev, rockchip_clk_put,
+ bank->db_clk);
+ if (ret) {
+ dev_err(bank->dev, "failed to register debounce clk action\n");
+ return ret;
+ }
break;
case GPIO_TYPE_V1:
bank->gpio_regs = &gpio_regs_v1;
@@ -789,6 +803,9 @@ static void rockchip_gpio_remove(struct platform_device *pdev)
{
struct rockchip_pin_bank *bank = platform_get_drvdata(pdev);
+ irq_set_chained_handler_and_data(bank->irq, NULL, NULL);
+ if (bank->domain)
+ irq_domain_remove(bank->domain);
gpiochip_remove(&bank->gpio_chip);
}
--
2.54.0
More information about the linux-arm-kernel
mailing list