diff options
author | Rabin Vincent <rabin.vincent@stericsson.com> | 2011-11-22 05:03:14 -0500 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2011-11-22 22:25:43 -0500 |
commit | c0afabd3d553c521e003779c127143ffde55a16f (patch) | |
tree | 5a4a93f244e2e9cbc87f24958de3e83397f978fb /drivers/rtc/interface.c | |
parent | 27c9cd7e601632b3794e1c3344d37b86917ffb43 (diff) |
rtc: Disable the alarm in the hardware
Currently, the RTC code does not disable the alarm in the hardware.
This means that after a sequence such as the one below (the files are in the
RTC sysfs), the box will boot up after 2 minutes even though we've
asked for the alarm to be turned off.
# echo $((`cat since_epoch`)+120) > wakealarm
# echo 0 > wakealarm
# poweroff
Fix this by disabling the alarm when there are no timers to run.
Cc: stable@kernel.org
Cc: John Stultz <john.stultz@linaro.org>
Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'drivers/rtc/interface.c')
-rw-r--r-- | drivers/rtc/interface.c | 44 |
1 files changed, 34 insertions, 10 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 3195dbd3ec34..e3cf2f54221f 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
@@ -318,6 +318,20 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
318 | } | 318 | } |
319 | EXPORT_SYMBOL_GPL(rtc_read_alarm); | 319 | EXPORT_SYMBOL_GPL(rtc_read_alarm); |
320 | 320 | ||
321 | static int ___rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | ||
322 | { | ||
323 | int err; | ||
324 | |||
325 | if (!rtc->ops) | ||
326 | err = -ENODEV; | ||
327 | else if (!rtc->ops->set_alarm) | ||
328 | err = -EINVAL; | ||
329 | else | ||
330 | err = rtc->ops->set_alarm(rtc->dev.parent, alarm); | ||
331 | |||
332 | return err; | ||
333 | } | ||
334 | |||
321 | static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | 335 | static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
322 | { | 336 | { |
323 | struct rtc_time tm; | 337 | struct rtc_time tm; |
@@ -341,14 +355,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
341 | * over right here, before we set the alarm. | 355 | * over right here, before we set the alarm. |
342 | */ | 356 | */ |
343 | 357 | ||
344 | if (!rtc->ops) | 358 | return ___rtc_set_alarm(rtc, alarm); |
345 | err = -ENODEV; | ||
346 | else if (!rtc->ops->set_alarm) | ||
347 | err = -EINVAL; | ||
348 | else | ||
349 | err = rtc->ops->set_alarm(rtc->dev.parent, alarm); | ||
350 | |||
351 | return err; | ||
352 | } | 359 | } |
353 | 360 | ||
354 | int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | 361 | int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
@@ -762,6 +769,20 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) | |||
762 | return 0; | 769 | return 0; |
763 | } | 770 | } |
764 | 771 | ||
772 | static void rtc_alarm_disable(struct rtc_device *rtc) | ||
773 | { | ||
774 | struct rtc_wkalrm alarm; | ||
775 | struct rtc_time tm; | ||
776 | |||
777 | __rtc_read_time(rtc, &tm); | ||
778 | |||
779 | alarm.time = rtc_ktime_to_tm(ktime_add(rtc_tm_to_ktime(tm), | ||
780 | ktime_set(300, 0))); | ||
781 | alarm.enabled = 0; | ||
782 | |||
783 | ___rtc_set_alarm(rtc, &alarm); | ||
784 | } | ||
785 | |||
765 | /** | 786 | /** |
766 | * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue | 787 | * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue |
767 | * @rtc rtc device | 788 | * @rtc rtc device |
@@ -783,8 +804,10 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) | |||
783 | struct rtc_wkalrm alarm; | 804 | struct rtc_wkalrm alarm; |
784 | int err; | 805 | int err; |
785 | next = timerqueue_getnext(&rtc->timerqueue); | 806 | next = timerqueue_getnext(&rtc->timerqueue); |
786 | if (!next) | 807 | if (!next) { |
808 | rtc_alarm_disable(rtc); | ||
787 | return; | 809 | return; |
810 | } | ||
788 | alarm.time = rtc_ktime_to_tm(next->expires); | 811 | alarm.time = rtc_ktime_to_tm(next->expires); |
789 | alarm.enabled = 1; | 812 | alarm.enabled = 1; |
790 | err = __rtc_set_alarm(rtc, &alarm); | 813 | err = __rtc_set_alarm(rtc, &alarm); |
@@ -846,7 +869,8 @@ again: | |||
846 | err = __rtc_set_alarm(rtc, &alarm); | 869 | err = __rtc_set_alarm(rtc, &alarm); |
847 | if (err == -ETIME) | 870 | if (err == -ETIME) |
848 | goto again; | 871 | goto again; |
849 | } | 872 | } else |
873 | rtc_alarm_disable(rtc); | ||
850 | 874 | ||
851 | mutex_unlock(&rtc->ops_lock); | 875 | mutex_unlock(&rtc->ops_lock); |
852 | } | 876 | } |