aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/irq.c
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/kernel/irq.c
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/kernel/irq.c')
-rw-r--r--arch/arm/kernel/irq.c41
1 files changed, 27 insertions, 14 deletions
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);