diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/hrtimer.c | 53 |
1 files changed, 35 insertions, 18 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index e2f91ecc01a8..1363c1aac158 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -486,13 +486,14 @@ static inline int hrtimer_hres_active(void) | |||
486 | * next event | 486 | * next event |
487 | * Called with interrupts disabled and base->lock held | 487 | * Called with interrupts disabled and base->lock held |
488 | */ | 488 | */ |
489 | static void hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base) | 489 | static void |
490 | hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal) | ||
490 | { | 491 | { |
491 | int i; | 492 | int i; |
492 | struct hrtimer_clock_base *base = cpu_base->clock_base; | 493 | struct hrtimer_clock_base *base = cpu_base->clock_base; |
493 | ktime_t expires; | 494 | ktime_t expires, expires_next; |
494 | 495 | ||
495 | cpu_base->expires_next.tv64 = KTIME_MAX; | 496 | expires_next.tv64 = KTIME_MAX; |
496 | 497 | ||
497 | for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) { | 498 | for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) { |
498 | struct hrtimer *timer; | 499 | struct hrtimer *timer; |
@@ -508,10 +509,15 @@ static void hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base) | |||
508 | */ | 509 | */ |
509 | if (expires.tv64 < 0) | 510 | if (expires.tv64 < 0) |
510 | expires.tv64 = 0; | 511 | expires.tv64 = 0; |
511 | if (expires.tv64 < cpu_base->expires_next.tv64) | 512 | if (expires.tv64 < expires_next.tv64) |
512 | cpu_base->expires_next = expires; | 513 | expires_next = expires; |
513 | } | 514 | } |
514 | 515 | ||
516 | if (skip_equal && expires_next.tv64 == cpu_base->expires_next.tv64) | ||
517 | return; | ||
518 | |||
519 | cpu_base->expires_next.tv64 = expires_next.tv64; | ||
520 | |||
515 | if (cpu_base->expires_next.tv64 != KTIME_MAX) | 521 | if (cpu_base->expires_next.tv64 != KTIME_MAX) |
516 | tick_program_event(cpu_base->expires_next, 1); | 522 | tick_program_event(cpu_base->expires_next, 1); |
517 | } | 523 | } |
@@ -594,7 +600,7 @@ static void retrigger_next_event(void *arg) | |||
594 | base->clock_base[CLOCK_REALTIME].offset = | 600 | base->clock_base[CLOCK_REALTIME].offset = |
595 | timespec_to_ktime(realtime_offset); | 601 | timespec_to_ktime(realtime_offset); |
596 | 602 | ||
597 | hrtimer_force_reprogram(base); | 603 | hrtimer_force_reprogram(base, 0); |
598 | spin_unlock(&base->lock); | 604 | spin_unlock(&base->lock); |
599 | } | 605 | } |
600 | 606 | ||
@@ -707,7 +713,8 @@ static int hrtimer_switch_to_hres(void) | |||
707 | static inline int hrtimer_hres_active(void) { return 0; } | 713 | static inline int hrtimer_hres_active(void) { return 0; } |
708 | static inline int hrtimer_is_hres_enabled(void) { return 0; } | 714 | static inline int hrtimer_is_hres_enabled(void) { return 0; } |
709 | static inline int hrtimer_switch_to_hres(void) { return 0; } | 715 | static inline int hrtimer_switch_to_hres(void) { return 0; } |
710 | static inline void hrtimer_force_reprogram(struct hrtimer_cpu_base *base) { } | 716 | static inline void |
717 | hrtimer_force_reprogram(struct hrtimer_cpu_base *base, int skip_equal) { } | ||
711 | static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, | 718 | static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, |
712 | struct hrtimer_clock_base *base, | 719 | struct hrtimer_clock_base *base, |
713 | int wakeup) | 720 | int wakeup) |
@@ -850,19 +857,29 @@ static void __remove_hrtimer(struct hrtimer *timer, | |||
850 | struct hrtimer_clock_base *base, | 857 | struct hrtimer_clock_base *base, |
851 | unsigned long newstate, int reprogram) | 858 | unsigned long newstate, int reprogram) |
852 | { | 859 | { |
853 | if (timer->state & HRTIMER_STATE_ENQUEUED) { | 860 | if (!(timer->state & HRTIMER_STATE_ENQUEUED)) |
854 | /* | 861 | goto out; |
855 | * Remove the timer from the rbtree and replace the | 862 | |
856 | * first entry pointer if necessary. | 863 | /* |
857 | */ | 864 | * Remove the timer from the rbtree and replace the first |
858 | if (base->first == &timer->node) { | 865 | * entry pointer if necessary. |
859 | base->first = rb_next(&timer->node); | 866 | */ |
860 | /* Reprogram the clock event device. if enabled */ | 867 | if (base->first == &timer->node) { |
861 | if (reprogram && hrtimer_hres_active()) | 868 | base->first = rb_next(&timer->node); |
862 | hrtimer_force_reprogram(base->cpu_base); | 869 | #ifdef CONFIG_HIGH_RES_TIMERS |
870 | /* Reprogram the clock event device. if enabled */ | ||
871 | if (reprogram && hrtimer_hres_active()) { | ||
872 | ktime_t expires; | ||
873 | |||
874 | expires = ktime_sub(hrtimer_get_expires(timer), | ||
875 | base->offset); | ||
876 | if (base->cpu_base->expires_next.tv64 == expires.tv64) | ||
877 | hrtimer_force_reprogram(base->cpu_base, 1); | ||
863 | } | 878 | } |
864 | rb_erase(&timer->node, &base->active); | 879 | #endif |
865 | } | 880 | } |
881 | rb_erase(&timer->node, &base->active); | ||
882 | out: | ||
866 | timer->state = newstate; | 883 | timer->state = newstate; |
867 | } | 884 | } |
868 | 885 | ||