[PATCH] rtc: mt7622: allocate the RTC before requesting its IRQ
From: Myeonghun Pak
Date: Sat Oct 17 2026 - 23:44:56 EST
The alarm handler passes hw->rtc to rtc_update_irq(). Currently, the
managed IRQ is requested before the RTC is allocated. On detach, devres
unregisters the RTC and drops its allocation reference before freeing the
IRQ. If no other references remain, the RTC can be freed while the alarm
handler is still registered or running.
Allocate the RTC before requesting the IRQ, and initialize the hardware
and RTC operations before installing the handler. Register the RTC last,
once these dependencies are ready. Managed cleanup then unregisters the
RTC, frees the IRQ and waits for running handlers, and finally drops the
RTC allocation reference. The final irqwork cancellation therefore runs
after the IRQ producer has stopped.
This issue was identified as part of our ongoing research while
reviewing kernel code.
Fixes: ba5d018135ef ("rtc: mediatek: add driver for RTC on MT7622 SoC")
Assisted-by: LLM
Co-developed-by: Ijae Kim <ae878000@xxxxxxxxx>
Signed-off-by: Ijae Kim <ae878000@xxxxxxxxx>
Signed-off-by: Myeonghun Pak <mhun512@xxxxxxxxx>
---
Compile-tested with Clang, W=1. No hardware runtime testing.
Based on mainline 0fcb05b72344f40806cbe810de8872f1698bf053.
diff --git a/drivers/rtc/rtc-mt7622.c b/drivers/rtc/rtc-mt7622.c
index 9e17dd09d567..c86c8cf3f2d7 100644
--- a/drivers/rtc/rtc-mt7622.c
+++ b/drivers/rtc/rtc-mt7622.c
@@ -324,11 +324,20 @@
if (ret)
return ret;
+ hw->rtc = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(hw->rtc)) {
+ ret = PTR_ERR(hw->rtc);
+ goto err;
+ }
+
hw->irq = platform_get_irq(pdev, 0);
if (hw->irq < 0) {
ret = hw->irq;
goto err;
}
+
+ mtk_rtc_hw_init(hw);
+ hw->rtc->ops = &mtk_rtc_ops;
ret = devm_request_irq(&pdev->dev, hw->irq, mtk_rtc_alarmirq,
0, dev_name(&pdev->dev), hw);
@@ -337,14 +346,10 @@
goto err;
}
- mtk_rtc_hw_init(hw);
-
device_init_wakeup(&pdev->dev, true);
- hw->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
- &mtk_rtc_ops, THIS_MODULE);
- if (IS_ERR(hw->rtc)) {
- ret = PTR_ERR(hw->rtc);
+ ret = devm_rtc_register_device(hw->rtc);
+ if (ret) {
dev_err(&pdev->dev, "Unable to register device\n");
goto err;
}