aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2009-03-23 13:28:15 -0400
committerThomas Gleixner <tglx@linutronix.de>2009-03-24 07:15:23 -0400
commit3aa551c9b4c40018f0e261a178e3d25478dc04a9 (patch)
tree2a696109273fcc421d774cc8fefa4180331a85ad /include
parent80c5520811d3805adcb15c570ea5e2d489fa5d0b (diff)
genirq: add threaded interrupt handler support
Add support for threaded interrupt handlers: A device driver can request that its main interrupt handler runs in a thread. To achive this the device driver requests the interrupt with request_threaded_irq() and provides additionally to the handler a thread function. The handler function is called in hard interrupt context and needs to check whether the interrupt originated from the device. If the interrupt originated from the device then the handler can either return IRQ_HANDLED or IRQ_WAKE_THREAD. IRQ_HANDLED is returned when no further action is required. IRQ_WAKE_THREAD causes the genirq code to invoke the threaded (main) handler. When IRQ_WAKE_THREAD is returned handler must have disabled the interrupt on the device level. This is mandatory for shared interrupt handlers, but we need to do it as well for obscure x86 hardware where disabling an interrupt on the IO_APIC level redirects the interrupt to the legacy PIC interrupt lines. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include')
-rw-r--r--include/linux/hardirq.h2
-rw-r--r--include/linux/interrupt.h37
-rw-r--r--include/linux/irq.h5
-rw-r--r--include/linux/irqreturn.h2
-rw-r--r--include/linux/sched.h5
5 files changed, 48 insertions, 3 deletions
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index f83288347dda..2dfaadbdb2ac 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -105,7 +105,7 @@
105# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET 105# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
106#endif 106#endif
107 107
108#ifdef CONFIG_SMP 108#if defined(CONFIG_SMP) || defined(CONFIG_GENERIC_HARDIRQS)
109extern void synchronize_irq(unsigned int irq); 109extern void synchronize_irq(unsigned int irq);
110#else 110#else
111# define synchronize_irq(irq) barrier() 111# define synchronize_irq(irq) barrier()
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 0c9cb63e6895..6fc2b720c231 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -59,6 +59,16 @@
59#define IRQF_NOBALANCING 0x00000800 59#define IRQF_NOBALANCING 0x00000800
60#define IRQF_IRQPOLL 0x00001000 60#define IRQF_IRQPOLL 0x00001000
61 61
62/*
63 * Bits used by threaded handlers:
64 * IRQTF_RUNTHREAD - signals that the interrupt handler thread should run
65 * IRQTF_DIED - handler thread died
66 */
67enum {
68 IRQTF_RUNTHREAD,
69 IRQTF_DIED,
70};
71
62typedef irqreturn_t (*irq_handler_t)(int, void *); 72typedef irqreturn_t (*irq_handler_t)(int, void *);
63 73
64/** 74/**
@@ -71,6 +81,9 @@ typedef irqreturn_t (*irq_handler_t)(int, void *);
71 * @next: pointer to the next irqaction for shared interrupts 81 * @next: pointer to the next irqaction for shared interrupts
72 * @irq: interrupt number 82 * @irq: interrupt number
73 * @dir: pointer to the proc/irq/NN/name entry 83 * @dir: pointer to the proc/irq/NN/name entry
84 * @thread_fn: interupt handler function for threaded interrupts
85 * @thread: thread pointer for threaded interrupts
86 * @thread_flags: flags related to @thread
74 */ 87 */
75struct irqaction { 88struct irqaction {
76 irq_handler_t handler; 89 irq_handler_t handler;
@@ -81,11 +94,31 @@ struct irqaction {
81 struct irqaction *next; 94 struct irqaction *next;
82 int irq; 95 int irq;
83 struct proc_dir_entry *dir; 96 struct proc_dir_entry *dir;
97 irq_handler_t thread_fn;
98 struct task_struct *thread;
99 unsigned long thread_flags;
84}; 100};
85 101
86extern irqreturn_t no_action(int cpl, void *dev_id); 102extern irqreturn_t no_action(int cpl, void *dev_id);
87extern int __must_check request_irq(unsigned int, irq_handler_t handler, 103
88 unsigned long, const char *, void *); 104extern int __must_check
105request_threaded_irq(unsigned int irq, irq_handler_t handler,
106 irq_handler_t thread_fn,
107 unsigned long flags, const char *name, void *dev);
108
109static inline int __must_check
110request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
111 const char *name, void *dev)
112{
113 return request_threaded_irq(irq, handler, NULL, flags, name, dev);
114}
115
116#ifdef CONFIG_GENERIC_HARDIRQS
117extern void exit_irq_thread(void);
118#else
119static inline void exit_irq_thread(void) { }
120#endif
121
89extern void free_irq(unsigned int, void *); 122extern void free_irq(unsigned int, void *);
90 123
91struct device; 124struct device;
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 873e4ac11b81..8b1cf0630210 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -20,6 +20,7 @@
20#include <linux/irqreturn.h> 20#include <linux/irqreturn.h>
21#include <linux/irqnr.h> 21#include <linux/irqnr.h>
22#include <linux/errno.h> 22#include <linux/errno.h>
23#include <linux/wait.h>
23 24
24#include <asm/irq.h> 25#include <asm/irq.h>
25#include <asm/ptrace.h> 26#include <asm/ptrace.h>
@@ -155,6 +156,8 @@ struct irq_2_iommu;
155 * @affinity: IRQ affinity on SMP 156 * @affinity: IRQ affinity on SMP
156 * @cpu: cpu index useful for balancing 157 * @cpu: cpu index useful for balancing
157 * @pending_mask: pending rebalanced interrupts 158 * @pending_mask: pending rebalanced interrupts
159 * @threads_active: number of irqaction threads currently running
160 * @wait_for_threads: wait queue for sync_irq to wait for threaded handlers
158 * @dir: /proc/irq/ procfs entry 161 * @dir: /proc/irq/ procfs entry
159 * @name: flow handler name for /proc/interrupts output 162 * @name: flow handler name for /proc/interrupts output
160 */ 163 */
@@ -186,6 +189,8 @@ struct irq_desc {
186 cpumask_var_t pending_mask; 189 cpumask_var_t pending_mask;
187#endif 190#endif
188#endif 191#endif
192 atomic_t threads_active;
193 wait_queue_head_t wait_for_threads;
189#ifdef CONFIG_PROC_FS 194#ifdef CONFIG_PROC_FS
190 struct proc_dir_entry *dir; 195 struct proc_dir_entry *dir;
191#endif 196#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 @@
5 * enum irqreturn 5 * enum irqreturn
6 * @IRQ_NONE interrupt was not from this device 6 * @IRQ_NONE interrupt was not from this device
7 * @IRQ_HANDLED interrupt was handled by this device 7 * @IRQ_HANDLED interrupt was handled by this device
8 * @IRQ_WAKE_THREAD handler requests to wake the handler thread
8 */ 9 */
9enum irqreturn { 10enum irqreturn {
10 IRQ_NONE, 11 IRQ_NONE,
11 IRQ_HANDLED, 12 IRQ_HANDLED,
13 IRQ_WAKE_THREAD,
12}; 14};
13 15
14typedef enum irqreturn irqreturn_t; 16typedef enum irqreturn irqreturn_t;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 46d680643f89..38b77b0f56e5 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1292,6 +1292,11 @@ struct task_struct {
1292/* Protection of (de-)allocation: mm, files, fs, tty, keyrings */ 1292/* Protection of (de-)allocation: mm, files, fs, tty, keyrings */
1293 spinlock_t alloc_lock; 1293 spinlock_t alloc_lock;
1294 1294
1295#ifdef CONFIG_GENERIC_HARDIRQS
1296 /* IRQ handler threads */
1297 struct irqaction *irqaction;
1298#endif
1299
1295 /* Protection of the PI data structures: */ 1300 /* Protection of the PI data structures: */
1296 spinlock_t pi_lock; 1301 spinlock_t pi_lock;
1297 1302