]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
rtc: isl1208: Balance enable_irq_wake() with disable_irq_wake() on cleanup
authorJohn Madieu <john.madieu.xa@bp.renesas.com>
Sat, 25 Apr 2026 15:49:59 +0000 (15:49 +0000)
committerAlexandre Belloni <alexandre.belloni@bootlin.com>
Mon, 22 Jun 2026 21:28:57 +0000 (23:28 +0200)
isl1208_setup_irq() calls enable_irq_wake() after a successful
IRQ request, but the driver has no remove path that balances it.
The driver is devm-only, so on unbind devm releases the IRQ -
but enable_irq_wake() is not undone by IRQ release, so the wake
count for that IRQ stays incremented.

Each rebind therefore leaks one wake reference; the leak doubles
for the chip variant that has a separate evdet IRQ, since
isl1208_setup_irq() is then called twice during probe.

Register a devm action that calls disable_irq_wake() per IRQ.
While at it, check enable_irq_wake()'s return value:
on failure, propagate the error rather than silently registering
a disable action for an IRQ whose wake state was never enabled.

Fixes: 9ece7cd833a3 ("rtc: isl1208: Add "evdet" interrupt source for isl1219")
Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
Link: https://patch.msgid.link/20260425154959.2796261-3-john.madieu.xa@bp.renesas.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
drivers/rtc/rtc-isl1208.c

index bcaa766a506865f21f7efc7ea3a1e00beab79dff..9bdd5d12157188973ce4b2983b2ee13e64abc278 100644 (file)
@@ -822,6 +822,11 @@ static const struct nvmem_config isl1208_nvmem_config = {
        .reg_write = isl1208_nvmem_write,
 };
 
+static void isl1208_disable_irq_wake_action(void *data)
+{
+       disable_irq_wake((unsigned long)data);
+}
+
 static int isl1208_setup_irq(struct i2c_client *client, int irq)
 {
        int rc = devm_request_threaded_irq(&client->dev, irq, NULL,
@@ -831,7 +836,15 @@ static int isl1208_setup_irq(struct i2c_client *client, int irq)
                                        client);
        if (!rc) {
                device_init_wakeup(&client->dev, true);
-               enable_irq_wake(irq);
+               rc = enable_irq_wake(irq);
+               if (rc)
+                       return rc;
+
+               rc = devm_add_action_or_reset(&client->dev,
+                                             isl1208_disable_irq_wake_action,
+                                             (void *)(unsigned long)irq);
+               if (rc)
+                       return rc;
        } else {
                dev_err(&client->dev,
                        "Unable to request irq %d, no alarm support\n",