diff options
author | Rob Herring <rob.herring@calxeda.com> | 2011-10-21 18:14:27 -0400 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2011-10-31 09:03:27 -0400 |
commit | f37a53cc5d8a8fb199e41386d125d8c2ed9e54ef (patch) | |
tree | ccf7658e1dae54e7b3eeaa8413dd86d4b865eaec /arch/arm/common | |
parent | b3f7ed0324091e2cb23fe1b3c10570700f614014 (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.c | 15 |
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 | ||
565 | void __init gic_init(unsigned int gic_nr, unsigned int irq_start, | 566 | void __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); |