Merge branch 'linus' into irq/threaded
Ingo Molnar [Sun, 5 Apr 2009 23:41:22 +0000 (01:41 +0200)]
Conflicts:
include/linux/irq.h
kernel/irq/handle.c

1  2 
include/linux/hardirq.h
include/linux/interrupt.h
include/linux/irq.h
include/linux/sched.h
kernel/exit.c
kernel/irq/handle.c
kernel/irq/manage.c

Simple merge
Simple merge
@@@ -20,7 -21,7 +21,8 @@@
  #include <linux/irqreturn.h>
  #include <linux/irqnr.h>
  #include <linux/errno.h>
+ #include <linux/topology.h>
 +#include <linux/wait.h>
  
  #include <asm/irq.h>
  #include <asm/ptrace.h>
Simple merge
diff --cc kernel/exit.c
Simple merge
@@@ -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);
Simple merge