summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilton Miller <miltonm@bga.com>2011-05-24 20:34:18 +0000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-05-26 13:38:59 +1000
commit4dd602900196bcc00505485e2a363caec4f3fd93 (patch)
tree4876c904feadff354e9da9c21ce7e6b6d77a458b
parent9b7882515864117d0015a3484c0ba0eee6713de9 (diff)
powerpc: Fix irq_free_virt by adjusting bounds before loop
Instead of looping over each irq and checking against the irq array bounds, adjust the bounds before looping. The old code will not free any irq if the irq + count is above irq_virq_count because the test in the loop is testing irq + count instead of irq + i. This code checks the limits to avoid unsigned integer overflows. Signed-off-by: Milton Miller <miltonm@bga.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/kernel/irq.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 6cb3fcd7fc37..5b428e308666 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -1007,14 +1007,23 @@ void irq_free_virt(unsigned int virq, unsigned int count)
WARN_ON (virq < NUM_ISA_INTERRUPTS);
WARN_ON (count == 0 || (virq + count) > irq_virq_count);
+ if (virq < NUM_ISA_INTERRUPTS) {
+ if (virq + count < NUM_ISA_INTERRUPTS)
+ return;
+ count =- NUM_ISA_INTERRUPTS - virq;
+ virq = NUM_ISA_INTERRUPTS;
+ }
+
+ if (count > irq_virq_count || virq > irq_virq_count - count) {
+ if (virq > irq_virq_count)
+ return;
+ count = irq_virq_count - virq;
+ }
+
raw_spin_lock_irqsave(&irq_big_lock, flags);
for (i = virq; i < (virq + count); i++) {
struct irq_host *host;
- if (i < NUM_ISA_INTERRUPTS ||
- (virq + count) > irq_virq_count)
- continue;
-
host = irq_map[i].host;
irq_map[i].hwirq = host->inval_irq;
smp_wmb();