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