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: 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>
This commit is contained in:
parent
309caa9cc6
commit
354e6f72d6
|
@ -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 @@
|
||||||
#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 {
|
||||||
* 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;
|
||||||
/*
|
/*
|
||||||
* 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 @@
|
||||||
#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)
|
||||||
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)
|
||||||
* 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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
/*
|
/*
|
||||||
* 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;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user