diff options
Diffstat (limited to 'drivers/rtc/interface.c')
-rw-r--r-- | drivers/rtc/interface.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 9a2bd4947007..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); @@ -561,7 +571,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); |