diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-07-21 10:00:57 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-07-21 10:04:17 -0400 |
commit | 5dfc54e087c15f823ee9b6541d2f0f314e69cbed (patch) | |
tree | 845cabe598342a9dea2b77dafef629961ee0c89c /arch/arm/common | |
parent | 2ef75701d1711a1feee2a82b42a2597ddc05f88b (diff) |
ARM: GIC: avoid routing interrupts to offline CPUs
The irq_set_affinity() method can be called with masks which include
offline CPUs. This allows offline CPUs to have interrupts routed to
them by writing to /proc/irq/*/smp_affinity after hotplug has taken
a CPU offline. Fix this by ensuring that we select a target CPU
present in both the required affinity and the online CPU mask.
Ensure that we return IRQ_SET_MASK_OK (which happens to be 0) on
success to ensure generic code copies the new mask into the irq_data
structure.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/common')
-rw-r--r-- | arch/arm/common/gic.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 635d9857b07a..7bdd91766d65 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c | |||
@@ -179,10 +179,10 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, | |||
179 | { | 179 | { |
180 | void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3); | 180 | void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3); |
181 | unsigned int shift = (d->irq % 4) * 8; | 181 | unsigned int shift = (d->irq % 4) * 8; |
182 | unsigned int cpu = cpumask_first(mask_val); | 182 | unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask); |
183 | u32 val, mask, bit; | 183 | u32 val, mask, bit; |
184 | 184 | ||
185 | if (cpu >= 8) | 185 | if (cpu >= 8 || cpu >= nr_cpu_ids) |
186 | return -EINVAL; | 186 | return -EINVAL; |
187 | 187 | ||
188 | mask = 0xff << shift; | 188 | mask = 0xff << shift; |
@@ -193,7 +193,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, | |||
193 | writel_relaxed(val | bit, reg); | 193 | writel_relaxed(val | bit, reg); |
194 | spin_unlock(&irq_controller_lock); | 194 | spin_unlock(&irq_controller_lock); |
195 | 195 | ||
196 | return 0; | 196 | return IRQ_SET_MASK_OK; |
197 | } | 197 | } |
198 | #endif | 198 | #endif |
199 | 199 | ||