aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorMilton Miller <miltonm@bga.com>2011-05-24 16:34:18 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-05-25 23:38:59 -0400
commit4dd602900196bcc00505485e2a363caec4f3fd93 (patch)
tree4876c904feadff354e9da9c21ce7e6b6d77a458b /arch/powerpc/kernel
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>
Diffstat (limited to 'arch/powerpc/kernel')
-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)
1007 WARN_ON (virq < NUM_ISA_INTERRUPTS); 1007 WARN_ON (virq < NUM_ISA_INTERRUPTS);
1008 WARN_ON (count == 0 || (virq + count) > irq_virq_count); 1008 WARN_ON (count == 0 || (virq + count) > irq_virq_count);
1009 1009
1010 if (virq < NUM_ISA_INTERRUPTS) {
1011 if (virq + count < NUM_ISA_INTERRUPTS)
1012 return;
1013 count =- NUM_ISA_INTERRUPTS - virq;
1014 virq = NUM_ISA_INTERRUPTS;
1015 }
1016
1017 if (count > irq_virq_count || virq > irq_virq_count - count) {
1018 if (virq > irq_virq_count)
1019 return;
1020 count = irq_virq_count - virq;
1021 }
1022
1010 raw_spin_lock_irqsave(&irq_big_lock, flags); 1023 raw_spin_lock_irqsave(&irq_big_lock, flags);
1011 for (i = virq; i < (virq + count); i++) { 1024 for (i = virq; i < (virq + count); i++) {
1012 struct irq_host *host; 1025 struct irq_host *host;
1013 1026
1014 if (i < NUM_ISA_INTERRUPTS ||
1015 (virq + count) > irq_virq_count)
1016 continue;
1017
1018 host = irq_map[i].host; 1027 host = irq_map[i].host;
1019 irq_map[i].hwirq = host->inval_irq; 1028 irq_map[i].hwirq = host->inval_irq;
1020 smp_wmb(); 1029 smp_wmb();