|
@@ -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;
|
|
@@ -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;
|
|
@@ -279,8 +282,10 @@ 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);
|
|
@@ -288,9 +293,11 @@ static int alarmtimer_suspend(struct device *dev)
|
|
|
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)
|
|
@@ -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:
|