aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/interface.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2025-10-11 11:56:47 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2025-10-11 11:56:47 -0700
commit98906f9d850e4882004749eccb8920649dc98456 (patch)
tree868d47f0bcda26f20eb7bf06437ab344738130e5 /drivers/rtc/interface.c
parentMerge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi (diff)
parentrtc: interface: Ensure alarm irq is enabled when UIE is enabled (diff)
downloadlinux-98906f9d850e4882004749eccb8920649dc98456.tar.gz
linux-98906f9d850e4882004749eccb8920649dc98456.zip
Merge tag 'rtc-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
Pull RTC updates from Alexandre Belloni: "This cycle, we have a new RTC driver, for the SpacemiT P1. The optee driver gets alarm support. We also get a fix for a race condition that was fairly rare unless while stress testing the alarms. Subsystem: - Fix race when setting alarm - Ensure alarm irq is enabled when UIE is enabled - remove unneeded 'fast_io' parameter in regmap_config New driver: - SpacemiT P1 RTC Drivers: - efi: Remove wakeup functionality - optee: add alarms support - s3c: Drop support for S3C2410 - zynqmp: Restore alarm functionality after kexec transition" * tag 'rtc-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (29 commits) rtc: interface: Ensure alarm irq is enabled when UIE is enabled rtc: tps6586x: Fix initial enable_irq/disable_irq balance rtc: cpcap: Fix initial enable_irq/disable_irq balance rtc: isl12022: Fix initial enable_irq/disable_irq balance rtc: interface: Fix long-standing race when setting alarm rtc: pcf2127: fix watchdog interrupt mask on pcf2131 rtc: zynqmp: Restore alarm functionality after kexec transition rtc: amlogic-a4: Optimize global variables rtc: sd2405al: Add I2C address. rtc: Kconfig: move symbols to proper section rtc: optee: make optee_rtc_pm_ops static rtc: optee: Fix error code in optee_rtc_read_alarm() rtc: optee: fix error code in probe() dt-bindings: rtc: Convert apm,xgene-rtc to DT schema rtc: spacemit: support the SpacemiT P1 RTC rtc: optee: add alarm related rtc ops to optee rtc driver rtc: optee: remove unnecessary memory operations rtc: optee: fix memory leak on driver removal rtc: x1205: Fix Xicor X1205 vendor prefix dt-bindings: rtc: Fix Xicor X1205 vendor prefix ...
Diffstat (limited to 'drivers/rtc/interface.c')
-rw-r--r--drivers/rtc/interface.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index dc741ba29fa3..b8b298efd9a9 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -443,6 +443,29 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
else
err = rtc->ops->set_alarm(rtc->dev.parent, alarm);
+ /*
+ * Check for potential race described above. If the waiting for next
+ * second, and the second just ticked since the check above, either
+ *
+ * 1) It ticked after the alarm was set, and an alarm irq should be
+ * generated.
+ *
+ * 2) It ticked before the alarm was set, and alarm irq most likely will
+ * not be generated.
+ *
+ * While we cannot easily check for which of these two scenarios we
+ * are in, we can return -ETIME to signal that the timer has already
+ * expired, which is true in both cases.
+ */
+ if ((scheduled - now) <= 1) {
+ err = __rtc_read_time(rtc, &tm);
+ if (err)
+ return err;
+ now = rtc_tm_to_time64(&tm);
+ if (scheduled <= now)
+ return -ETIME;
+ }
+
trace_rtc_set_alarm(rtc_tm_to_time64(&alarm->time), err);
return err;
}
@@ -594,6 +617,10 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled)
rtc->uie_rtctimer.node.expires = ktime_add(now, onesec);
rtc->uie_rtctimer.period = ktime_set(1, 0);
err = rtc_timer_enqueue(rtc, &rtc->uie_rtctimer);
+ if (!err && rtc->ops && rtc->ops->alarm_irq_enable)
+ err = rtc->ops->alarm_irq_enable(rtc->dev.parent, 1);
+ if (err)
+ goto out;
} else {
rtc_timer_remove(rtc, &rtc->uie_rtctimer);
}