aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2009-05-21 12:28:33 -0400
committerPaul Mundt <lethal@linux-sh.org>2009-05-21 12:28:33 -0400
commit05ff3004d278b54760abd71530506d803182c71d (patch)
treed00343e85051b7cf4d671b9131581dfa6ad35456
parentfa1d43ab451084785153d37ae559c4fdd1546a5b (diff)
sh: irq: Teach ipr and intc about dynamically allocating irq_descs.
This hooks in irq_to_desc_alloc_cpu() to the necessary code paths in the intc and ipr controller registration paths. As these are the primary call paths for all SH CPUs, this alone will make all CPUs sparse IRQ ready. There is the added benefit now that each CPU contains specific IPR and INTC tables, so only the vectors with interrupt sources backing them will ever see an irq_desc instantiation. This effectively packs irq_desc down to match the CPU, rather than padding NR_IRQS out to cover the valid vector range. Boards with extra sources will still have to fiddle with the nr_irqs setting, but they can continue doing so through the machvec as before. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r--arch/sh/kernel/cpu/irq/ipr.c8
-rw-r--r--drivers/sh/intc.c12
2 files changed, 18 insertions, 2 deletions
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index 3eb17ee5540e..fa0c8467a280 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -59,10 +59,18 @@ void register_ipr_controller(struct ipr_desc *desc)
59 59
60 for (i = 0; i < desc->nr_irqs; i++) { 60 for (i = 0; i < desc->nr_irqs; i++) {
61 struct ipr_data *p = desc->ipr_data + i; 61 struct ipr_data *p = desc->ipr_data + i;
62 struct irq_desc *irq_desc;
62 63
63 BUG_ON(p->ipr_idx >= desc->nr_offsets); 64 BUG_ON(p->ipr_idx >= desc->nr_offsets);
64 BUG_ON(!desc->ipr_offsets[p->ipr_idx]); 65 BUG_ON(!desc->ipr_offsets[p->ipr_idx]);
65 66
67 irq_desc = irq_to_desc_alloc_cpu(p->irq, smp_processor_id());
68 if (unlikely(!irq_desc)) {
69 printk(KERN_INFO "can not get irq_desc for %d\n",
70 p->irq);
71 continue;
72 }
73
66 disable_irq_nosync(p->irq); 74 disable_irq_nosync(p->irq);
67 set_irq_chip_and_handler_name(p->irq, &desc->chip, 75 set_irq_chip_and_handler_name(p->irq, &desc->chip,
68 handle_level_irq, "level"); 76 handle_level_irq, "level");
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index 12d13d99b6f0..098b767e9afd 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -671,7 +671,7 @@ unsigned int intc_evt2irq(unsigned int vector)
671 671
672void __init register_intc_controller(struct intc_desc *desc) 672void __init register_intc_controller(struct intc_desc *desc)
673{ 673{
674 unsigned int i, k, smp; 674 unsigned int i, k, smp, cpu = smp_processor_id();
675 struct intc_desc_int *d; 675 struct intc_desc_int *d;
676 676
677 d = alloc_bootmem(sizeof(*d)); 677 d = alloc_bootmem(sizeof(*d));
@@ -770,11 +770,19 @@ void __init register_intc_controller(struct intc_desc *desc)
770 /* register the vectors one by one */ 770 /* register the vectors one by one */
771 for (i = 0; i < desc->nr_vectors; i++) { 771 for (i = 0; i < desc->nr_vectors; i++) {
772 struct intc_vect *vect = desc->vectors + i; 772 struct intc_vect *vect = desc->vectors + i;
773 unsigned int irq = evt2irq(vect->vect);
774 struct irq_desc *irq_desc;
773 775
774 if (!vect->enum_id) 776 if (!vect->enum_id)
775 continue; 777 continue;
776 778
777 intc_register_irq(desc, d, vect->enum_id, evt2irq(vect->vect)); 779 irq_desc = irq_to_desc_alloc_cpu(irq, cpu);
780 if (unlikely(!irq_desc)) {
781 printk(KERN_INFO "can not get irq_desc for %d\n", irq);
782 continue;
783 }
784
785 intc_register_irq(desc, d, vect->enum_id, irq);
778 } 786 }
779} 787}
780 788