diff options
Diffstat (limited to 'kernel/irq/handle.c')
-rw-r--r-- | kernel/irq/handle.c | 63 |
1 files changed, 31 insertions, 32 deletions
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 26e08754744f..a60018402f42 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c | |||
@@ -11,14 +11,15 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/irq.h> | 13 | #include <linux/irq.h> |
14 | #include <linux/slab.h> | ||
14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
15 | #include <linux/random.h> | 16 | #include <linux/random.h> |
16 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
17 | #include <linux/kernel_stat.h> | 18 | #include <linux/kernel_stat.h> |
18 | #include <linux/rculist.h> | 19 | #include <linux/rculist.h> |
19 | #include <linux/hash.h> | 20 | #include <linux/hash.h> |
20 | #include <trace/irq.h> | ||
21 | #include <linux/bootmem.h> | 21 | #include <linux/bootmem.h> |
22 | #include <trace/events/irq.h> | ||
22 | 23 | ||
23 | #include "internals.h" | 24 | #include "internals.h" |
24 | 25 | ||
@@ -81,45 +82,48 @@ static struct irq_desc irq_desc_init = { | |||
81 | .lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock), | 82 | .lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock), |
82 | }; | 83 | }; |
83 | 84 | ||
84 | void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr) | 85 | void __ref init_kstat_irqs(struct irq_desc *desc, int node, int nr) |
85 | { | 86 | { |
86 | int node; | ||
87 | void *ptr; | 87 | void *ptr; |
88 | 88 | ||
89 | node = cpu_to_node(cpu); | 89 | if (slab_is_available()) |
90 | ptr = kzalloc_node(nr * sizeof(*desc->kstat_irqs), GFP_ATOMIC, node); | 90 | ptr = kzalloc_node(nr * sizeof(*desc->kstat_irqs), |
91 | GFP_ATOMIC, node); | ||
92 | else | ||
93 | ptr = alloc_bootmem_node(NODE_DATA(node), | ||
94 | nr * sizeof(*desc->kstat_irqs)); | ||
91 | 95 | ||
92 | /* | 96 | /* |
93 | * don't overwite if can not get new one | 97 | * don't overwite if can not get new one |
94 | * init_copy_kstat_irqs() could still use old one | 98 | * init_copy_kstat_irqs() could still use old one |
95 | */ | 99 | */ |
96 | if (ptr) { | 100 | if (ptr) { |
97 | printk(KERN_DEBUG " alloc kstat_irqs on cpu %d node %d\n", | 101 | printk(KERN_DEBUG " alloc kstat_irqs on node %d\n", node); |
98 | cpu, node); | ||
99 | desc->kstat_irqs = ptr; | 102 | desc->kstat_irqs = ptr; |
100 | } | 103 | } |
101 | } | 104 | } |
102 | 105 | ||
103 | static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu) | 106 | static void init_one_irq_desc(int irq, struct irq_desc *desc, int node) |
104 | { | 107 | { |
105 | memcpy(desc, &irq_desc_init, sizeof(struct irq_desc)); | 108 | memcpy(desc, &irq_desc_init, sizeof(struct irq_desc)); |
106 | 109 | ||
107 | spin_lock_init(&desc->lock); | 110 | spin_lock_init(&desc->lock); |
108 | desc->irq = irq; | 111 | desc->irq = irq; |
109 | #ifdef CONFIG_SMP | 112 | #ifdef CONFIG_SMP |
110 | desc->cpu = cpu; | 113 | desc->node = node; |
111 | #endif | 114 | #endif |
112 | lockdep_set_class(&desc->lock, &irq_desc_lock_class); | 115 | lockdep_set_class(&desc->lock, &irq_desc_lock_class); |
113 | init_kstat_irqs(desc, cpu, nr_cpu_ids); | 116 | init_kstat_irqs(desc, node, nr_cpu_ids); |
114 | if (!desc->kstat_irqs) { | 117 | if (!desc->kstat_irqs) { |
115 | printk(KERN_ERR "can not alloc kstat_irqs\n"); | 118 | printk(KERN_ERR "can not alloc kstat_irqs\n"); |
116 | BUG_ON(1); | 119 | BUG_ON(1); |
117 | } | 120 | } |
118 | if (!init_alloc_desc_masks(desc, cpu, false)) { | 121 | if (!alloc_desc_masks(desc, node, false)) { |
119 | printk(KERN_ERR "can not alloc irq_desc cpumasks\n"); | 122 | printk(KERN_ERR "can not alloc irq_desc cpumasks\n"); |
120 | BUG_ON(1); | 123 | BUG_ON(1); |
121 | } | 124 | } |
122 | arch_init_chip_data(desc, cpu); | 125 | init_desc_masks(desc); |
126 | arch_init_chip_data(desc, node); | ||
123 | } | 127 | } |
124 | 128 | ||
125 | /* | 129 | /* |
@@ -169,7 +173,8 @@ int __init early_irq_init(void) | |||
169 | desc[i].irq = i; | 173 | desc[i].irq = i; |
170 | desc[i].kstat_irqs = kstat_irqs_legacy + i * nr_cpu_ids; | 174 | desc[i].kstat_irqs = kstat_irqs_legacy + i * nr_cpu_ids; |
171 | lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); | 175 | lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); |
172 | init_alloc_desc_masks(&desc[i], 0, true); | 176 | alloc_desc_masks(&desc[i], 0, true); |
177 | init_desc_masks(&desc[i]); | ||
173 | irq_desc_ptrs[i] = desc + i; | 178 | irq_desc_ptrs[i] = desc + i; |
174 | } | 179 | } |
175 | 180 | ||
@@ -187,11 +192,10 @@ struct irq_desc *irq_to_desc(unsigned int irq) | |||
187 | return NULL; | 192 | return NULL; |
188 | } | 193 | } |
189 | 194 | ||
190 | struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) | 195 | struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node) |
191 | { | 196 | { |
192 | struct irq_desc *desc; | 197 | struct irq_desc *desc; |
193 | unsigned long flags; | 198 | unsigned long flags; |
194 | int node; | ||
195 | 199 | ||
196 | if (irq >= nr_irqs) { | 200 | if (irq >= nr_irqs) { |
197 | WARN(1, "irq (%d) >= nr_irqs (%d) in irq_to_desc_alloc\n", | 201 | WARN(1, "irq (%d) >= nr_irqs (%d) in irq_to_desc_alloc\n", |
@@ -210,15 +214,17 @@ struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) | |||
210 | if (desc) | 214 | if (desc) |
211 | goto out_unlock; | 215 | goto out_unlock; |
212 | 216 | ||
213 | node = cpu_to_node(cpu); | 217 | if (slab_is_available()) |
214 | desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node); | 218 | desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node); |
215 | printk(KERN_DEBUG " alloc irq_desc for %d on cpu %d node %d\n", | 219 | else |
216 | irq, cpu, node); | 220 | desc = alloc_bootmem_node(NODE_DATA(node), sizeof(*desc)); |
221 | |||
222 | printk(KERN_DEBUG " alloc irq_desc for %d on node %d\n", irq, node); | ||
217 | if (!desc) { | 223 | if (!desc) { |
218 | printk(KERN_ERR "can not alloc irq_desc\n"); | 224 | printk(KERN_ERR "can not alloc irq_desc\n"); |
219 | BUG_ON(1); | 225 | BUG_ON(1); |
220 | } | 226 | } |
221 | init_one_irq_desc(irq, desc, cpu); | 227 | init_one_irq_desc(irq, desc, node); |
222 | 228 | ||
223 | irq_desc_ptrs[irq] = desc; | 229 | irq_desc_ptrs[irq] = desc; |
224 | 230 | ||
@@ -256,7 +262,8 @@ int __init early_irq_init(void) | |||
256 | 262 | ||
257 | for (i = 0; i < count; i++) { | 263 | for (i = 0; i < count; i++) { |
258 | desc[i].irq = i; | 264 | desc[i].irq = i; |
259 | init_alloc_desc_masks(&desc[i], 0, true); | 265 | alloc_desc_masks(&desc[i], 0, true); |
266 | init_desc_masks(&desc[i]); | ||
260 | desc[i].kstat_irqs = kstat_irqs_all[i]; | 267 | desc[i].kstat_irqs = kstat_irqs_all[i]; |
261 | } | 268 | } |
262 | return arch_early_irq_init(); | 269 | return arch_early_irq_init(); |
@@ -267,7 +274,7 @@ struct irq_desc *irq_to_desc(unsigned int irq) | |||
267 | return (irq < NR_IRQS) ? irq_desc + irq : NULL; | 274 | return (irq < NR_IRQS) ? irq_desc + irq : NULL; |
268 | } | 275 | } |
269 | 276 | ||
270 | struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) | 277 | struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node) |
271 | { | 278 | { |
272 | return irq_to_desc(irq); | 279 | return irq_to_desc(irq); |
273 | } | 280 | } |
@@ -348,9 +355,6 @@ static void warn_no_thread(unsigned int irq, struct irqaction *action) | |||
348 | "but no thread function available.", irq, action->name); | 355 | "but no thread function available.", irq, action->name); |
349 | } | 356 | } |
350 | 357 | ||
351 | DEFINE_TRACE(irq_handler_entry); | ||
352 | DEFINE_TRACE(irq_handler_exit); | ||
353 | |||
354 | /** | 358 | /** |
355 | * handle_IRQ_event - irq action chain handler | 359 | * handle_IRQ_event - irq action chain handler |
356 | * @irq: the interrupt number | 360 | * @irq: the interrupt number |
@@ -453,11 +457,8 @@ unsigned int __do_IRQ(unsigned int irq) | |||
453 | /* | 457 | /* |
454 | * No locking required for CPU-local interrupts: | 458 | * No locking required for CPU-local interrupts: |
455 | */ | 459 | */ |
456 | if (desc->chip->ack) { | 460 | if (desc->chip->ack) |
457 | desc->chip->ack(irq); | 461 | desc->chip->ack(irq); |
458 | /* get new one */ | ||
459 | desc = irq_remap_to_desc(irq, desc); | ||
460 | } | ||
461 | if (likely(!(desc->status & IRQ_DISABLED))) { | 462 | if (likely(!(desc->status & IRQ_DISABLED))) { |
462 | action_ret = handle_IRQ_event(irq, desc->action); | 463 | action_ret = handle_IRQ_event(irq, desc->action); |
463 | if (!noirqdebug) | 464 | if (!noirqdebug) |
@@ -468,10 +469,8 @@ unsigned int __do_IRQ(unsigned int irq) | |||
468 | } | 469 | } |
469 | 470 | ||
470 | spin_lock(&desc->lock); | 471 | spin_lock(&desc->lock); |
471 | if (desc->chip->ack) { | 472 | if (desc->chip->ack) |
472 | desc->chip->ack(irq); | 473 | desc->chip->ack(irq); |
473 | desc = irq_remap_to_desc(irq, desc); | ||
474 | } | ||
475 | /* | 474 | /* |
476 | * REPLAY is when Linux resends an IRQ that was dropped earlier | 475 | * REPLAY is when Linux resends an IRQ that was dropped earlier |
477 | * WAITING is used by probe to mark irqs that are being tested | 476 | * WAITING is used by probe to mark irqs that are being tested |