Hi Arnd, Today's linux-next merge of the arm-soc tree got a conflict in arch/arm/common/gic.c between commits 292b293ceef2 ("ARM: gic: consolidate PPI handling") and 28af690a284d ("ARM: gic, local timers: use the request_percpu_irq() interface") from the arm tree and commits 2071a2a4b8ed ("ARM: gic: add irq_domain support") and e3f14d321b34 ("ARM: gic: add OF based initialization") from the arm-soc tree. I hacked it up (almost certainly incorrectly - see below). Someone will have to provide Linus with a fix for this. -- Cheers, Stephen Rothwell sfr@canb.auug.org.au diff --cc arch/arm/common/gic.c index 016c1ae,65cf39d..0000000 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@@ -29,9 -29,10 +29,13 @@@ #include #include #include +#include +#include +#include + #include + #include + #include + #include #include #include @@@ -259,14 -259,14 +262,15 @@@ void __init gic_cascade_irq(unsigned in irq_set_chained_handler(irq, gic_handle_cascade_irq); } - static void __init gic_dist_init(struct gic_chip_data *gic, - unsigned int irq_start) + static void __init gic_dist_init(struct gic_chip_data *gic) { - unsigned int gic_irqs, irq_limit, i; + unsigned int i, irq; u32 cpumask; + unsigned int gic_irqs = gic->gic_irqs; + struct irq_domain *domain = &gic->domain; void __iomem *base = gic->dist_base; u32 cpu = 0; + u32 nrppis = 0, ppi_base = 0; #ifdef CONFIG_SMP cpu = cpu_logical_map(smp_processor_id()); @@@ -279,34 -279,6 +283,23 @@@ writel_relaxed(0, base + GIC_DIST_CTRL); /* - * Find out how many interrupts are supported. - * The GIC only supports up to 1020 interrupt sources. - */ - gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f; - gic_irqs = (gic_irqs + 1) * 32; - if (gic_irqs > 1020) - gic_irqs = 1020; - - gic->gic_irqs = gic_irqs; - - /* + * Nobody would be insane enough to use PPIs on a secondary + * GIC, right? + */ + if (gic == &gic_data[0]) { + nrppis = (32 - irq_start) & 31; + + /* The GIC only supports up to 16 PPIs. */ + if (nrppis > 16) + BUG(); + + ppi_base = gic->irq_offset + 32 - nrppis; + } + + pr_info("Configuring GIC with %d sources (%d PPIs)\n", + gic_irqs, (gic == &gic_data[0]) ? nrppis : 0); + + /* * Set all global interrupts to be level triggered, active low. */ for (i = 32; i < gic_irqs; i += 16) @@@ -332,29 -304,12 +325,22 @@@ writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32); /* - * Limit number of interrupts registered to the platform maximum - */ - irq_limit = gic->irq_offset + gic_irqs; - if (WARN_ON(irq_limit > NR_IRQS)) - irq_limit = NR_IRQS; - - /* * Setup the Linux IRQ subsystem. */ + for (i = 0; i < nrppis; i++) { + int ppi = i + ppi_base; + + irq_set_percpu_devid(ppi); + irq_set_chip_and_handler(ppi, &gic_chip, + handle_percpu_devid_irq); + irq_set_chip_data(ppi, gic); + set_irq_flags(ppi, IRQF_VALID | IRQF_NOAUTOEN); + } + - for (i = irq_start + nrppis; i < irq_limit; i++) { - irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq); - irq_set_chip_data(i, gic); - set_irq_flags(i, IRQF_VALID | IRQF_PROBE); + irq_domain_for_each_irq(domain, i, irq) { + irq_set_chip_and_handler(irq, &gic_chip, handle_fasteoi_irq); + irq_set_chip_data(irq, gic); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } writel_relaxed(1, base + GIC_DIST_CTRL);