.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * Alarmtimer interface |
---|
3 | 4 | * |
---|
.. | .. |
---|
10 | 11 | * Copyright (C) 2010 IBM Corperation |
---|
11 | 12 | * |
---|
12 | 13 | * 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 | 14 | */ |
---|
18 | 15 | #include <linux/time.h> |
---|
19 | 16 | #include <linux/hrtimer.h> |
---|
.. | .. |
---|
29 | 26 | #include <linux/freezer.h> |
---|
30 | 27 | #include <linux/compat.h> |
---|
31 | 28 | #include <linux/module.h> |
---|
| 29 | +#include <linux/time_namespace.h> |
---|
32 | 30 | |
---|
33 | 31 | #include "posix-timers.h" |
---|
34 | 32 | |
---|
35 | 33 | #define CREATE_TRACE_POINTS |
---|
36 | 34 | #include <trace/events/alarmtimer.h> |
---|
37 | 35 | |
---|
| 36 | +#undef CREATE_TRACE_POINTS |
---|
| 37 | +#include <trace/hooks/wakeupbypass.h> |
---|
38 | 38 | /** |
---|
39 | 39 | * struct alarm_base - Alarm timer bases |
---|
40 | 40 | * @lock: Lock for syncrhonized access to the base |
---|
41 | 41 | * @timerqueue: Timerqueue head managing the list of events |
---|
42 | | - * @gettime: Function to read the time correlating to the base |
---|
| 42 | + * @get_ktime: Function to read the time correlating to the base |
---|
| 43 | + * @get_timespec: Function to read the namespace time correlating to the base |
---|
43 | 44 | * @base_clockid: clockid for the base |
---|
44 | 45 | */ |
---|
45 | 46 | static struct alarm_base { |
---|
46 | 47 | spinlock_t lock; |
---|
47 | 48 | struct timerqueue_head timerqueue; |
---|
48 | | - ktime_t (*gettime)(void); |
---|
| 49 | + ktime_t (*get_ktime)(void); |
---|
| 50 | + void (*get_timespec)(struct timespec64 *tp); |
---|
49 | 51 | clockid_t base_clockid; |
---|
50 | 52 | } alarm_bases[ALARM_NUMTYPE]; |
---|
51 | 53 | |
---|
.. | .. |
---|
58 | 60 | #endif |
---|
59 | 61 | |
---|
60 | 62 | #ifdef CONFIG_RTC_CLASS |
---|
61 | | -static struct wakeup_source *ws; |
---|
62 | | - |
---|
63 | 63 | /* rtc timer and device for setting alarm wakeups at suspend */ |
---|
64 | 64 | static struct rtc_timer rtctimer; |
---|
65 | 65 | static struct rtc_device *rtcdev; |
---|
.. | .. |
---|
69 | 69 | * alarmtimer_get_rtcdev - Return selected rtcdevice |
---|
70 | 70 | * |
---|
71 | 71 | * This function returns the rtc device to use for wakealarms. |
---|
72 | | - * If one has not already been chosen, it checks to see if a |
---|
73 | | - * functional rtc device is available. |
---|
74 | 72 | */ |
---|
75 | 73 | struct rtc_device *alarmtimer_get_rtcdev(void) |
---|
76 | 74 | { |
---|
.. | .. |
---|
90 | 88 | { |
---|
91 | 89 | unsigned long flags; |
---|
92 | 90 | struct rtc_device *rtc = to_rtc_device(dev); |
---|
93 | | - struct wakeup_source *__ws; |
---|
| 91 | + struct platform_device *pdev; |
---|
94 | 92 | int ret = 0; |
---|
95 | 93 | |
---|
96 | 94 | if (rtcdev) |
---|
.. | .. |
---|
101 | 99 | if (!device_may_wakeup(rtc->dev.parent)) |
---|
102 | 100 | return -1; |
---|
103 | 101 | |
---|
104 | | - __ws = wakeup_source_register(dev, "alarmtimer"); |
---|
| 102 | + pdev = platform_device_register_data(dev, "alarmtimer", |
---|
| 103 | + PLATFORM_DEVID_AUTO, NULL, 0); |
---|
| 104 | + if (!IS_ERR(pdev)) |
---|
| 105 | + device_init_wakeup(&pdev->dev, true); |
---|
105 | 106 | |
---|
106 | 107 | spin_lock_irqsave(&rtcdev_lock, flags); |
---|
107 | | - if (!rtcdev) { |
---|
| 108 | + if (!IS_ERR(pdev) && !rtcdev) { |
---|
108 | 109 | if (!try_module_get(rtc->owner)) { |
---|
109 | 110 | ret = -1; |
---|
110 | 111 | goto unlock; |
---|
.. | .. |
---|
113 | 114 | rtcdev = rtc; |
---|
114 | 115 | /* hold a reference so it doesn't go away */ |
---|
115 | 116 | get_device(dev); |
---|
116 | | - ws = __ws; |
---|
117 | | - __ws = NULL; |
---|
| 117 | + pdev = NULL; |
---|
| 118 | + } else { |
---|
| 119 | + ret = -1; |
---|
118 | 120 | } |
---|
119 | 121 | unlock: |
---|
120 | 122 | spin_unlock_irqrestore(&rtcdev_lock, flags); |
---|
121 | 123 | |
---|
122 | | - wakeup_source_unregister(__ws); |
---|
| 124 | + platform_device_unregister(pdev); |
---|
123 | 125 | |
---|
124 | 126 | return ret; |
---|
125 | 127 | } |
---|
.. | .. |
---|
143 | 145 | class_interface_unregister(&alarmtimer_rtc_interface); |
---|
144 | 146 | } |
---|
145 | 147 | #else |
---|
146 | | -struct rtc_device *alarmtimer_get_rtcdev(void) |
---|
147 | | -{ |
---|
148 | | - return NULL; |
---|
149 | | -} |
---|
150 | | -#define rtcdev (NULL) |
---|
151 | 148 | static inline int alarmtimer_rtc_interface_setup(void) { return 0; } |
---|
152 | 149 | static inline void alarmtimer_rtc_interface_remove(void) { } |
---|
153 | 150 | static inline void alarmtimer_rtc_timer_init(void) { } |
---|
.. | .. |
---|
197 | 194 | * When a alarm timer fires, this runs through the timerqueue to |
---|
198 | 195 | * see which alarms expired, and runs those. If there are more alarm |
---|
199 | 196 | * timers queued for the future, we set the hrtimer to fire when |
---|
200 | | - * when the next future alarm timer expires. |
---|
| 197 | + * the next future alarm timer expires. |
---|
201 | 198 | */ |
---|
202 | 199 | static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer) |
---|
203 | 200 | { |
---|
.. | .. |
---|
212 | 209 | spin_unlock_irqrestore(&base->lock, flags); |
---|
213 | 210 | |
---|
214 | 211 | if (alarm->function) |
---|
215 | | - restart = alarm->function(alarm, base->gettime()); |
---|
| 212 | + restart = alarm->function(alarm, base->get_ktime()); |
---|
216 | 213 | |
---|
217 | 214 | spin_lock_irqsave(&base->lock, flags); |
---|
218 | 215 | if (restart != ALARMTIMER_NORESTART) { |
---|
.. | .. |
---|
222 | 219 | } |
---|
223 | 220 | spin_unlock_irqrestore(&base->lock, flags); |
---|
224 | 221 | |
---|
225 | | - trace_alarmtimer_fired(alarm, base->gettime()); |
---|
| 222 | + trace_alarmtimer_fired(alarm, base->get_ktime()); |
---|
226 | 223 | return ret; |
---|
227 | 224 | |
---|
228 | 225 | } |
---|
.. | .. |
---|
230 | 227 | ktime_t alarm_expires_remaining(const struct alarm *alarm) |
---|
231 | 228 | { |
---|
232 | 229 | struct alarm_base *base = &alarm_bases[alarm->type]; |
---|
233 | | - return ktime_sub(alarm->node.expires, base->gettime()); |
---|
| 230 | + return ktime_sub(alarm->node.expires, base->get_ktime()); |
---|
234 | 231 | } |
---|
235 | 232 | EXPORT_SYMBOL_GPL(alarm_expires_remaining); |
---|
236 | 233 | |
---|
.. | .. |
---|
238 | 235 | /** |
---|
239 | 236 | * alarmtimer_suspend - Suspend time callback |
---|
240 | 237 | * @dev: unused |
---|
241 | | - * @state: unused |
---|
242 | 238 | * |
---|
243 | 239 | * When we are going into suspend, we look through the bases |
---|
244 | 240 | * to see which is the soonest timer to expire. We then |
---|
.. | .. |
---|
252 | 248 | struct rtc_device *rtc; |
---|
253 | 249 | unsigned long flags; |
---|
254 | 250 | struct rtc_time tm; |
---|
| 251 | + int wakeup_bypass_enabled = 0; |
---|
255 | 252 | |
---|
256 | 253 | spin_lock_irqsave(&freezer_delta_lock, flags); |
---|
257 | 254 | min = freezer_delta; |
---|
.. | .. |
---|
259 | 256 | type = freezer_alarmtype; |
---|
260 | 257 | freezer_delta = 0; |
---|
261 | 258 | spin_unlock_irqrestore(&freezer_delta_lock, flags); |
---|
| 259 | + |
---|
| 260 | + trace_android_vh_wakeup_bypass(&wakeup_bypass_enabled); |
---|
| 261 | + if (wakeup_bypass_enabled) |
---|
| 262 | + return 0; |
---|
262 | 263 | |
---|
263 | 264 | rtc = alarmtimer_get_rtcdev(); |
---|
264 | 265 | /* If we have no rtcdev, just return */ |
---|
.. | .. |
---|
276 | 277 | spin_unlock_irqrestore(&base->lock, flags); |
---|
277 | 278 | if (!next) |
---|
278 | 279 | continue; |
---|
279 | | - delta = ktime_sub(next->expires, base->gettime()); |
---|
| 280 | + delta = ktime_sub(next->expires, base->get_ktime()); |
---|
280 | 281 | if (!min || (delta < min)) { |
---|
281 | 282 | expires = next->expires; |
---|
282 | 283 | min = delta; |
---|
.. | .. |
---|
287 | 288 | return 0; |
---|
288 | 289 | |
---|
289 | 290 | if (ktime_to_ns(min) < 2 * NSEC_PER_SEC) { |
---|
290 | | - __pm_wakeup_event(ws, 2 * MSEC_PER_SEC); |
---|
| 291 | + pm_wakeup_event(dev, 2 * MSEC_PER_SEC); |
---|
291 | 292 | return -EBUSY; |
---|
292 | 293 | } |
---|
293 | 294 | |
---|
.. | .. |
---|
302 | 303 | /* Set alarm, if in the past reject suspend briefly to handle */ |
---|
303 | 304 | ret = rtc_timer_start(rtc, &rtctimer, now, 0); |
---|
304 | 305 | if (ret < 0) |
---|
305 | | - __pm_wakeup_event(ws, MSEC_PER_SEC); |
---|
| 306 | + pm_wakeup_event(dev, MSEC_PER_SEC); |
---|
306 | 307 | return ret; |
---|
307 | 308 | } |
---|
308 | 309 | |
---|
.. | .. |
---|
370 | 371 | hrtimer_start(&alarm->timer, alarm->node.expires, HRTIMER_MODE_ABS); |
---|
371 | 372 | spin_unlock_irqrestore(&base->lock, flags); |
---|
372 | 373 | |
---|
373 | | - trace_alarmtimer_start(alarm, base->gettime()); |
---|
| 374 | + trace_alarmtimer_start(alarm, base->get_ktime()); |
---|
374 | 375 | } |
---|
375 | 376 | EXPORT_SYMBOL_GPL(alarm_start); |
---|
376 | 377 | |
---|
.. | .. |
---|
383 | 384 | { |
---|
384 | 385 | struct alarm_base *base = &alarm_bases[alarm->type]; |
---|
385 | 386 | |
---|
386 | | - start = ktime_add_safe(start, base->gettime()); |
---|
| 387 | + start = ktime_add_safe(start, base->get_ktime()); |
---|
387 | 388 | alarm_start(alarm, start); |
---|
388 | 389 | } |
---|
389 | 390 | EXPORT_SYMBOL_GPL(alarm_start_relative); |
---|
.. | .. |
---|
420 | 421 | alarmtimer_dequeue(base, alarm); |
---|
421 | 422 | spin_unlock_irqrestore(&base->lock, flags); |
---|
422 | 423 | |
---|
423 | | - trace_alarmtimer_cancel(alarm, base->gettime()); |
---|
| 424 | + trace_alarmtimer_cancel(alarm, base->get_ktime()); |
---|
424 | 425 | return ret; |
---|
425 | 426 | } |
---|
426 | 427 | EXPORT_SYMBOL_GPL(alarm_try_to_cancel); |
---|
.. | .. |
---|
438 | 439 | int ret = alarm_try_to_cancel(alarm); |
---|
439 | 440 | if (ret >= 0) |
---|
440 | 441 | return ret; |
---|
441 | | - hrtimer_grab_expiry_lock(&alarm->timer); |
---|
| 442 | + hrtimer_cancel_wait_running(&alarm->timer); |
---|
442 | 443 | } |
---|
443 | 444 | } |
---|
444 | 445 | EXPORT_SYMBOL_GPL(alarm_cancel); |
---|
.. | .. |
---|
476 | 477 | } |
---|
477 | 478 | EXPORT_SYMBOL_GPL(alarm_forward); |
---|
478 | 479 | |
---|
479 | | -u64 alarm_forward_now(struct alarm *alarm, ktime_t interval) |
---|
| 480 | +static u64 __alarm_forward_now(struct alarm *alarm, ktime_t interval, bool throttle) |
---|
480 | 481 | { |
---|
481 | 482 | struct alarm_base *base = &alarm_bases[alarm->type]; |
---|
| 483 | + ktime_t now = base->get_ktime(); |
---|
482 | 484 | |
---|
483 | | - return alarm_forward(alarm, base->gettime(), interval); |
---|
| 485 | + if (IS_ENABLED(CONFIG_HIGH_RES_TIMERS) && throttle) { |
---|
| 486 | + /* |
---|
| 487 | + * Same issue as with posix_timer_fn(). Timers which are |
---|
| 488 | + * periodic but the signal is ignored can starve the system |
---|
| 489 | + * with a very small interval. The real fix which was |
---|
| 490 | + * promised in the context of posix_timer_fn() never |
---|
| 491 | + * materialized, but someone should really work on it. |
---|
| 492 | + * |
---|
| 493 | + * To prevent DOS fake @now to be 1 jiffie out which keeps |
---|
| 494 | + * the overrun accounting correct but creates an |
---|
| 495 | + * inconsistency vs. timer_gettime(2). |
---|
| 496 | + */ |
---|
| 497 | + ktime_t kj = NSEC_PER_SEC / HZ; |
---|
| 498 | + |
---|
| 499 | + if (interval < kj) |
---|
| 500 | + now = ktime_add(now, kj); |
---|
| 501 | + } |
---|
| 502 | + |
---|
| 503 | + return alarm_forward(alarm, now, interval); |
---|
| 504 | +} |
---|
| 505 | + |
---|
| 506 | +u64 alarm_forward_now(struct alarm *alarm, ktime_t interval) |
---|
| 507 | +{ |
---|
| 508 | + return __alarm_forward_now(alarm, interval, false); |
---|
484 | 509 | } |
---|
485 | 510 | EXPORT_SYMBOL_GPL(alarm_forward_now); |
---|
486 | 511 | |
---|
.. | .. |
---|
506 | 531 | return; |
---|
507 | 532 | } |
---|
508 | 533 | |
---|
509 | | - delta = ktime_sub(absexp, base->gettime()); |
---|
| 534 | + delta = ktime_sub(absexp, base->get_ktime()); |
---|
510 | 535 | |
---|
511 | 536 | spin_lock_irqsave(&freezer_delta_lock, flags); |
---|
512 | 537 | if (!freezer_delta || (delta < freezer_delta)) { |
---|
.. | .. |
---|
554 | 579 | if (posix_timer_event(ptr, si_private) && ptr->it_interval) { |
---|
555 | 580 | /* |
---|
556 | 581 | * Handle ignored signals and rearm the timer. This will go |
---|
557 | | - * away once we handle ignored signals proper. |
---|
| 582 | + * away once we handle ignored signals proper. Ensure that |
---|
| 583 | + * small intervals cannot starve the system. |
---|
558 | 584 | */ |
---|
559 | | - ptr->it_overrun += alarm_forward_now(alarm, ptr->it_interval); |
---|
| 585 | + ptr->it_overrun += __alarm_forward_now(alarm, ptr->it_interval, true); |
---|
560 | 586 | ++ptr->it_requeue_pending; |
---|
561 | 587 | ptr->it_active = 1; |
---|
562 | 588 | result = ALARMTIMER_RESTART; |
---|
.. | .. |
---|
612 | 638 | } |
---|
613 | 639 | |
---|
614 | 640 | /** |
---|
| 641 | + * alarm_timer_wait_running - Posix timer callback to wait for a timer |
---|
| 642 | + * @timr: Pointer to the posixtimer data struct |
---|
| 643 | + * |
---|
| 644 | + * Called from the core code when timer cancel detected that the callback |
---|
| 645 | + * is running. @timr is unlocked and rcu read lock is held to prevent it |
---|
| 646 | + * from being freed. |
---|
| 647 | + */ |
---|
| 648 | +static void alarm_timer_wait_running(struct k_itimer *timr) |
---|
| 649 | +{ |
---|
| 650 | + hrtimer_cancel_wait_running(&timr->it.alarm.alarmtimer.timer); |
---|
| 651 | +} |
---|
| 652 | + |
---|
| 653 | +/** |
---|
615 | 654 | * alarm_timer_arm - Posix timer callback to arm a timer |
---|
616 | 655 | * @timr: Pointer to the posixtimer data struct |
---|
617 | 656 | * @expires: The new expiry time |
---|
.. | .. |
---|
625 | 664 | struct alarm_base *base = &alarm_bases[alarm->type]; |
---|
626 | 665 | |
---|
627 | 666 | if (!absolute) |
---|
628 | | - expires = ktime_add_safe(expires, base->gettime()); |
---|
| 667 | + expires = ktime_add_safe(expires, base->get_ktime()); |
---|
629 | 668 | if (sigev_none) |
---|
630 | 669 | alarm->node.expires = expires; |
---|
631 | 670 | else |
---|
.. | .. |
---|
650 | 689 | } |
---|
651 | 690 | |
---|
652 | 691 | /** |
---|
653 | | - * alarm_clock_get - posix clock_get interface |
---|
| 692 | + * alarm_clock_get_timespec - posix clock_get_timespec interface |
---|
654 | 693 | * @which_clock: clockid |
---|
655 | 694 | * @tp: timespec to fill. |
---|
656 | 695 | * |
---|
657 | | - * Provides the underlying alarm base time. |
---|
| 696 | + * Provides the underlying alarm base time in a tasks time namespace. |
---|
658 | 697 | */ |
---|
659 | | -static int alarm_clock_get(clockid_t which_clock, struct timespec64 *tp) |
---|
| 698 | +static int alarm_clock_get_timespec(clockid_t which_clock, struct timespec64 *tp) |
---|
660 | 699 | { |
---|
661 | 700 | struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)]; |
---|
662 | 701 | |
---|
663 | 702 | if (!alarmtimer_get_rtcdev()) |
---|
664 | 703 | return -EINVAL; |
---|
665 | 704 | |
---|
666 | | - *tp = ktime_to_timespec64(base->gettime()); |
---|
| 705 | + base->get_timespec(tp); |
---|
| 706 | + |
---|
667 | 707 | return 0; |
---|
| 708 | +} |
---|
| 709 | + |
---|
| 710 | +/** |
---|
| 711 | + * alarm_clock_get_ktime - posix clock_get_ktime interface |
---|
| 712 | + * @which_clock: clockid |
---|
| 713 | + * |
---|
| 714 | + * Provides the underlying alarm base time in the root namespace. |
---|
| 715 | + */ |
---|
| 716 | +static ktime_t alarm_clock_get_ktime(clockid_t which_clock) |
---|
| 717 | +{ |
---|
| 718 | + struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)]; |
---|
| 719 | + |
---|
| 720 | + if (!alarmtimer_get_rtcdev()) |
---|
| 721 | + return -EINVAL; |
---|
| 722 | + |
---|
| 723 | + return base->get_ktime(); |
---|
668 | 724 | } |
---|
669 | 725 | |
---|
670 | 726 | /** |
---|
.. | .. |
---|
740 | 796 | struct timespec64 rmt; |
---|
741 | 797 | ktime_t rem; |
---|
742 | 798 | |
---|
743 | | - rem = ktime_sub(absexp, alarm_bases[type].gettime()); |
---|
| 799 | + rem = ktime_sub(absexp, alarm_bases[type].get_ktime()); |
---|
744 | 800 | |
---|
745 | 801 | if (rem <= 0) |
---|
746 | 802 | return 0; |
---|
.. | .. |
---|
809 | 865 | exp = timespec64_to_ktime(*tsreq); |
---|
810 | 866 | /* Convert (if necessary) to absolute time */ |
---|
811 | 867 | if (flags != TIMER_ABSTIME) { |
---|
812 | | - ktime_t now = alarm_bases[type].gettime(); |
---|
| 868 | + ktime_t now = alarm_bases[type].get_ktime(); |
---|
813 | 869 | |
---|
814 | 870 | exp = ktime_add_safe(now, exp); |
---|
| 871 | + } else { |
---|
| 872 | + exp = timens_ktime_to_host(which_clock, exp); |
---|
815 | 873 | } |
---|
816 | 874 | |
---|
817 | 875 | ret = alarmtimer_do_nsleep(&alarm, exp, type); |
---|
.. | .. |
---|
830 | 888 | |
---|
831 | 889 | const struct k_clock alarm_clock = { |
---|
832 | 890 | .clock_getres = alarm_clock_getres, |
---|
833 | | - .clock_get = alarm_clock_get, |
---|
| 891 | + .clock_get_ktime = alarm_clock_get_ktime, |
---|
| 892 | + .clock_get_timespec = alarm_clock_get_timespec, |
---|
834 | 893 | .timer_create = alarm_timer_create, |
---|
835 | 894 | .timer_set = common_timer_set, |
---|
836 | 895 | .timer_del = common_timer_del, |
---|
.. | .. |
---|
840 | 899 | .timer_forward = alarm_timer_forward, |
---|
841 | 900 | .timer_remaining = alarm_timer_remaining, |
---|
842 | 901 | .timer_try_to_cancel = alarm_timer_try_to_cancel, |
---|
| 902 | + .timer_wait_running = alarm_timer_wait_running, |
---|
843 | 903 | .nsleep = alarm_timer_nsleep, |
---|
844 | 904 | }; |
---|
845 | 905 | #endif /* CONFIG_POSIX_TIMERS */ |
---|
.. | .. |
---|
858 | 918 | } |
---|
859 | 919 | }; |
---|
860 | 920 | |
---|
| 921 | +static void get_boottime_timespec(struct timespec64 *tp) |
---|
| 922 | +{ |
---|
| 923 | + ktime_get_boottime_ts64(tp); |
---|
| 924 | + timens_add_boottime(tp); |
---|
| 925 | +} |
---|
| 926 | + |
---|
861 | 927 | /** |
---|
862 | 928 | * alarmtimer_init - Initialize alarm timer code |
---|
863 | 929 | * |
---|
.. | .. |
---|
866 | 932 | */ |
---|
867 | 933 | static int __init alarmtimer_init(void) |
---|
868 | 934 | { |
---|
869 | | - struct platform_device *pdev; |
---|
870 | | - int error = 0; |
---|
| 935 | + int error; |
---|
871 | 936 | int i; |
---|
872 | 937 | |
---|
873 | 938 | alarmtimer_rtc_timer_init(); |
---|
874 | 939 | |
---|
875 | 940 | /* Initialize alarm bases */ |
---|
876 | 941 | alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME; |
---|
877 | | - alarm_bases[ALARM_REALTIME].gettime = &ktime_get_real; |
---|
| 942 | + alarm_bases[ALARM_REALTIME].get_ktime = &ktime_get_real; |
---|
| 943 | + alarm_bases[ALARM_REALTIME].get_timespec = ktime_get_real_ts64; |
---|
878 | 944 | alarm_bases[ALARM_BOOTTIME].base_clockid = CLOCK_BOOTTIME; |
---|
879 | | - alarm_bases[ALARM_BOOTTIME].gettime = &ktime_get_boottime; |
---|
| 945 | + alarm_bases[ALARM_BOOTTIME].get_ktime = &ktime_get_boottime; |
---|
| 946 | + alarm_bases[ALARM_BOOTTIME].get_timespec = get_boottime_timespec; |
---|
880 | 947 | for (i = 0; i < ALARM_NUMTYPE; i++) { |
---|
881 | 948 | timerqueue_init_head(&alarm_bases[i].timerqueue); |
---|
882 | 949 | spin_lock_init(&alarm_bases[i].lock); |
---|
.. | .. |
---|
890 | 957 | if (error) |
---|
891 | 958 | goto out_if; |
---|
892 | 959 | |
---|
893 | | - pdev = platform_device_register_simple("alarmtimer", -1, NULL, 0); |
---|
894 | | - if (IS_ERR(pdev)) { |
---|
895 | | - error = PTR_ERR(pdev); |
---|
896 | | - goto out_drv; |
---|
897 | | - } |
---|
898 | 960 | return 0; |
---|
899 | | - |
---|
900 | | -out_drv: |
---|
901 | | - platform_driver_unregister(&alarmtimer_driver); |
---|
902 | 961 | out_if: |
---|
903 | 962 | alarmtimer_rtc_interface_remove(); |
---|
904 | 963 | return error; |
---|