aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/alarmtimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time/alarmtimer.c')
-rw-r--r--kernel/time/alarmtimer.c158
1 files changed, 88 insertions, 70 deletions
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index 2d966244ea60..59f369f98a04 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -42,15 +42,75 @@ static struct alarm_base {
42 clockid_t base_clockid; 42 clockid_t base_clockid;
43} alarm_bases[ALARM_NUMTYPE]; 43} alarm_bases[ALARM_NUMTYPE];
44 44
45/* freezer delta & lock used to handle clock_nanosleep triggered wakeups */
46static ktime_t freezer_delta;
47static DEFINE_SPINLOCK(freezer_delta_lock);
48
45#ifdef CONFIG_RTC_CLASS 49#ifdef CONFIG_RTC_CLASS
46/* rtc timer and device for setting alarm wakeups at suspend */ 50/* rtc timer and device for setting alarm wakeups at suspend */
47static struct rtc_timer rtctimer; 51static struct rtc_timer rtctimer;
48static struct rtc_device *rtcdev; 52static struct rtc_device *rtcdev;
49#endif 53static DEFINE_SPINLOCK(rtcdev_lock);
50 54
51/* freezer delta & lock used to handle clock_nanosleep triggered wakeups */ 55/**
52static ktime_t freezer_delta; 56 * has_wakealarm - check rtc device has wakealarm ability
53static DEFINE_SPINLOCK(freezer_delta_lock); 57 * @dev: current device
58 * @name_ptr: name to be returned
59 *
60 * This helper function checks to see if the rtc device can wake
61 * from suspend.
62 */
63static int has_wakealarm(struct device *dev, void *name_ptr)
64{
65 struct rtc_device *candidate = to_rtc_device(dev);
66
67 if (!candidate->ops->set_alarm)
68 return 0;
69 if (!device_may_wakeup(candidate->dev.parent))
70 return 0;
71
72 *(const char **)name_ptr = dev_name(dev);
73 return 1;
74}
75
76/**
77 * alarmtimer_get_rtcdev - Return selected rtcdevice
78 *
79 * This function returns the rtc device to use for wakealarms.
80 * If one has not already been chosen, it checks to see if a
81 * functional rtc device is available.
82 */
83static struct rtc_device *alarmtimer_get_rtcdev(void)
84{
85 struct device *dev;
86 char *str;
87 unsigned long flags;
88 struct rtc_device *ret;
89
90 spin_lock_irqsave(&rtcdev_lock, flags);
91 if (!rtcdev) {
92 /* Find an rtc device and init the rtc_timer */
93 dev = class_find_device(rtc_class, NULL, &str, has_wakealarm);
94 /* If we have a device then str is valid. See has_wakealarm() */
95 if (dev) {
96 rtcdev = rtc_class_open(str);
97 /*
98 * Drop the reference we got in class_find_device,
99 * rtc_open takes its own.
100 */
101 put_device(dev);
102 rtc_timer_init(&rtctimer, NULL, NULL);
103 }
104 }
105 ret = rtcdev;
106 spin_unlock_irqrestore(&rtcdev_lock, flags);
107
108 return ret;
109}
110#else
111#define alarmtimer_get_rtcdev() (0)
112#define rtcdev (0)
113#endif
54 114
55 115
56/** 116/**
@@ -166,6 +226,7 @@ static int alarmtimer_suspend(struct device *dev)
166 struct rtc_time tm; 226 struct rtc_time tm;
167 ktime_t min, now; 227 ktime_t min, now;
168 unsigned long flags; 228 unsigned long flags;
229 struct rtc_device *rtc;
169 int i; 230 int i;
170 231
171 spin_lock_irqsave(&freezer_delta_lock, flags); 232 spin_lock_irqsave(&freezer_delta_lock, flags);
@@ -173,8 +234,9 @@ static int alarmtimer_suspend(struct device *dev)
173 freezer_delta = ktime_set(0, 0); 234 freezer_delta = ktime_set(0, 0);
174 spin_unlock_irqrestore(&freezer_delta_lock, flags); 235 spin_unlock_irqrestore(&freezer_delta_lock, flags);
175 236
237 rtc = rtcdev;
176 /* If we have no rtcdev, just return */ 238 /* If we have no rtcdev, just return */
177 if (!rtcdev) 239 if (!rtc)
178 return 0; 240 return 0;
179 241
180 /* Find the soonest timer to expire*/ 242 /* Find the soonest timer to expire*/
@@ -199,12 +261,12 @@ static int alarmtimer_suspend(struct device *dev)
199 WARN_ON(min.tv64 < NSEC_PER_SEC); 261 WARN_ON(min.tv64 < NSEC_PER_SEC);
200 262
201 /* Setup an rtc timer to fire that far in the future */ 263 /* Setup an rtc timer to fire that far in the future */
202 rtc_timer_cancel(rtcdev, &rtctimer); 264 rtc_timer_cancel(rtc, &rtctimer);
203 rtc_read_time(rtcdev, &tm); 265 rtc_read_time(rtc, &tm);
204 now = rtc_tm_to_ktime(tm); 266 now = rtc_tm_to_ktime(tm);
205 now = ktime_add(now, min); 267 now = ktime_add(now, min);
206 268
207 rtc_timer_start(rtcdev, &rtctimer, now, ktime_set(0, 0)); 269 rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0));
208 270
209 return 0; 271 return 0;
210} 272}
@@ -322,6 +384,9 @@ static int alarm_clock_getres(const clockid_t which_clock, struct timespec *tp)
322{ 384{
323 clockid_t baseid = alarm_bases[clock2alarm(which_clock)].base_clockid; 385 clockid_t baseid = alarm_bases[clock2alarm(which_clock)].base_clockid;
324 386
387 if (!alarmtimer_get_rtcdev())
388 return -ENOTSUPP;
389
325 return hrtimer_get_res(baseid, tp); 390 return hrtimer_get_res(baseid, tp);
326} 391}
327 392
@@ -336,6 +401,9 @@ static int alarm_clock_get(clockid_t which_clock, struct timespec *tp)
336{ 401{
337 struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)]; 402 struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)];
338 403
404 if (!alarmtimer_get_rtcdev())
405 return -ENOTSUPP;
406
339 *tp = ktime_to_timespec(base->gettime()); 407 *tp = ktime_to_timespec(base->gettime());
340 return 0; 408 return 0;
341} 409}
@@ -351,6 +419,9 @@ static int alarm_timer_create(struct k_itimer *new_timer)
351 enum alarmtimer_type type; 419 enum alarmtimer_type type;
352 struct alarm_base *base; 420 struct alarm_base *base;
353 421
422 if (!alarmtimer_get_rtcdev())
423 return -ENOTSUPP;
424
354 if (!capable(CAP_WAKE_ALARM)) 425 if (!capable(CAP_WAKE_ALARM))
355 return -EPERM; 426 return -EPERM;
356 427
@@ -385,6 +456,9 @@ static void alarm_timer_get(struct k_itimer *timr,
385 */ 456 */
386static int alarm_timer_del(struct k_itimer *timr) 457static int alarm_timer_del(struct k_itimer *timr)
387{ 458{
459 if (!rtcdev)
460 return -ENOTSUPP;
461
388 alarm_cancel(&timr->it.alarmtimer); 462 alarm_cancel(&timr->it.alarmtimer);
389 return 0; 463 return 0;
390} 464}
@@ -402,6 +476,9 @@ static int alarm_timer_set(struct k_itimer *timr, int flags,
402 struct itimerspec *new_setting, 476 struct itimerspec *new_setting,
403 struct itimerspec *old_setting) 477 struct itimerspec *old_setting)
404{ 478{
479 if (!rtcdev)
480 return -ENOTSUPP;
481
405 /* Save old values */ 482 /* Save old values */
406 old_setting->it_interval = 483 old_setting->it_interval =
407 ktime_to_timespec(timr->it.alarmtimer.period); 484 ktime_to_timespec(timr->it.alarmtimer.period);
@@ -541,6 +618,9 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
541 int ret = 0; 618 int ret = 0;
542 struct restart_block *restart; 619 struct restart_block *restart;
543 620
621 if (!alarmtimer_get_rtcdev())
622 return -ENOTSUPP;
623
544 if (!capable(CAP_WAKE_ALARM)) 624 if (!capable(CAP_WAKE_ALARM))
545 return -EPERM; 625 return -EPERM;
546 626
@@ -638,65 +718,3 @@ static int __init alarmtimer_init(void)
638} 718}
639device_initcall(alarmtimer_init); 719device_initcall(alarmtimer_init);
640 720
641#ifdef CONFIG_RTC_CLASS
642/**
643 * has_wakealarm - check rtc device has wakealarm ability
644 * @dev: current device
645 * @name_ptr: name to be returned
646 *
647 * This helper function checks to see if the rtc device can wake
648 * from suspend.
649 */
650static int __init has_wakealarm(struct device *dev, void *name_ptr)
651{
652 struct rtc_device *candidate = to_rtc_device(dev);
653
654 if (!candidate->ops->set_alarm)
655 return 0;
656 if (!device_may_wakeup(candidate->dev.parent))
657 return 0;
658
659 *(const char **)name_ptr = dev_name(dev);
660 return 1;
661}
662
663/**
664 * alarmtimer_init_late - Late initializing of alarmtimer code
665 *
666 * This function locates a rtc device to use for wakealarms.
667 * Run as late_initcall to make sure rtc devices have been
668 * registered.
669 */
670static int __init alarmtimer_init_late(void)
671{
672 struct device *dev;
673 char *str;
674
675 /* Find an rtc device and init the rtc_timer */
676 dev = class_find_device(rtc_class, NULL, &str, has_wakealarm);
677 /* If we have a device then str is valid. See has_wakealarm() */
678 if (dev) {
679 rtcdev = rtc_class_open(str);
680 /*
681 * Drop the reference we got in class_find_device,
682 * rtc_open takes its own.
683 */
684 put_device(dev);
685 }
686 if (!rtcdev) {
687 printk(KERN_WARNING "No RTC device found, ALARM timers will"
688 " not wake from suspend");
689 }
690 rtc_timer_init(&rtctimer, NULL, NULL);
691
692 return 0;
693}
694#else
695static int __init alarmtimer_init_late(void)
696{
697 printk(KERN_WARNING "Kernel not built with RTC support, ALARM timers"
698 " will not wake from suspend");
699 return 0;
700}
701#endif
702late_initcall(alarmtimer_init_late);