diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-05-08 04:50:00 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-05-08 04:50:00 -0400 |
commit | f066a155334642b8a206eec625b1925d88c48aeb (patch) | |
tree | cb12975e60b70d1dae3b7397bab955de78a4d01e /kernel/irq/handle.c | |
parent | e7c064889606aab3569669078c69b87b2c527e72 (diff) | |
parent | 33df4db04a79660150e1948e3296eeb451ac121b (diff) |
Merge branch 'x86/urgent' into x86/xen
Conflicts:
arch/frv/include/asm/pgtable.h
arch/x86/include/asm/required-features.h
arch/x86/xen/mmu.c
Merge reason: x86/xen was on a .29 base still, move it to a fresher
branch and pick up Xen fixes as well, plus resolve
conflicts
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/irq/handle.c')
-rw-r--r-- | kernel/irq/handle.c | 52 |
1 files changed, 49 insertions, 3 deletions
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 343acecae629..26e08754744f 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c | |||
@@ -339,6 +339,15 @@ irqreturn_t no_action(int cpl, void *dev_id) | |||
339 | return IRQ_NONE; | 339 | return IRQ_NONE; |
340 | } | 340 | } |
341 | 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 | |||
342 | DEFINE_TRACE(irq_handler_entry); | 351 | DEFINE_TRACE(irq_handler_entry); |
343 | DEFINE_TRACE(irq_handler_exit); | 352 | DEFINE_TRACE(irq_handler_exit); |
344 | 353 | ||
@@ -354,8 +363,6 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action) | |||
354 | irqreturn_t ret, retval = IRQ_NONE; | 363 | irqreturn_t ret, retval = IRQ_NONE; |
355 | unsigned int status = 0; | 364 | unsigned int status = 0; |
356 | 365 | ||
357 | WARN_ONCE(!in_irq(), "BUG: IRQ handler called from non-hardirq context!"); | ||
358 | |||
359 | if (!(action->flags & IRQF_DISABLED)) | 366 | if (!(action->flags & IRQF_DISABLED)) |
360 | local_irq_enable_in_hardirq(); | 367 | local_irq_enable_in_hardirq(); |
361 | 368 | ||
@@ -363,8 +370,47 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action) | |||
363 | trace_irq_handler_entry(irq, action); | 370 | trace_irq_handler_entry(irq, action); |
364 | ret = action->handler(irq, action->dev_id); | 371 | ret = action->handler(irq, action->dev_id); |
365 | trace_irq_handler_exit(irq, action, ret); | 372 | trace_irq_handler_exit(irq, action, ret); |
366 | if (ret == IRQ_HANDLED) | 373 | |
374 | switch (ret) { | ||
375 | case IRQ_WAKE_THREAD: | ||
376 | /* | ||
377 | * Set result to handled so the spurious check | ||
378 | * does not trigger. | ||
379 | */ | ||
380 | ret = IRQ_HANDLED; | ||
381 | |||
382 | /* | ||
383 | * Catch drivers which return WAKE_THREAD but | ||
384 | * did not set up a thread function | ||
385 | */ | ||
386 | if (unlikely(!action->thread_fn)) { | ||
387 | warn_no_thread(irq, action); | ||
388 | break; | ||
389 | } | ||
390 | |||
391 | /* | ||
392 | * Wake up the handler thread for this | ||
393 | * action. In case the thread crashed and was | ||
394 | * killed we just pretend that we handled the | ||
395 | * interrupt. The hardirq handler above has | ||
396 | * disabled the device interrupt, so no irq | ||
397 | * storm is lurking. | ||
398 | */ | ||
399 | if (likely(!test_bit(IRQTF_DIED, | ||
400 | &action->thread_flags))) { | ||
401 | set_bit(IRQTF_RUNTHREAD, &action->thread_flags); | ||
402 | wake_up_process(action->thread); | ||
403 | } | ||
404 | |||
405 | /* Fall through to add to randomness */ | ||
406 | case IRQ_HANDLED: | ||
367 | status |= action->flags; | 407 | status |= action->flags; |
408 | break; | ||
409 | |||
410 | default: | ||
411 | break; | ||
412 | } | ||
413 | |||
368 | retval |= ret; | 414 | retval |= ret; |
369 | action = action->next; | 415 | action = action->next; |
370 | } while (action); | 416 | } while (action); |