diff options
Diffstat (limited to 'kernel/hrtimer.c')
| -rw-r--r-- | kernel/hrtimer.c | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index ec4cb9f3e3b7..b74860aaf5f1 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
| @@ -135,7 +135,7 @@ EXPORT_SYMBOL_GPL(ktime_get_ts); | |||
| 135 | static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base) | 135 | static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base) |
| 136 | { | 136 | { |
| 137 | ktime_t xtim, tomono; | 137 | ktime_t xtim, tomono; |
| 138 | struct timespec xts; | 138 | struct timespec xts, tom; |
| 139 | unsigned long seq; | 139 | unsigned long seq; |
| 140 | 140 | ||
| 141 | do { | 141 | do { |
| @@ -145,10 +145,11 @@ static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base) | |||
| 145 | #else | 145 | #else |
| 146 | xts = xtime; | 146 | xts = xtime; |
| 147 | #endif | 147 | #endif |
| 148 | tom = wall_to_monotonic; | ||
| 148 | } while (read_seqretry(&xtime_lock, seq)); | 149 | } while (read_seqretry(&xtime_lock, seq)); |
| 149 | 150 | ||
| 150 | xtim = timespec_to_ktime(xts); | 151 | xtim = timespec_to_ktime(xts); |
| 151 | tomono = timespec_to_ktime(wall_to_monotonic); | 152 | tomono = timespec_to_ktime(tom); |
| 152 | base->clock_base[CLOCK_REALTIME].softirq_time = xtim; | 153 | base->clock_base[CLOCK_REALTIME].softirq_time = xtim; |
| 153 | base->clock_base[CLOCK_MONOTONIC].softirq_time = | 154 | base->clock_base[CLOCK_MONOTONIC].softirq_time = |
| 154 | ktime_add(xtim, tomono); | 155 | ktime_add(xtim, tomono); |
| @@ -458,6 +459,18 @@ void clock_was_set(void) | |||
| 458 | } | 459 | } |
| 459 | 460 | ||
| 460 | /* | 461 | /* |
| 462 | * During resume we might have to reprogram the high resolution timer | ||
| 463 | * interrupt (on the local CPU): | ||
| 464 | */ | ||
| 465 | void hres_timers_resume(void) | ||
| 466 | { | ||
| 467 | WARN_ON_ONCE(num_online_cpus() > 1); | ||
| 468 | |||
| 469 | /* Retrigger the CPU local events: */ | ||
| 470 | retrigger_next_event(NULL); | ||
| 471 | } | ||
| 472 | |||
| 473 | /* | ||
| 461 | * Check, whether the timer is on the callback pending list | 474 | * Check, whether the timer is on the callback pending list |
| 462 | */ | 475 | */ |
| 463 | static inline int hrtimer_cb_pending(const struct hrtimer *timer) | 476 | static inline int hrtimer_cb_pending(const struct hrtimer *timer) |
| @@ -644,6 +657,12 @@ hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval) | |||
| 644 | orun++; | 657 | orun++; |
| 645 | } | 658 | } |
| 646 | timer->expires = ktime_add(timer->expires, interval); | 659 | timer->expires = ktime_add(timer->expires, interval); |
| 660 | /* | ||
| 661 | * Make sure, that the result did not wrap with a very large | ||
| 662 | * interval. | ||
| 663 | */ | ||
| 664 | if (timer->expires.tv64 < 0) | ||
| 665 | timer->expires = ktime_set(KTIME_SEC_MAX, 0); | ||
| 647 | 666 | ||
| 648 | return orun; | 667 | return orun; |
| 649 | } | 668 | } |
| @@ -807,7 +826,12 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode) | |||
| 807 | 826 | ||
| 808 | timer_stats_hrtimer_set_start_info(timer); | 827 | timer_stats_hrtimer_set_start_info(timer); |
| 809 | 828 | ||
| 810 | enqueue_hrtimer(timer, new_base, base == new_base); | 829 | /* |
| 830 | * Only allow reprogramming if the new base is on this CPU. | ||
| 831 | * (it might still be on another CPU if the timer was pending) | ||
| 832 | */ | ||
| 833 | enqueue_hrtimer(timer, new_base, | ||
| 834 | new_base->cpu_base == &__get_cpu_var(hrtimer_bases)); | ||
| 811 | 835 | ||
| 812 | unlock_hrtimer_base(timer, &flags); | 836 | unlock_hrtimer_base(timer, &flags); |
| 813 | 837 | ||
