Skip to content

Commit

Permalink
alarmtimer: Implement minimum alarm interval for allowing suspend
Browse files Browse the repository at this point in the history
alarmtimer suspend return -EBUSY if the next alarm will fire in less
than 2 seconds.  This allows one RTC seconds tick to occur subsequent
to this check before the alarm wakeup time is set, ensuring the wakeup
time is still in the future (assuming the RTC does not tick one more
second prior to setting the alarm).

If suspend is rejected due to an imminent alarm, hold a wakeup source
for 2 seconds to process the alarm prior to reattempting suspend.

If setting the alarm incurs an -ETIME for an alarm set in the past,
or any other problem setting the alarm, abort suspend and hold a
wakelock for 1 second while the alarm is allowed to be serviced or
other hopefully transient conditions preventing the alarm clear up.

Signed-off-by: Todd Poynor <toddpoynor@google.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
  • Loading branch information
Todd Poynor authored and John Stultz committed Sep 24, 2012
1 parent ec145ba commit 59a93c2
Showing 1 changed file with 13 additions and 5 deletions.
18 changes: 13 additions & 5 deletions kernel/time/alarmtimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ static struct alarm_base {
static ktime_t freezer_delta;
static DEFINE_SPINLOCK(freezer_delta_lock);

static struct wakeup_source *ws;

#ifdef CONFIG_RTC_CLASS
/* rtc timer and device for setting alarm wakeups at suspend */
static struct rtc_timer rtctimer;
Expand Down Expand Up @@ -250,6 +252,7 @@ static int alarmtimer_suspend(struct device *dev)
unsigned long flags;
struct rtc_device *rtc;
int i;
int ret;

spin_lock_irqsave(&freezer_delta_lock, flags);
min = freezer_delta;
Expand Down Expand Up @@ -279,18 +282,22 @@ static int alarmtimer_suspend(struct device *dev)
if (min.tv64 == 0)
return 0;

/* XXX - Should we enforce a minimum sleep time? */
WARN_ON(min.tv64 < NSEC_PER_SEC);
if (ktime_to_ns(min) < 2 * NSEC_PER_SEC) {
__pm_wakeup_event(ws, 2 * MSEC_PER_SEC);
return -EBUSY;
}

/* Setup an rtc timer to fire that far in the future */
rtc_timer_cancel(rtc, &rtctimer);
rtc_read_time(rtc, &tm);
now = rtc_tm_to_ktime(tm);
now = ktime_add(now, min);

rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0));

return 0;
/* Set alarm, if in the past reject suspend briefly to handle */
ret = rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0));
if (ret < 0)
__pm_wakeup_event(ws, MSEC_PER_SEC);
return ret;
}
#else
static int alarmtimer_suspend(struct device *dev)
Expand Down Expand Up @@ -821,6 +828,7 @@ static int __init alarmtimer_init(void)
error = PTR_ERR(pdev);
goto out_drv;
}
ws = wakeup_source_register("alarmtimer");
return 0;

out_drv:
Expand Down

0 comments on commit 59a93c2

Please sign in to comment.