irqchip: gic(-v3): Mask PPIs during disable_percpu_irq()

By default, when disable_percpu_irq() is called, the IRQ chip's
.irq_mask() function is invoked. This is not the case for the
current GIC drivers however, since integration of the following
commits:

 c8e0c91f (arm: gic: Add irq_disable callback fixup)
 1270c40f (irqchip: gic: Add arch extension to GIC v3)

These changes implement .irq_disable() hooks, the presence of which
alters the behavior of disable_percpu_irq(), causing .irq_disable() to
be called instead of .irq_mask().

As a result, when disable_percpu_irq() is called, the PPI interrupt
is no longer disabled immediately. It will be lazily disabled the
next time it fires (if it fires), similar to what's done for all SPI.

This lazy-disablement of PPIs can cause problems on systems where
CPU hotplug puts cores into a low power state. If a CPU is hotpluged-
out and collapsed, a PPI from an active peripheral may fire. Since
the PPI is not masked, the CPU will receive the interrupt, waking it
from its slumber.

At best, this is bad for power reasons. The CPU will wake up and park
itself in a loop until someone decides to intentionally hotplug-in
the CPU again.  At worst, the CPU will wake up when its power
requirements (voltage, current) are not being considered, and the
system may crash in fun and interesting ways.

Revert back to the previous behaviour of masking PPIs immediately
upon calling disable_percpu_irq() by adding a call to .irq_mask()
from within .irq_disable().

This change only affects PPIs. APIs for raising SGIs contain other
protections to prevent them from being sent to offline CPUs
unintentionally. SPI are anyways migrated to other CPUs during hotplug
and, in the case of GICv3, are explicitly disabled via ICC_GRPEN1_EL1
for hotplug-removed CPUs.

This change addresses an issue where level-triggered arch_timer
interrupts are seen to wake-up offlined CPUs.

Change-Id: Id652c0ffd44c2a662a20a1308b754da672eb2b7d
Signed-off-by: Matt Wagantall <mattw@codeaurora.org>
Signed-off-by: Prasad Sodagudi <psodagud@codeaurora.org>
This commit is contained in:
Matt Wagantall 2015-03-26 23:19:04 -07:00 committed by Prasad Sodagudi
parent 35731dbb93
commit 6699819715

View file

@ -289,6 +289,9 @@ static int gic_irq_get_irqchip_state(struct irq_data *d,
}
static void gic_disable_irq(struct irq_data *d)
{
/* don't lazy-disable PPIs */
if (gic_irq(d) < 32)
gic_mask_irq(d);
if (gic_arch_extn.irq_disable)
gic_arch_extn.irq_disable(d);
}