diff options
Diffstat (limited to 'kernel/hrtimer.c')
-rw-r--r-- | kernel/hrtimer.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index e379ef0e9c20..dea4c9124ac8 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -590,7 +590,6 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, | |||
590 | list_add_tail(&timer->cb_entry, | 590 | list_add_tail(&timer->cb_entry, |
591 | &base->cpu_base->cb_pending); | 591 | &base->cpu_base->cb_pending); |
592 | timer->state = HRTIMER_STATE_PENDING; | 592 | timer->state = HRTIMER_STATE_PENDING; |
593 | raise_softirq(HRTIMER_SOFTIRQ); | ||
594 | return 1; | 593 | return 1; |
595 | default: | 594 | default: |
596 | BUG(); | 595 | BUG(); |
@@ -633,6 +632,11 @@ static int hrtimer_switch_to_hres(void) | |||
633 | return 1; | 632 | return 1; |
634 | } | 633 | } |
635 | 634 | ||
635 | static inline void hrtimer_raise_softirq(void) | ||
636 | { | ||
637 | raise_softirq(HRTIMER_SOFTIRQ); | ||
638 | } | ||
639 | |||
636 | #else | 640 | #else |
637 | 641 | ||
638 | static inline int hrtimer_hres_active(void) { return 0; } | 642 | static inline int hrtimer_hres_active(void) { return 0; } |
@@ -651,6 +655,7 @@ static inline int hrtimer_reprogram(struct hrtimer *timer, | |||
651 | { | 655 | { |
652 | return 0; | 656 | return 0; |
653 | } | 657 | } |
658 | static inline void hrtimer_raise_softirq(void) { } | ||
654 | 659 | ||
655 | #endif /* CONFIG_HIGH_RES_TIMERS */ | 660 | #endif /* CONFIG_HIGH_RES_TIMERS */ |
656 | 661 | ||
@@ -850,7 +855,7 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode) | |||
850 | { | 855 | { |
851 | struct hrtimer_clock_base *base, *new_base; | 856 | struct hrtimer_clock_base *base, *new_base; |
852 | unsigned long flags; | 857 | unsigned long flags; |
853 | int ret; | 858 | int ret, raise; |
854 | 859 | ||
855 | base = lock_hrtimer_base(timer, &flags); | 860 | base = lock_hrtimer_base(timer, &flags); |
856 | 861 | ||
@@ -884,8 +889,18 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode) | |||
884 | enqueue_hrtimer(timer, new_base, | 889 | enqueue_hrtimer(timer, new_base, |
885 | new_base->cpu_base == &__get_cpu_var(hrtimer_bases)); | 890 | new_base->cpu_base == &__get_cpu_var(hrtimer_bases)); |
886 | 891 | ||
892 | /* | ||
893 | * The timer may be expired and moved to the cb_pending | ||
894 | * list. We can not raise the softirq with base lock held due | ||
895 | * to a possible deadlock with runqueue lock. | ||
896 | */ | ||
897 | raise = timer->state == HRTIMER_STATE_PENDING; | ||
898 | |||
887 | unlock_hrtimer_base(timer, &flags); | 899 | unlock_hrtimer_base(timer, &flags); |
888 | 900 | ||
901 | if (raise) | ||
902 | hrtimer_raise_softirq(); | ||
903 | |||
889 | return ret; | 904 | return ret; |
890 | } | 905 | } |
891 | EXPORT_SYMBOL_GPL(hrtimer_start); | 906 | EXPORT_SYMBOL_GPL(hrtimer_start); |