diff options
Diffstat (limited to 'kernel/hrtimer.c')
| -rw-r--r-- | kernel/hrtimer.c | 22 | 
1 files changed, 22 insertions, 0 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index d55092ceee29..6b715c0af1b1 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -234,6 +234,11 @@ again:  			goto again;  		}  		timer->base = new_base; +	} else { +		if (cpu != this_cpu && hrtimer_check_target(timer, new_base)) { +			cpu = this_cpu; +			goto again; +		}  	}  	return new_base;  } @@ -569,6 +574,23 @@ hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal)  	cpu_base->expires_next.tv64 = expires_next.tv64; +	/* +	 * If a hang was detected in the last timer interrupt then we +	 * leave the hang delay active in the hardware. We want the +	 * system to make progress. That also prevents the following +	 * scenario: +	 * T1 expires 50ms from now +	 * T2 expires 5s from now +	 * +	 * T1 is removed, so this code is called and would reprogram +	 * the hardware to 5s from now. Any hrtimer_start after that +	 * will not reprogram the hardware due to hang_detected being +	 * set. So we'd effectivly block all timers until the T2 event +	 * fires. +	 */ +	if (cpu_base->hang_detected) +		return; +  	if (cpu_base->expires_next.tv64 != KTIME_MAX)  		tick_program_event(cpu_base->expires_next, 1);  }  | 
