[RFC] preliminary support for sparse IRQ
flat view
From: Eric Miao <hidden>
Date: 2009-12-28 05:03:37
Subsystem:
arm port, the rest · Maintainers:
Russell King, Linus Torvalds
commit 0dfd0ec8edf8a704d88903ba94c5dc377008e56c
Author: Eric Miao [off-list ref]
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 [off-list ref]
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(unsignedint 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;