diff options
| author | John Madieu <john.madieu.xa@bp.renesas.com> | 2026-04-25 15:49:59 +0000 |
|---|---|---|
| committer | Alexandre Belloni <alexandre.belloni@bootlin.com> | 2026-06-22 23:28:57 +0200 |
| commit | 1afe4f19d6ad404621150f0e91feeccf12fb1037 (patch) | |
| tree | 376cc68bd49d46e84b30aa9edbdfb927d8240613 /drivers/rtc | |
| parent | 041ca8884410a4f70b40521f34258c7b773ea5c2 (diff) | |
| download | linux-next-1afe4f19d6ad404621150f0e91feeccf12fb1037.tar.gz linux-next-1afe4f19d6ad404621150f0e91feeccf12fb1037.zip | |
rtc: isl1208: Balance enable_irq_wake() with disable_irq_wake() on cleanup
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>
Diffstat (limited to 'drivers/rtc')
| -rw-r--r-- | drivers/rtc/rtc-isl1208.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index bcaa766a5068..9bdd5d121571 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -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", |
