summaryrefslogtreecommitdiffstats
path: root/include/linux/interrupt.h
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2009-03-23 18:28:15 +0100
committerThomas Gleixner <tglx@linutronix.de>2009-03-24 12:15:23 +0100
commit3aa551c9b4c40018f0e261a178e3d25478dc04a9 (patch)
tree2a696109273fcc421d774cc8fefa4180331a85ad /include/linux/interrupt.h
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/linux/interrupt.h')
-rw-r--r--include/linux/interrupt.h37
1 files changed, 35 insertions, 2 deletions
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 0c9cb63e689..6fc2b720c23 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -59,6 +59,16 @@
#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
+ */
+enum {
+ IRQTF_RUNTHREAD,
+ IRQTF_DIED,
+};
+
typedef irqreturn_t (*irq_handler_t)(int, void *);
/**
@@ -71,6 +81,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,11 +94,31 @@ 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 *);
+
+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);
+}
+
+#ifdef CONFIG_GENERIC_HARDIRQS
+extern void exit_irq_thread(void);
+#else
+static inline void exit_irq_thread(void) { }
+#endif
+
extern void free_irq(unsigned int, void *);
struct device;