Commit e6afec9b authored by Pawel Moll's avatar Pawel Moll Committed by Russell King

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: default avatarPawel Moll <pawel.moll@arm.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent e8a7e48b
...@@ -210,7 +210,7 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) ...@@ -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, void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
unsigned int irq_start) unsigned int irq_start)
{ {
unsigned int max_irq, i; unsigned int gic_irqs, irq_limit, i;
u32 cpumask = 1 << smp_processor_id(); u32 cpumask = 1 << smp_processor_id();
if (gic_nr >= MAX_GIC_NR) if (gic_nr >= MAX_GIC_NR)
...@@ -226,47 +226,49 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base, ...@@ -226,47 +226,49 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
/* /*
* Find out how many interrupts are supported. * 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. * 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)) gic_irqs = readl(base + GIC_DIST_CTR) & 0x1f;
max_irq = max(1020, NR_IRQS); gic_irqs = (gic_irqs + 1) * 32;
if (gic_irqs > 1020)
gic_irqs = 1020;
/* /*
* Set all global interrupts to be level triggered, active low. * 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); writel(0, base + GIC_DIST_CONFIG + i * 4 / 16);
/* /*
* Set all global interrupts to this CPU only. * 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); writel(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
/* /*
* Set priority on all global interrupts. * 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); writel(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
/* /*
* Disable all interrupts. Leave the PPI and SGIs alone * Disable all interrupts. Leave the PPI and SGIs alone
* as these enables are banked registers. * 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); 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. * 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(i, &gic_chip);
set_irq_chip_data(i, &gic_data[gic_nr]); set_irq_chip_data(i, &gic_data[gic_nr]);
set_irq_handler(i, handle_level_irq); set_irq_handler(i, handle_level_irq);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment