| .. | .. |
|---|
| 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; |
|---|