aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/handle.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/irq/handle.c')
-rw-r--r--kernel/irq/handle.c63
1 files changed, 41 insertions, 22 deletions
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 3aba8d12f328..412370ab9a34 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -17,6 +17,8 @@
17#include <linux/kernel_stat.h> 17#include <linux/kernel_stat.h>
18#include <linux/rculist.h> 18#include <linux/rculist.h>
19#include <linux/hash.h> 19#include <linux/hash.h>
20#include <trace/irq.h>
21#include <linux/bootmem.h>
20 22
21#include "internals.h" 23#include "internals.h"
22 24
@@ -69,6 +71,7 @@ int nr_irqs = NR_IRQS;
69EXPORT_SYMBOL_GPL(nr_irqs); 71EXPORT_SYMBOL_GPL(nr_irqs);
70 72
71#ifdef CONFIG_SPARSE_IRQ 73#ifdef CONFIG_SPARSE_IRQ
74
72static struct irq_desc irq_desc_init = { 75static struct irq_desc irq_desc_init = {
73 .irq = -1, 76 .irq = -1,
74 .status = IRQ_DISABLED, 77 .status = IRQ_DISABLED,
@@ -76,9 +79,6 @@ static struct irq_desc irq_desc_init = {
76 .handle_irq = handle_bad_irq, 79 .handle_irq = handle_bad_irq,
77 .depth = 1, 80 .depth = 1,
78 .lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock), 81 .lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
79#ifdef CONFIG_SMP
80 .affinity = CPU_MASK_ALL
81#endif
82}; 82};
83 83
84void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr) 84void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr)
@@ -113,6 +113,10 @@ static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu)
113 printk(KERN_ERR "can not alloc kstat_irqs\n"); 113 printk(KERN_ERR "can not alloc kstat_irqs\n");
114 BUG_ON(1); 114 BUG_ON(1);
115 } 115 }
116 if (!init_alloc_desc_masks(desc, cpu, false)) {
117 printk(KERN_ERR "can not alloc irq_desc cpumasks\n");
118 BUG_ON(1);
119 }
116 arch_init_chip_data(desc, cpu); 120 arch_init_chip_data(desc, cpu);
117} 121}
118 122
@@ -121,7 +125,7 @@ static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu)
121 */ 125 */
122DEFINE_SPINLOCK(sparse_irq_lock); 126DEFINE_SPINLOCK(sparse_irq_lock);
123 127
124struct irq_desc *irq_desc_ptrs[NR_IRQS] __read_mostly; 128struct irq_desc **irq_desc_ptrs __read_mostly;
125 129
126static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = { 130static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = {
127 [0 ... NR_IRQS_LEGACY-1] = { 131 [0 ... NR_IRQS_LEGACY-1] = {
@@ -131,14 +135,10 @@ static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_sm
131 .handle_irq = handle_bad_irq, 135 .handle_irq = handle_bad_irq,
132 .depth = 1, 136 .depth = 1,
133 .lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock), 137 .lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
134#ifdef CONFIG_SMP
135 .affinity = CPU_MASK_ALL
136#endif
137 } 138 }
138}; 139};
139 140
140/* FIXME: use bootmem alloc ...*/ 141static unsigned int *kstat_irqs_legacy;
141static unsigned int kstat_irqs_legacy[NR_IRQS_LEGACY][NR_CPUS];
142 142
143int __init early_irq_init(void) 143int __init early_irq_init(void)
144{ 144{
@@ -148,18 +148,30 @@ int __init early_irq_init(void)
148 148
149 init_irq_default_affinity(); 149 init_irq_default_affinity();
150 150
151 /* initialize nr_irqs based on nr_cpu_ids */
152 arch_probe_nr_irqs();
153 printk(KERN_INFO "NR_IRQS:%d nr_irqs:%d\n", NR_IRQS, nr_irqs);
154
151 desc = irq_desc_legacy; 155 desc = irq_desc_legacy;
152 legacy_count = ARRAY_SIZE(irq_desc_legacy); 156 legacy_count = ARRAY_SIZE(irq_desc_legacy);
153 157
158 /* allocate irq_desc_ptrs array based on nr_irqs */
159 irq_desc_ptrs = alloc_bootmem(nr_irqs * sizeof(void *));
160
161 /* allocate based on nr_cpu_ids */
162 /* FIXME: invert kstat_irgs, and it'd be a per_cpu_alloc'd thing */
163 kstat_irqs_legacy = alloc_bootmem(NR_IRQS_LEGACY * nr_cpu_ids *
164 sizeof(int));
165
154 for (i = 0; i < legacy_count; i++) { 166 for (i = 0; i < legacy_count; i++) {
155 desc[i].irq = i; 167 desc[i].irq = i;
156 desc[i].kstat_irqs = kstat_irqs_legacy[i]; 168 desc[i].kstat_irqs = kstat_irqs_legacy + i * nr_cpu_ids;
157 lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); 169 lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
158 170 init_alloc_desc_masks(&desc[i], 0, true);
159 irq_desc_ptrs[i] = desc + i; 171 irq_desc_ptrs[i] = desc + i;
160 } 172 }
161 173
162 for (i = legacy_count; i < NR_IRQS; i++) 174 for (i = legacy_count; i < nr_irqs; i++)
163 irq_desc_ptrs[i] = NULL; 175 irq_desc_ptrs[i] = NULL;
164 176
165 return arch_early_irq_init(); 177 return arch_early_irq_init();
@@ -167,7 +179,10 @@ int __init early_irq_init(void)
167 179
168struct irq_desc *irq_to_desc(unsigned int irq) 180struct irq_desc *irq_to_desc(unsigned int irq)
169{ 181{
170 return (irq < NR_IRQS) ? irq_desc_ptrs[irq] : NULL; 182 if (irq_desc_ptrs && irq < nr_irqs)
183 return irq_desc_ptrs[irq];
184
185 return NULL;
171} 186}
172 187
173struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) 188struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu)
@@ -176,10 +191,9 @@ struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu)
176 unsigned long flags; 191 unsigned long flags;
177 int node; 192 int node;
178 193
179 if (irq >= NR_IRQS) { 194 if (irq >= nr_irqs) {
180 printk(KERN_WARNING "irq >= NR_IRQS in irq_to_desc_alloc: %d %d\n", 195 WARN(1, "irq (%d) >= nr_irqs (%d) in irq_to_desc_alloc\n",
181 irq, NR_IRQS); 196 irq, nr_irqs);
182 WARN_ON(1);
183 return NULL; 197 return NULL;
184 } 198 }
185 199
@@ -221,9 +235,6 @@ struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
221 .handle_irq = handle_bad_irq, 235 .handle_irq = handle_bad_irq,
222 .depth = 1, 236 .depth = 1,
223 .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock), 237 .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock),
224#ifdef CONFIG_SMP
225 .affinity = CPU_MASK_ALL
226#endif
227 } 238 }
228}; 239};
229 240
@@ -235,12 +246,15 @@ int __init early_irq_init(void)
235 246
236 init_irq_default_affinity(); 247 init_irq_default_affinity();
237 248
249 printk(KERN_INFO "NR_IRQS:%d\n", NR_IRQS);
250
238 desc = irq_desc; 251 desc = irq_desc;
239 count = ARRAY_SIZE(irq_desc); 252 count = ARRAY_SIZE(irq_desc);
240 253
241 for (i = 0; i < count; i++) 254 for (i = 0; i < count; i++) {
242 desc[i].irq = i; 255 desc[i].irq = i;
243 256 init_alloc_desc_masks(&desc[i], 0, true);
257 }
244 return arch_early_irq_init(); 258 return arch_early_irq_init();
245} 259}
246 260
@@ -316,6 +330,9 @@ irqreturn_t no_action(int cpl, void *dev_id)
316 return IRQ_NONE; 330 return IRQ_NONE;
317} 331}
318 332
333DEFINE_TRACE(irq_handler_entry);
334DEFINE_TRACE(irq_handler_exit);
335
319/** 336/**
320 * handle_IRQ_event - irq action chain handler 337 * handle_IRQ_event - irq action chain handler
321 * @irq: the interrupt number 338 * @irq: the interrupt number
@@ -332,7 +349,9 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
332 local_irq_enable_in_hardirq(); 349 local_irq_enable_in_hardirq();
333 350
334 do { 351 do {
352 trace_irq_handler_entry(irq, action);
335 ret = action->handler(irq, action->dev_id); 353 ret = action->handler(irq, action->dev_id);
354 trace_irq_handler_exit(irq, action, ret);
336 if (ret == IRQ_HANDLED) 355 if (ret == IRQ_HANDLED)
337 status |= action->flags; 356 status |= action->flags;
338 retval |= ret; 357 retval |= ret;