diff options
Diffstat (limited to 'kernel/time')
-rw-r--r-- | kernel/time/alarmtimer.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index aa27d391bfc8..54e7145c5414 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c | |||
@@ -46,6 +46,8 @@ static struct alarm_base { | |||
46 | static ktime_t freezer_delta; | 46 | static ktime_t freezer_delta; |
47 | static DEFINE_SPINLOCK(freezer_delta_lock); | 47 | static DEFINE_SPINLOCK(freezer_delta_lock); |
48 | 48 | ||
49 | static struct wakeup_source *ws; | ||
50 | |||
49 | #ifdef CONFIG_RTC_CLASS | 51 | #ifdef CONFIG_RTC_CLASS |
50 | /* rtc timer and device for setting alarm wakeups at suspend */ | 52 | /* rtc timer and device for setting alarm wakeups at suspend */ |
51 | static struct rtc_timer rtctimer; | 53 | static struct rtc_timer rtctimer; |
@@ -250,6 +252,7 @@ static int alarmtimer_suspend(struct device *dev) | |||
250 | unsigned long flags; | 252 | unsigned long flags; |
251 | struct rtc_device *rtc; | 253 | struct rtc_device *rtc; |
252 | int i; | 254 | int i; |
255 | int ret; | ||
253 | 256 | ||
254 | spin_lock_irqsave(&freezer_delta_lock, flags); | 257 | spin_lock_irqsave(&freezer_delta_lock, flags); |
255 | min = freezer_delta; | 258 | min = freezer_delta; |
@@ -279,8 +282,10 @@ static int alarmtimer_suspend(struct device *dev) | |||
279 | if (min.tv64 == 0) | 282 | if (min.tv64 == 0) |
280 | return 0; | 283 | return 0; |
281 | 284 | ||
282 | /* XXX - Should we enforce a minimum sleep time? */ | 285 | if (ktime_to_ns(min) < 2 * NSEC_PER_SEC) { |
283 | WARN_ON(min.tv64 < NSEC_PER_SEC); | 286 | __pm_wakeup_event(ws, 2 * MSEC_PER_SEC); |
287 | return -EBUSY; | ||
288 | } | ||
284 | 289 | ||
285 | /* Setup an rtc timer to fire that far in the future */ | 290 | /* Setup an rtc timer to fire that far in the future */ |
286 | rtc_timer_cancel(rtc, &rtctimer); | 291 | rtc_timer_cancel(rtc, &rtctimer); |
@@ -288,9 +293,11 @@ static int alarmtimer_suspend(struct device *dev) | |||
288 | now = rtc_tm_to_ktime(tm); | 293 | now = rtc_tm_to_ktime(tm); |
289 | now = ktime_add(now, min); | 294 | now = ktime_add(now, min); |
290 | 295 | ||
291 | rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0)); | 296 | /* Set alarm, if in the past reject suspend briefly to handle */ |
292 | 297 | ret = rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0)); | |
293 | return 0; | 298 | if (ret < 0) |
299 | __pm_wakeup_event(ws, MSEC_PER_SEC); | ||
300 | return ret; | ||
294 | } | 301 | } |
295 | #else | 302 | #else |
296 | static int alarmtimer_suspend(struct device *dev) | 303 | static int alarmtimer_suspend(struct device *dev) |
@@ -821,6 +828,7 @@ static int __init alarmtimer_init(void) | |||
821 | error = PTR_ERR(pdev); | 828 | error = PTR_ERR(pdev); |
822 | goto out_drv; | 829 | goto out_drv; |
823 | } | 830 | } |
831 | ws = wakeup_source_register("alarmtimer"); | ||
824 | return 0; | 832 | return 0; |
825 | 833 | ||
826 | out_drv: | 834 | out_drv: |