Merge branch 'irq/threaded' of git://git.kernel.org/pub/scm/linux/kernel/git/tip...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 7 Apr 2009 21:07:52 +0000 (14:07 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 7 Apr 2009 21:07:52 +0000 (14:07 -0700)
* 'irq/threaded' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  genirq: fix devres.o build for GENERIC_HARDIRQS=n
  genirq: provide old request_irq() for CONFIG_GENERIC_HARDIRQ=n
  genirq: threaded irq handlers review fixups
  genirq: add support for threaded interrupts to devres
  genirq: add threaded interrupt handler support

1  2 
include/linux/interrupt.h
kernel/exit.c

  #define IRQF_NOBALANCING      0x00000800
  #define IRQF_IRQPOLL          0x00001000
  
+ /*
+  * Bits used by threaded handlers:
+  * IRQTF_RUNTHREAD - signals that the interrupt handler thread should run
+  * IRQTF_DIED      - handler thread died
+  * IRQTF_WARNED    - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed
+  */
+ enum {
+       IRQTF_RUNTHREAD,
+       IRQTF_DIED,
+       IRQTF_WARNED,
+ };
  typedef irqreturn_t (*irq_handler_t)(int, void *);
  
  /**
@@@ -71,6 -83,9 +83,9 @@@
   * @next:     pointer to the next irqaction for shared interrupts
   * @irq:      interrupt number
   * @dir:      pointer to the proc/irq/NN/name entry
+  * @thread_fn:        interupt handler function for threaded interrupts
+  * @thread:   thread pointer for threaded interrupts
+  * @thread_flags:     flags related to @thread
   */
  struct irqaction {
        irq_handler_t handler;
        struct irqaction *next;
        int irq;
        struct proc_dir_entry *dir;
+       irq_handler_t thread_fn;
+       struct task_struct *thread;
+       unsigned long thread_flags;
  };
  
  extern irqreturn_t no_action(int cpl, void *dev_id);
- extern int __must_check request_irq(unsigned int, irq_handler_t handler,
-                      unsigned long, const char *, void *);
+ #ifdef CONFIG_GENERIC_HARDIRQS
+ extern int __must_check
+ request_threaded_irq(unsigned int irq, irq_handler_t handler,
+                    irq_handler_t thread_fn,
+                    unsigned long flags, const char *name, void *dev);
+ static inline int __must_check
+ request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
+           const char *name, void *dev)
+ {
+       return request_threaded_irq(irq, handler, NULL, flags, name, dev);
+ }
+ extern void exit_irq_thread(void);
+ #else
+ extern int __must_check
+ request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
+           const char *name, void *dev);
+ /*
+  * Special function to avoid ifdeffery in kernel/irq/devres.c which
+  * gets magically built by GENERIC_HARDIRQS=n architectures (sparc,
+  * m68k). I really love these $@%#!* obvious Makefile references:
+  * ../../../kernel/irq/devres.o
+  */
+ static inline int __must_check
+ request_threaded_irq(unsigned int irq, irq_handler_t handler,
+                    irq_handler_t thread_fn,
+                    unsigned long flags, const char *name, void *dev)
+ {
+       return request_irq(irq, handler, flags, name, dev);
+ }
+ static inline void exit_irq_thread(void) { }
+ #endif
  extern void free_irq(unsigned int, void *);
  
  struct device;
  
- extern int __must_check devm_request_irq(struct device *dev, unsigned int irq,
-                           irq_handler_t handler, unsigned long irqflags,
-                           const char *devname, void *dev_id);
+ extern int __must_check
+ devm_request_threaded_irq(struct device *dev, unsigned int irq,
+                         irq_handler_t handler, irq_handler_t thread_fn,
+                         unsigned long irqflags, const char *devname,
+                         void *dev_id);
+ static inline int __must_check
+ devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler,
+                unsigned long irqflags, const char *devname, void *dev_id)
+ {
+       return devm_request_threaded_irq(dev, irq, handler, NULL, irqflags,
+                                        devname, dev_id);
+ }
  extern void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id);
  
  /*
@@@ -299,7 -364,6 +364,7 @@@ extern void softirq_init(void)
  #define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
  extern void raise_softirq_irqoff(unsigned int nr);
  extern void raise_softirq(unsigned int nr);
 +extern void wakeup_softirqd(void);
  
  /* This is the worklist that queues up per-cpu softirq work.
   *
diff --combined kernel/exit.c
@@@ -837,7 -837,8 +837,7 @@@ static void exit_notify(struct task_str
         */
        if (tsk->exit_signal != SIGCHLD && !task_detached(tsk) &&
            (tsk->parent_exec_id != tsk->real_parent->self_exec_id ||
 -           tsk->self_exec_id != tsk->parent_exec_id) &&
 -          !capable(CAP_KILL))
 +           tsk->self_exec_id != tsk->parent_exec_id))
                tsk->exit_signal = SIGCHLD;
  
        signal = tracehook_notify_death(tsk, &cookie, group_dead);
@@@ -923,6 -924,8 +923,8 @@@ NORET_TYPE void do_exit(long code
                schedule();
        }
  
+       exit_irq_thread();
        exit_signals(tsk);  /* sets PF_EXITING */
        /*
         * tsk->flags are checked in the futex code to protect against