aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/irq.h
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2011-09-23 12:03:06 -0400
committerThomas Gleixner <tglx@linutronix.de>2011-10-03 09:35:26 -0400
commit31d9d9b6d83030f748d013e61502fa5477e2ac0e (patch)
tree503670b94d594c09daa83c047b426e7b5328aa76 /include/linux/irq.h
parent60f96b41f71d2a13d1c0a457b8b77958f77142d1 (diff)
genirq: Add support for per-cpu dev_id interrupts
The ARM GIC interrupt controller offers per CPU interrupts (PPIs), which are usually used to connect local timers to each core. Each CPU has its own private interface to the GIC, and only sees the PPIs that are directly connect to it. While these timers are separate devices and have a separate interrupt line to a core, they all use the same IRQ number. For these devices, request_irq() is not the right API as it assumes that an IRQ number is visible by a number of CPUs (through the affinity setting), but makes it very awkward to express that an IRQ number can be handled by all CPUs, and yet be a different interrupt line on each CPU, requiring a different dev_id cookie to be passed back to the handler. The *_percpu_irq() functions is designed to overcome these limitations, by providing a per-cpu dev_id vector: int request_percpu_irq(unsigned int irq, irq_handler_t handler, const char *devname, void __percpu *percpu_dev_id); void free_percpu_irq(unsigned int, void __percpu *); int setup_percpu_irq(unsigned int irq, struct irqaction *new); void remove_percpu_irq(unsigned int irq, struct irqaction *act); void enable_percpu_irq(unsigned int irq); void disable_percpu_irq(unsigned int irq); The API has a number of limitations: - no interrupt sharing - no threading - common handler across all the CPUs Once the interrupt is requested using setup_percpu_irq() or request_percpu_irq(), it must be enabled by each core that wishes its local interrupt to be delivered. Based on an initial patch by Thomas Gleixner. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Cc: linux-arm-kernel@lists.infradead.org Link: http://lkml.kernel.org/r/1316793788-14500-2-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'include/linux/irq.h')
-rw-r--r--include/linux/irq.h16
1 files changed, 15 insertions, 1 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 73e31abeba1c..59e49c80cc2c 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -66,6 +66,7 @@ typedef void (*irq_preflow_handler_t)(struct irq_data *data);
66 * IRQ_NO_BALANCING - Interrupt cannot be balanced (affinity set) 66 * IRQ_NO_BALANCING - Interrupt cannot be balanced (affinity set)
67 * IRQ_MOVE_PCNTXT - Interrupt can be migrated from process context 67 * IRQ_MOVE_PCNTXT - Interrupt can be migrated from process context
68 * IRQ_NESTED_TRHEAD - Interrupt nests into another thread 68 * IRQ_NESTED_TRHEAD - Interrupt nests into another thread
69 * IRQ_PER_CPU_DEVID - Dev_id is a per-cpu variable
69 */ 70 */
70enum { 71enum {
71 IRQ_TYPE_NONE = 0x00000000, 72 IRQ_TYPE_NONE = 0x00000000,
@@ -88,12 +89,13 @@ enum {
88 IRQ_MOVE_PCNTXT = (1 << 14), 89 IRQ_MOVE_PCNTXT = (1 << 14),
89 IRQ_NESTED_THREAD = (1 << 15), 90 IRQ_NESTED_THREAD = (1 << 15),
90 IRQ_NOTHREAD = (1 << 16), 91 IRQ_NOTHREAD = (1 << 16),
92 IRQ_PER_CPU_DEVID = (1 << 17),
91}; 93};
92 94
93#define IRQF_MODIFY_MASK \ 95#define IRQF_MODIFY_MASK \
94 (IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \ 96 (IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
95 IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \ 97 IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \
96 IRQ_PER_CPU | IRQ_NESTED_THREAD) 98 IRQ_PER_CPU | IRQ_NESTED_THREAD | IRQ_NOTHREAD | IRQ_PER_CPU_DEVID)
97 99
98#define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING) 100#define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING)
99 101
@@ -367,6 +369,8 @@ enum {
367struct irqaction; 369struct irqaction;
368extern int setup_irq(unsigned int irq, struct irqaction *new); 370extern int setup_irq(unsigned int irq, struct irqaction *new);
369extern void remove_irq(unsigned int irq, struct irqaction *act); 371extern void remove_irq(unsigned int irq, struct irqaction *act);
372extern int setup_percpu_irq(unsigned int irq, struct irqaction *new);
373extern void remove_percpu_irq(unsigned int irq, struct irqaction *act);
370 374
371extern void irq_cpu_online(void); 375extern void irq_cpu_online(void);
372extern void irq_cpu_offline(void); 376extern void irq_cpu_offline(void);
@@ -394,6 +398,7 @@ extern void handle_edge_irq(unsigned int irq, struct irq_desc *desc);
394extern void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc); 398extern void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc);
395extern void handle_simple_irq(unsigned int irq, struct irq_desc *desc); 399extern void handle_simple_irq(unsigned int irq, struct irq_desc *desc);
396extern void handle_percpu_irq(unsigned int irq, struct irq_desc *desc); 400extern void handle_percpu_irq(unsigned int irq, struct irq_desc *desc);
401extern void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc);
397extern void handle_bad_irq(unsigned int irq, struct irq_desc *desc); 402extern void handle_bad_irq(unsigned int irq, struct irq_desc *desc);
398extern void handle_nested_irq(unsigned int irq); 403extern void handle_nested_irq(unsigned int irq);
399 404
@@ -422,6 +427,8 @@ static inline void irq_set_chip_and_handler(unsigned int irq, struct irq_chip *c
422 irq_set_chip_and_handler_name(irq, chip, handle, NULL); 427 irq_set_chip_and_handler_name(irq, chip, handle, NULL);
423} 428}
424 429
430extern int irq_set_percpu_devid(unsigned int irq);
431
425extern void 432extern void
426__irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, 433__irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
427 const char *name); 434 const char *name);
@@ -483,6 +490,13 @@ static inline void irq_set_nested_thread(unsigned int irq, bool nest)
483 irq_clear_status_flags(irq, IRQ_NESTED_THREAD); 490 irq_clear_status_flags(irq, IRQ_NESTED_THREAD);
484} 491}
485 492
493static inline void irq_set_percpu_devid_flags(unsigned int irq)
494{
495 irq_set_status_flags(irq,
496 IRQ_NOAUTOEN | IRQ_PER_CPU | IRQ_NOTHREAD |
497 IRQ_NOPROBE | IRQ_PER_CPU_DEVID);
498}
499
486/* Handle dynamic irq creation and destruction */ 500/* Handle dynamic irq creation and destruction */
487extern unsigned int create_irq_nr(unsigned int irq_want, int node); 501extern unsigned int create_irq_nr(unsigned int irq_want, int node);
488extern int create_irq(void); 502extern int create_irq(void);