From: Ingo Molnar Date: Sun, 5 Apr 2009 23:41:22 +0000 (+0200) Subject: Merge branch 'linus' into irq/threaded X-Git-Tag: v2.6.30-rc1~3^2 X-Git-Url: https://bbs.cooldavid.org/git/?a=commitdiff_plain;h=9efe21cb82b5dbe3b0b2ae4de4eccc64ecb94e95;p=net-next-2.6.git Merge branch 'linus' into irq/threaded Conflicts: include/linux/irq.h kernel/irq/handle.c --- 9efe21cb82b5dbe3b0b2ae4de4eccc64ecb94e95 diff --cc include/linux/irq.h index 8b1cf063021,974890b3c52..ca507c9426b --- a/include/linux/irq.h +++ b/include/linux/irq.h @@@ -20,7 -21,7 +21,8 @@@ #include #include #include + #include +#include #include #include diff --cc kernel/irq/handle.c index 38b49a9e508,343acecae62..d82142be8dd --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@@ -338,15 -339,9 +339,18 @@@ irqreturn_t no_action(int cpl, void *de return IRQ_NONE; } +static void warn_no_thread(unsigned int irq, struct irqaction *action) +{ + if (test_and_set_bit(IRQTF_WARNED, &action->thread_flags)) + return; + + printk(KERN_WARNING "IRQ %d device %s returned IRQ_WAKE_THREAD " + "but no thread function available.", irq, action->name); +} + + DEFINE_TRACE(irq_handler_entry); + DEFINE_TRACE(irq_handler_exit); + /** * handle_IRQ_event - irq action chain handler * @irq: the interrupt number @@@ -365,48 -360,11 +369,50 @@@ irqreturn_t handle_IRQ_event(unsigned i local_irq_enable_in_hardirq(); do { + trace_irq_handler_entry(irq, action); ret = action->handler(irq, action->dev_id); + trace_irq_handler_exit(irq, action, ret); - if (ret == IRQ_HANDLED) + + switch (ret) { + case IRQ_WAKE_THREAD: + /* + * Set result to handled so the spurious check + * does not trigger. + */ + ret = IRQ_HANDLED; + + /* + * Catch drivers which return WAKE_THREAD but + * did not set up a thread function + */ + if (unlikely(!action->thread_fn)) { + warn_no_thread(irq, action); + break; + } + + /* + * Wake up the handler thread for this + * action. In case the thread crashed and was + * killed we just pretend that we handled the + * interrupt. The hardirq handler above has + * disabled the device interrupt, so no irq + * storm is lurking. + */ + if (likely(!test_bit(IRQTF_DIED, + &action->thread_flags))) { + set_bit(IRQTF_RUNTHREAD, &action->thread_flags); + wake_up_process(action->thread); + } + + /* Fall through to add to randomness */ + case IRQ_HANDLED: status |= action->flags; + break; + + default: + break; + } + retval |= ret; action = action->next; } while (action);