diff options
Diffstat (limited to 'kernel/hrtimer.c')
| -rw-r--r-- | kernel/hrtimer.c | 38 | 
1 files changed, 20 insertions, 18 deletions
| diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 6db7a5ed52b5..cc47812d3feb 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -44,6 +44,8 @@  #include <linux/err.h>  #include <linux/debugobjects.h>  #include <linux/sched.h> +#include <linux/sched/sysctl.h> +#include <linux/sched/rt.h>  #include <linux/timer.h>  #include <asm/uaccess.h> @@ -640,21 +642,9 @@ static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base)   * and expiry check is done in the hrtimer_interrupt or in the softirq.   */  static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, -					    struct hrtimer_clock_base *base, -					    int wakeup) +					    struct hrtimer_clock_base *base)  { -	if (base->cpu_base->hres_active && hrtimer_reprogram(timer, base)) { -		if (wakeup) { -			raw_spin_unlock(&base->cpu_base->lock); -			raise_softirq_irqoff(HRTIMER_SOFTIRQ); -			raw_spin_lock(&base->cpu_base->lock); -		} else -			__raise_softirq_irqoff(HRTIMER_SOFTIRQ); - -		return 1; -	} - -	return 0; +	return base->cpu_base->hres_active && hrtimer_reprogram(timer, base);  }  static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base) @@ -735,8 +725,7 @@ static inline int hrtimer_switch_to_hres(void) { return 0; }  static inline void  hrtimer_force_reprogram(struct hrtimer_cpu_base *base, int skip_equal) { }  static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, -					    struct hrtimer_clock_base *base, -					    int wakeup) +					    struct hrtimer_clock_base *base)  {  	return 0;  } @@ -995,8 +984,21 @@ int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,  	 *  	 * XXX send_remote_softirq() ?  	 */ -	if (leftmost && new_base->cpu_base == &__get_cpu_var(hrtimer_bases)) -		hrtimer_enqueue_reprogram(timer, new_base, wakeup); +	if (leftmost && new_base->cpu_base == &__get_cpu_var(hrtimer_bases) +		&& hrtimer_enqueue_reprogram(timer, new_base)) { +		if (wakeup) { +			/* +			 * We need to drop cpu_base->lock to avoid a +			 * lock ordering issue vs. rq->lock. +			 */ +			raw_spin_unlock(&new_base->cpu_base->lock); +			raise_softirq_irqoff(HRTIMER_SOFTIRQ); +			local_irq_restore(flags); +			return ret; +		} else { +			__raise_softirq_irqoff(HRTIMER_SOFTIRQ); +		} +	}  	unlock_hrtimer_base(timer, &flags); |