[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