diff options
author | Frederic Weisbecker <fweisbec@gmail.com> | 2014-08-18 01:36:07 +0200 |
---|---|---|
committer | Frederic Weisbecker <fweisbec@gmail.com> | 2014-09-13 18:46:41 +0200 |
commit | 9b01f5bf3999a3db5b1bbd9fdfd80d8d304e94ee (patch) | |
tree | 6536b57cc841ab42187b94245ca7fddf192a12ba /kernel/time | |
parent | 4327b15f64b2580dad40d2674d50fc44f1b699c1 (diff) | |
download | blackbird-op-linux-9b01f5bf3999a3db5b1bbd9fdfd80d8d304e94ee.tar.gz blackbird-op-linux-9b01f5bf3999a3db5b1bbd9fdfd80d8d304e94ee.zip |
nohz: nohz full depends on irq work self IPI support
The nohz full functionality depends on IRQ work to trigger its own
interrupts. As it's used to restart the tick, we can't rely on the tick
fallback for irq work callbacks, ie: we can't use the tick to restart
the tick itself.
Lets reject the full dynticks initialization if that arch support isn't
available.
As a side effect, this makes sure that nohz kick is never called from
the tick. That otherwise would result in illegal hrtimer self-cancellation
and lockup.
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Diffstat (limited to 'kernel/time')
-rw-r--r-- | kernel/time/tick-sched.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index eb4af016ac65..5a9ff243588c 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -365,6 +365,20 @@ void __init tick_nohz_init(void) return; } + /* + * Full dynticks uses irq work to drive the tick rescheduling on safe + * locking contexts. But then we need irq work to raise its own + * interrupts to avoid circular dependency on the tick + */ + if (!arch_irq_work_has_interrupt()) { + pr_warning("NO_HZ: Can't run full dynticks because arch doesn't " + "support irq work self-IPIs\n"); + cpumask_clear(tick_nohz_full_mask); + cpumask_copy(housekeeping_mask, cpu_possible_mask); + tick_nohz_full_running = false; + return; + } + cpu = smp_processor_id(); if (cpumask_test_cpu(cpu, tick_nohz_full_mask)) { |