Skip to content

Commit

Permalink
ARM: 6197/2: preliminary support for sparse IRQ
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
eric miao authored and Russell King committed Jul 9, 2010
1 parent 309caa9 commit 354e6f7
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 14 deletions.
12 changes: 12 additions & 0 deletions arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions arch/arm/include/asm/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#define irq_canonicalize(i) (i)
#endif

#define NR_IRQS_LEGACY 16

/*
* Use this value to indicate lack of interrupt
* capability
Expand Down
1 change: 1 addition & 0 deletions arch/arm/include/asm/mach/arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
1 change: 1 addition & 0 deletions arch/arm/include/asm/mach/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down
41 changes: 27 additions & 14 deletions arch/arm/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,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;

Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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);
Expand Down
1 change: 1 addition & 0 deletions arch/arm/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 354e6f7

Please sign in to comment.