diff options
Diffstat (limited to 'kernel/time/alarmtimer.c')
-rw-r--r-- | kernel/time/alarmtimer.c | 720 |
1 files changed, 720 insertions, 0 deletions
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c new file mode 100644 index 000000000000..59f369f98a04 --- /dev/null +++ b/kernel/time/alarmtimer.c | |||
@@ -0,0 +1,720 @@ | |||
1 | /* | ||
2 | * Alarmtimer interface | ||
3 | * | ||
4 | * This interface provides a timer which is similarto hrtimers, | ||
5 | * but triggers a RTC alarm if the box is suspend. | ||
6 | * | ||
7 | * This interface is influenced by the Android RTC Alarm timer | ||
8 | * interface. | ||
9 | * | ||
10 | * Copyright (C) 2010 IBM Corperation | ||
11 | * | ||
12 | * Author: John Stultz <john.stultz@linaro.org> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | */ | ||
18 | #include <linux/time.h> | ||
19 | #include <linux/hrtimer.h> | ||
20 | #include <linux/timerqueue.h> | ||
21 | #include <linux/rtc.h> | ||
22 | #include <linux/alarmtimer.h> | ||
23 | #include <linux/mutex.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/posix-timers.h> | ||
26 | #include <linux/workqueue.h> | ||
27 | #include <linux/freezer.h> | ||
28 | |||
29 | /** | ||
30 | * struct alarm_base - Alarm timer bases | ||
31 | * @lock: Lock for syncrhonized access to the base | ||
32 | * @timerqueue: Timerqueue head managing the list of events | ||
33 | * @timer: hrtimer used to schedule events while running | ||
34 | * @gettime: Function to read the time correlating to the base | ||
35 | * @base_clockid: clockid for the base | ||
36 | */ | ||
37 | static struct alarm_base { | ||
38 | spinlock_t lock; | ||
39 | struct timerqueue_head timerqueue; | ||
40 | struct hrtimer timer; | ||
41 | ktime_t (*gettime)(void); | ||
42 | clockid_t base_clockid; | ||
43 | } alarm_bases[ALARM_NUMTYPE]; | ||
44 | |||
45 | /* freezer delta & lock used to handle clock_nanosleep triggered wakeups */ | ||
46 | static ktime_t freezer_delta; | ||
47 | static DEFINE_SPINLOCK(freezer_delta_lock); | ||
48 | |||
49 | #ifdef CONFIG_RTC_CLASS | ||
50 | /* rtc timer and device for setting alarm wakeups at suspend */ | ||
51 | static struct rtc_timer rtctimer; | ||
52 | static struct rtc_device *rtcdev; | ||
53 | static DEFINE_SPINLOCK(rtcdev_lock); | ||
54 | |||
55 | /** | ||
56 | * has_wakealarm - check rtc device has wakealarm ability | ||
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 | */ | ||
63 | static 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 | */ | ||
83 | static 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 | ||
114 | |||
115 | |||
116 | /** | ||
117 | * alarmtimer_enqueue - Adds an alarm timer to an alarm_base timerqueue | ||
118 | * @base: pointer to the base where the timer is being run | ||
119 | * @alarm: pointer to alarm being enqueued. | ||
120 | * | ||
121 | * Adds alarm to a alarm_base timerqueue and if necessary sets | ||
122 | * an hrtimer to run. | ||
123 | * | ||
124 | * Must hold base->lock when calling. | ||
125 | */ | ||
126 | static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm) | ||
127 | { | ||
128 | timerqueue_add(&base->timerqueue, &alarm->node); | ||
129 | if (&alarm->node == timerqueue_getnext(&base->timerqueue)) { | ||
130 | hrtimer_try_to_cancel(&base->timer); | ||
131 | hrtimer_start(&base->timer, alarm->node.expires, | ||
132 | HRTIMER_MODE_ABS); | ||
133 | } | ||
134 | } | ||
135 | |||
136 | /** | ||
137 | * alarmtimer_remove - Removes an alarm timer from an alarm_base timerqueue | ||
138 | * @base: pointer to the base where the timer is running | ||
139 | * @alarm: pointer to alarm being removed | ||
140 | * | ||
141 | * Removes alarm to a alarm_base timerqueue and if necessary sets | ||
142 | * a new timer to run. | ||
143 | * | ||
144 | * Must hold base->lock when calling. | ||
145 | */ | ||
146 | static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm) | ||
147 | { | ||
148 | struct timerqueue_node *next = timerqueue_getnext(&base->timerqueue); | ||
149 | |||
150 | timerqueue_del(&base->timerqueue, &alarm->node); | ||
151 | if (next == &alarm->node) { | ||
152 | hrtimer_try_to_cancel(&base->timer); | ||
153 | next = timerqueue_getnext(&base->timerqueue); | ||
154 | if (!next) | ||
155 | return; | ||
156 | hrtimer_start(&base->timer, next->expires, HRTIMER_MODE_ABS); | ||
157 | } | ||
158 | } | ||
159 | |||
160 | |||
161 | /** | ||
162 | * alarmtimer_fired - Handles alarm hrtimer being fired. | ||
163 | * @timer: pointer to hrtimer being run | ||
164 | * | ||
165 | * When a alarm timer fires, this runs through the timerqueue to | ||
166 | * see which alarms expired, and runs those. If there are more alarm | ||
167 | * timers queued for the future, we set the hrtimer to fire when | ||
168 | * when the next future alarm timer expires. | ||
169 | */ | ||
170 | static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer) | ||
171 | { | ||
172 | struct alarm_base *base = container_of(timer, struct alarm_base, timer); | ||
173 | struct timerqueue_node *next; | ||
174 | unsigned long flags; | ||
175 | ktime_t now; | ||
176 | int ret = HRTIMER_NORESTART; | ||
177 | |||
178 | spin_lock_irqsave(&base->lock, flags); | ||
179 | now = base->gettime(); | ||
180 | while ((next = timerqueue_getnext(&base->timerqueue))) { | ||
181 | struct alarm *alarm; | ||
182 | ktime_t expired = next->expires; | ||
183 | |||
184 | if (expired.tv64 >= now.tv64) | ||
185 | break; | ||
186 | |||
187 | alarm = container_of(next, struct alarm, node); | ||
188 | |||
189 | timerqueue_del(&base->timerqueue, &alarm->node); | ||
190 | alarm->enabled = 0; | ||
191 | /* Re-add periodic timers */ | ||
192 | if (alarm->period.tv64) { | ||
193 | alarm->node.expires = ktime_add(expired, alarm->period); | ||
194 | timerqueue_add(&base->timerqueue, &alarm->node); | ||
195 | alarm->enabled = 1; | ||
196 | } | ||
197 | spin_unlock_irqrestore(&base->lock, flags); | ||
198 | if (alarm->function) | ||
199 | alarm->function(alarm); | ||
200 | spin_lock_irqsave(&base->lock, flags); | ||
201 | } | ||
202 | |||
203 | if (next) { | ||
204 | hrtimer_set_expires(&base->timer, next->expires); | ||
205 | ret = HRTIMER_RESTART; | ||
206 | } | ||
207 | spin_unlock_irqrestore(&base->lock, flags); | ||
208 | |||
209 | return ret; | ||
210 | |||
211 | } | ||
212 | |||
213 | #ifdef CONFIG_RTC_CLASS | ||
214 | /** | ||
215 | * alarmtimer_suspend - Suspend time callback | ||
216 | * @dev: unused | ||
217 | * @state: unused | ||
218 | * | ||
219 | * When we are going into suspend, we look through the bases | ||
220 | * to see which is the soonest timer to expire. We then | ||
221 | * set an rtc timer to fire that far into the future, which | ||
222 | * will wake us from suspend. | ||
223 | */ | ||
224 | static int alarmtimer_suspend(struct device *dev) | ||
225 | { | ||
226 | struct rtc_time tm; | ||
227 | ktime_t min, now; | ||
228 | unsigned long flags; | ||
229 | struct rtc_device *rtc; | ||
230 | int i; | ||
231 | |||
232 | spin_lock_irqsave(&freezer_delta_lock, flags); | ||
233 | min = freezer_delta; | ||
234 | freezer_delta = ktime_set(0, 0); | ||
235 | spin_unlock_irqrestore(&freezer_delta_lock, flags); | ||
236 | |||
237 | rtc = rtcdev; | ||
238 | /* If we have no rtcdev, just return */ | ||
239 | if (!rtc) | ||
240 | return 0; | ||
241 | |||
242 | /* Find the soonest timer to expire*/ | ||
243 | for (i = 0; i < ALARM_NUMTYPE; i++) { | ||
244 | struct alarm_base *base = &alarm_bases[i]; | ||
245 | struct timerqueue_node *next; | ||
246 | ktime_t delta; | ||
247 | |||
248 | spin_lock_irqsave(&base->lock, flags); | ||
249 | next = timerqueue_getnext(&base->timerqueue); | ||
250 | spin_unlock_irqrestore(&base->lock, flags); | ||
251 | if (!next) | ||
252 | continue; | ||
253 | delta = ktime_sub(next->expires, base->gettime()); | ||
254 | if (!min.tv64 || (delta.tv64 < min.tv64)) | ||
255 | min = delta; | ||
256 | } | ||
257 | if (min.tv64 == 0) | ||
258 | return 0; | ||
259 | |||
260 | /* XXX - Should we enforce a minimum sleep time? */ | ||
261 | WARN_ON(min.tv64 < NSEC_PER_SEC); | ||
262 | |||
263 | /* Setup an rtc timer to fire that far in the future */ | ||
264 | rtc_timer_cancel(rtc, &rtctimer); | ||
265 | rtc_read_time(rtc, &tm); | ||
266 | now = rtc_tm_to_ktime(tm); | ||
267 | now = ktime_add(now, min); | ||
268 | |||
269 | rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0)); | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | #else | ||
274 | static int alarmtimer_suspend(struct device *dev) | ||
275 | { | ||
276 | return 0; | ||
277 | } | ||
278 | #endif | ||
279 | |||
280 | static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type) | ||
281 | { | ||
282 | ktime_t delta; | ||
283 | unsigned long flags; | ||
284 | struct alarm_base *base = &alarm_bases[type]; | ||
285 | |||
286 | delta = ktime_sub(absexp, base->gettime()); | ||
287 | |||
288 | spin_lock_irqsave(&freezer_delta_lock, flags); | ||
289 | if (!freezer_delta.tv64 || (delta.tv64 < freezer_delta.tv64)) | ||
290 | freezer_delta = delta; | ||
291 | spin_unlock_irqrestore(&freezer_delta_lock, flags); | ||
292 | } | ||
293 | |||
294 | |||
295 | /** | ||
296 | * alarm_init - Initialize an alarm structure | ||
297 | * @alarm: ptr to alarm to be initialized | ||
298 | * @type: the type of the alarm | ||
299 | * @function: callback that is run when the alarm fires | ||
300 | */ | ||
301 | void alarm_init(struct alarm *alarm, enum alarmtimer_type type, | ||
302 | void (*function)(struct alarm *)) | ||
303 | { | ||
304 | timerqueue_init(&alarm->node); | ||
305 | alarm->period = ktime_set(0, 0); | ||
306 | alarm->function = function; | ||
307 | alarm->type = type; | ||
308 | alarm->enabled = 0; | ||
309 | } | ||
310 | |||
311 | /** | ||
312 | * alarm_start - Sets an alarm to fire | ||
313 | * @alarm: ptr to alarm to set | ||
314 | * @start: time to run the alarm | ||
315 | * @period: period at which the alarm will recur | ||
316 | */ | ||
317 | void alarm_start(struct alarm *alarm, ktime_t start, ktime_t period) | ||
318 | { | ||
319 | struct alarm_base *base = &alarm_bases[alarm->type]; | ||
320 | unsigned long flags; | ||
321 | |||
322 | spin_lock_irqsave(&base->lock, flags); | ||
323 | if (alarm->enabled) | ||
324 | alarmtimer_remove(base, alarm); | ||
325 | alarm->node.expires = start; | ||
326 | alarm->period = period; | ||
327 | alarmtimer_enqueue(base, alarm); | ||
328 | alarm->enabled = 1; | ||
329 | spin_unlock_irqrestore(&base->lock, flags); | ||
330 | } | ||
331 | |||
332 | /** | ||
333 | * alarm_cancel - Tries to cancel an alarm timer | ||
334 | * @alarm: ptr to alarm to be canceled | ||
335 | */ | ||
336 | void alarm_cancel(struct alarm *alarm) | ||
337 | { | ||
338 | struct alarm_base *base = &alarm_bases[alarm->type]; | ||
339 | unsigned long flags; | ||
340 | |||
341 | spin_lock_irqsave(&base->lock, flags); | ||
342 | if (alarm->enabled) | ||
343 | alarmtimer_remove(base, alarm); | ||
344 | alarm->enabled = 0; | ||
345 | spin_unlock_irqrestore(&base->lock, flags); | ||
346 | } | ||
347 | |||
348 | |||
349 | /** | ||
350 | * clock2alarm - helper that converts from clockid to alarmtypes | ||
351 | * @clockid: clockid. | ||
352 | */ | ||
353 | static enum alarmtimer_type clock2alarm(clockid_t clockid) | ||
354 | { | ||
355 | if (clockid == CLOCK_REALTIME_ALARM) | ||
356 | return ALARM_REALTIME; | ||
357 | if (clockid == CLOCK_BOOTTIME_ALARM) | ||
358 | return ALARM_BOOTTIME; | ||
359 | return -1; | ||
360 | } | ||
361 | |||
362 | /** | ||
363 | * alarm_handle_timer - Callback for posix timers | ||
364 | * @alarm: alarm that fired | ||
365 | * | ||
366 | * Posix timer callback for expired alarm timers. | ||
367 | */ | ||
368 | static void alarm_handle_timer(struct alarm *alarm) | ||
369 | { | ||
370 | struct k_itimer *ptr = container_of(alarm, struct k_itimer, | ||
371 | it.alarmtimer); | ||
372 | if (posix_timer_event(ptr, 0) != 0) | ||
373 | ptr->it_overrun++; | ||
374 | } | ||
375 | |||
376 | /** | ||
377 | * alarm_clock_getres - posix getres interface | ||
378 | * @which_clock: clockid | ||
379 | * @tp: timespec to fill | ||
380 | * | ||
381 | * Returns the granularity of underlying alarm base clock | ||
382 | */ | ||
383 | static int alarm_clock_getres(const clockid_t which_clock, struct timespec *tp) | ||
384 | { | ||
385 | clockid_t baseid = alarm_bases[clock2alarm(which_clock)].base_clockid; | ||
386 | |||
387 | if (!alarmtimer_get_rtcdev()) | ||
388 | return -ENOTSUPP; | ||
389 | |||
390 | return hrtimer_get_res(baseid, tp); | ||
391 | } | ||
392 | |||
393 | /** | ||
394 | * alarm_clock_get - posix clock_get interface | ||
395 | * @which_clock: clockid | ||
396 | * @tp: timespec to fill. | ||
397 | * | ||
398 | * Provides the underlying alarm base time. | ||
399 | */ | ||
400 | static int alarm_clock_get(clockid_t which_clock, struct timespec *tp) | ||
401 | { | ||
402 | struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)]; | ||
403 | |||
404 | if (!alarmtimer_get_rtcdev()) | ||
405 | return -ENOTSUPP; | ||
406 | |||
407 | *tp = ktime_to_timespec(base->gettime()); | ||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | /** | ||
412 | * alarm_timer_create - posix timer_create interface | ||
413 | * @new_timer: k_itimer pointer to manage | ||
414 | * | ||
415 | * Initializes the k_itimer structure. | ||
416 | */ | ||
417 | static int alarm_timer_create(struct k_itimer *new_timer) | ||
418 | { | ||
419 | enum alarmtimer_type type; | ||
420 | struct alarm_base *base; | ||
421 | |||
422 | if (!alarmtimer_get_rtcdev()) | ||
423 | return -ENOTSUPP; | ||
424 | |||
425 | if (!capable(CAP_WAKE_ALARM)) | ||
426 | return -EPERM; | ||
427 | |||
428 | type = clock2alarm(new_timer->it_clock); | ||
429 | base = &alarm_bases[type]; | ||
430 | alarm_init(&new_timer->it.alarmtimer, type, alarm_handle_timer); | ||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | /** | ||
435 | * alarm_timer_get - posix timer_get interface | ||
436 | * @new_timer: k_itimer pointer | ||
437 | * @cur_setting: itimerspec data to fill | ||
438 | * | ||
439 | * Copies the itimerspec data out from the k_itimer | ||
440 | */ | ||
441 | static void alarm_timer_get(struct k_itimer *timr, | ||
442 | struct itimerspec *cur_setting) | ||
443 | { | ||
444 | cur_setting->it_interval = | ||
445 | ktime_to_timespec(timr->it.alarmtimer.period); | ||
446 | cur_setting->it_value = | ||
447 | ktime_to_timespec(timr->it.alarmtimer.node.expires); | ||
448 | return; | ||
449 | } | ||
450 | |||
451 | /** | ||
452 | * alarm_timer_del - posix timer_del interface | ||
453 | * @timr: k_itimer pointer to be deleted | ||
454 | * | ||
455 | * Cancels any programmed alarms for the given timer. | ||
456 | */ | ||
457 | static int alarm_timer_del(struct k_itimer *timr) | ||
458 | { | ||
459 | if (!rtcdev) | ||
460 | return -ENOTSUPP; | ||
461 | |||
462 | alarm_cancel(&timr->it.alarmtimer); | ||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | /** | ||
467 | * alarm_timer_set - posix timer_set interface | ||
468 | * @timr: k_itimer pointer to be deleted | ||
469 | * @flags: timer flags | ||
470 | * @new_setting: itimerspec to be used | ||
471 | * @old_setting: itimerspec being replaced | ||
472 | * | ||
473 | * Sets the timer to new_setting, and starts the timer. | ||
474 | */ | ||
475 | static int alarm_timer_set(struct k_itimer *timr, int flags, | ||
476 | struct itimerspec *new_setting, | ||
477 | struct itimerspec *old_setting) | ||
478 | { | ||
479 | if (!rtcdev) | ||
480 | return -ENOTSUPP; | ||
481 | |||
482 | /* Save old values */ | ||
483 | old_setting->it_interval = | ||
484 | ktime_to_timespec(timr->it.alarmtimer.period); | ||
485 | old_setting->it_value = | ||
486 | ktime_to_timespec(timr->it.alarmtimer.node.expires); | ||
487 | |||
488 | /* If the timer was already set, cancel it */ | ||
489 | alarm_cancel(&timr->it.alarmtimer); | ||
490 | |||
491 | /* start the timer */ | ||
492 | alarm_start(&timr->it.alarmtimer, | ||
493 | timespec_to_ktime(new_setting->it_value), | ||
494 | timespec_to_ktime(new_setting->it_interval)); | ||
495 | return 0; | ||
496 | } | ||
497 | |||
498 | /** | ||
499 | * alarmtimer_nsleep_wakeup - Wakeup function for alarm_timer_nsleep | ||
500 | * @alarm: ptr to alarm that fired | ||
501 | * | ||
502 | * Wakes up the task that set the alarmtimer | ||
503 | */ | ||
504 | static void alarmtimer_nsleep_wakeup(struct alarm *alarm) | ||
505 | { | ||
506 | struct task_struct *task = (struct task_struct *)alarm->data; | ||
507 | |||
508 | alarm->data = NULL; | ||
509 | if (task) | ||
510 | wake_up_process(task); | ||
511 | } | ||
512 | |||
513 | /** | ||
514 | * alarmtimer_do_nsleep - Internal alarmtimer nsleep implementation | ||
515 | * @alarm: ptr to alarmtimer | ||
516 | * @absexp: absolute expiration time | ||
517 | * | ||
518 | * Sets the alarm timer and sleeps until it is fired or interrupted. | ||
519 | */ | ||
520 | static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp) | ||
521 | { | ||
522 | alarm->data = (void *)current; | ||
523 | do { | ||
524 | set_current_state(TASK_INTERRUPTIBLE); | ||
525 | alarm_start(alarm, absexp, ktime_set(0, 0)); | ||
526 | if (likely(alarm->data)) | ||
527 | schedule(); | ||
528 | |||
529 | alarm_cancel(alarm); | ||
530 | } while (alarm->data && !signal_pending(current)); | ||
531 | |||
532 | __set_current_state(TASK_RUNNING); | ||
533 | |||
534 | return (alarm->data == NULL); | ||
535 | } | ||
536 | |||
537 | |||
538 | /** | ||
539 | * update_rmtp - Update remaining timespec value | ||
540 | * @exp: expiration time | ||
541 | * @type: timer type | ||
542 | * @rmtp: user pointer to remaining timepsec value | ||
543 | * | ||
544 | * Helper function that fills in rmtp value with time between | ||
545 | * now and the exp value | ||
546 | */ | ||
547 | static int update_rmtp(ktime_t exp, enum alarmtimer_type type, | ||
548 | struct timespec __user *rmtp) | ||
549 | { | ||
550 | struct timespec rmt; | ||
551 | ktime_t rem; | ||
552 | |||
553 | rem = ktime_sub(exp, alarm_bases[type].gettime()); | ||
554 | |||
555 | if (rem.tv64 <= 0) | ||
556 | return 0; | ||
557 | rmt = ktime_to_timespec(rem); | ||
558 | |||
559 | if (copy_to_user(rmtp, &rmt, sizeof(*rmtp))) | ||
560 | return -EFAULT; | ||
561 | |||
562 | return 1; | ||
563 | |||
564 | } | ||
565 | |||
566 | /** | ||
567 | * alarm_timer_nsleep_restart - restartblock alarmtimer nsleep | ||
568 | * @restart: ptr to restart block | ||
569 | * | ||
570 | * Handles restarted clock_nanosleep calls | ||
571 | */ | ||
572 | static long __sched alarm_timer_nsleep_restart(struct restart_block *restart) | ||
573 | { | ||
574 | enum alarmtimer_type type = restart->nanosleep.clockid; | ||
575 | ktime_t exp; | ||
576 | struct timespec __user *rmtp; | ||
577 | struct alarm alarm; | ||
578 | int ret = 0; | ||
579 | |||
580 | exp.tv64 = restart->nanosleep.expires; | ||
581 | alarm_init(&alarm, type, alarmtimer_nsleep_wakeup); | ||
582 | |||
583 | if (alarmtimer_do_nsleep(&alarm, exp)) | ||
584 | goto out; | ||
585 | |||
586 | if (freezing(current)) | ||
587 | alarmtimer_freezerset(exp, type); | ||
588 | |||
589 | rmtp = restart->nanosleep.rmtp; | ||
590 | if (rmtp) { | ||
591 | ret = update_rmtp(exp, type, rmtp); | ||
592 | if (ret <= 0) | ||
593 | goto out; | ||
594 | } | ||
595 | |||
596 | |||
597 | /* The other values in restart are already filled in */ | ||
598 | ret = -ERESTART_RESTARTBLOCK; | ||
599 | out: | ||
600 | return ret; | ||
601 | } | ||
602 | |||
603 | /** | ||
604 | * alarm_timer_nsleep - alarmtimer nanosleep | ||
605 | * @which_clock: clockid | ||
606 | * @flags: determins abstime or relative | ||
607 | * @tsreq: requested sleep time (abs or rel) | ||
608 | * @rmtp: remaining sleep time saved | ||
609 | * | ||
610 | * Handles clock_nanosleep calls against _ALARM clockids | ||
611 | */ | ||
612 | static int alarm_timer_nsleep(const clockid_t which_clock, int flags, | ||
613 | struct timespec *tsreq, struct timespec __user *rmtp) | ||
614 | { | ||
615 | enum alarmtimer_type type = clock2alarm(which_clock); | ||
616 | struct alarm alarm; | ||
617 | ktime_t exp; | ||
618 | int ret = 0; | ||
619 | struct restart_block *restart; | ||
620 | |||
621 | if (!alarmtimer_get_rtcdev()) | ||
622 | return -ENOTSUPP; | ||
623 | |||
624 | if (!capable(CAP_WAKE_ALARM)) | ||
625 | return -EPERM; | ||
626 | |||
627 | alarm_init(&alarm, type, alarmtimer_nsleep_wakeup); | ||
628 | |||
629 | exp = timespec_to_ktime(*tsreq); | ||
630 | /* Convert (if necessary) to absolute time */ | ||
631 | if (flags != TIMER_ABSTIME) { | ||
632 | ktime_t now = alarm_bases[type].gettime(); | ||
633 | exp = ktime_add(now, exp); | ||
634 | } | ||
635 | |||
636 | if (alarmtimer_do_nsleep(&alarm, exp)) | ||
637 | goto out; | ||
638 | |||
639 | if (freezing(current)) | ||
640 | alarmtimer_freezerset(exp, type); | ||
641 | |||
642 | /* abs timers don't set remaining time or restart */ | ||
643 | if (flags == TIMER_ABSTIME) { | ||
644 | ret = -ERESTARTNOHAND; | ||
645 | goto out; | ||
646 | } | ||
647 | |||
648 | if (rmtp) { | ||
649 | ret = update_rmtp(exp, type, rmtp); | ||
650 | if (ret <= 0) | ||
651 | goto out; | ||
652 | } | ||
653 | |||
654 | restart = ¤t_thread_info()->restart_block; | ||
655 | restart->fn = alarm_timer_nsleep_restart; | ||
656 | restart->nanosleep.clockid = type; | ||
657 | restart->nanosleep.expires = exp.tv64; | ||
658 | restart->nanosleep.rmtp = rmtp; | ||
659 | ret = -ERESTART_RESTARTBLOCK; | ||
660 | |||
661 | out: | ||
662 | return ret; | ||
663 | } | ||
664 | |||
665 | |||
666 | /* Suspend hook structures */ | ||
667 | static const struct dev_pm_ops alarmtimer_pm_ops = { | ||
668 | .suspend = alarmtimer_suspend, | ||
669 | }; | ||
670 | |||
671 | static struct platform_driver alarmtimer_driver = { | ||
672 | .driver = { | ||
673 | .name = "alarmtimer", | ||
674 | .pm = &alarmtimer_pm_ops, | ||
675 | } | ||
676 | }; | ||
677 | |||
678 | /** | ||
679 | * alarmtimer_init - Initialize alarm timer code | ||
680 | * | ||
681 | * This function initializes the alarm bases and registers | ||
682 | * the posix clock ids. | ||
683 | */ | ||
684 | static int __init alarmtimer_init(void) | ||
685 | { | ||
686 | int error = 0; | ||
687 | int i; | ||
688 | struct k_clock alarm_clock = { | ||
689 | .clock_getres = alarm_clock_getres, | ||
690 | .clock_get = alarm_clock_get, | ||
691 | .timer_create = alarm_timer_create, | ||
692 | .timer_set = alarm_timer_set, | ||
693 | .timer_del = alarm_timer_del, | ||
694 | .timer_get = alarm_timer_get, | ||
695 | .nsleep = alarm_timer_nsleep, | ||
696 | }; | ||
697 | |||
698 | posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock); | ||
699 | posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock); | ||
700 | |||
701 | /* Initialize alarm bases */ | ||
702 | alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME; | ||
703 | alarm_bases[ALARM_REALTIME].gettime = &ktime_get_real; | ||
704 | alarm_bases[ALARM_BOOTTIME].base_clockid = CLOCK_BOOTTIME; | ||
705 | alarm_bases[ALARM_BOOTTIME].gettime = &ktime_get_boottime; | ||
706 | for (i = 0; i < ALARM_NUMTYPE; i++) { | ||
707 | timerqueue_init_head(&alarm_bases[i].timerqueue); | ||
708 | spin_lock_init(&alarm_bases[i].lock); | ||
709 | hrtimer_init(&alarm_bases[i].timer, | ||
710 | alarm_bases[i].base_clockid, | ||
711 | HRTIMER_MODE_ABS); | ||
712 | alarm_bases[i].timer.function = alarmtimer_fired; | ||
713 | } | ||
714 | error = platform_driver_register(&alarmtimer_driver); | ||
715 | platform_device_register_simple("alarmtimer", -1, NULL, 0); | ||
716 | |||
717 | return error; | ||
718 | } | ||
719 | device_initcall(alarmtimer_init); | ||
720 | |||