diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-07 14:07:52 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-07 14:07:52 -0700 | 
| commit | c61b79b6ef266890954213a701d8f6021d8c1289 (patch) | |
| tree | 9b000a7dae5a782a0d667137ab43e4f1bea70d58 /include/linux | |
| parent | 2b2ec7554cf7ec5e4412f89a5af6abe8ce950700 (diff) | |
| parent | 9efe21cb82b5dbe3b0b2ae4de4eccc64ecb94e95 (diff) | |
Merge branch 'irq/threaded' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* '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
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/hardirq.h | 2 | ||||
| -rw-r--r-- | include/linux/interrupt.h | 75 | ||||
| -rw-r--r-- | include/linux/irq.h | 5 | ||||
| -rw-r--r-- | include/linux/irqreturn.h | 2 | ||||
| -rw-r--r-- | include/linux/sched.h | 5 | 
5 files changed, 83 insertions, 6 deletions
| diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index faa1cf848bcd..45257475623c 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h @@ -116,7 +116,7 @@  # define IRQ_EXIT_OFFSET HARDIRQ_OFFSET  #endif -#ifdef CONFIG_SMP +#if defined(CONFIG_SMP) || defined(CONFIG_GENERIC_HARDIRQS)  extern void synchronize_irq(unsigned int irq);  #else  # define synchronize_irq(irq)	barrier() diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 8a9613d0c674..91bb76f44f14 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -59,6 +59,18 @@  #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 @@ typedef irqreturn_t (*irq_handler_t)(int, void *);   * @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; @@ -81,18 +96,68 @@ struct irqaction {  	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);  /* diff --git a/include/linux/irq.h b/include/linux/irq.h index 974890b3c52f..ca507c9426b0 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -22,6 +22,7 @@  #include <linux/irqnr.h>  #include <linux/errno.h>  #include <linux/topology.h> +#include <linux/wait.h>  #include <asm/irq.h>  #include <asm/ptrace.h> @@ -158,6 +159,8 @@ struct irq_2_iommu;   * @affinity:		IRQ affinity on SMP   * @cpu:		cpu index useful for balancing   * @pending_mask:	pending rebalanced interrupts + * @threads_active:	number of irqaction threads currently running + * @wait_for_threads:	wait queue for sync_irq to wait for threaded handlers   * @dir:		/proc/irq/ procfs entry   * @name:		flow handler name for /proc/interrupts output   */ @@ -189,6 +192,8 @@ struct irq_desc {  	cpumask_var_t		pending_mask;  #endif  #endif +	atomic_t		threads_active; +	wait_queue_head_t       wait_for_threads;  #ifdef CONFIG_PROC_FS  	struct proc_dir_entry	*dir;  #endif diff --git a/include/linux/irqreturn.h b/include/linux/irqreturn.h index c5584ca5b8c9..819acaaac3f5 100644 --- a/include/linux/irqreturn.h +++ b/include/linux/irqreturn.h @@ -5,10 +5,12 @@   * enum irqreturn   * @IRQ_NONE		interrupt was not from this device   * @IRQ_HANDLED		interrupt was handled by this device + * @IRQ_WAKE_THREAD	handler requests to wake the handler thread   */  enum irqreturn {  	IRQ_NONE,  	IRQ_HANDLED, +	IRQ_WAKE_THREAD,  };  typedef enum irqreturn irqreturn_t; diff --git a/include/linux/sched.h b/include/linux/sched.h index b94f3541f67b..c96140210d1c 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1294,6 +1294,11 @@ struct task_struct {  /* Protection of (de-)allocation: mm, files, fs, tty, keyrings */  	spinlock_t alloc_lock; +#ifdef CONFIG_GENERIC_HARDIRQS +	/* IRQ handler threads */ +	struct irqaction *irqaction; +#endif +  	/* Protection of the PI data structures: */  	spinlock_t pi_lock; | 
