aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/common
diff options
context:
space:
mode:
authorRob Herring <rob.herring@calxeda.com>2011-10-21 18:14:27 -0400
committerArnd Bergmann <arnd@arndb.de>2011-10-31 09:03:27 -0400
commitf37a53cc5d8a8fb199e41386d125d8c2ed9e54ef (patch)
treeccf7658e1dae54e7b3eeaa8413dd86d4b865eaec /arch/arm/common
parentb3f7ed0324091e2cb23fe1b3c10570700f614014 (diff)
ARM: gic: fix irq_alloc_descs handling for sparse irq
Commit "ARM: gic: add irq_domain support" (b49b6ff) breaks SPARSE_IRQ on platforms with GIC. When SPARSE_IRQ is enabled, all NR_IRQS or mach_desc->nr_irqs will be allocated by arch_probe_nr_irqs(). This caused irq_alloc_descs to allocate irq_descs after the pre-allocated space. Make irq_alloc_descs search for an exact irq range and assume it has been pre-allocated on failure. For DT probing dynamic allocation is used. DT enabled platforms should set their nr_irqs to NR_IRQ_LEGACY and have all irq_chips allocate their irq_descs with irq_alloc_descs if SPARSE_IRQ is enabled. gic_init irq_start param is changed to be signed with negative meaning do dynamic Linux irq assigment. Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Diffstat (limited to 'arch/arm/common')
-rw-r--r--arch/arm/common/gic.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 1333e68b1f96..9d77777076f0 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -24,6 +24,7 @@
24 */ 24 */
25#include <linux/init.h> 25#include <linux/init.h>
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/err.h>
27#include <linux/export.h> 28#include <linux/export.h>
28#include <linux/list.h> 29#include <linux/list.h>
29#include <linux/smp.h> 30#include <linux/smp.h>
@@ -562,7 +563,7 @@ const struct irq_domain_ops gic_irq_domain_ops = {
562#endif 563#endif
563}; 564};
564 565
565void __init gic_init(unsigned int gic_nr, unsigned int irq_start, 566void __init gic_init(unsigned int gic_nr, int irq_start,
566 void __iomem *dist_base, void __iomem *cpu_base) 567 void __iomem *dist_base, void __iomem *cpu_base)
567{ 568{
568 struct gic_chip_data *gic; 569 struct gic_chip_data *gic;
@@ -583,7 +584,8 @@ void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
583 if (gic_nr == 0) { 584 if (gic_nr == 0) {
584 gic_cpu_base_addr = cpu_base; 585 gic_cpu_base_addr = cpu_base;
585 domain->hwirq_base = 16; 586 domain->hwirq_base = 16;
586 irq_start = (irq_start & ~31) + 16; 587 if (irq_start > 0)
588 irq_start = (irq_start & ~31) + 16;
587 } else 589 } else
588 domain->hwirq_base = 32; 590 domain->hwirq_base = 32;
589 591
@@ -598,8 +600,13 @@ void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
598 gic->gic_irqs = gic_irqs; 600 gic->gic_irqs = gic_irqs;
599 601
600 domain->nr_irq = gic_irqs - domain->hwirq_base; 602 domain->nr_irq = gic_irqs - domain->hwirq_base;
601 domain->irq_base = irq_alloc_descs(-1, irq_start, domain->nr_irq, 603 domain->irq_base = irq_alloc_descs(irq_start, 16, domain->nr_irq,
602 numa_node_id()); 604 numa_node_id());
605 if (IS_ERR_VALUE(domain->irq_base)) {
606 WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
607 irq_start);
608 domain->irq_base = irq_start;
609 }
603 domain->priv = gic; 610 domain->priv = gic;
604 domain->ops = &gic_irq_domain_ops; 611 domain->ops = &gic_irq_domain_ops;
605 irq_domain_add(domain); 612 irq_domain_add(domain);
@@ -659,7 +666,7 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent)
659 666
660 domain->of_node = of_node_get(node); 667 domain->of_node = of_node_get(node);
661 668
662 gic_init(gic_cnt, 16, dist_base, cpu_base); 669 gic_init(gic_cnt, -1, dist_base, cpu_base);
663 670
664 if (parent) { 671 if (parent) {
665 irq = irq_of_parse_and_map(node, 0); 672 irq = irq_of_parse_and_map(node, 0);