aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authoreric miao <eric.y.miao@gmail.com>2010-06-25 04:46:09 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-07-09 09:41:33 -0400
commit354e6f72d6fd5d3d2963efe030265972866cd969 (patch)
tree2ec7973825a42f4d15d233375c5db3b073658421 /arch/arm
parent309caa9cc6ff39d261264ec4ff10e29489afc8f8 (diff)
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>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Kconfig12
-rw-r--r--arch/arm/include/asm/irq.h2
-rw-r--r--arch/arm/include/asm/mach/arch.h1
-rw-r--r--arch/arm/include/asm/mach/irq.h1
-rw-r--r--arch/arm/kernel/irq.c41
-rw-r--r--arch/arm/kernel/setup.c1
6 files changed, 44 insertions, 14 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 1f254bd6c937..9a0ed364d4f7 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1289,6 +1289,18 @@ config HW_PERF_EVENTS
1289 Enable hardware performance counter support for perf events. If 1289 Enable hardware performance counter support for perf events. If
1290 disabled, perf events will use software events only. 1290 disabled, perf events will use software events only.
1291 1291
1292config SPARSE_IRQ
1293 bool "Support sparse irq numbering"
1294 depends on EXPERIMENTAL
1295 help
1296 This enables support for sparse irqs. This is useful in general
1297 as most CPUs have a fairly sparse array of IRQ vectors, which
1298 the irq_desc then maps directly on to. Systems with a high
1299 number of off-chip IRQs will want to treat this as
1300 experimental until they have been independently verified.
1301
1302 If you don't know what to do here, say N.
1303
1292source "mm/Kconfig" 1304source "mm/Kconfig"
1293 1305
1294config LEDS 1306config LEDS
diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h
index 237282f7c762..2721a5814cb9 100644
--- a/arch/arm/include/asm/irq.h
+++ b/arch/arm/include/asm/irq.h
@@ -7,6 +7,8 @@
7#define irq_canonicalize(i) (i) 7#define irq_canonicalize(i) (i)
8#endif 8#endif
9 9
10#define NR_IRQS_LEGACY 16
11
10/* 12/*
11 * Use this value to indicate lack of interrupt 13 * Use this value to indicate lack of interrupt
12 * capability 14 * capability
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index c59842dc7cb8..5ee6f85236a4 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -20,6 +20,7 @@ struct machine_desc {
20 * by assembler code in head.S, head-common.S 20 * by assembler code in head.S, head-common.S
21 */ 21 */
22 unsigned int nr; /* architecture number */ 22 unsigned int nr; /* architecture number */
23 unsigned int nr_irqs; /* number of IRQs */
23 unsigned int phys_io; /* start of physical io */ 24 unsigned int phys_io; /* start of physical io */
24 unsigned int io_pg_offst; /* byte offset for io 25 unsigned int io_pg_offst; /* byte offset for io
25 * page tabe entry */ 26 * page tabe entry */
diff --git a/arch/arm/include/asm/mach/irq.h b/arch/arm/include/asm/mach/irq.h
index 8920b2d6e3b8..ce3eee9fe26c 100644
--- a/arch/arm/include/asm/mach/irq.h
+++ b/arch/arm/include/asm/mach/irq.h
@@ -17,6 +17,7 @@ struct seq_file;
17/* 17/*
18 * This is internal. Do not use it. 18 * This is internal. Do not use it.
19 */ 19 */
20extern unsigned int arch_nr_irqs;
20extern void (*init_arch_irq)(void); 21extern void (*init_arch_irq)(void);
21extern void init_FIQ(void); 22extern void init_FIQ(void);
22extern int show_fiq_list(struct seq_file *, void *); 23extern int show_fiq_list(struct seq_file *, void *);
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 3b3d2c80509c..c0d5c3b3a760 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -47,12 +47,14 @@
47#define irq_finish(irq) do { } while (0) 47#define irq_finish(irq) do { } while (0)
48#endif 48#endif
49 49
50unsigned int arch_nr_irqs;
50void (*init_arch_irq)(void) __initdata = NULL; 51void (*init_arch_irq)(void) __initdata = NULL;
51unsigned long irq_err_count; 52unsigned long irq_err_count;
52 53
53int show_interrupts(struct seq_file *p, void *v) 54int show_interrupts(struct seq_file *p, void *v)
54{ 55{
55 int i = *(loff_t *) v, cpu; 56 int i = *(loff_t *) v, cpu;
57 struct irq_desc *desc;
56 struct irqaction * action; 58 struct irqaction * action;
57 unsigned long flags; 59 unsigned long flags;
58 60
@@ -67,24 +69,25 @@ int show_interrupts(struct seq_file *p, void *v)
67 seq_putc(p, '\n'); 69 seq_putc(p, '\n');
68 } 70 }
69 71
70 if (i < NR_IRQS) { 72 if (i < nr_irqs) {
71 raw_spin_lock_irqsave(&irq_desc[i].lock, flags); 73 desc = irq_to_desc(i);
72 action = irq_desc[i].action; 74 raw_spin_lock_irqsave(&desc->lock, flags);
75 action = desc->action;
73 if (!action) 76 if (!action)
74 goto unlock; 77 goto unlock;
75 78
76 seq_printf(p, "%3d: ", i); 79 seq_printf(p, "%3d: ", i);
77 for_each_present_cpu(cpu) 80 for_each_present_cpu(cpu)
78 seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu)); 81 seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
79 seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-"); 82 seq_printf(p, " %10s", desc->chip->name ? : "-");
80 seq_printf(p, " %s", action->name); 83 seq_printf(p, " %s", action->name);
81 for (action = action->next; action; action = action->next) 84 for (action = action->next; action; action = action->next)
82 seq_printf(p, ", %s", action->name); 85 seq_printf(p, ", %s", action->name);
83 86
84 seq_putc(p, '\n'); 87 seq_putc(p, '\n');
85unlock: 88unlock:
86 raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags); 89 raw_spin_unlock_irqrestore(&desc->lock, flags);
87 } else if (i == NR_IRQS) { 90 } else if (i == nr_irqs) {
88#ifdef CONFIG_FIQ 91#ifdef CONFIG_FIQ
89 show_fiq_list(p, v); 92 show_fiq_list(p, v);
90#endif 93#endif
@@ -112,7 +115,7 @@ asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
112 * Some hardware gives randomly wrong interrupts. Rather 115 * Some hardware gives randomly wrong interrupts. Rather
113 * than crashing, do something sensible. 116 * than crashing, do something sensible.
114 */ 117 */
115 if (unlikely(irq >= NR_IRQS)) { 118 if (unlikely(irq >= nr_irqs)) {
116 if (printk_ratelimit()) 119 if (printk_ratelimit())
117 printk(KERN_WARNING "Bad IRQ%u\n", irq); 120 printk(KERN_WARNING "Bad IRQ%u\n", irq);
118 ack_bad_irq(irq); 121 ack_bad_irq(irq);
@@ -132,12 +135,12 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)
132 struct irq_desc *desc; 135 struct irq_desc *desc;
133 unsigned long flags; 136 unsigned long flags;
134 137
135 if (irq >= NR_IRQS) { 138 if (irq >= nr_irqs) {
136 printk(KERN_ERR "Trying to set irq flags for IRQ%d\n", irq); 139 printk(KERN_ERR "Trying to set irq flags for IRQ%d\n", irq);
137 return; 140 return;
138 } 141 }
139 142
140 desc = irq_desc + irq; 143 desc = irq_to_desc(irq);
141 raw_spin_lock_irqsave(&desc->lock, flags); 144 raw_spin_lock_irqsave(&desc->lock, flags);
142 desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; 145 desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
143 if (iflags & IRQF_VALID) 146 if (iflags & IRQF_VALID)
@@ -151,14 +154,25 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)
151 154
152void __init init_IRQ(void) 155void __init init_IRQ(void)
153{ 156{
157 struct irq_desc *desc;
154 int irq; 158 int irq;
155 159
156 for (irq = 0; irq < NR_IRQS; irq++) 160 for (irq = 0; irq < nr_irqs; irq++) {
157 irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE; 161 desc = irq_to_desc_alloc_node(irq, 0);
162 desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE;
163 }
158 164
159 init_arch_irq(); 165 init_arch_irq();
160} 166}
161 167
168#ifdef CONFIG_SPARSE_IRQ
169int __init arch_probe_nr_irqs(void)
170{
171 nr_irqs = arch_nr_irqs ? arch_nr_irqs : NR_IRQS;
172 return 0;
173}
174#endif
175
162#ifdef CONFIG_HOTPLUG_CPU 176#ifdef CONFIG_HOTPLUG_CPU
163 177
164static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu) 178static 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)
178void migrate_irqs(void) 192void migrate_irqs(void)
179{ 193{
180 unsigned int i, cpu = smp_processor_id(); 194 unsigned int i, cpu = smp_processor_id();
195 struct irq_desc *desc;
181 196
182 for (i = 0; i < NR_IRQS; i++) { 197 for_each_irq_desc(i, desc) {
183 struct irq_desc *desc = irq_desc + i;
184
185 if (desc->node == cpu) { 198 if (desc->node == cpu) {
186 unsigned int newcpu = cpumask_any_and(desc->affinity, 199 unsigned int newcpu = cpumask_any_and(desc->affinity,
187 cpu_online_mask); 200 cpu_online_mask);
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 122d999bdc7c..7ae65dc594a4 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -729,6 +729,7 @@ void __init setup_arch(char **cmdline_p)
729 /* 729 /*
730 * Set up various architecture-specific pointers 730 * Set up various architecture-specific pointers
731 */ 731 */
732 arch_nr_irqs = mdesc->nr_irqs;
732 init_arch_irq = mdesc->init_irq; 733 init_arch_irq = mdesc->init_irq;
733 system_timer = mdesc->timer; 734 system_timer = mdesc->timer;
734 init_machine = mdesc->init_machine; 735 init_machine = mdesc->init_machine;