From adb17a053e460f20740d713c4843d6966e66b1b1 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 18 Oct 2021 17:23:36 +0200 Subject: rtc: expose RTC_FEATURE_UPDATE_INTERRUPT Set RTC_FEATURE_UPDATE_INTERRUPT by default and clear it when it is not supported. Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20211018152337.78732-1-alexandre.belloni@bootlin.com --- drivers/rtc/interface.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/rtc/interface.c') diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 9a2bd4947007..d005623e6eb3 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -561,7 +561,8 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) if (rtc->uie_rtctimer.enabled == enabled) goto out; - if (rtc->uie_unsupported || !test_bit(RTC_FEATURE_ALARM, rtc->features)) { + if (!test_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features) || + !test_bit(RTC_FEATURE_ALARM, rtc->features)) { mutex_unlock(&rtc->ops_lock); #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL return rtc_dev_update_irq_enable_emul(rtc, enabled); -- cgit From d87f741dddabd670a82bccf94ac73cec80209bc0 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sun, 7 Nov 2021 23:54:46 +0100 Subject: rtc: handle alarms with a minute resolution Handle alarms with a minute resolution in the core. Until now drivers have been open coding the seconds part removal and have been doing that wrongly. Most of them are rounding up which means the allow the system to miss deadlines. So, round down and let __rtc_set_alarm return immediately if the time has already passed. Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20211107225458.111068-1-alexandre.belloni@bootlin.com --- drivers/rtc/interface.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/rtc/interface.c') diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index d005623e6eb3..d8e835798153 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -423,6 +423,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) if (err) return err; now = rtc_tm_to_time64(&tm); + if (scheduled <= now) return -ETIME; /* @@ -447,6 +448,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) { + ktime_t alarm_time; int err; if (!rtc->ops) @@ -468,7 +470,15 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) if (rtc->aie_timer.enabled) rtc_timer_remove(rtc, &rtc->aie_timer); - rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); + alarm_time = rtc_tm_to_ktime(alarm->time); + /* + * Round down so we never miss a deadline, checking for past deadline is + * done in __rtc_set_alarm + */ + if (test_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features)) + alarm_time = ktime_sub_ns(alarm_time, (u64)alarm->time.tm_sec * NSEC_PER_SEC); + + rtc->aie_timer.node.expires = alarm_time; rtc->aie_timer.period = 0; if (alarm->enabled) err = rtc_timer_enqueue(rtc, &rtc->aie_timer); -- cgit