diff options
author | Pawel Moll <pawel.moll@arm.com> | 2010-11-26 13:45:43 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-11-30 13:38:57 +0000 |
commit | e6afec9b6808eff6dc392ac07c1552e87aebcdf7 (patch) | |
tree | 67ea03e347da896518f96c7611eb792bf6a9f374 /arch/arm | |
parent | e8a7e48bb248a1196484d3f8afa53bded2b24e71 (diff) |
ARM: 6496/1: GIC: Do not try to register more then NR_IRQS interrupts
This change limits number of GIC-originating interrupts to the
platform maximum (defined by NR_IRQS) while still initialising
all distributor registers.
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/common/gic.c | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 772f95f1aecd..fea1bd7249b6 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -210,7 +210,7 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) void __init gic_dist_init(unsigned int gic_nr, void __iomem *base, unsigned int irq_start) { - unsigned int max_irq, i; + unsigned int gic_irqs, irq_limit, i; u32 cpumask = 1 << smp_processor_id(); if (gic_nr >= MAX_GIC_NR) @@ -226,47 +226,49 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base, /* * Find out how many interrupts are supported. - */ - max_irq = readl(base + GIC_DIST_CTR) & 0x1f; - max_irq = (max_irq + 1) * 32; - - /* * The GIC only supports up to 1020 interrupt sources. - * Limit this to either the architected maximum, or the - * platform maximum. */ - if (max_irq > max(1020, NR_IRQS)) - max_irq = max(1020, NR_IRQS); + gic_irqs = readl(base + GIC_DIST_CTR) & 0x1f; + gic_irqs = (gic_irqs + 1) * 32; + if (gic_irqs > 1020) + gic_irqs = 1020; /* * Set all global interrupts to be level triggered, active low. */ - for (i = 32; i < max_irq; i += 16) + for (i = 32; i < gic_irqs; i += 16) writel(0, base + GIC_DIST_CONFIG + i * 4 / 16); /* * Set all global interrupts to this CPU only. */ - for (i = 32; i < max_irq; i += 4) + for (i = 32; i < gic_irqs; i += 4) writel(cpumask, base + GIC_DIST_TARGET + i * 4 / 4); /* * Set priority on all global interrupts. */ - for (i = 32; i < max_irq; i += 4) + for (i = 32; i < gic_irqs; i += 4) writel(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4); /* * Disable all interrupts. Leave the PPI and SGIs alone * as these enables are banked registers. */ - for (i = 32; i < max_irq; i += 32) + for (i = 32; i < gic_irqs; i += 32) writel(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32); /* + * Limit number of interrupts registered to the platform maximum + */ + irq_limit = gic_data[gic_nr].irq_offset + gic_irqs; + if (WARN_ON(irq_limit > NR_IRQS)) + irq_limit = NR_IRQS; + + /* * Setup the Linux IRQ subsystem. */ - for (i = irq_start; i < gic_data[gic_nr].irq_offset + max_irq; i++) { + for (i = irq_start; i < irq_limit; i++) { set_irq_chip(i, &gic_chip); set_irq_chip_data(i, &gic_data[gic_nr]); set_irq_handler(i, handle_level_irq); |