diff options
Diffstat (limited to 'kernel/time/timer.c')
| -rw-r--r-- | kernel/time/timer.c | 12 | 
1 files changed, 11 insertions, 1 deletions
diff --git a/kernel/time/timer.c b/kernel/time/timer.c index ff49ddcc9800..3b57a73f249a 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -642,7 +642,8 @@ trigger_dyntick_cpu(struct timer_base *base, struct timer_list *timer)  	 * the base lock:  	 */  	if (base->is_idle) { -		WARN_ON_ONCE(!(timer->flags & TIMER_PINNED)); +		WARN_ON_ONCE(!(timer->flags & TIMER_PINNED || +			       tick_nohz_full_cpu(base->cpu)));  		wake_up_nohz_cpu(base->cpu);  	}  } @@ -2292,6 +2293,13 @@ static inline u64 __get_next_timer_interrupt(unsigned long basej, u64 basem,  		 */  		if (!base_local->is_idle && time_after(nextevt, basej + 1)) {  			base_local->is_idle = true; +			/* +			 * Global timers queued locally while running in a task +			 * in nohz_full mode need a self-IPI to kick reprogramming +			 * in IRQ tail. +			 */ +			if (tick_nohz_full_cpu(base_local->cpu)) +				base_global->is_idle = true;  			trace_timer_base_idle(true, base_local->cpu);  		}  		*idle = base_local->is_idle; @@ -2364,6 +2372,8 @@ void timer_clear_idle(void)  	 * path. Required for BASE_LOCAL only.  	 */  	__this_cpu_write(timer_bases[BASE_LOCAL].is_idle, false); +	if (tick_nohz_full_cpu(smp_processor_id())) +		__this_cpu_write(timer_bases[BASE_GLOBAL].is_idle, false);  	trace_timer_base_idle(false, smp_processor_id());  	/* Activate without holding the timer_base->lock */  | 
