diff options
Diffstat (limited to 'kernel/hrtimer.c')
| -rw-r--r-- | kernel/hrtimer.c | 55 |
1 files changed, 35 insertions, 20 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index e5d98ce50f89..3e1c36e7998f 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
| @@ -509,13 +509,14 @@ static inline int hrtimer_hres_active(void) | |||
| 509 | * next event | 509 | * next event |
| 510 | * Called with interrupts disabled and base->lock held | 510 | * Called with interrupts disabled and base->lock held |
| 511 | */ | 511 | */ |
| 512 | static void hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base) | 512 | static void |
| 513 | hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal) | ||
| 513 | { | 514 | { |
| 514 | int i; | 515 | int i; |
| 515 | struct hrtimer_clock_base *base = cpu_base->clock_base; | 516 | struct hrtimer_clock_base *base = cpu_base->clock_base; |
| 516 | ktime_t expires; | 517 | ktime_t expires, expires_next; |
| 517 | 518 | ||
| 518 | cpu_base->expires_next.tv64 = KTIME_MAX; | 519 | expires_next.tv64 = KTIME_MAX; |
| 519 | 520 | ||
| 520 | for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) { | 521 | for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) { |
| 521 | struct hrtimer *timer; | 522 | struct hrtimer *timer; |
| @@ -531,10 +532,15 @@ static void hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base) | |||
| 531 | */ | 532 | */ |
| 532 | if (expires.tv64 < 0) | 533 | if (expires.tv64 < 0) |
| 533 | expires.tv64 = 0; | 534 | expires.tv64 = 0; |
| 534 | if (expires.tv64 < cpu_base->expires_next.tv64) | 535 | if (expires.tv64 < expires_next.tv64) |
| 535 | cpu_base->expires_next = expires; | 536 | expires_next = expires; |
| 536 | } | 537 | } |
| 537 | 538 | ||
| 539 | if (skip_equal && expires_next.tv64 == cpu_base->expires_next.tv64) | ||
| 540 | return; | ||
| 541 | |||
| 542 | cpu_base->expires_next.tv64 = expires_next.tv64; | ||
| 543 | |||
| 538 | if (cpu_base->expires_next.tv64 != KTIME_MAX) | 544 | if (cpu_base->expires_next.tv64 != KTIME_MAX) |
| 539 | tick_program_event(cpu_base->expires_next, 1); | 545 | tick_program_event(cpu_base->expires_next, 1); |
| 540 | } | 546 | } |
| @@ -617,7 +623,7 @@ static void retrigger_next_event(void *arg) | |||
| 617 | base->clock_base[CLOCK_REALTIME].offset = | 623 | base->clock_base[CLOCK_REALTIME].offset = |
| 618 | timespec_to_ktime(realtime_offset); | 624 | timespec_to_ktime(realtime_offset); |
| 619 | 625 | ||
| 620 | hrtimer_force_reprogram(base); | 626 | hrtimer_force_reprogram(base, 0); |
| 621 | spin_unlock(&base->lock); | 627 | spin_unlock(&base->lock); |
| 622 | } | 628 | } |
| 623 | 629 | ||
| @@ -720,8 +726,6 @@ static int hrtimer_switch_to_hres(void) | |||
| 720 | /* "Retrigger" the interrupt to get things going */ | 726 | /* "Retrigger" the interrupt to get things going */ |
| 721 | retrigger_next_event(NULL); | 727 | retrigger_next_event(NULL); |
| 722 | local_irq_restore(flags); | 728 | local_irq_restore(flags); |
| 723 | printk(KERN_DEBUG "Switched to high resolution mode on CPU %d\n", | ||
| 724 | smp_processor_id()); | ||
| 725 | return 1; | 729 | return 1; |
| 726 | } | 730 | } |
| 727 | 731 | ||
| @@ -730,7 +734,8 @@ static int hrtimer_switch_to_hres(void) | |||
| 730 | static inline int hrtimer_hres_active(void) { return 0; } | 734 | static inline int hrtimer_hres_active(void) { return 0; } |
| 731 | static inline int hrtimer_is_hres_enabled(void) { return 0; } | 735 | static inline int hrtimer_is_hres_enabled(void) { return 0; } |
| 732 | static inline int hrtimer_switch_to_hres(void) { return 0; } | 736 | static inline int hrtimer_switch_to_hres(void) { return 0; } |
| 733 | static inline void hrtimer_force_reprogram(struct hrtimer_cpu_base *base) { } | 737 | static inline void |
| 738 | hrtimer_force_reprogram(struct hrtimer_cpu_base *base, int skip_equal) { } | ||
| 734 | static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, | 739 | static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, |
| 735 | struct hrtimer_clock_base *base, | 740 | struct hrtimer_clock_base *base, |
| 736 | int wakeup) | 741 | int wakeup) |
| @@ -873,19 +878,29 @@ static void __remove_hrtimer(struct hrtimer *timer, | |||
| 873 | struct hrtimer_clock_base *base, | 878 | struct hrtimer_clock_base *base, |
| 874 | unsigned long newstate, int reprogram) | 879 | unsigned long newstate, int reprogram) |
| 875 | { | 880 | { |
| 876 | if (timer->state & HRTIMER_STATE_ENQUEUED) { | 881 | if (!(timer->state & HRTIMER_STATE_ENQUEUED)) |
| 877 | /* | 882 | goto out; |
| 878 | * Remove the timer from the rbtree and replace the | 883 | |
| 879 | * first entry pointer if necessary. | 884 | /* |
| 880 | */ | 885 | * Remove the timer from the rbtree and replace the first |
| 881 | if (base->first == &timer->node) { | 886 | * entry pointer if necessary. |
| 882 | base->first = rb_next(&timer->node); | 887 | */ |
| 883 | /* Reprogram the clock event device. if enabled */ | 888 | if (base->first == &timer->node) { |
| 884 | if (reprogram && hrtimer_hres_active()) | 889 | base->first = rb_next(&timer->node); |
| 885 | hrtimer_force_reprogram(base->cpu_base); | 890 | #ifdef CONFIG_HIGH_RES_TIMERS |
| 891 | /* Reprogram the clock event device. if enabled */ | ||
| 892 | if (reprogram && hrtimer_hres_active()) { | ||
| 893 | ktime_t expires; | ||
| 894 | |||
| 895 | expires = ktime_sub(hrtimer_get_expires(timer), | ||
| 896 | base->offset); | ||
| 897 | if (base->cpu_base->expires_next.tv64 == expires.tv64) | ||
| 898 | hrtimer_force_reprogram(base->cpu_base, 1); | ||
| 886 | } | 899 | } |
| 887 | rb_erase(&timer->node, &base->active); | 900 | #endif |
| 888 | } | 901 | } |
| 902 | rb_erase(&timer->node, &base->active); | ||
| 903 | out: | ||
| 889 | timer->state = newstate; | 904 | timer->state = newstate; |
| 890 | } | 905 | } |
| 891 | 906 | ||
