diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-04-08 11:02:50 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-04-08 11:02:57 -0400 |
commit | ff96e612cba32510e263e17b213235fe5746397e (patch) | |
tree | a8df57d76b10e0901a4fb76cd2987eb9826a560a /kernel/irq/handle.c | |
parent | cd84a42f315e50edd454c27a3da3951ccd3d735a (diff) | |
parent | 577c9c456f0e1371cbade38eaf91ae8e8a308555 (diff) |
Merge commit 'v2.6.30-rc1' into core/urgent
Merge reason: need latest upstream to queue up dependent fix
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/irq/handle.c')
-rw-r--r-- | kernel/irq/handle.c | 56 |
1 files changed, 55 insertions, 1 deletions
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 9ebf77968871..d82142be8dd2 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c | |||
@@ -17,6 +17,7 @@ | |||
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> | ||
20 | #include <linux/bootmem.h> | 21 | #include <linux/bootmem.h> |
21 | 22 | ||
22 | #include "internals.h" | 23 | #include "internals.h" |
@@ -338,6 +339,18 @@ irqreturn_t no_action(int cpl, void *dev_id) | |||
338 | return IRQ_NONE; | 339 | return IRQ_NONE; |
339 | } | 340 | } |
340 | 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 | |||
341 | /** | 354 | /** |
342 | * handle_IRQ_event - irq action chain handler | 355 | * handle_IRQ_event - irq action chain handler |
343 | * @irq: the interrupt number | 356 | * @irq: the interrupt number |
@@ -356,9 +369,50 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action) | |||
356 | local_irq_enable_in_hardirq(); | 369 | local_irq_enable_in_hardirq(); |
357 | 370 | ||
358 | do { | 371 | do { |
372 | trace_irq_handler_entry(irq, action); | ||
359 | ret = action->handler(irq, action->dev_id); | 373 | ret = action->handler(irq, action->dev_id); |
360 | 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: | ||
361 | status |= action->flags; | 409 | status |= action->flags; |
410 | break; | ||
411 | |||
412 | default: | ||
413 | break; | ||
414 | } | ||
415 | |||
362 | retval |= ret; | 416 | retval |= ret; |
363 | action = action->next; | 417 | action = action->next; |
364 | } while (action); | 418 | } while (action); |