diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2013-05-06 10:30:22 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2013-05-29 04:57:10 -0400 |
commit | 966dc736b819999cd2d3a6408d47d33b579f7d56 (patch) | |
tree | 49935202236e9d0b66cf7f9330d8c99eecc89b51 | |
parent | af80b0fed67261dcba2ce2406db1d553d07cbe75 (diff) |
genirq: Generic chip: Cache per irq bit mask
Cache the per irq bit mask instead of recalculating it over and over.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Russell King - ARM Linux <linux@arm.linux.org.uk>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Jean-Francois Moine <moinejf@free.fr>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Gregory Clement <gregory.clement@free-electrons.com>
Cc: Gerlando Falauto <gerlando.falauto@keymile.com>
Cc: Rob Landley <rob@landley.net>
Acked-by: Grant Likely <grant.likely@linaro.org>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Link: http://lkml.kernel.org/r/20130506142539.227119865@linutronix.de
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r-- | include/linux/irq.h | 4 | ||||
-rw-r--r-- | kernel/irq/generic-chip.c | 23 |
2 files changed, 18 insertions, 9 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h index 7f1f0157fd00..d5fc7f5a49b8 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -119,6 +119,7 @@ struct irq_domain; | |||
119 | 119 | ||
120 | /** | 120 | /** |
121 | * struct irq_data - per irq and irq chip data passed down to chip functions | 121 | * struct irq_data - per irq and irq chip data passed down to chip functions |
122 | * @mask: precomputed bitmask for accessing the chip registers | ||
122 | * @irq: interrupt number | 123 | * @irq: interrupt number |
123 | * @hwirq: hardware interrupt number, local to the interrupt domain | 124 | * @hwirq: hardware interrupt number, local to the interrupt domain |
124 | * @node: node index useful for balancing | 125 | * @node: node index useful for balancing |
@@ -138,6 +139,7 @@ struct irq_domain; | |||
138 | * irq_data. | 139 | * irq_data. |
139 | */ | 140 | */ |
140 | struct irq_data { | 141 | struct irq_data { |
142 | u32 mask; | ||
141 | unsigned int irq; | 143 | unsigned int irq; |
142 | unsigned long hwirq; | 144 | unsigned long hwirq; |
143 | unsigned int node; | 145 | unsigned int node; |
@@ -705,11 +707,13 @@ struct irq_chip_generic { | |||
705 | * irq chips which need to call irq_set_wake() on | 707 | * irq chips which need to call irq_set_wake() on |
706 | * the parent irq. Usually GPIO implementations | 708 | * the parent irq. Usually GPIO implementations |
707 | * @IRQ_GC_MASK_CACHE_PER_TYPE: Mask cache is chip type private | 709 | * @IRQ_GC_MASK_CACHE_PER_TYPE: Mask cache is chip type private |
710 | * @IRQ_GC_NO_MASK: Do not calculate irq_data->mask | ||
708 | */ | 711 | */ |
709 | enum irq_gc_flags { | 712 | enum irq_gc_flags { |
710 | IRQ_GC_INIT_MASK_CACHE = 1 << 0, | 713 | IRQ_GC_INIT_MASK_CACHE = 1 << 0, |
711 | IRQ_GC_INIT_NESTED_LOCK = 1 << 1, | 714 | IRQ_GC_INIT_NESTED_LOCK = 1 << 1, |
712 | IRQ_GC_MASK_CACHE_PER_TYPE = 1 << 2, | 715 | IRQ_GC_MASK_CACHE_PER_TYPE = 1 << 2, |
716 | IRQ_GC_NO_MASK = 1 << 3, | ||
713 | }; | 717 | }; |
714 | 718 | ||
715 | /* Generic chip callback functions */ | 719 | /* Generic chip callback functions */ |
diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c index da2a94191fc5..957155cebbac 100644 --- a/kernel/irq/generic-chip.c +++ b/kernel/irq/generic-chip.c | |||
@@ -35,7 +35,7 @@ void irq_gc_mask_disable_reg(struct irq_data *d) | |||
35 | { | 35 | { |
36 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 36 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
37 | struct irq_chip_type *ct = irq_data_get_chip_type(d); | 37 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
38 | u32 mask = 1 << (d->irq - gc->irq_base); | 38 | u32 mask = d->mask; |
39 | 39 | ||
40 | irq_gc_lock(gc); | 40 | irq_gc_lock(gc); |
41 | irq_reg_writel(mask, gc->reg_base + ct->regs.disable); | 41 | irq_reg_writel(mask, gc->reg_base + ct->regs.disable); |
@@ -54,7 +54,7 @@ void irq_gc_mask_set_bit(struct irq_data *d) | |||
54 | { | 54 | { |
55 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 55 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
56 | struct irq_chip_type *ct = irq_data_get_chip_type(d); | 56 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
57 | u32 mask = 1 << (d->irq - gc->irq_base); | 57 | u32 mask = d->mask; |
58 | 58 | ||
59 | irq_gc_lock(gc); | 59 | irq_gc_lock(gc); |
60 | *ct->mask_cache |= mask; | 60 | *ct->mask_cache |= mask; |
@@ -73,7 +73,7 @@ void irq_gc_mask_clr_bit(struct irq_data *d) | |||
73 | { | 73 | { |
74 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 74 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
75 | struct irq_chip_type *ct = irq_data_get_chip_type(d); | 75 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
76 | u32 mask = 1 << (d->irq - gc->irq_base); | 76 | u32 mask = d->mask; |
77 | 77 | ||
78 | irq_gc_lock(gc); | 78 | irq_gc_lock(gc); |
79 | *ct->mask_cache &= ~mask; | 79 | *ct->mask_cache &= ~mask; |
@@ -92,7 +92,7 @@ void irq_gc_unmask_enable_reg(struct irq_data *d) | |||
92 | { | 92 | { |
93 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 93 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
94 | struct irq_chip_type *ct = irq_data_get_chip_type(d); | 94 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
95 | u32 mask = 1 << (d->irq - gc->irq_base); | 95 | u32 mask = d->mask; |
96 | 96 | ||
97 | irq_gc_lock(gc); | 97 | irq_gc_lock(gc); |
98 | irq_reg_writel(mask, gc->reg_base + ct->regs.enable); | 98 | irq_reg_writel(mask, gc->reg_base + ct->regs.enable); |
@@ -108,7 +108,7 @@ void irq_gc_ack_set_bit(struct irq_data *d) | |||
108 | { | 108 | { |
109 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 109 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
110 | struct irq_chip_type *ct = irq_data_get_chip_type(d); | 110 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
111 | u32 mask = 1 << (d->irq - gc->irq_base); | 111 | u32 mask = d->mask; |
112 | 112 | ||
113 | irq_gc_lock(gc); | 113 | irq_gc_lock(gc); |
114 | irq_reg_writel(mask, gc->reg_base + ct->regs.ack); | 114 | irq_reg_writel(mask, gc->reg_base + ct->regs.ack); |
@@ -123,7 +123,7 @@ void irq_gc_ack_clr_bit(struct irq_data *d) | |||
123 | { | 123 | { |
124 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 124 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
125 | struct irq_chip_type *ct = irq_data_get_chip_type(d); | 125 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
126 | u32 mask = ~(1 << (d->irq - gc->irq_base)); | 126 | u32 mask = ~d->mask; |
127 | 127 | ||
128 | irq_gc_lock(gc); | 128 | irq_gc_lock(gc); |
129 | irq_reg_writel(mask, gc->reg_base + ct->regs.ack); | 129 | irq_reg_writel(mask, gc->reg_base + ct->regs.ack); |
@@ -138,7 +138,7 @@ void irq_gc_mask_disable_reg_and_ack(struct irq_data *d) | |||
138 | { | 138 | { |
139 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 139 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
140 | struct irq_chip_type *ct = irq_data_get_chip_type(d); | 140 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
141 | u32 mask = 1 << (d->irq - gc->irq_base); | 141 | u32 mask = d->mask; |
142 | 142 | ||
143 | irq_gc_lock(gc); | 143 | irq_gc_lock(gc); |
144 | irq_reg_writel(mask, gc->reg_base + ct->regs.mask); | 144 | irq_reg_writel(mask, gc->reg_base + ct->regs.mask); |
@@ -154,7 +154,7 @@ void irq_gc_eoi(struct irq_data *d) | |||
154 | { | 154 | { |
155 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 155 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
156 | struct irq_chip_type *ct = irq_data_get_chip_type(d); | 156 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
157 | u32 mask = 1 << (d->irq - gc->irq_base); | 157 | u32 mask = d->mask; |
158 | 158 | ||
159 | irq_gc_lock(gc); | 159 | irq_gc_lock(gc); |
160 | irq_reg_writel(mask, gc->reg_base + ct->regs.eoi); | 160 | irq_reg_writel(mask, gc->reg_base + ct->regs.eoi); |
@@ -172,7 +172,7 @@ void irq_gc_eoi(struct irq_data *d) | |||
172 | int irq_gc_set_wake(struct irq_data *d, unsigned int on) | 172 | int irq_gc_set_wake(struct irq_data *d, unsigned int on) |
173 | { | 173 | { |
174 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 174 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
175 | u32 mask = 1 << (d->irq - gc->irq_base); | 175 | u32 mask = d->mask; |
176 | 176 | ||
177 | if (!(mask & gc->wake_enabled)) | 177 | if (!(mask & gc->wake_enabled)) |
178 | return -EINVAL; | 178 | return -EINVAL; |
@@ -264,6 +264,11 @@ void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk, | |||
264 | if (flags & IRQ_GC_INIT_NESTED_LOCK) | 264 | if (flags & IRQ_GC_INIT_NESTED_LOCK) |
265 | irq_set_lockdep_class(i, &irq_nested_lock_class); | 265 | irq_set_lockdep_class(i, &irq_nested_lock_class); |
266 | 266 | ||
267 | if (!(flags & IRQ_GC_NO_MASK)) { | ||
268 | struct irq_data *d = irq_get_irq_data(i); | ||
269 | |||
270 | d->mask = 1 << (i - gc->irq_base); | ||
271 | } | ||
267 | irq_set_chip_and_handler(i, &ct->chip, ct->handler); | 272 | irq_set_chip_and_handler(i, &ct->chip, ct->handler); |
268 | irq_set_chip_data(i, gc); | 273 | irq_set_chip_data(i, gc); |
269 | irq_modify_status(i, clr, set); | 274 | irq_modify_status(i, clr, set); |