aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2012-01-05 18:21:19 -0500
committerJohn Stultz <john.stultz@linaro.org>2012-01-26 22:41:30 -0500
commitbd729d72b428261f2975360e0c117d7d7a2cd6e8 (patch)
tree73ebfff880ba7d96cb5d82e0811b0476ab310c16 /drivers/rtc
parenta99cbf6b43a7b3b15f6139b2d9ac4ecceccd3c99 (diff)
rtc: Avoid setting alarm to a time in the past
In some cases at boot up, the RTC alarm may be set in the past, but still have the enabled flag on. This was causing problems, because we would then enqueue the alarm into the timerqueue, but it would never fire. This would clog up the timerqueue and keep other alarms from working. The fix is to check the alarm against the current rtc time at boot and avoid enqueueing the alarm if it is in the past. Reported-by: NeilBrown <neilb@suse.de> Tested-by: NeilBrown <neilb@suse.de> Tested-by: Sander Eikelenboom <linux@eikelenboom.it> Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/interface.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 8a1c031391d6..c55a16041b6e 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -380,18 +380,27 @@ EXPORT_SYMBOL_GPL(rtc_set_alarm);
380int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) 380int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
381{ 381{
382 int err; 382 int err;
383 struct rtc_time now;
383 384
384 err = rtc_valid_tm(&alarm->time); 385 err = rtc_valid_tm(&alarm->time);
385 if (err != 0) 386 if (err != 0)
386 return err; 387 return err;
387 388
389 err = rtc_read_time(rtc, &now);
390 if (err)
391 return err;
392
388 err = mutex_lock_interruptible(&rtc->ops_lock); 393 err = mutex_lock_interruptible(&rtc->ops_lock);
389 if (err) 394 if (err)
390 return err; 395 return err;
391 396
392 rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); 397 rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time);
393 rtc->aie_timer.period = ktime_set(0, 0); 398 rtc->aie_timer.period = ktime_set(0, 0);
394 if (alarm->enabled) { 399
400 /* Alarm has to be enabled & in the futrure for us to enqueue it */
401 if (alarm->enabled && (rtc_tm_to_ktime(now).tv64 <
402 rtc->aie_timer.node.expires.tv64)) {
403
395 rtc->aie_timer.enabled = 1; 404 rtc->aie_timer.enabled = 1;
396 timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node); 405 timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node);
397 } 406 }