提交 354e6f72 编写于 作者: E eric miao 提交者: Russell King

ARM: 6197/2: preliminary support for sparse IRQ

So to allow NR_IRQS to be dynamic and platforms to specify the number
of IRQs really needed.
Acked-by: NPaul Mundt <lethal@linux-sh.org>
Signed-off-by: NEric Miao <eric.y.miao@gmail.com>
Signed-off-by: NRussell King <rmk+kernel@arm.linux.org.uk>
上级 309caa9c
...@@ -1289,6 +1289,18 @@ config HW_PERF_EVENTS ...@@ -1289,6 +1289,18 @@ config HW_PERF_EVENTS
Enable hardware performance counter support for perf events. If Enable hardware performance counter support for perf events. If
disabled, perf events will use software events only. 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" source "mm/Kconfig"
config LEDS config LEDS
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#define irq_canonicalize(i) (i) #define irq_canonicalize(i) (i)
#endif #endif
#define NR_IRQS_LEGACY 16
/* /*
* Use this value to indicate lack of interrupt * Use this value to indicate lack of interrupt
* capability * capability
......
...@@ -20,6 +20,7 @@ struct machine_desc { ...@@ -20,6 +20,7 @@ struct machine_desc {
* by assembler code in head.S, head-common.S * by assembler code in head.S, head-common.S
*/ */
unsigned int nr; /* architecture number */ unsigned int nr; /* architecture number */
unsigned int nr_irqs; /* number of IRQs */
unsigned int phys_io; /* start of physical io */ unsigned int phys_io; /* start of physical io */
unsigned int io_pg_offst; /* byte offset for io unsigned int io_pg_offst; /* byte offset for io
* page tabe entry */ * page tabe entry */
......
...@@ -17,6 +17,7 @@ struct seq_file; ...@@ -17,6 +17,7 @@ struct seq_file;
/* /*
* This is internal. Do not use it. * This is internal. Do not use it.
*/ */
extern unsigned int arch_nr_irqs;
extern void (*init_arch_irq)(void); extern void (*init_arch_irq)(void);
extern void init_FIQ(void); extern void init_FIQ(void);
extern int show_fiq_list(struct seq_file *, void *); extern int show_fiq_list(struct seq_file *, void *);
......
...@@ -47,12 +47,14 @@ ...@@ -47,12 +47,14 @@
#define irq_finish(irq) do { } while (0) #define irq_finish(irq) do { } while (0)
#endif #endif
unsigned int arch_nr_irqs;
void (*init_arch_irq)(void) __initdata = NULL; void (*init_arch_irq)(void) __initdata = NULL;
unsigned long irq_err_count; unsigned long irq_err_count;
int show_interrupts(struct seq_file *p, void *v) int show_interrupts(struct seq_file *p, void *v)
{ {
int i = *(loff_t *) v, cpu; int i = *(loff_t *) v, cpu;
struct irq_desc *desc;
struct irqaction * action; struct irqaction * action;
unsigned long flags; unsigned long flags;
...@@ -67,24 +69,25 @@ int show_interrupts(struct seq_file *p, void *v) ...@@ -67,24 +69,25 @@ int show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n'); seq_putc(p, '\n');
} }
if (i < NR_IRQS) { if (i < nr_irqs) {
raw_spin_lock_irqsave(&irq_desc[i].lock, flags); desc = irq_to_desc(i);
action = irq_desc[i].action; raw_spin_lock_irqsave(&desc->lock, flags);
action = desc->action;
if (!action) if (!action)
goto unlock; goto unlock;
seq_printf(p, "%3d: ", i); seq_printf(p, "%3d: ", i);
for_each_present_cpu(cpu) for_each_present_cpu(cpu)
seq_printf(p, "%10u ", kstat_irqs_cpu(i, 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); seq_printf(p, " %s", action->name);
for (action = action->next; action; action = action->next) for (action = action->next; action; action = action->next)
seq_printf(p, ", %s", action->name); seq_printf(p, ", %s", action->name);
seq_putc(p, '\n'); seq_putc(p, '\n');
unlock: unlock:
raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags); raw_spin_unlock_irqrestore(&desc->lock, flags);
} else if (i == NR_IRQS) { } else if (i == nr_irqs) {
#ifdef CONFIG_FIQ #ifdef CONFIG_FIQ
show_fiq_list(p, v); show_fiq_list(p, v);
#endif #endif
...@@ -112,7 +115,7 @@ asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs) ...@@ -112,7 +115,7 @@ asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
* Some hardware gives randomly wrong interrupts. Rather * Some hardware gives randomly wrong interrupts. Rather
* than crashing, do something sensible. * than crashing, do something sensible.
*/ */
if (unlikely(irq >= NR_IRQS)) { if (unlikely(irq >= nr_irqs)) {
if (printk_ratelimit()) if (printk_ratelimit())
printk(KERN_WARNING "Bad IRQ%u\n", irq); printk(KERN_WARNING "Bad IRQ%u\n", irq);
ack_bad_irq(irq); ack_bad_irq(irq);
...@@ -132,12 +135,12 @@ void set_irq_flags(unsigned int irq, unsigned int iflags) ...@@ -132,12 +135,12 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)
struct irq_desc *desc; struct irq_desc *desc;
unsigned long flags; unsigned long flags;
if (irq >= NR_IRQS) { if (irq >= nr_irqs) {
printk(KERN_ERR "Trying to set irq flags for IRQ%d\n", irq); printk(KERN_ERR "Trying to set irq flags for IRQ%d\n", irq);
return; return;
} }
desc = irq_desc + irq; desc = irq_to_desc(irq);
raw_spin_lock_irqsave(&desc->lock, flags); raw_spin_lock_irqsave(&desc->lock, flags);
desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
if (iflags & IRQF_VALID) if (iflags & IRQF_VALID)
...@@ -151,14 +154,25 @@ void set_irq_flags(unsigned int irq, unsigned int iflags) ...@@ -151,14 +154,25 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)
void __init init_IRQ(void) void __init init_IRQ(void)
{ {
struct irq_desc *desc;
int irq; int irq;
for (irq = 0; irq < NR_IRQS; irq++) for (irq = 0; irq < nr_irqs; irq++) {
irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE; desc = irq_to_desc_alloc_node(irq, 0);
desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE;
}
init_arch_irq(); 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 #ifdef CONFIG_HOTPLUG_CPU
static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu) static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu)
...@@ -178,10 +192,9 @@ static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu) ...@@ -178,10 +192,9 @@ static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu)
void migrate_irqs(void) void migrate_irqs(void)
{ {
unsigned int i, cpu = smp_processor_id(); unsigned int i, cpu = smp_processor_id();
struct irq_desc *desc;
for (i = 0; i < NR_IRQS; i++) { for_each_irq_desc(i, desc) {
struct irq_desc *desc = irq_desc + i;
if (desc->node == cpu) { if (desc->node == cpu) {
unsigned int newcpu = cpumask_any_and(desc->affinity, unsigned int newcpu = cpumask_any_and(desc->affinity,
cpu_online_mask); cpu_online_mask);
......
...@@ -729,6 +729,7 @@ void __init setup_arch(char **cmdline_p) ...@@ -729,6 +729,7 @@ void __init setup_arch(char **cmdline_p)
/* /*
* Set up various architecture-specific pointers * Set up various architecture-specific pointers
*/ */
arch_nr_irqs = mdesc->nr_irqs;
init_arch_irq = mdesc->init_irq; init_arch_irq = mdesc->init_irq;
system_timer = mdesc->timer; system_timer = mdesc->timer;
init_machine = mdesc->init_machine; init_machine = mdesc->init_machine;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册