[RFC] preliminary support for sparse IRQ

Eric Miao eric.y.miao at gmail.com
Mon Dec 28 00:03:37 EST 2009


commit 0dfd0ec8edf8a704d88903ba94c5dc377008e56c
Author: Eric Miao <eric.y.miao at gmail.com>
Date:   Mon Dec 28 12:59:59 2009 +0800

    [ARM] preliminary support for sparse IRQ

    So to allow NR_IRQS to be dynamic and platforms to specify the number
    of IRQs really needed.

    Signed-off-by: Eric Miao <eric.y.miao at gmail.com>

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 233a222..d57b5c3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -917,6 +917,18 @@ config ARM_ERRATA_460075
 	  ACTLR register. Note that setting specific bits in the ACTLR register
 	  may not be available in non-secure mode.

+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.
+
 endmenu

 source "arch/arm/common/Kconfig"
diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h
index 328f14a..a1ea728 100644
--- a/arch/arm/include/asm/irq.h
+++ b/arch/arm/include/asm/irq.h
@@ -7,6 +7,8 @@
 #define irq_canonicalize(i)	(i)
 #endif

+#define NR_IRQS_LEGACY	16
+
 /*
  * Use this value to indicate lack of interrupt
  * capability
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index c59842d..5ee6f85 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -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	*/
diff --git a/arch/arm/include/asm/mach/irq.h b/arch/arm/include/asm/mach/irq.h
index 8920b2d..ce3eee9 100644
--- a/arch/arm/include/asm/mach/irq.h
+++ b/arch/arm/include/asm/mach/irq.h
@@ -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 *);
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index b7cb45b..6b6b4ef 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -48,12 +48,14 @@
 #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;

@@ -68,24 +70,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
@@ -113,7 +116,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);
@@ -133,12 +136,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)
@@ -152,14 +155,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)
@@ -179,10 +193,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);
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index c6c57b6..747f4ad 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -629,7 +629,7 @@ __tagtable(ATAG_REVISION, parse_tag_revision);

 static int __init parse_tag_cmdline(const struct tag *tag)
 {
-	strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
+	//strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
 	return 0;
 }

@@ -755,6 +755,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;



More information about the linux-arm-kernel mailing list