ARM: 6197/2: preliminary support for sparse IRQ
authoreric miao <eric.y.miao@gmail.com>
Fri, 25 Jun 2010 08:46:09 +0000 (09:46 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Fri, 9 Jul 2010 13:41:33 +0000 (14:41 +0100)
So to allow NR_IRQS to be dynamic and platforms to specify the number
of IRQs really needed.

Acked-by: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Eric Miao <eric.y.miao@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/Kconfig
arch/arm/include/asm/irq.h
arch/arm/include/asm/mach/arch.h
arch/arm/include/asm/mach/irq.h
arch/arm/kernel/irq.c
arch/arm/kernel/setup.c

index 1f254bd..9a0ed36 100644 (file)
@@ -1289,6 +1289,18 @@ config HW_PERF_EVENTS
          Enable hardware performance counter support for perf events. If
          disabled, perf events will use software events only.
 
+config SPARSE_IRQ
+       bool "Support sparse irq numbering"
+       depends on EXPERIMENTAL
+       help
+         This enables support for sparse irqs. This is useful in general
+         as most CPUs have a fairly sparse array of IRQ vectors, which
+         the irq_desc then maps directly on to. Systems with a high
+         number of off-chip IRQs will want to treat this as
+         experimental until they have been independently verified.
+
+         If you don't know what to do here, say N.
+
 source "mm/Kconfig"
 
 config LEDS
index 237282f..2721a58 100644 (file)
@@ -7,6 +7,8 @@
 #define irq_canonicalize(i)    (i)
 #endif
 
+#define NR_IRQS_LEGACY 16
+
 /*
  * Use this value to indicate lack of interrupt
  * capability
index c59842d..5ee6f85 100644 (file)
@@ -20,6 +20,7 @@ struct machine_desc {
         * by assembler code in head.S, head-common.S
         */
        unsigned int            nr;             /* architecture number  */
+       unsigned int            nr_irqs;        /* number of IRQs */
        unsigned int            phys_io;        /* start of physical io */
        unsigned int            io_pg_offst;    /* byte offset for io 
                                                 * page tabe entry      */
index 8920b2d..ce3eee9 100644 (file)
@@ -17,6 +17,7 @@ struct seq_file;
 /*
  * This is internal.  Do not use it.
  */
+extern unsigned int arch_nr_irqs;
 extern void (*init_arch_irq)(void);
 extern void init_FIQ(void);
 extern int show_fiq_list(struct seq_file *, void *);
index 3b3d2c8..c0d5c3b 100644 (file)
 #define irq_finish(irq) do { } while (0)
 #endif
 
+unsigned int arch_nr_irqs;
 void (*init_arch_irq)(void) __initdata = NULL;
 unsigned long irq_err_count;
 
 int show_interrupts(struct seq_file *p, void *v)
 {
        int i = *(loff_t *) v, cpu;
+       struct irq_desc *desc;
        struct irqaction * action;
        unsigned long flags;
 
@@ -67,24 +69,25 @@ int show_interrupts(struct seq_file *p, void *v)
                seq_putc(p, '\n');
        }
 
-       if (i < NR_IRQS) {
-               raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-               action = irq_desc[i].action;
+       if (i < nr_irqs) {
+               desc = irq_to_desc(i);
+               raw_spin_lock_irqsave(&desc->lock, flags);
+               action = desc->action;
                if (!action)
                        goto unlock;
 
                seq_printf(p, "%3d: ", i);
                for_each_present_cpu(cpu)
                        seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
-               seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
+               seq_printf(p, " %10s", desc->chip->name ? : "-");
                seq_printf(p, "  %s", action->name);
                for (action = action->next; action; action = action->next)
                        seq_printf(p, ", %s", action->name);
 
                seq_putc(p, '\n');
 unlock:
-               raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-       } else if (i == NR_IRQS) {
+               raw_spin_unlock_irqrestore(&desc->lock, flags);
+       } else if (i == nr_irqs) {
 #ifdef CONFIG_FIQ
                show_fiq_list(p, v);
 #endif
@@ -112,7 +115,7 @@ asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
         * Some hardware gives randomly wrong interrupts.  Rather
         * than crashing, do something sensible.
         */
-       if (unlikely(irq >= NR_IRQS)) {
+       if (unlikely(irq >= nr_irqs)) {
                if (printk_ratelimit())
                        printk(KERN_WARNING "Bad IRQ%u\n", irq);
                ack_bad_irq(irq);
@@ -132,12 +135,12 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)
        struct irq_desc *desc;
        unsigned long flags;
 
-       if (irq >= NR_IRQS) {
+       if (irq >= nr_irqs) {
                printk(KERN_ERR "Trying to set irq flags for IRQ%d\n", irq);
                return;
        }
 
-       desc = irq_desc + irq;
+       desc = irq_to_desc(irq);
        raw_spin_lock_irqsave(&desc->lock, flags);
        desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
        if (iflags & IRQF_VALID)
@@ -151,14 +154,25 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)
 
 void __init init_IRQ(void)
 {
+       struct irq_desc *desc;
        int irq;
 
-       for (irq = 0; irq < NR_IRQS; irq++)
-               irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE;
+       for (irq = 0; irq < nr_irqs; irq++) {
+               desc = irq_to_desc_alloc_node(irq, 0);
+               desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE;
+       }
 
        init_arch_irq();
 }
 
+#ifdef CONFIG_SPARSE_IRQ
+int __init arch_probe_nr_irqs(void)
+{
+       nr_irqs = arch_nr_irqs ? arch_nr_irqs : NR_IRQS;
+       return 0;
+}
+#endif
+
 #ifdef CONFIG_HOTPLUG_CPU
 
 static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu)
@@ -178,10 +192,9 @@ static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu)
 void migrate_irqs(void)
 {
        unsigned int i, cpu = smp_processor_id();
+       struct irq_desc *desc;
 
-       for (i = 0; i < NR_IRQS; i++) {
-               struct irq_desc *desc = irq_desc + i;
-
+       for_each_irq_desc(i, desc) {
                if (desc->node == cpu) {
                        unsigned int newcpu = cpumask_any_and(desc->affinity,
                                                              cpu_online_mask);
index 122d999..7ae65dc 100644 (file)
@@ -729,6 +729,7 @@ void __init setup_arch(char **cmdline_p)
        /*
         * Set up various architecture-specific pointers
         */
+       arch_nr_irqs = mdesc->nr_irqs;
        init_arch_irq = mdesc->init_irq;
        system_timer = mdesc->timer;
        init_machine = mdesc->init_machine;