diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2011-02-10 09:14:20 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2011-02-19 06:58:24 -0500 |
commit | 781295762defc709a609efc01d8bb065276cd9a2 (patch) | |
tree | 21f035b5f92571c8c3559b5e94eb0e1aa4113a36 | |
parent | 3836ca08aad4575c120ccf328652f3873eea9063 (diff) |
genirq: Add preflow handler support
sparc64 needs to call a preflow handler on certain interrupts befor
calling the action chain. Integrate it into handle_fasteoi_irq. Must
be enabled via CONFIG_IRQ_FASTEOI_PREFLOW. No impact when disabled.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/irq.h | 3 | ||||
-rw-r--r-- | include/linux/irqdesc.h | 14 | ||||
-rw-r--r-- | kernel/irq/Kconfig | 3 | ||||
-rw-r--r-- | kernel/irq/chip.c | 11 |
4 files changed, 30 insertions, 1 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h index 3e29e2f42e04..36390970693c 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -29,9 +29,10 @@ | |||
29 | #include <asm/irq_regs.h> | 29 | #include <asm/irq_regs.h> |
30 | 30 | ||
31 | struct irq_desc; | 31 | struct irq_desc; |
32 | struct irq_data; | ||
32 | typedef void (*irq_flow_handler_t)(unsigned int irq, | 33 | typedef void (*irq_flow_handler_t)(unsigned int irq, |
33 | struct irq_desc *desc); | 34 | struct irq_desc *desc); |
34 | 35 | typedef void (*irq_preflow_handler_t)(struct irq_data *data); | |
35 | 36 | ||
36 | /* | 37 | /* |
37 | * IRQ line status. | 38 | * IRQ line status. |
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index 36c95f08023d..2f87d6441302 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h | |||
@@ -63,6 +63,9 @@ struct irq_desc { | |||
63 | struct timer_rand_state *timer_rand_state; | 63 | struct timer_rand_state *timer_rand_state; |
64 | unsigned int __percpu *kstat_irqs; | 64 | unsigned int __percpu *kstat_irqs; |
65 | irq_flow_handler_t handle_irq; | 65 | irq_flow_handler_t handle_irq; |
66 | #ifdef CONFIG_IRQ_PREFLOW_FASTEOI | ||
67 | irq_preflow_handler_t preflow_handler; | ||
68 | #endif | ||
66 | struct irqaction *action; /* IRQ action list */ | 69 | struct irqaction *action; /* IRQ action list */ |
67 | #ifdef CONFIG_GENERIC_HARDIRQS_NO_COMPAT | 70 | #ifdef CONFIG_GENERIC_HARDIRQS_NO_COMPAT |
68 | unsigned int status_use_accessors; | 71 | unsigned int status_use_accessors; |
@@ -187,6 +190,17 @@ static inline void __set_irq_handler_unlocked(int irq, | |||
187 | desc = irq_to_desc(irq); | 190 | desc = irq_to_desc(irq); |
188 | desc->handle_irq = handler; | 191 | desc->handle_irq = handler; |
189 | } | 192 | } |
193 | |||
194 | #ifdef CONFIG_IRQ_PREFLOW_FASTEOI | ||
195 | static inline void | ||
196 | __irq_set_preflow_handler(unsigned int irq, irq_preflow_handler_t handler) | ||
197 | { | ||
198 | struct irq_desc *desc; | ||
199 | |||
200 | desc = irq_to_desc(irq); | ||
201 | desc->preflow_handler = handler; | ||
202 | } | ||
203 | #endif | ||
190 | #endif | 204 | #endif |
191 | 205 | ||
192 | #endif | 206 | #endif |
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig index 48ad25f5fa59..9149be729e45 100644 --- a/kernel/irq/Kconfig +++ b/kernel/irq/Kconfig | |||
@@ -35,6 +35,9 @@ config AUTO_IRQ_AFFINITY | |||
35 | config HARDIRQS_SW_RESEND | 35 | config HARDIRQS_SW_RESEND |
36 | def_bool n | 36 | def_bool n |
37 | 37 | ||
38 | config IRQ_PREFLOW_FASTEOI | ||
39 | def_bool n | ||
40 | |||
38 | config SPARSE_IRQ | 41 | config SPARSE_IRQ |
39 | bool "Support sparse irq numbering" | 42 | bool "Support sparse irq numbering" |
40 | depends on HAVE_SPARSE_IRQ | 43 | depends on HAVE_SPARSE_IRQ |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 2a36038b8f59..08be5d182be3 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -471,6 +471,16 @@ out_unlock: | |||
471 | } | 471 | } |
472 | EXPORT_SYMBOL_GPL(handle_level_irq); | 472 | EXPORT_SYMBOL_GPL(handle_level_irq); |
473 | 473 | ||
474 | #ifdef CONFIG_IRQ_PREFLOW_FASTEOI | ||
475 | static inline void preflow_handler(struct irq_desc *desc) | ||
476 | { | ||
477 | if (desc->preflow_handler) | ||
478 | desc->preflow_handler(&desc->irq_data); | ||
479 | } | ||
480 | #else | ||
481 | static inline void preflow_handler(struct irq_desc *desc) { } | ||
482 | #endif | ||
483 | |||
474 | /** | 484 | /** |
475 | * handle_fasteoi_irq - irq handler for transparent controllers | 485 | * handle_fasteoi_irq - irq handler for transparent controllers |
476 | * @irq: the interrupt number | 486 | * @irq: the interrupt number |
@@ -503,6 +513,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | |||
503 | mask_irq(desc); | 513 | mask_irq(desc); |
504 | goto out; | 514 | goto out; |
505 | } | 515 | } |
516 | preflow_handler(desc); | ||
506 | handle_irq_event(desc); | 517 | handle_irq_event(desc); |
507 | out: | 518 | out: |
508 | desc->irq_data.chip->irq_eoi(&desc->irq_data); | 519 | desc->irq_data.chip->irq_eoi(&desc->irq_data); |