diff options
Diffstat (limited to 'kernel/irq')
-rw-r--r-- | kernel/irq/Makefile | 1 | ||||
-rw-r--r-- | kernel/irq/chip.c | 12 | ||||
-rw-r--r-- | kernel/irq/devres.c | 16 | ||||
-rw-r--r-- | kernel/irq/handle.c | 149 | ||||
-rw-r--r-- | kernel/irq/internals.h | 10 | ||||
-rw-r--r-- | kernel/irq/manage.c | 424 | ||||
-rw-r--r-- | kernel/irq/migration.c | 12 | ||||
-rw-r--r-- | kernel/irq/numa_migrate.c | 31 | ||||
-rw-r--r-- | kernel/irq/pm.c | 79 | ||||
-rw-r--r-- | kernel/irq/proc.c | 4 | ||||
-rw-r--r-- | kernel/irq/spurious.c | 14 |
11 files changed, 580 insertions, 172 deletions
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile index 4dd5b1edac98..3394f8f52964 100644 --- a/kernel/irq/Makefile +++ b/kernel/irq/Makefile | |||
@@ -4,3 +4,4 @@ obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o | |||
4 | obj-$(CONFIG_PROC_FS) += proc.o | 4 | obj-$(CONFIG_PROC_FS) += proc.o |
5 | obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o | 5 | obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o |
6 | obj-$(CONFIG_NUMA_MIGRATE_IRQ_DESC) += numa_migrate.o | 6 | obj-$(CONFIG_NUMA_MIGRATE_IRQ_DESC) += numa_migrate.o |
7 | obj-$(CONFIG_PM_SLEEP) += pm.o | ||
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 7de11bd64dfe..c687ba4363f2 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -46,7 +46,10 @@ void dynamic_irq_init(unsigned int irq) | |||
46 | desc->irq_count = 0; | 46 | desc->irq_count = 0; |
47 | desc->irqs_unhandled = 0; | 47 | desc->irqs_unhandled = 0; |
48 | #ifdef CONFIG_SMP | 48 | #ifdef CONFIG_SMP |
49 | cpumask_setall(&desc->affinity); | 49 | cpumask_setall(desc->affinity); |
50 | #ifdef CONFIG_GENERIC_PENDING_IRQ | ||
51 | cpumask_clear(desc->pending_mask); | ||
52 | #endif | ||
50 | #endif | 53 | #endif |
51 | spin_unlock_irqrestore(&desc->lock, flags); | 54 | spin_unlock_irqrestore(&desc->lock, flags); |
52 | } | 55 | } |
@@ -78,6 +81,7 @@ void dynamic_irq_cleanup(unsigned int irq) | |||
78 | desc->handle_irq = handle_bad_irq; | 81 | desc->handle_irq = handle_bad_irq; |
79 | desc->chip = &no_irq_chip; | 82 | desc->chip = &no_irq_chip; |
80 | desc->name = NULL; | 83 | desc->name = NULL; |
84 | clear_kstat_irqs(desc); | ||
81 | spin_unlock_irqrestore(&desc->lock, flags); | 85 | spin_unlock_irqrestore(&desc->lock, flags); |
82 | } | 86 | } |
83 | 87 | ||
@@ -290,7 +294,8 @@ static inline void mask_ack_irq(struct irq_desc *desc, int irq) | |||
290 | desc->chip->mask_ack(irq); | 294 | desc->chip->mask_ack(irq); |
291 | else { | 295 | else { |
292 | desc->chip->mask(irq); | 296 | desc->chip->mask(irq); |
293 | desc->chip->ack(irq); | 297 | if (desc->chip->ack) |
298 | desc->chip->ack(irq); | ||
294 | } | 299 | } |
295 | } | 300 | } |
296 | 301 | ||
@@ -476,7 +481,8 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
476 | kstat_incr_irqs_this_cpu(irq, desc); | 481 | kstat_incr_irqs_this_cpu(irq, desc); |
477 | 482 | ||
478 | /* Start handling the irq */ | 483 | /* Start handling the irq */ |
479 | desc->chip->ack(irq); | 484 | if (desc->chip->ack) |
485 | desc->chip->ack(irq); | ||
480 | desc = irq_remap_to_desc(irq, desc); | 486 | desc = irq_remap_to_desc(irq, desc); |
481 | 487 | ||
482 | /* Mark the IRQ currently in progress.*/ | 488 | /* Mark the IRQ currently in progress.*/ |
diff --git a/kernel/irq/devres.c b/kernel/irq/devres.c index 38a25b8d8bff..d06df9c41cba 100644 --- a/kernel/irq/devres.c +++ b/kernel/irq/devres.c | |||
@@ -26,10 +26,12 @@ static int devm_irq_match(struct device *dev, void *res, void *data) | |||
26 | } | 26 | } |
27 | 27 | ||
28 | /** | 28 | /** |
29 | * devm_request_irq - allocate an interrupt line for a managed device | 29 | * devm_request_threaded_irq - allocate an interrupt line for a managed device |
30 | * @dev: device to request interrupt for | 30 | * @dev: device to request interrupt for |
31 | * @irq: Interrupt line to allocate | 31 | * @irq: Interrupt line to allocate |
32 | * @handler: Function to be called when the IRQ occurs | 32 | * @handler: Function to be called when the IRQ occurs |
33 | * @thread_fn: function to be called in a threaded interrupt context. NULL | ||
34 | * for devices which handle everything in @handler | ||
33 | * @irqflags: Interrupt type flags | 35 | * @irqflags: Interrupt type flags |
34 | * @devname: An ascii name for the claiming device | 36 | * @devname: An ascii name for the claiming device |
35 | * @dev_id: A cookie passed back to the handler function | 37 | * @dev_id: A cookie passed back to the handler function |
@@ -42,9 +44,10 @@ static int devm_irq_match(struct device *dev, void *res, void *data) | |||
42 | * If an IRQ allocated with this function needs to be freed | 44 | * If an IRQ allocated with this function needs to be freed |
43 | * separately, dev_free_irq() must be used. | 45 | * separately, dev_free_irq() must be used. |
44 | */ | 46 | */ |
45 | int devm_request_irq(struct device *dev, unsigned int irq, | 47 | int devm_request_threaded_irq(struct device *dev, unsigned int irq, |
46 | irq_handler_t handler, unsigned long irqflags, | 48 | irq_handler_t handler, irq_handler_t thread_fn, |
47 | const char *devname, void *dev_id) | 49 | unsigned long irqflags, const char *devname, |
50 | void *dev_id) | ||
48 | { | 51 | { |
49 | struct irq_devres *dr; | 52 | struct irq_devres *dr; |
50 | int rc; | 53 | int rc; |
@@ -54,7 +57,8 @@ int devm_request_irq(struct device *dev, unsigned int irq, | |||
54 | if (!dr) | 57 | if (!dr) |
55 | return -ENOMEM; | 58 | return -ENOMEM; |
56 | 59 | ||
57 | rc = request_irq(irq, handler, irqflags, devname, dev_id); | 60 | rc = request_threaded_irq(irq, handler, thread_fn, irqflags, devname, |
61 | dev_id); | ||
58 | if (rc) { | 62 | if (rc) { |
59 | devres_free(dr); | 63 | devres_free(dr); |
60 | return rc; | 64 | return rc; |
@@ -66,7 +70,7 @@ int devm_request_irq(struct device *dev, unsigned int irq, | |||
66 | 70 | ||
67 | return 0; | 71 | return 0; |
68 | } | 72 | } |
69 | EXPORT_SYMBOL(devm_request_irq); | 73 | EXPORT_SYMBOL(devm_request_threaded_irq); |
70 | 74 | ||
71 | /** | 75 | /** |
72 | * devm_free_irq - free an interrupt | 76 | * devm_free_irq - free an interrupt |
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 3aba8d12f328..d82142be8dd2 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; | |||
69 | EXPORT_SYMBOL_GPL(nr_irqs); | 71 | EXPORT_SYMBOL_GPL(nr_irqs); |
70 | 72 | ||
71 | #ifdef CONFIG_SPARSE_IRQ | 73 | #ifdef CONFIG_SPARSE_IRQ |
74 | |||
72 | static struct irq_desc irq_desc_init = { | 75 | static struct irq_desc irq_desc_init = { |
73 | .irq = -1, | 76 | .irq = -1, |
74 | .status = IRQ_DISABLED, | 77 | .status = IRQ_DISABLED, |
@@ -76,26 +79,25 @@ 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 | ||
84 | void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr) | 84 | void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr) |
85 | { | 85 | { |
86 | unsigned long bytes; | ||
87 | char *ptr; | ||
88 | int node; | 86 | int node; |
89 | 87 | void *ptr; | |
90 | /* Compute how many bytes we need per irq and allocate them */ | ||
91 | bytes = nr * sizeof(unsigned int); | ||
92 | 88 | ||
93 | node = cpu_to_node(cpu); | 89 | node = cpu_to_node(cpu); |
94 | ptr = kzalloc_node(bytes, GFP_ATOMIC, node); | 90 | ptr = kzalloc_node(nr * sizeof(*desc->kstat_irqs), GFP_ATOMIC, node); |
95 | printk(KERN_DEBUG " alloc kstat_irqs on cpu %d node %d\n", cpu, node); | ||
96 | 91 | ||
97 | if (ptr) | 92 | /* |
98 | desc->kstat_irqs = (unsigned int *)ptr; | 93 | * don't overwite if can not get new one |
94 | * init_copy_kstat_irqs() could still use old one | ||
95 | */ | ||
96 | if (ptr) { | ||
97 | printk(KERN_DEBUG " alloc kstat_irqs on cpu %d node %d\n", | ||
98 | cpu, node); | ||
99 | desc->kstat_irqs = ptr; | ||
100 | } | ||
99 | } | 101 | } |
100 | 102 | ||
101 | static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu) | 103 | static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu) |
@@ -113,6 +115,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"); | 115 | printk(KERN_ERR "can not alloc kstat_irqs\n"); |
114 | BUG_ON(1); | 116 | BUG_ON(1); |
115 | } | 117 | } |
118 | if (!init_alloc_desc_masks(desc, cpu, false)) { | ||
119 | printk(KERN_ERR "can not alloc irq_desc cpumasks\n"); | ||
120 | BUG_ON(1); | ||
121 | } | ||
116 | arch_init_chip_data(desc, cpu); | 122 | arch_init_chip_data(desc, cpu); |
117 | } | 123 | } |
118 | 124 | ||
@@ -121,7 +127,7 @@ static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu) | |||
121 | */ | 127 | */ |
122 | DEFINE_SPINLOCK(sparse_irq_lock); | 128 | DEFINE_SPINLOCK(sparse_irq_lock); |
123 | 129 | ||
124 | struct irq_desc *irq_desc_ptrs[NR_IRQS] __read_mostly; | 130 | struct irq_desc **irq_desc_ptrs __read_mostly; |
125 | 131 | ||
126 | static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = { | 132 | static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = { |
127 | [0 ... NR_IRQS_LEGACY-1] = { | 133 | [0 ... NR_IRQS_LEGACY-1] = { |
@@ -131,14 +137,10 @@ static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_sm | |||
131 | .handle_irq = handle_bad_irq, | 137 | .handle_irq = handle_bad_irq, |
132 | .depth = 1, | 138 | .depth = 1, |
133 | .lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock), | 139 | .lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock), |
134 | #ifdef CONFIG_SMP | ||
135 | .affinity = CPU_MASK_ALL | ||
136 | #endif | ||
137 | } | 140 | } |
138 | }; | 141 | }; |
139 | 142 | ||
140 | /* FIXME: use bootmem alloc ...*/ | 143 | static unsigned int *kstat_irqs_legacy; |
141 | static unsigned int kstat_irqs_legacy[NR_IRQS_LEGACY][NR_CPUS]; | ||
142 | 144 | ||
143 | int __init early_irq_init(void) | 145 | int __init early_irq_init(void) |
144 | { | 146 | { |
@@ -148,18 +150,30 @@ int __init early_irq_init(void) | |||
148 | 150 | ||
149 | init_irq_default_affinity(); | 151 | init_irq_default_affinity(); |
150 | 152 | ||
153 | /* initialize nr_irqs based on nr_cpu_ids */ | ||
154 | arch_probe_nr_irqs(); | ||
155 | printk(KERN_INFO "NR_IRQS:%d nr_irqs:%d\n", NR_IRQS, nr_irqs); | ||
156 | |||
151 | desc = irq_desc_legacy; | 157 | desc = irq_desc_legacy; |
152 | legacy_count = ARRAY_SIZE(irq_desc_legacy); | 158 | legacy_count = ARRAY_SIZE(irq_desc_legacy); |
153 | 159 | ||
160 | /* allocate irq_desc_ptrs array based on nr_irqs */ | ||
161 | irq_desc_ptrs = alloc_bootmem(nr_irqs * sizeof(void *)); | ||
162 | |||
163 | /* allocate based on nr_cpu_ids */ | ||
164 | /* FIXME: invert kstat_irgs, and it'd be a per_cpu_alloc'd thing */ | ||
165 | kstat_irqs_legacy = alloc_bootmem(NR_IRQS_LEGACY * nr_cpu_ids * | ||
166 | sizeof(int)); | ||
167 | |||
154 | for (i = 0; i < legacy_count; i++) { | 168 | for (i = 0; i < legacy_count; i++) { |
155 | desc[i].irq = i; | 169 | desc[i].irq = i; |
156 | desc[i].kstat_irqs = kstat_irqs_legacy[i]; | 170 | desc[i].kstat_irqs = kstat_irqs_legacy + i * nr_cpu_ids; |
157 | lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); | 171 | lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); |
158 | 172 | init_alloc_desc_masks(&desc[i], 0, true); | |
159 | irq_desc_ptrs[i] = desc + i; | 173 | irq_desc_ptrs[i] = desc + i; |
160 | } | 174 | } |
161 | 175 | ||
162 | for (i = legacy_count; i < NR_IRQS; i++) | 176 | for (i = legacy_count; i < nr_irqs; i++) |
163 | irq_desc_ptrs[i] = NULL; | 177 | irq_desc_ptrs[i] = NULL; |
164 | 178 | ||
165 | return arch_early_irq_init(); | 179 | return arch_early_irq_init(); |
@@ -167,7 +181,10 @@ int __init early_irq_init(void) | |||
167 | 181 | ||
168 | struct irq_desc *irq_to_desc(unsigned int irq) | 182 | struct irq_desc *irq_to_desc(unsigned int irq) |
169 | { | 183 | { |
170 | return (irq < NR_IRQS) ? irq_desc_ptrs[irq] : NULL; | 184 | if (irq_desc_ptrs && irq < nr_irqs) |
185 | return irq_desc_ptrs[irq]; | ||
186 | |||
187 | return NULL; | ||
171 | } | 188 | } |
172 | 189 | ||
173 | struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) | 190 | struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) |
@@ -176,10 +193,9 @@ struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) | |||
176 | unsigned long flags; | 193 | unsigned long flags; |
177 | int node; | 194 | int node; |
178 | 195 | ||
179 | if (irq >= NR_IRQS) { | 196 | if (irq >= nr_irqs) { |
180 | printk(KERN_WARNING "irq >= NR_IRQS in irq_to_desc_alloc: %d %d\n", | 197 | WARN(1, "irq (%d) >= nr_irqs (%d) in irq_to_desc_alloc\n", |
181 | irq, NR_IRQS); | 198 | irq, nr_irqs); |
182 | WARN_ON(1); | ||
183 | return NULL; | 199 | return NULL; |
184 | } | 200 | } |
185 | 201 | ||
@@ -221,12 +237,10 @@ struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { | |||
221 | .handle_irq = handle_bad_irq, | 237 | .handle_irq = handle_bad_irq, |
222 | .depth = 1, | 238 | .depth = 1, |
223 | .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock), | 239 | .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock), |
224 | #ifdef CONFIG_SMP | ||
225 | .affinity = CPU_MASK_ALL | ||
226 | #endif | ||
227 | } | 240 | } |
228 | }; | 241 | }; |
229 | 242 | ||
243 | static unsigned int kstat_irqs_all[NR_IRQS][NR_CPUS]; | ||
230 | int __init early_irq_init(void) | 244 | int __init early_irq_init(void) |
231 | { | 245 | { |
232 | struct irq_desc *desc; | 246 | struct irq_desc *desc; |
@@ -235,12 +249,16 @@ int __init early_irq_init(void) | |||
235 | 249 | ||
236 | init_irq_default_affinity(); | 250 | init_irq_default_affinity(); |
237 | 251 | ||
252 | printk(KERN_INFO "NR_IRQS:%d\n", NR_IRQS); | ||
253 | |||
238 | desc = irq_desc; | 254 | desc = irq_desc; |
239 | count = ARRAY_SIZE(irq_desc); | 255 | count = ARRAY_SIZE(irq_desc); |
240 | 256 | ||
241 | for (i = 0; i < count; i++) | 257 | for (i = 0; i < count; i++) { |
242 | desc[i].irq = i; | 258 | desc[i].irq = i; |
243 | 259 | init_alloc_desc_masks(&desc[i], 0, true); | |
260 | desc[i].kstat_irqs = kstat_irqs_all[i]; | ||
261 | } | ||
244 | return arch_early_irq_init(); | 262 | return arch_early_irq_init(); |
245 | } | 263 | } |
246 | 264 | ||
@@ -255,6 +273,11 @@ struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) | |||
255 | } | 273 | } |
256 | #endif /* !CONFIG_SPARSE_IRQ */ | 274 | #endif /* !CONFIG_SPARSE_IRQ */ |
257 | 275 | ||
276 | void clear_kstat_irqs(struct irq_desc *desc) | ||
277 | { | ||
278 | memset(desc->kstat_irqs, 0, nr_cpu_ids * sizeof(*(desc->kstat_irqs))); | ||
279 | } | ||
280 | |||
258 | /* | 281 | /* |
259 | * What should we do if we get a hw irq event on an illegal vector? | 282 | * What should we do if we get a hw irq event on an illegal vector? |
260 | * Each architecture has to answer this themself. | 283 | * Each architecture has to answer this themself. |
@@ -316,6 +339,18 @@ irqreturn_t no_action(int cpl, void *dev_id) | |||
316 | return IRQ_NONE; | 339 | return IRQ_NONE; |
317 | } | 340 | } |
318 | 341 | ||
342 | static void warn_no_thread(unsigned int irq, struct irqaction *action) | ||
343 | { | ||
344 | if (test_and_set_bit(IRQTF_WARNED, &action->thread_flags)) | ||
345 | return; | ||
346 | |||
347 | printk(KERN_WARNING "IRQ %d device %s returned IRQ_WAKE_THREAD " | ||
348 | "but no thread function available.", irq, action->name); | ||
349 | } | ||
350 | |||
351 | DEFINE_TRACE(irq_handler_entry); | ||
352 | DEFINE_TRACE(irq_handler_exit); | ||
353 | |||
319 | /** | 354 | /** |
320 | * handle_IRQ_event - irq action chain handler | 355 | * handle_IRQ_event - irq action chain handler |
321 | * @irq: the interrupt number | 356 | * @irq: the interrupt number |
@@ -328,13 +363,56 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action) | |||
328 | irqreturn_t ret, retval = IRQ_NONE; | 363 | irqreturn_t ret, retval = IRQ_NONE; |
329 | unsigned int status = 0; | 364 | unsigned int status = 0; |
330 | 365 | ||
366 | WARN_ONCE(!in_irq(), "BUG: IRQ handler called from non-hardirq context!"); | ||
367 | |||
331 | if (!(action->flags & IRQF_DISABLED)) | 368 | if (!(action->flags & IRQF_DISABLED)) |
332 | local_irq_enable_in_hardirq(); | 369 | local_irq_enable_in_hardirq(); |
333 | 370 | ||
334 | do { | 371 | do { |
372 | trace_irq_handler_entry(irq, action); | ||
335 | ret = action->handler(irq, action->dev_id); | 373 | ret = action->handler(irq, action->dev_id); |
336 | if (ret == IRQ_HANDLED) | 374 | trace_irq_handler_exit(irq, action, ret); |
375 | |||
376 | switch (ret) { | ||
377 | case IRQ_WAKE_THREAD: | ||
378 | /* | ||
379 | * Set result to handled so the spurious check | ||
380 | * does not trigger. | ||
381 | */ | ||
382 | ret = IRQ_HANDLED; | ||
383 | |||
384 | /* | ||
385 | * Catch drivers which return WAKE_THREAD but | ||
386 | * did not set up a thread function | ||
387 | */ | ||
388 | if (unlikely(!action->thread_fn)) { | ||
389 | warn_no_thread(irq, action); | ||
390 | break; | ||
391 | } | ||
392 | |||
393 | /* | ||
394 | * Wake up the handler thread for this | ||
395 | * action. In case the thread crashed and was | ||
396 | * killed we just pretend that we handled the | ||
397 | * interrupt. The hardirq handler above has | ||
398 | * disabled the device interrupt, so no irq | ||
399 | * storm is lurking. | ||
400 | */ | ||
401 | if (likely(!test_bit(IRQTF_DIED, | ||
402 | &action->thread_flags))) { | ||
403 | set_bit(IRQTF_RUNTHREAD, &action->thread_flags); | ||
404 | wake_up_process(action->thread); | ||
405 | } | ||
406 | |||
407 | /* Fall through to add to randomness */ | ||
408 | case IRQ_HANDLED: | ||
337 | status |= action->flags; | 409 | status |= action->flags; |
410 | break; | ||
411 | |||
412 | default: | ||
413 | break; | ||
414 | } | ||
415 | |||
338 | retval |= ret; | 416 | retval |= ret; |
339 | action = action->next; | 417 | action = action->next; |
340 | } while (action); | 418 | } while (action); |
@@ -347,6 +425,11 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action) | |||
347 | } | 425 | } |
348 | 426 | ||
349 | #ifndef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ | 427 | #ifndef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ |
428 | |||
429 | #ifdef CONFIG_ENABLE_WARN_DEPRECATED | ||
430 | # warning __do_IRQ is deprecated. Please convert to proper flow handlers | ||
431 | #endif | ||
432 | |||
350 | /** | 433 | /** |
351 | * __do_IRQ - original all in one highlevel IRQ handler | 434 | * __do_IRQ - original all in one highlevel IRQ handler |
352 | * @irq: the interrupt number | 435 | * @irq: the interrupt number |
@@ -467,12 +550,10 @@ void early_init_irq_lock_class(void) | |||
467 | } | 550 | } |
468 | } | 551 | } |
469 | 552 | ||
470 | #ifdef CONFIG_SPARSE_IRQ | ||
471 | unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) | 553 | unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) |
472 | { | 554 | { |
473 | struct irq_desc *desc = irq_to_desc(irq); | 555 | struct irq_desc *desc = irq_to_desc(irq); |
474 | return desc ? desc->kstat_irqs[cpu] : 0; | 556 | return desc ? desc->kstat_irqs[cpu] : 0; |
475 | } | 557 | } |
476 | #endif | ||
477 | EXPORT_SYMBOL(kstat_irqs_cpu); | 558 | EXPORT_SYMBOL(kstat_irqs_cpu); |
478 | 559 | ||
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index e6d0a43cc125..01ce20eab38f 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h | |||
@@ -12,11 +12,21 @@ extern void compat_irq_chip_set_default_handler(struct irq_desc *desc); | |||
12 | 12 | ||
13 | extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, | 13 | extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, |
14 | unsigned long flags); | 14 | unsigned long flags); |
15 | extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp); | ||
16 | extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume); | ||
15 | 17 | ||
16 | extern struct lock_class_key irq_desc_lock_class; | 18 | extern struct lock_class_key irq_desc_lock_class; |
17 | extern void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr); | 19 | extern void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr); |
20 | extern void clear_kstat_irqs(struct irq_desc *desc); | ||
18 | extern spinlock_t sparse_irq_lock; | 21 | extern spinlock_t sparse_irq_lock; |
22 | |||
23 | #ifdef CONFIG_SPARSE_IRQ | ||
24 | /* irq_desc_ptrs allocated at boot time */ | ||
25 | extern struct irq_desc **irq_desc_ptrs; | ||
26 | #else | ||
27 | /* irq_desc_ptrs is a fixed size array */ | ||
19 | extern struct irq_desc *irq_desc_ptrs[NR_IRQS]; | 28 | extern struct irq_desc *irq_desc_ptrs[NR_IRQS]; |
29 | #endif | ||
20 | 30 | ||
21 | #ifdef CONFIG_PROC_FS | 31 | #ifdef CONFIG_PROC_FS |
22 | extern void register_irq_proc(unsigned int irq, struct irq_desc *desc); | 32 | extern void register_irq_proc(unsigned int irq, struct irq_desc *desc); |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 291f03664552..7e2e7dd4cd2f 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -8,16 +8,15 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/irq.h> | 10 | #include <linux/irq.h> |
11 | #include <linux/kthread.h> | ||
11 | #include <linux/module.h> | 12 | #include <linux/module.h> |
12 | #include <linux/random.h> | 13 | #include <linux/random.h> |
13 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
14 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/sched.h> | ||
15 | 17 | ||
16 | #include "internals.h" | 18 | #include "internals.h" |
17 | 19 | ||
18 | #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS) | ||
19 | cpumask_var_t irq_default_affinity; | ||
20 | |||
21 | /** | 20 | /** |
22 | * synchronize_irq - wait for pending IRQ handlers (on other CPUs) | 21 | * synchronize_irq - wait for pending IRQ handlers (on other CPUs) |
23 | * @irq: interrupt number to wait for | 22 | * @irq: interrupt number to wait for |
@@ -53,9 +52,18 @@ void synchronize_irq(unsigned int irq) | |||
53 | 52 | ||
54 | /* Oops, that failed? */ | 53 | /* Oops, that failed? */ |
55 | } while (status & IRQ_INPROGRESS); | 54 | } while (status & IRQ_INPROGRESS); |
55 | |||
56 | /* | ||
57 | * We made sure that no hardirq handler is running. Now verify | ||
58 | * that no threaded handlers are active. | ||
59 | */ | ||
60 | wait_event(desc->wait_for_threads, !atomic_read(&desc->threads_active)); | ||
56 | } | 61 | } |
57 | EXPORT_SYMBOL(synchronize_irq); | 62 | EXPORT_SYMBOL(synchronize_irq); |
58 | 63 | ||
64 | #ifdef CONFIG_SMP | ||
65 | cpumask_var_t irq_default_affinity; | ||
66 | |||
59 | /** | 67 | /** |
60 | * irq_can_set_affinity - Check if the affinity of a given irq can be set | 68 | * irq_can_set_affinity - Check if the affinity of a given irq can be set |
61 | * @irq: Interrupt to check | 69 | * @irq: Interrupt to check |
@@ -72,6 +80,18 @@ int irq_can_set_affinity(unsigned int irq) | |||
72 | return 1; | 80 | return 1; |
73 | } | 81 | } |
74 | 82 | ||
83 | static void | ||
84 | irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask) | ||
85 | { | ||
86 | struct irqaction *action = desc->action; | ||
87 | |||
88 | while (action) { | ||
89 | if (action->thread) | ||
90 | set_cpus_allowed_ptr(action->thread, cpumask); | ||
91 | action = action->next; | ||
92 | } | ||
93 | } | ||
94 | |||
75 | /** | 95 | /** |
76 | * irq_set_affinity - Set the irq affinity of a given irq | 96 | * irq_set_affinity - Set the irq affinity of a given irq |
77 | * @irq: Interrupt to set affinity | 97 | * @irq: Interrupt to set affinity |
@@ -90,16 +110,17 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask) | |||
90 | 110 | ||
91 | #ifdef CONFIG_GENERIC_PENDING_IRQ | 111 | #ifdef CONFIG_GENERIC_PENDING_IRQ |
92 | if (desc->status & IRQ_MOVE_PCNTXT || desc->status & IRQ_DISABLED) { | 112 | if (desc->status & IRQ_MOVE_PCNTXT || desc->status & IRQ_DISABLED) { |
93 | cpumask_copy(&desc->affinity, cpumask); | 113 | cpumask_copy(desc->affinity, cpumask); |
94 | desc->chip->set_affinity(irq, cpumask); | 114 | desc->chip->set_affinity(irq, cpumask); |
95 | } else { | 115 | } else { |
96 | desc->status |= IRQ_MOVE_PENDING; | 116 | desc->status |= IRQ_MOVE_PENDING; |
97 | cpumask_copy(&desc->pending_mask, cpumask); | 117 | cpumask_copy(desc->pending_mask, cpumask); |
98 | } | 118 | } |
99 | #else | 119 | #else |
100 | cpumask_copy(&desc->affinity, cpumask); | 120 | cpumask_copy(desc->affinity, cpumask); |
101 | desc->chip->set_affinity(irq, cpumask); | 121 | desc->chip->set_affinity(irq, cpumask); |
102 | #endif | 122 | #endif |
123 | irq_set_thread_affinity(desc, cpumask); | ||
103 | desc->status |= IRQ_AFFINITY_SET; | 124 | desc->status |= IRQ_AFFINITY_SET; |
104 | spin_unlock_irqrestore(&desc->lock, flags); | 125 | spin_unlock_irqrestore(&desc->lock, flags); |
105 | return 0; | 126 | return 0; |
@@ -109,7 +130,7 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask) | |||
109 | /* | 130 | /* |
110 | * Generic version of the affinity autoselector. | 131 | * Generic version of the affinity autoselector. |
111 | */ | 132 | */ |
112 | int do_irq_select_affinity(unsigned int irq, struct irq_desc *desc) | 133 | static int setup_affinity(unsigned int irq, struct irq_desc *desc) |
113 | { | 134 | { |
114 | if (!irq_can_set_affinity(irq)) | 135 | if (!irq_can_set_affinity(irq)) |
115 | return 0; | 136 | return 0; |
@@ -119,21 +140,21 @@ int do_irq_select_affinity(unsigned int irq, struct irq_desc *desc) | |||
119 | * one of the targets is online. | 140 | * one of the targets is online. |
120 | */ | 141 | */ |
121 | if (desc->status & (IRQ_AFFINITY_SET | IRQ_NO_BALANCING)) { | 142 | if (desc->status & (IRQ_AFFINITY_SET | IRQ_NO_BALANCING)) { |
122 | if (cpumask_any_and(&desc->affinity, cpu_online_mask) | 143 | if (cpumask_any_and(desc->affinity, cpu_online_mask) |
123 | < nr_cpu_ids) | 144 | < nr_cpu_ids) |
124 | goto set_affinity; | 145 | goto set_affinity; |
125 | else | 146 | else |
126 | desc->status &= ~IRQ_AFFINITY_SET; | 147 | desc->status &= ~IRQ_AFFINITY_SET; |
127 | } | 148 | } |
128 | 149 | ||
129 | cpumask_and(&desc->affinity, cpu_online_mask, irq_default_affinity); | 150 | cpumask_and(desc->affinity, cpu_online_mask, irq_default_affinity); |
130 | set_affinity: | 151 | set_affinity: |
131 | desc->chip->set_affinity(irq, &desc->affinity); | 152 | desc->chip->set_affinity(irq, desc->affinity); |
132 | 153 | ||
133 | return 0; | 154 | return 0; |
134 | } | 155 | } |
135 | #else | 156 | #else |
136 | static inline int do_irq_select_affinity(unsigned int irq, struct irq_desc *d) | 157 | static inline int setup_affinity(unsigned int irq, struct irq_desc *d) |
137 | { | 158 | { |
138 | return irq_select_affinity(irq); | 159 | return irq_select_affinity(irq); |
139 | } | 160 | } |
@@ -149,19 +170,35 @@ int irq_select_affinity_usr(unsigned int irq) | |||
149 | int ret; | 170 | int ret; |
150 | 171 | ||
151 | spin_lock_irqsave(&desc->lock, flags); | 172 | spin_lock_irqsave(&desc->lock, flags); |
152 | ret = do_irq_select_affinity(irq, desc); | 173 | ret = setup_affinity(irq, desc); |
174 | if (!ret) | ||
175 | irq_set_thread_affinity(desc, desc->affinity); | ||
153 | spin_unlock_irqrestore(&desc->lock, flags); | 176 | spin_unlock_irqrestore(&desc->lock, flags); |
154 | 177 | ||
155 | return ret; | 178 | return ret; |
156 | } | 179 | } |
157 | 180 | ||
158 | #else | 181 | #else |
159 | static inline int do_irq_select_affinity(int irq, struct irq_desc *desc) | 182 | static inline int setup_affinity(unsigned int irq, struct irq_desc *desc) |
160 | { | 183 | { |
161 | return 0; | 184 | return 0; |
162 | } | 185 | } |
163 | #endif | 186 | #endif |
164 | 187 | ||
188 | void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend) | ||
189 | { | ||
190 | if (suspend) { | ||
191 | if (!desc->action || (desc->action->flags & IRQF_TIMER)) | ||
192 | return; | ||
193 | desc->status |= IRQ_SUSPENDED; | ||
194 | } | ||
195 | |||
196 | if (!desc->depth++) { | ||
197 | desc->status |= IRQ_DISABLED; | ||
198 | desc->chip->disable(irq); | ||
199 | } | ||
200 | } | ||
201 | |||
165 | /** | 202 | /** |
166 | * disable_irq_nosync - disable an irq without waiting | 203 | * disable_irq_nosync - disable an irq without waiting |
167 | * @irq: Interrupt to disable | 204 | * @irq: Interrupt to disable |
@@ -182,10 +219,7 @@ void disable_irq_nosync(unsigned int irq) | |||
182 | return; | 219 | return; |
183 | 220 | ||
184 | spin_lock_irqsave(&desc->lock, flags); | 221 | spin_lock_irqsave(&desc->lock, flags); |
185 | if (!desc->depth++) { | 222 | __disable_irq(desc, irq, false); |
186 | desc->status |= IRQ_DISABLED; | ||
187 | desc->chip->disable(irq); | ||
188 | } | ||
189 | spin_unlock_irqrestore(&desc->lock, flags); | 223 | spin_unlock_irqrestore(&desc->lock, flags); |
190 | } | 224 | } |
191 | EXPORT_SYMBOL(disable_irq_nosync); | 225 | EXPORT_SYMBOL(disable_irq_nosync); |
@@ -215,15 +249,21 @@ void disable_irq(unsigned int irq) | |||
215 | } | 249 | } |
216 | EXPORT_SYMBOL(disable_irq); | 250 | EXPORT_SYMBOL(disable_irq); |
217 | 251 | ||
218 | static void __enable_irq(struct irq_desc *desc, unsigned int irq) | 252 | void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume) |
219 | { | 253 | { |
254 | if (resume) | ||
255 | desc->status &= ~IRQ_SUSPENDED; | ||
256 | |||
220 | switch (desc->depth) { | 257 | switch (desc->depth) { |
221 | case 0: | 258 | case 0: |
259 | err_out: | ||
222 | WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n", irq); | 260 | WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n", irq); |
223 | break; | 261 | break; |
224 | case 1: { | 262 | case 1: { |
225 | unsigned int status = desc->status & ~IRQ_DISABLED; | 263 | unsigned int status = desc->status & ~IRQ_DISABLED; |
226 | 264 | ||
265 | if (desc->status & IRQ_SUSPENDED) | ||
266 | goto err_out; | ||
227 | /* Prevent probing on this irq: */ | 267 | /* Prevent probing on this irq: */ |
228 | desc->status = status | IRQ_NOPROBE; | 268 | desc->status = status | IRQ_NOPROBE; |
229 | check_irq_resend(desc, irq); | 269 | check_irq_resend(desc, irq); |
@@ -253,7 +293,7 @@ void enable_irq(unsigned int irq) | |||
253 | return; | 293 | return; |
254 | 294 | ||
255 | spin_lock_irqsave(&desc->lock, flags); | 295 | spin_lock_irqsave(&desc->lock, flags); |
256 | __enable_irq(desc, irq); | 296 | __enable_irq(desc, irq, false); |
257 | spin_unlock_irqrestore(&desc->lock, flags); | 297 | spin_unlock_irqrestore(&desc->lock, flags); |
258 | } | 298 | } |
259 | EXPORT_SYMBOL(enable_irq); | 299 | EXPORT_SYMBOL(enable_irq); |
@@ -384,14 +424,98 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, | |||
384 | return ret; | 424 | return ret; |
385 | } | 425 | } |
386 | 426 | ||
427 | static int irq_wait_for_interrupt(struct irqaction *action) | ||
428 | { | ||
429 | while (!kthread_should_stop()) { | ||
430 | set_current_state(TASK_INTERRUPTIBLE); | ||
431 | |||
432 | if (test_and_clear_bit(IRQTF_RUNTHREAD, | ||
433 | &action->thread_flags)) { | ||
434 | __set_current_state(TASK_RUNNING); | ||
435 | return 0; | ||
436 | } | ||
437 | schedule(); | ||
438 | } | ||
439 | return -1; | ||
440 | } | ||
441 | |||
442 | /* | ||
443 | * Interrupt handler thread | ||
444 | */ | ||
445 | static int irq_thread(void *data) | ||
446 | { | ||
447 | struct sched_param param = { .sched_priority = MAX_USER_RT_PRIO/2, }; | ||
448 | struct irqaction *action = data; | ||
449 | struct irq_desc *desc = irq_to_desc(action->irq); | ||
450 | int wake; | ||
451 | |||
452 | sched_setscheduler(current, SCHED_FIFO, ¶m); | ||
453 | current->irqaction = action; | ||
454 | |||
455 | while (!irq_wait_for_interrupt(action)) { | ||
456 | |||
457 | atomic_inc(&desc->threads_active); | ||
458 | |||
459 | spin_lock_irq(&desc->lock); | ||
460 | if (unlikely(desc->status & IRQ_DISABLED)) { | ||
461 | /* | ||
462 | * CHECKME: We might need a dedicated | ||
463 | * IRQ_THREAD_PENDING flag here, which | ||
464 | * retriggers the thread in check_irq_resend() | ||
465 | * but AFAICT IRQ_PENDING should be fine as it | ||
466 | * retriggers the interrupt itself --- tglx | ||
467 | */ | ||
468 | desc->status |= IRQ_PENDING; | ||
469 | spin_unlock_irq(&desc->lock); | ||
470 | } else { | ||
471 | spin_unlock_irq(&desc->lock); | ||
472 | |||
473 | action->thread_fn(action->irq, action->dev_id); | ||
474 | } | ||
475 | |||
476 | wake = atomic_dec_and_test(&desc->threads_active); | ||
477 | |||
478 | if (wake && waitqueue_active(&desc->wait_for_threads)) | ||
479 | wake_up(&desc->wait_for_threads); | ||
480 | } | ||
481 | |||
482 | /* | ||
483 | * Clear irqaction. Otherwise exit_irq_thread() would make | ||
484 | * fuzz about an active irq thread going into nirvana. | ||
485 | */ | ||
486 | current->irqaction = NULL; | ||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | /* | ||
491 | * Called from do_exit() | ||
492 | */ | ||
493 | void exit_irq_thread(void) | ||
494 | { | ||
495 | struct task_struct *tsk = current; | ||
496 | |||
497 | if (!tsk->irqaction) | ||
498 | return; | ||
499 | |||
500 | printk(KERN_ERR | ||
501 | "exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n", | ||
502 | tsk->comm ? tsk->comm : "", tsk->pid, tsk->irqaction->irq); | ||
503 | |||
504 | /* | ||
505 | * Set the THREAD DIED flag to prevent further wakeups of the | ||
506 | * soon to be gone threaded handler. | ||
507 | */ | ||
508 | set_bit(IRQTF_DIED, &tsk->irqaction->flags); | ||
509 | } | ||
510 | |||
387 | /* | 511 | /* |
388 | * Internal function to register an irqaction - typically used to | 512 | * Internal function to register an irqaction - typically used to |
389 | * allocate special interrupts that are part of the architecture. | 513 | * allocate special interrupts that are part of the architecture. |
390 | */ | 514 | */ |
391 | static int | 515 | static int |
392 | __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new) | 516 | __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) |
393 | { | 517 | { |
394 | struct irqaction *old, **p; | 518 | struct irqaction *old, **old_ptr; |
395 | const char *old_name = NULL; | 519 | const char *old_name = NULL; |
396 | unsigned long flags; | 520 | unsigned long flags; |
397 | int shared = 0; | 521 | int shared = 0; |
@@ -420,11 +544,31 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new) | |||
420 | } | 544 | } |
421 | 545 | ||
422 | /* | 546 | /* |
547 | * Threaded handler ? | ||
548 | */ | ||
549 | if (new->thread_fn) { | ||
550 | struct task_struct *t; | ||
551 | |||
552 | t = kthread_create(irq_thread, new, "irq/%d-%s", irq, | ||
553 | new->name); | ||
554 | if (IS_ERR(t)) | ||
555 | return PTR_ERR(t); | ||
556 | /* | ||
557 | * We keep the reference to the task struct even if | ||
558 | * the thread dies to avoid that the interrupt code | ||
559 | * references an already freed task_struct. | ||
560 | */ | ||
561 | get_task_struct(t); | ||
562 | new->thread = t; | ||
563 | wake_up_process(t); | ||
564 | } | ||
565 | |||
566 | /* | ||
423 | * The following block of code has to be executed atomically | 567 | * The following block of code has to be executed atomically |
424 | */ | 568 | */ |
425 | spin_lock_irqsave(&desc->lock, flags); | 569 | spin_lock_irqsave(&desc->lock, flags); |
426 | p = &desc->action; | 570 | old_ptr = &desc->action; |
427 | old = *p; | 571 | old = *old_ptr; |
428 | if (old) { | 572 | if (old) { |
429 | /* | 573 | /* |
430 | * Can't share interrupts unless both agree to and are | 574 | * Can't share interrupts unless both agree to and are |
@@ -447,8 +591,8 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new) | |||
447 | 591 | ||
448 | /* add new interrupt at end of irq queue */ | 592 | /* add new interrupt at end of irq queue */ |
449 | do { | 593 | do { |
450 | p = &old->next; | 594 | old_ptr = &old->next; |
451 | old = *p; | 595 | old = *old_ptr; |
452 | } while (old); | 596 | } while (old); |
453 | shared = 1; | 597 | shared = 1; |
454 | } | 598 | } |
@@ -456,15 +600,15 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new) | |||
456 | if (!shared) { | 600 | if (!shared) { |
457 | irq_chip_set_defaults(desc->chip); | 601 | irq_chip_set_defaults(desc->chip); |
458 | 602 | ||
603 | init_waitqueue_head(&desc->wait_for_threads); | ||
604 | |||
459 | /* Setup the type (level, edge polarity) if configured: */ | 605 | /* Setup the type (level, edge polarity) if configured: */ |
460 | if (new->flags & IRQF_TRIGGER_MASK) { | 606 | if (new->flags & IRQF_TRIGGER_MASK) { |
461 | ret = __irq_set_trigger(desc, irq, | 607 | ret = __irq_set_trigger(desc, irq, |
462 | new->flags & IRQF_TRIGGER_MASK); | 608 | new->flags & IRQF_TRIGGER_MASK); |
463 | 609 | ||
464 | if (ret) { | 610 | if (ret) |
465 | spin_unlock_irqrestore(&desc->lock, flags); | 611 | goto out_thread; |
466 | return ret; | ||
467 | } | ||
468 | } else | 612 | } else |
469 | compat_irq_chip_set_default_handler(desc); | 613 | compat_irq_chip_set_default_handler(desc); |
470 | #if defined(CONFIG_IRQ_PER_CPU) | 614 | #if defined(CONFIG_IRQ_PER_CPU) |
@@ -488,7 +632,7 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new) | |||
488 | desc->status |= IRQ_NO_BALANCING; | 632 | desc->status |= IRQ_NO_BALANCING; |
489 | 633 | ||
490 | /* Set default affinity mask once everything is setup */ | 634 | /* Set default affinity mask once everything is setup */ |
491 | do_irq_select_affinity(irq, desc); | 635 | setup_affinity(irq, desc); |
492 | 636 | ||
493 | } else if ((new->flags & IRQF_TRIGGER_MASK) | 637 | } else if ((new->flags & IRQF_TRIGGER_MASK) |
494 | && (new->flags & IRQF_TRIGGER_MASK) | 638 | && (new->flags & IRQF_TRIGGER_MASK) |
@@ -499,7 +643,7 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new) | |||
499 | (int)(new->flags & IRQF_TRIGGER_MASK)); | 643 | (int)(new->flags & IRQF_TRIGGER_MASK)); |
500 | } | 644 | } |
501 | 645 | ||
502 | *p = new; | 646 | *old_ptr = new; |
503 | 647 | ||
504 | /* Reset broken irq detection when installing new handler */ | 648 | /* Reset broken irq detection when installing new handler */ |
505 | desc->irq_count = 0; | 649 | desc->irq_count = 0; |
@@ -511,7 +655,7 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new) | |||
511 | */ | 655 | */ |
512 | if (shared && (desc->status & IRQ_SPURIOUS_DISABLED)) { | 656 | if (shared && (desc->status & IRQ_SPURIOUS_DISABLED)) { |
513 | desc->status &= ~IRQ_SPURIOUS_DISABLED; | 657 | desc->status &= ~IRQ_SPURIOUS_DISABLED; |
514 | __enable_irq(desc, irq); | 658 | __enable_irq(desc, irq, false); |
515 | } | 659 | } |
516 | 660 | ||
517 | spin_unlock_irqrestore(&desc->lock, flags); | 661 | spin_unlock_irqrestore(&desc->lock, flags); |
@@ -532,8 +676,19 @@ mismatch: | |||
532 | dump_stack(); | 676 | dump_stack(); |
533 | } | 677 | } |
534 | #endif | 678 | #endif |
679 | ret = -EBUSY; | ||
680 | |||
681 | out_thread: | ||
535 | spin_unlock_irqrestore(&desc->lock, flags); | 682 | spin_unlock_irqrestore(&desc->lock, flags); |
536 | return -EBUSY; | 683 | if (new->thread) { |
684 | struct task_struct *t = new->thread; | ||
685 | |||
686 | new->thread = NULL; | ||
687 | if (likely(!test_bit(IRQTF_DIED, &new->thread_flags))) | ||
688 | kthread_stop(t); | ||
689 | put_task_struct(t); | ||
690 | } | ||
691 | return ret; | ||
537 | } | 692 | } |
538 | 693 | ||
539 | /** | 694 | /** |
@@ -549,97 +704,138 @@ int setup_irq(unsigned int irq, struct irqaction *act) | |||
549 | 704 | ||
550 | return __setup_irq(irq, desc, act); | 705 | return __setup_irq(irq, desc, act); |
551 | } | 706 | } |
707 | EXPORT_SYMBOL_GPL(setup_irq); | ||
552 | 708 | ||
553 | /** | 709 | /* |
554 | * free_irq - free an interrupt | 710 | * Internal function to unregister an irqaction - used to free |
555 | * @irq: Interrupt line to free | 711 | * regular and special interrupts that are part of the architecture. |
556 | * @dev_id: Device identity to free | ||
557 | * | ||
558 | * Remove an interrupt handler. The handler is removed and if the | ||
559 | * interrupt line is no longer in use by any driver it is disabled. | ||
560 | * On a shared IRQ the caller must ensure the interrupt is disabled | ||
561 | * on the card it drives before calling this function. The function | ||
562 | * does not return until any executing interrupts for this IRQ | ||
563 | * have completed. | ||
564 | * | ||
565 | * This function must not be called from interrupt context. | ||
566 | */ | 712 | */ |
567 | void free_irq(unsigned int irq, void *dev_id) | 713 | static struct irqaction *__free_irq(unsigned int irq, void *dev_id) |
568 | { | 714 | { |
569 | struct irq_desc *desc = irq_to_desc(irq); | 715 | struct irq_desc *desc = irq_to_desc(irq); |
570 | struct irqaction **p; | 716 | struct irqaction *action, **action_ptr; |
717 | struct task_struct *irqthread; | ||
571 | unsigned long flags; | 718 | unsigned long flags; |
572 | 719 | ||
573 | WARN_ON(in_interrupt()); | 720 | WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq); |
574 | 721 | ||
575 | if (!desc) | 722 | if (!desc) |
576 | return; | 723 | return NULL; |
577 | 724 | ||
578 | spin_lock_irqsave(&desc->lock, flags); | 725 | spin_lock_irqsave(&desc->lock, flags); |
579 | p = &desc->action; | 726 | |
727 | /* | ||
728 | * There can be multiple actions per IRQ descriptor, find the right | ||
729 | * one based on the dev_id: | ||
730 | */ | ||
731 | action_ptr = &desc->action; | ||
580 | for (;;) { | 732 | for (;;) { |
581 | struct irqaction *action = *p; | 733 | action = *action_ptr; |
734 | |||
735 | if (!action) { | ||
736 | WARN(1, "Trying to free already-free IRQ %d\n", irq); | ||
737 | spin_unlock_irqrestore(&desc->lock, flags); | ||
582 | 738 | ||
583 | if (action) { | 739 | return NULL; |
584 | struct irqaction **pp = p; | 740 | } |
585 | 741 | ||
586 | p = &action->next; | 742 | if (action->dev_id == dev_id) |
587 | if (action->dev_id != dev_id) | 743 | break; |
588 | continue; | 744 | action_ptr = &action->next; |
745 | } | ||
589 | 746 | ||
590 | /* Found it - now remove it from the list of entries */ | 747 | /* Found it - now remove it from the list of entries: */ |
591 | *pp = action->next; | 748 | *action_ptr = action->next; |
592 | 749 | ||
593 | /* Currently used only by UML, might disappear one day.*/ | 750 | /* Currently used only by UML, might disappear one day: */ |
594 | #ifdef CONFIG_IRQ_RELEASE_METHOD | 751 | #ifdef CONFIG_IRQ_RELEASE_METHOD |
595 | if (desc->chip->release) | 752 | if (desc->chip->release) |
596 | desc->chip->release(irq, dev_id); | 753 | desc->chip->release(irq, dev_id); |
597 | #endif | 754 | #endif |
598 | 755 | ||
599 | if (!desc->action) { | 756 | /* If this was the last handler, shut down the IRQ line: */ |
600 | desc->status |= IRQ_DISABLED; | 757 | if (!desc->action) { |
601 | if (desc->chip->shutdown) | 758 | desc->status |= IRQ_DISABLED; |
602 | desc->chip->shutdown(irq); | 759 | if (desc->chip->shutdown) |
603 | else | 760 | desc->chip->shutdown(irq); |
604 | desc->chip->disable(irq); | 761 | else |
605 | } | 762 | desc->chip->disable(irq); |
606 | spin_unlock_irqrestore(&desc->lock, flags); | 763 | } |
607 | unregister_handler_proc(irq, action); | 764 | |
765 | irqthread = action->thread; | ||
766 | action->thread = NULL; | ||
767 | |||
768 | spin_unlock_irqrestore(&desc->lock, flags); | ||
769 | |||
770 | unregister_handler_proc(irq, action); | ||
771 | |||
772 | /* Make sure it's not being used on another CPU: */ | ||
773 | synchronize_irq(irq); | ||
774 | |||
775 | if (irqthread) { | ||
776 | if (!test_bit(IRQTF_DIED, &action->thread_flags)) | ||
777 | kthread_stop(irqthread); | ||
778 | put_task_struct(irqthread); | ||
779 | } | ||
608 | 780 | ||
609 | /* Make sure it's not being used on another CPU */ | ||
610 | synchronize_irq(irq); | ||
611 | #ifdef CONFIG_DEBUG_SHIRQ | ||
612 | /* | ||
613 | * It's a shared IRQ -- the driver ought to be | ||
614 | * prepared for it to happen even now it's | ||
615 | * being freed, so let's make sure.... We do | ||
616 | * this after actually deregistering it, to | ||
617 | * make sure that a 'real' IRQ doesn't run in | ||
618 | * parallel with our fake | ||
619 | */ | ||
620 | if (action->flags & IRQF_SHARED) { | ||
621 | local_irq_save(flags); | ||
622 | action->handler(irq, dev_id); | ||
623 | local_irq_restore(flags); | ||
624 | } | ||
625 | #endif | ||
626 | kfree(action); | ||
627 | return; | ||
628 | } | ||
629 | printk(KERN_ERR "Trying to free already-free IRQ %d\n", irq); | ||
630 | #ifdef CONFIG_DEBUG_SHIRQ | 781 | #ifdef CONFIG_DEBUG_SHIRQ |
631 | dump_stack(); | 782 | /* |
632 | #endif | 783 | * It's a shared IRQ -- the driver ought to be prepared for an IRQ |
633 | spin_unlock_irqrestore(&desc->lock, flags); | 784 | * event to happen even now it's being freed, so let's make sure that |
634 | return; | 785 | * is so by doing an extra call to the handler .... |
786 | * | ||
787 | * ( We do this after actually deregistering it, to make sure that a | ||
788 | * 'real' IRQ doesn't run in * parallel with our fake. ) | ||
789 | */ | ||
790 | if (action->flags & IRQF_SHARED) { | ||
791 | local_irq_save(flags); | ||
792 | action->handler(irq, dev_id); | ||
793 | local_irq_restore(flags); | ||
635 | } | 794 | } |
795 | #endif | ||
796 | return action; | ||
797 | } | ||
798 | |||
799 | /** | ||
800 | * remove_irq - free an interrupt | ||
801 | * @irq: Interrupt line to free | ||
802 | * @act: irqaction for the interrupt | ||
803 | * | ||
804 | * Used to remove interrupts statically setup by the early boot process. | ||
805 | */ | ||
806 | void remove_irq(unsigned int irq, struct irqaction *act) | ||
807 | { | ||
808 | __free_irq(irq, act->dev_id); | ||
809 | } | ||
810 | EXPORT_SYMBOL_GPL(remove_irq); | ||
811 | |||
812 | /** | ||
813 | * free_irq - free an interrupt allocated with request_irq | ||
814 | * @irq: Interrupt line to free | ||
815 | * @dev_id: Device identity to free | ||
816 | * | ||
817 | * Remove an interrupt handler. The handler is removed and if the | ||
818 | * interrupt line is no longer in use by any driver it is disabled. | ||
819 | * On a shared IRQ the caller must ensure the interrupt is disabled | ||
820 | * on the card it drives before calling this function. The function | ||
821 | * does not return until any executing interrupts for this IRQ | ||
822 | * have completed. | ||
823 | * | ||
824 | * This function must not be called from interrupt context. | ||
825 | */ | ||
826 | void free_irq(unsigned int irq, void *dev_id) | ||
827 | { | ||
828 | kfree(__free_irq(irq, dev_id)); | ||
636 | } | 829 | } |
637 | EXPORT_SYMBOL(free_irq); | 830 | EXPORT_SYMBOL(free_irq); |
638 | 831 | ||
639 | /** | 832 | /** |
640 | * request_irq - allocate an interrupt line | 833 | * request_threaded_irq - allocate an interrupt line |
641 | * @irq: Interrupt line to allocate | 834 | * @irq: Interrupt line to allocate |
642 | * @handler: Function to be called when the IRQ occurs | 835 | * @handler: Function to be called when the IRQ occurs. |
836 | * Primary handler for threaded interrupts | ||
837 | * @thread_fn: Function called from the irq handler thread | ||
838 | * If NULL, no irq thread is created | ||
643 | * @irqflags: Interrupt type flags | 839 | * @irqflags: Interrupt type flags |
644 | * @devname: An ascii name for the claiming device | 840 | * @devname: An ascii name for the claiming device |
645 | * @dev_id: A cookie passed back to the handler function | 841 | * @dev_id: A cookie passed back to the handler function |
@@ -651,6 +847,15 @@ EXPORT_SYMBOL(free_irq); | |||
651 | * raises, you must take care both to initialise your hardware | 847 | * raises, you must take care both to initialise your hardware |
652 | * and to set up the interrupt handler in the right order. | 848 | * and to set up the interrupt handler in the right order. |
653 | * | 849 | * |
850 | * If you want to set up a threaded irq handler for your device | ||
851 | * then you need to supply @handler and @thread_fn. @handler ist | ||
852 | * still called in hard interrupt context and has to check | ||
853 | * whether the interrupt originates from the device. If yes it | ||
854 | * needs to disable the interrupt on the device and return | ||
855 | * IRQ_THREAD_WAKE which will wake up the handler thread and run | ||
856 | * @thread_fn. This split handler design is necessary to support | ||
857 | * shared interrupts. | ||
858 | * | ||
654 | * Dev_id must be globally unique. Normally the address of the | 859 | * Dev_id must be globally unique. Normally the address of the |
655 | * device data structure is used as the cookie. Since the handler | 860 | * device data structure is used as the cookie. Since the handler |
656 | * receives this value it makes sense to use it. | 861 | * receives this value it makes sense to use it. |
@@ -666,8 +871,9 @@ EXPORT_SYMBOL(free_irq); | |||
666 | * IRQF_TRIGGER_* Specify active edge(s) or level | 871 | * IRQF_TRIGGER_* Specify active edge(s) or level |
667 | * | 872 | * |
668 | */ | 873 | */ |
669 | int request_irq(unsigned int irq, irq_handler_t handler, | 874 | int request_threaded_irq(unsigned int irq, irq_handler_t handler, |
670 | unsigned long irqflags, const char *devname, void *dev_id) | 875 | irq_handler_t thread_fn, unsigned long irqflags, |
876 | const char *devname, void *dev_id) | ||
671 | { | 877 | { |
672 | struct irqaction *action; | 878 | struct irqaction *action; |
673 | struct irq_desc *desc; | 879 | struct irq_desc *desc; |
@@ -679,11 +885,12 @@ int request_irq(unsigned int irq, irq_handler_t handler, | |||
679 | * the behavior is classified as "will not fix" so we need to | 885 | * the behavior is classified as "will not fix" so we need to |
680 | * start nudging drivers away from using that idiom. | 886 | * start nudging drivers away from using that idiom. |
681 | */ | 887 | */ |
682 | if ((irqflags & (IRQF_SHARED|IRQF_DISABLED)) | 888 | if ((irqflags & (IRQF_SHARED|IRQF_DISABLED)) == |
683 | == (IRQF_SHARED|IRQF_DISABLED)) | 889 | (IRQF_SHARED|IRQF_DISABLED)) { |
684 | pr_warning("IRQ %d/%s: IRQF_DISABLED is not " | 890 | pr_warning( |
685 | "guaranteed on shared IRQs\n", | 891 | "IRQ %d/%s: IRQF_DISABLED is not guaranteed on shared IRQs\n", |
686 | irq, devname); | 892 | irq, devname); |
893 | } | ||
687 | 894 | ||
688 | #ifdef CONFIG_LOCKDEP | 895 | #ifdef CONFIG_LOCKDEP |
689 | /* | 896 | /* |
@@ -709,15 +916,14 @@ int request_irq(unsigned int irq, irq_handler_t handler, | |||
709 | if (!handler) | 916 | if (!handler) |
710 | return -EINVAL; | 917 | return -EINVAL; |
711 | 918 | ||
712 | action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC); | 919 | action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); |
713 | if (!action) | 920 | if (!action) |
714 | return -ENOMEM; | 921 | return -ENOMEM; |
715 | 922 | ||
716 | action->handler = handler; | 923 | action->handler = handler; |
924 | action->thread_fn = thread_fn; | ||
717 | action->flags = irqflags; | 925 | action->flags = irqflags; |
718 | cpus_clear(action->mask); | ||
719 | action->name = devname; | 926 | action->name = devname; |
720 | action->next = NULL; | ||
721 | action->dev_id = dev_id; | 927 | action->dev_id = dev_id; |
722 | 928 | ||
723 | retval = __setup_irq(irq, desc, action); | 929 | retval = __setup_irq(irq, desc, action); |
@@ -745,4 +951,4 @@ int request_irq(unsigned int irq, irq_handler_t handler, | |||
745 | #endif | 951 | #endif |
746 | return retval; | 952 | return retval; |
747 | } | 953 | } |
748 | EXPORT_SYMBOL(request_irq); | 954 | EXPORT_SYMBOL(request_threaded_irq); |
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c index bd72329e630c..e05ad9be43b7 100644 --- a/kernel/irq/migration.c +++ b/kernel/irq/migration.c | |||
@@ -18,7 +18,7 @@ void move_masked_irq(int irq) | |||
18 | 18 | ||
19 | desc->status &= ~IRQ_MOVE_PENDING; | 19 | desc->status &= ~IRQ_MOVE_PENDING; |
20 | 20 | ||
21 | if (unlikely(cpumask_empty(&desc->pending_mask))) | 21 | if (unlikely(cpumask_empty(desc->pending_mask))) |
22 | return; | 22 | return; |
23 | 23 | ||
24 | if (!desc->chip->set_affinity) | 24 | if (!desc->chip->set_affinity) |
@@ -38,13 +38,13 @@ void move_masked_irq(int irq) | |||
38 | * For correct operation this depends on the caller | 38 | * For correct operation this depends on the caller |
39 | * masking the irqs. | 39 | * masking the irqs. |
40 | */ | 40 | */ |
41 | if (likely(cpumask_any_and(&desc->pending_mask, cpu_online_mask) | 41 | if (likely(cpumask_any_and(desc->pending_mask, cpu_online_mask) |
42 | < nr_cpu_ids)) { | 42 | < nr_cpu_ids)) { |
43 | cpumask_and(&desc->affinity, | 43 | cpumask_and(desc->affinity, |
44 | &desc->pending_mask, cpu_online_mask); | 44 | desc->pending_mask, cpu_online_mask); |
45 | desc->chip->set_affinity(irq, &desc->affinity); | 45 | desc->chip->set_affinity(irq, desc->affinity); |
46 | } | 46 | } |
47 | cpumask_clear(&desc->pending_mask); | 47 | cpumask_clear(desc->pending_mask); |
48 | } | 48 | } |
49 | 49 | ||
50 | void move_native_irq(int irq) | 50 | void move_native_irq(int irq) |
diff --git a/kernel/irq/numa_migrate.c b/kernel/irq/numa_migrate.c index acd88356ac76..44bbdcbaf8d2 100644 --- a/kernel/irq/numa_migrate.c +++ b/kernel/irq/numa_migrate.c | |||
@@ -17,16 +17,11 @@ static void init_copy_kstat_irqs(struct irq_desc *old_desc, | |||
17 | struct irq_desc *desc, | 17 | struct irq_desc *desc, |
18 | int cpu, int nr) | 18 | int cpu, int nr) |
19 | { | 19 | { |
20 | unsigned long bytes; | ||
21 | |||
22 | init_kstat_irqs(desc, cpu, nr); | 20 | init_kstat_irqs(desc, cpu, nr); |
23 | 21 | ||
24 | if (desc->kstat_irqs != old_desc->kstat_irqs) { | 22 | if (desc->kstat_irqs != old_desc->kstat_irqs) |
25 | /* Compute how many bytes we need per irq and allocate them */ | 23 | memcpy(desc->kstat_irqs, old_desc->kstat_irqs, |
26 | bytes = nr * sizeof(unsigned int); | 24 | nr * sizeof(*desc->kstat_irqs)); |
27 | |||
28 | memcpy(desc->kstat_irqs, old_desc->kstat_irqs, bytes); | ||
29 | } | ||
30 | } | 25 | } |
31 | 26 | ||
32 | static void free_kstat_irqs(struct irq_desc *old_desc, struct irq_desc *desc) | 27 | static void free_kstat_irqs(struct irq_desc *old_desc, struct irq_desc *desc) |
@@ -38,20 +33,28 @@ static void free_kstat_irqs(struct irq_desc *old_desc, struct irq_desc *desc) | |||
38 | old_desc->kstat_irqs = NULL; | 33 | old_desc->kstat_irqs = NULL; |
39 | } | 34 | } |
40 | 35 | ||
41 | static void init_copy_one_irq_desc(int irq, struct irq_desc *old_desc, | 36 | static bool init_copy_one_irq_desc(int irq, struct irq_desc *old_desc, |
42 | struct irq_desc *desc, int cpu) | 37 | struct irq_desc *desc, int cpu) |
43 | { | 38 | { |
44 | memcpy(desc, old_desc, sizeof(struct irq_desc)); | 39 | memcpy(desc, old_desc, sizeof(struct irq_desc)); |
40 | if (!init_alloc_desc_masks(desc, cpu, false)) { | ||
41 | printk(KERN_ERR "irq %d: can not get new irq_desc cpumask " | ||
42 | "for migration.\n", irq); | ||
43 | return false; | ||
44 | } | ||
45 | spin_lock_init(&desc->lock); | 45 | spin_lock_init(&desc->lock); |
46 | desc->cpu = cpu; | 46 | desc->cpu = cpu; |
47 | lockdep_set_class(&desc->lock, &irq_desc_lock_class); | 47 | lockdep_set_class(&desc->lock, &irq_desc_lock_class); |
48 | init_copy_kstat_irqs(old_desc, desc, cpu, nr_cpu_ids); | 48 | init_copy_kstat_irqs(old_desc, desc, cpu, nr_cpu_ids); |
49 | init_copy_desc_masks(old_desc, desc); | ||
49 | arch_init_copy_chip_data(old_desc, desc, cpu); | 50 | arch_init_copy_chip_data(old_desc, desc, cpu); |
51 | return true; | ||
50 | } | 52 | } |
51 | 53 | ||
52 | static void free_one_irq_desc(struct irq_desc *old_desc, struct irq_desc *desc) | 54 | static void free_one_irq_desc(struct irq_desc *old_desc, struct irq_desc *desc) |
53 | { | 55 | { |
54 | free_kstat_irqs(old_desc, desc); | 56 | free_kstat_irqs(old_desc, desc); |
57 | free_desc_masks(old_desc, desc); | ||
55 | arch_free_chip_data(old_desc, desc); | 58 | arch_free_chip_data(old_desc, desc); |
56 | } | 59 | } |
57 | 60 | ||
@@ -76,12 +79,18 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc, | |||
76 | node = cpu_to_node(cpu); | 79 | node = cpu_to_node(cpu); |
77 | desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node); | 80 | desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node); |
78 | if (!desc) { | 81 | if (!desc) { |
79 | printk(KERN_ERR "irq %d: can not get new irq_desc for migration.\n", irq); | 82 | printk(KERN_ERR "irq %d: can not get new irq_desc " |
83 | "for migration.\n", irq); | ||
84 | /* still use old one */ | ||
85 | desc = old_desc; | ||
86 | goto out_unlock; | ||
87 | } | ||
88 | if (!init_copy_one_irq_desc(irq, old_desc, desc, cpu)) { | ||
80 | /* still use old one */ | 89 | /* still use old one */ |
90 | kfree(desc); | ||
81 | desc = old_desc; | 91 | desc = old_desc; |
82 | goto out_unlock; | 92 | goto out_unlock; |
83 | } | 93 | } |
84 | init_copy_one_irq_desc(irq, old_desc, desc, cpu); | ||
85 | 94 | ||
86 | irq_desc_ptrs[irq] = desc; | 95 | irq_desc_ptrs[irq] = desc; |
87 | spin_unlock_irqrestore(&sparse_irq_lock, flags); | 96 | spin_unlock_irqrestore(&sparse_irq_lock, flags); |
diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c new file mode 100644 index 000000000000..638d8bedec14 --- /dev/null +++ b/kernel/irq/pm.c | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * linux/kernel/irq/pm.c | ||
3 | * | ||
4 | * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | ||
5 | * | ||
6 | * This file contains power management functions related to interrupts. | ||
7 | */ | ||
8 | |||
9 | #include <linux/irq.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | |||
13 | #include "internals.h" | ||
14 | |||
15 | /** | ||
16 | * suspend_device_irqs - disable all currently enabled interrupt lines | ||
17 | * | ||
18 | * During system-wide suspend or hibernation device interrupts need to be | ||
19 | * disabled at the chip level and this function is provided for this purpose. | ||
20 | * It disables all interrupt lines that are enabled at the moment and sets the | ||
21 | * IRQ_SUSPENDED flag for them. | ||
22 | */ | ||
23 | void suspend_device_irqs(void) | ||
24 | { | ||
25 | struct irq_desc *desc; | ||
26 | int irq; | ||
27 | |||
28 | for_each_irq_desc(irq, desc) { | ||
29 | unsigned long flags; | ||
30 | |||
31 | spin_lock_irqsave(&desc->lock, flags); | ||
32 | __disable_irq(desc, irq, true); | ||
33 | spin_unlock_irqrestore(&desc->lock, flags); | ||
34 | } | ||
35 | |||
36 | for_each_irq_desc(irq, desc) | ||
37 | if (desc->status & IRQ_SUSPENDED) | ||
38 | synchronize_irq(irq); | ||
39 | } | ||
40 | EXPORT_SYMBOL_GPL(suspend_device_irqs); | ||
41 | |||
42 | /** | ||
43 | * resume_device_irqs - enable interrupt lines disabled by suspend_device_irqs() | ||
44 | * | ||
45 | * Enable all interrupt lines previously disabled by suspend_device_irqs() that | ||
46 | * have the IRQ_SUSPENDED flag set. | ||
47 | */ | ||
48 | void resume_device_irqs(void) | ||
49 | { | ||
50 | struct irq_desc *desc; | ||
51 | int irq; | ||
52 | |||
53 | for_each_irq_desc(irq, desc) { | ||
54 | unsigned long flags; | ||
55 | |||
56 | if (!(desc->status & IRQ_SUSPENDED)) | ||
57 | continue; | ||
58 | |||
59 | spin_lock_irqsave(&desc->lock, flags); | ||
60 | __enable_irq(desc, irq, true); | ||
61 | spin_unlock_irqrestore(&desc->lock, flags); | ||
62 | } | ||
63 | } | ||
64 | EXPORT_SYMBOL_GPL(resume_device_irqs); | ||
65 | |||
66 | /** | ||
67 | * check_wakeup_irqs - check if any wake-up interrupts are pending | ||
68 | */ | ||
69 | int check_wakeup_irqs(void) | ||
70 | { | ||
71 | struct irq_desc *desc; | ||
72 | int irq; | ||
73 | |||
74 | for_each_irq_desc(irq, desc) | ||
75 | if ((desc->status & IRQ_WAKEUP) && (desc->status & IRQ_PENDING)) | ||
76 | return -EBUSY; | ||
77 | |||
78 | return 0; | ||
79 | } | ||
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index aae3f742bcec..692363dd591f 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c | |||
@@ -20,11 +20,11 @@ static struct proc_dir_entry *root_irq_dir; | |||
20 | static int irq_affinity_proc_show(struct seq_file *m, void *v) | 20 | static int irq_affinity_proc_show(struct seq_file *m, void *v) |
21 | { | 21 | { |
22 | struct irq_desc *desc = irq_to_desc((long)m->private); | 22 | struct irq_desc *desc = irq_to_desc((long)m->private); |
23 | const struct cpumask *mask = &desc->affinity; | 23 | const struct cpumask *mask = desc->affinity; |
24 | 24 | ||
25 | #ifdef CONFIG_GENERIC_PENDING_IRQ | 25 | #ifdef CONFIG_GENERIC_PENDING_IRQ |
26 | if (desc->status & IRQ_MOVE_PENDING) | 26 | if (desc->status & IRQ_MOVE_PENDING) |
27 | mask = &desc->pending_mask; | 27 | mask = desc->pending_mask; |
28 | #endif | 28 | #endif |
29 | seq_cpumask(m, mask); | 29 | seq_cpumask(m, mask); |
30 | seq_putc(m, '\n'); | 30 | seq_putc(m, '\n'); |
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index dd364c11e56e..4d568294de3e 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c | |||
@@ -104,7 +104,7 @@ static int misrouted_irq(int irq) | |||
104 | return ok; | 104 | return ok; |
105 | } | 105 | } |
106 | 106 | ||
107 | static void poll_spurious_irqs(unsigned long dummy) | 107 | static void poll_all_shared_irqs(void) |
108 | { | 108 | { |
109 | struct irq_desc *desc; | 109 | struct irq_desc *desc; |
110 | int i; | 110 | int i; |
@@ -123,11 +123,23 @@ static void poll_spurious_irqs(unsigned long dummy) | |||
123 | 123 | ||
124 | try_one_irq(i, desc); | 124 | try_one_irq(i, desc); |
125 | } | 125 | } |
126 | } | ||
127 | |||
128 | static void poll_spurious_irqs(unsigned long dummy) | ||
129 | { | ||
130 | poll_all_shared_irqs(); | ||
126 | 131 | ||
127 | mod_timer(&poll_spurious_irq_timer, | 132 | mod_timer(&poll_spurious_irq_timer, |
128 | jiffies + POLL_SPURIOUS_IRQ_INTERVAL); | 133 | jiffies + POLL_SPURIOUS_IRQ_INTERVAL); |
129 | } | 134 | } |
130 | 135 | ||
136 | #ifdef CONFIG_DEBUG_SHIRQ | ||
137 | void debug_poll_all_shared_irqs(void) | ||
138 | { | ||
139 | poll_all_shared_irqs(); | ||
140 | } | ||
141 | #endif | ||
142 | |||
131 | /* | 143 | /* |
132 | * If 99,900 of the previous 100,000 interrupts have not been handled | 144 | * If 99,900 of the previous 100,000 interrupts have not been handled |
133 | * then assume that the IRQ is stuck in some manner. Drop a diagnostic | 145 | * then assume that the IRQ is stuck in some manner. Drop a diagnostic |