aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--kernel/exit.c2
-rw-r--r--kernel/irq/handle.c31
-rw-r--r--kernel/irq/manage.c192
8 files changed, 259 insertions, 17 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
diff --git a/kernel/exit.c b/kernel/exit.c
index 167e1e3ad7c6..ca0b3488c4a9 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1037,6 +1037,8 @@ NORET_TYPE void do_exit(long code)
1037 schedule(); 1037 schedule();
1038 } 1038 }
1039 1039
1040 exit_irq_thread();
1041
1040 exit_signals(tsk); /* sets PF_EXITING */ 1042 exit_signals(tsk); /* sets PF_EXITING */
1041 /* 1043 /*
1042 * tsk->flags are checked in the futex code to protect against 1044 * tsk->flags are checked in the futex code to protect against
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 9ebf77968871..fe8f45374e86 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -357,8 +357,37 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
357 357
358 do { 358 do {
359 ret = action->handler(irq, action->dev_id); 359 ret = action->handler(irq, action->dev_id);
360 if (ret == IRQ_HANDLED) 360
361 switch (ret) {
362 case IRQ_WAKE_THREAD:
363 /*
364 * Wake up the handler thread for this
365 * action. In case the thread crashed and was
366 * killed we just pretend that we handled the
367 * interrupt. The hardirq handler above has
368 * disabled the device interrupt, so no irq
369 * storm is lurking.
370 */
371 if (likely(!test_bit(IRQTF_DIED,
372 &action->thread_flags))) {
373 set_bit(IRQTF_RUNTHREAD, &action->thread_flags);
374 wake_up_process(action->thread);
375 }
376
377 /*
378 * Set it to handled so the spurious check
379 * does not trigger.
380 */
381 ret = IRQ_HANDLED;
382 /* Fall through to add to randomness */
383 case IRQ_HANDLED:
361 status |= action->flags; 384 status |= action->flags;
385 break;
386
387 default:
388 break;
389 }
390
362 retval |= ret; 391 retval |= ret;
363 action = action->next; 392 action = action->next;
364 } while (action); 393 } while (action);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 6458e99984c0..a4c1ab86cd25 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -8,16 +8,15 @@
8 */ 8 */
9 9
10#include <linux/irq.h> 10#include <linux/irq.h>
11#include <linux/kthread.h>
11#include <linux/module.h> 12#include <linux/module.h>
12#include <linux/random.h> 13#include <linux/random.h>
13#include <linux/interrupt.h> 14#include <linux/interrupt.h>
14#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/sched.h>
15 17
16#include "internals.h" 18#include "internals.h"
17 19
18#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS)
19cpumask_var_t irq_default_affinity;
20
21/** 20/**
22 * synchronize_irq - wait for pending IRQ handlers (on other CPUs) 21 * synchronize_irq - wait for pending IRQ handlers (on other CPUs)
23 * @irq: interrupt number to wait for 22 * @irq: interrupt number to wait for
@@ -53,9 +52,18 @@ void synchronize_irq(unsigned int irq)
53 52
54 /* Oops, that failed? */ 53 /* Oops, that failed? */
55 } while (status & IRQ_INPROGRESS); 54 } while (status & IRQ_INPROGRESS);
55
56 /*
57 * We made sure that no hardirq handler is running. Now verify
58 * that no threaded handlers are active.
59 */
60 wait_event(desc->wait_for_threads, !atomic_read(&desc->threads_active));
56} 61}
57EXPORT_SYMBOL(synchronize_irq); 62EXPORT_SYMBOL(synchronize_irq);
58 63
64#ifdef CONFIG_SMP
65cpumask_var_t irq_default_affinity;
66
59/** 67/**
60 * irq_can_set_affinity - Check if the affinity of a given irq can be set 68 * irq_can_set_affinity - Check if the affinity of a given irq can be set
61 * @irq: Interrupt to check 69 * @irq: Interrupt to check
@@ -72,6 +80,18 @@ int irq_can_set_affinity(unsigned int irq)
72 return 1; 80 return 1;
73} 81}
74 82
83static void
84irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask)
85{
86 struct irqaction *action = desc->action;
87
88 while (action) {
89 if (action->thread)
90 set_cpus_allowed_ptr(action->thread, cpumask);
91 action = action->next;
92 }
93}
94
75/** 95/**
76 * irq_set_affinity - Set the irq affinity of a given irq 96 * irq_set_affinity - Set the irq affinity of a given irq
77 * @irq: Interrupt to set affinity 97 * @irq: Interrupt to set affinity
@@ -100,6 +120,7 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
100 cpumask_copy(desc->affinity, cpumask); 120 cpumask_copy(desc->affinity, cpumask);
101 desc->chip->set_affinity(irq, cpumask); 121 desc->chip->set_affinity(irq, cpumask);
102#endif 122#endif
123 irq_set_thread_affinity(desc, cpumask);
103 desc->status |= IRQ_AFFINITY_SET; 124 desc->status |= IRQ_AFFINITY_SET;
104 spin_unlock_irqrestore(&desc->lock, flags); 125 spin_unlock_irqrestore(&desc->lock, flags);
105 return 0; 126 return 0;
@@ -150,6 +171,8 @@ int irq_select_affinity_usr(unsigned int irq)
150 171
151 spin_lock_irqsave(&desc->lock, flags); 172 spin_lock_irqsave(&desc->lock, flags);
152 ret = setup_affinity(irq, desc); 173 ret = setup_affinity(irq, desc);
174 if (!ret)
175 irq_set_thread_affinity(desc, desc->affinity);
153 spin_unlock_irqrestore(&desc->lock, flags); 176 spin_unlock_irqrestore(&desc->lock, flags);
154 177
155 return ret; 178 return ret;
@@ -384,6 +407,93 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
384 return ret; 407 return ret;
385} 408}
386 409
410static inline int irq_thread_should_run(struct irqaction *action)
411{
412 return test_and_clear_bit(IRQTF_RUNTHREAD, &action->thread_flags);
413}
414
415static int irq_wait_for_interrupt(struct irqaction *action)
416{
417 while (!kthread_should_stop()) {
418 set_current_state(TASK_INTERRUPTIBLE);
419 if (irq_thread_should_run(action)) {
420 __set_current_state(TASK_RUNNING);
421 return 0;
422 } else
423 schedule();
424 }
425 return -1;
426}
427
428/*
429 * Interrupt handler thread
430 */
431static int irq_thread(void *data)
432{
433 struct sched_param param = { .sched_priority = MAX_USER_RT_PRIO/2, };
434 struct irqaction *action = data;
435 struct irq_desc *desc = irq_to_desc(action->irq);
436 int wake;
437
438 sched_setscheduler(current, SCHED_FIFO, &param);
439 current->irqaction = action;
440
441 while (!irq_wait_for_interrupt(action)) {
442
443 atomic_inc(&desc->threads_active);
444
445 spin_lock_irq(&desc->lock);
446 if (unlikely(desc->status & IRQ_DISABLED)) {
447 /*
448 * CHECKME: We might need a dedicated
449 * IRQ_THREAD_PENDING flag here, which
450 * retriggers the thread in check_irq_resend()
451 * but AFAICT IRQ_PENDING should be fine as it
452 * retriggers the interrupt itself --- tglx
453 */
454 desc->status |= IRQ_PENDING;
455 spin_unlock_irq(&desc->lock);
456 } else {
457 spin_unlock_irq(&desc->lock);
458
459 action->thread_fn(action->irq, action->dev_id);
460 }
461
462 wake = atomic_dec_and_test(&desc->threads_active);
463
464 if (wake && waitqueue_active(&desc->wait_for_threads))
465 wake_up(&desc->wait_for_threads);
466 }
467
468 /*
469 * Clear irqaction. Otherwise exit_irq_thread() would make
470 * fuzz about an active irq thread going into nirvana.
471 */
472 current->irqaction = NULL;
473 return 0;
474}
475
476/*
477 * Called from do_exit()
478 */
479void exit_irq_thread(void)
480{
481 struct task_struct *tsk = current;
482
483 if (!tsk->irqaction)
484 return;
485
486 printk(KERN_ERR
487 "exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n",
488 tsk->comm ? tsk->comm : "", tsk->pid, tsk->irqaction->irq);
489
490 /*
491 * Set the THREAD DIED flag to prevent further wakeups of the
492 * soon to be gone threaded handler.
493 */
494 set_bit(IRQTF_DIED, &tsk->irqaction->flags);
495}
496
387/* 497/*
388 * Internal function to register an irqaction - typically used to 498 * Internal function to register an irqaction - typically used to
389 * allocate special interrupts that are part of the architecture. 499 * allocate special interrupts that are part of the architecture.
@@ -420,6 +530,26 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
420 } 530 }
421 531
422 /* 532 /*
533 * Threaded handler ?
534 */
535 if (new->thread_fn) {
536 struct task_struct *t;
537
538 t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
539 new->name);
540 if (IS_ERR(t))
541 return PTR_ERR(t);
542 /*
543 * We keep the reference to the task struct even if
544 * the thread dies to avoid that the interrupt code
545 * references an already freed task_struct.
546 */
547 get_task_struct(t);
548 new->thread = t;
549 wake_up_process(t);
550 }
551
552 /*
423 * The following block of code has to be executed atomically 553 * The following block of code has to be executed atomically
424 */ 554 */
425 spin_lock_irqsave(&desc->lock, flags); 555 spin_lock_irqsave(&desc->lock, flags);
@@ -456,15 +586,15 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
456 if (!shared) { 586 if (!shared) {
457 irq_chip_set_defaults(desc->chip); 587 irq_chip_set_defaults(desc->chip);
458 588
589 init_waitqueue_head(&desc->wait_for_threads);
590
459 /* Setup the type (level, edge polarity) if configured: */ 591 /* Setup the type (level, edge polarity) if configured: */
460 if (new->flags & IRQF_TRIGGER_MASK) { 592 if (new->flags & IRQF_TRIGGER_MASK) {
461 ret = __irq_set_trigger(desc, irq, 593 ret = __irq_set_trigger(desc, irq,
462 new->flags & IRQF_TRIGGER_MASK); 594 new->flags & IRQF_TRIGGER_MASK);
463 595
464 if (ret) { 596 if (ret)
465 spin_unlock_irqrestore(&desc->lock, flags); 597 goto out_thread;
466 return ret;
467 }
468 } else 598 } else
469 compat_irq_chip_set_default_handler(desc); 599 compat_irq_chip_set_default_handler(desc);
470#if defined(CONFIG_IRQ_PER_CPU) 600#if defined(CONFIG_IRQ_PER_CPU)
@@ -532,8 +662,19 @@ mismatch:
532 dump_stack(); 662 dump_stack();
533 } 663 }
534#endif 664#endif
665 ret = -EBUSY;
666
667out_thread:
535 spin_unlock_irqrestore(&desc->lock, flags); 668 spin_unlock_irqrestore(&desc->lock, flags);
536 return -EBUSY; 669 if (new->thread) {
670 struct task_struct *t = new->thread;
671
672 new->thread = NULL;
673 if (likely(!test_bit(IRQTF_DIED, &new->thread_flags)))
674 kthread_stop(t);
675 put_task_struct(t);
676 }
677 return ret;
537} 678}
538 679
539/** 680/**
@@ -559,6 +700,7 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
559{ 700{
560 struct irq_desc *desc = irq_to_desc(irq); 701 struct irq_desc *desc = irq_to_desc(irq);
561 struct irqaction *action, **action_ptr; 702 struct irqaction *action, **action_ptr;
703 struct task_struct *irqthread;
562 unsigned long flags; 704 unsigned long flags;
563 705
564 WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq); 706 WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq);
@@ -605,6 +747,10 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
605 else 747 else
606 desc->chip->disable(irq); 748 desc->chip->disable(irq);
607 } 749 }
750
751 irqthread = action->thread;
752 action->thread = NULL;
753
608 spin_unlock_irqrestore(&desc->lock, flags); 754 spin_unlock_irqrestore(&desc->lock, flags);
609 755
610 unregister_handler_proc(irq, action); 756 unregister_handler_proc(irq, action);
@@ -612,6 +758,12 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
612 /* Make sure it's not being used on another CPU: */ 758 /* Make sure it's not being used on another CPU: */
613 synchronize_irq(irq); 759 synchronize_irq(irq);
614 760
761 if (irqthread) {
762 if (!test_bit(IRQTF_DIED, &action->thread_flags))
763 kthread_stop(irqthread);
764 put_task_struct(irqthread);
765 }
766
615#ifdef CONFIG_DEBUG_SHIRQ 767#ifdef CONFIG_DEBUG_SHIRQ
616 /* 768 /*
617 * It's a shared IRQ -- the driver ought to be prepared for an IRQ 769 * It's a shared IRQ -- the driver ought to be prepared for an IRQ
@@ -664,9 +816,12 @@ void free_irq(unsigned int irq, void *dev_id)
664EXPORT_SYMBOL(free_irq); 816EXPORT_SYMBOL(free_irq);
665 817
666/** 818/**
667 * request_irq - allocate an interrupt line 819 * request_threaded_irq - allocate an interrupt line
668 * @irq: Interrupt line to allocate 820 * @irq: Interrupt line to allocate
669 * @handler: Function to be called when the IRQ occurs 821 * @handler: Function to be called when the IRQ occurs.
822 * Primary handler for threaded interrupts
823 * @thread_fn: Function called from the irq handler thread
824 * If NULL, no irq thread is created
670 * @irqflags: Interrupt type flags 825 * @irqflags: Interrupt type flags
671 * @devname: An ascii name for the claiming device 826 * @devname: An ascii name for the claiming device
672 * @dev_id: A cookie passed back to the handler function 827 * @dev_id: A cookie passed back to the handler function
@@ -678,6 +833,15 @@ EXPORT_SYMBOL(free_irq);
678 * raises, you must take care both to initialise your hardware 833 * raises, you must take care both to initialise your hardware
679 * and to set up the interrupt handler in the right order. 834 * and to set up the interrupt handler in the right order.
680 * 835 *
836 * If you want to set up a threaded irq handler for your device
837 * then you need to supply @handler and @thread_fn. @handler ist
838 * still called in hard interrupt context and has to check
839 * whether the interrupt originates from the device. If yes it
840 * needs to disable the interrupt on the device and return
841 * IRQ_THREAD_WAKE which will wake up the handler thread and run
842 * @thread_fn. This split handler design is necessary to support
843 * shared interrupts.
844 *
681 * Dev_id must be globally unique. Normally the address of the 845 * Dev_id must be globally unique. Normally the address of the
682 * device data structure is used as the cookie. Since the handler 846 * device data structure is used as the cookie. Since the handler
683 * receives this value it makes sense to use it. 847 * receives this value it makes sense to use it.
@@ -693,8 +857,9 @@ EXPORT_SYMBOL(free_irq);
693 * IRQF_TRIGGER_* Specify active edge(s) or level 857 * IRQF_TRIGGER_* Specify active edge(s) or level
694 * 858 *
695 */ 859 */
696int request_irq(unsigned int irq, irq_handler_t handler, 860int request_threaded_irq(unsigned int irq, irq_handler_t handler,
697 unsigned long irqflags, const char *devname, void *dev_id) 861 irq_handler_t thread_fn, unsigned long irqflags,
862 const char *devname, void *dev_id)
698{ 863{
699 struct irqaction *action; 864 struct irqaction *action;
700 struct irq_desc *desc; 865 struct irq_desc *desc;
@@ -742,6 +907,7 @@ int request_irq(unsigned int irq, irq_handler_t handler,
742 return -ENOMEM; 907 return -ENOMEM;
743 908
744 action->handler = handler; 909 action->handler = handler;
910 action->thread_fn = thread_fn;
745 action->flags = irqflags; 911 action->flags = irqflags;
746 action->name = devname; 912 action->name = devname;
747 action->dev_id = dev_id; 913 action->dev_id = dev_id;
@@ -771,4 +937,4 @@ int request_irq(unsigned int irq, irq_handler_t handler,
771#endif 937#endif
772 return retval; 938 return retval;
773} 939}
774EXPORT_SYMBOL(request_irq); 940EXPORT_SYMBOL(request_threaded_irq);