[RFC PATCH 2/3] [ARM] Preliminary support for dynamic IRQ
Ben Dooks
ben-linux at fluff.org
Fri Feb 5 03:13:15 EST 2010
On Thu, Feb 04, 2010 at 11:11:58AM -0800, Eric Miao wrote:
> To solve the mess that a heavy usage of board IRQs on ARM and the
> diversity, we might end up with a dynamic solution, where SPARSE_IRQ
> looks so far fit at least.
I'm not sure that SPARSE_IRQ is really the right solution at the moment,
having just spent some time thinking about this wrt to the samsung range
of socs, it doesn't seem to be a huge gain.
I think a better solution would be to have a lazy interrupt solution based
around the same methods as the sparse irq where each soc registers the
ranges of interrupts supported and then when request_irq() is called the
irq_desc is created. Currently some of the Samsung range have nearly 28KiB
of irq_desc allocated...
> commit 59e902671333e2b3c39cb39a47e2c6b673c9f406
> Author: Eric Miao <eric.y.miao at gmail.com>
> Date: Wed Feb 3 18:16:43 2010 -0800
>
> [ARM] Preliminary support for dynamic IRQ
>
> Signed-off-by: Eric Miao <eric.y.miao at gmail.com>
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 4c33ca8..c95484c 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -920,6 +920,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
> +
Do we really want to set this for everyone?
> /*
> * Use this value to indicate lack of interrupt
> * capability
> diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
> index b7cb45b..e62f39b 100644
> --- a/arch/arm/kernel/irq.c
> +++ b/arch/arm/kernel/irq.c
> @@ -54,6 +54,7 @@ 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 +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
> @@ -113,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);
> @@ -133,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)
> @@ -152,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;
> + }
looks like we'll just end up with everyone allocating an IRQ.
>
> init_arch_irq();
> }
>
> +#ifdef CONFIG_SPARSE_IRQ
> +int __init arch_probe_nr_irqs(void)
> +{
> + 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 +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);
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
--
Ben
Q: What's a light-year?
A: One-third less calories than a regular year.
More information about the linux-arm-kernel
mailing list