diff options
author | Ludovic Desroches <ludovic.desroches@atmel.com> | 2015-09-21 09:46:04 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2015-09-22 09:55:51 -0400 |
commit | d32dc9aa10c739363c775baf4499416b2e0dc11f (patch) | |
tree | 3c1db86bcea785272bc66a737c9d8f598b634bf1 | |
parent | 1f93e4a96c9109378204c147b3eec0d0e8100fde (diff) |
irqchip/atmel-aic5: Use per chip mask caches in mask/unmask()
When masking/unmasking interrupts, mask_cache is updated and used later
for suspend/resume. Unfortunately, it always was the mask_cache
associated with the first irq chip which was updated. So when performing
resume, only irqs 0-31 could be enabled.
Fixes: b1479ebb7720 ("irqchip: atmel-aic: Add atmel AIC/AIC5 drivers")
Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
Cc: <sasha.levin@oracle.com>
Cc: <linux-arm-kernel@lists.infradead.org>
Cc: <nicolas.ferre@atmel.com>
Cc: <alexandre.belloni@free-electrons.com>
Cc: <boris.brezillon@free-electrons.com>
Cc: <Wenyou.Yang@atmel.com>
Cc: <jason@lakedaemon.net>
Cc: <marc.zyngier@arm.com>
Cc: stable@vger.kernel.org #3.18
Link: http://lkml.kernel.org/r/1442843173-2390-1-git-send-email-ludovic.desroches@atmel.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r-- | drivers/irqchip/irq-atmel-aic5.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/drivers/irqchip/irq-atmel-aic5.c b/drivers/irqchip/irq-atmel-aic5.c index 9da9942ac83c..f6d680485bee 100644 --- a/drivers/irqchip/irq-atmel-aic5.c +++ b/drivers/irqchip/irq-atmel-aic5.c | |||
@@ -88,28 +88,36 @@ static void aic5_mask(struct irq_data *d) | |||
88 | { | 88 | { |
89 | struct irq_domain *domain = d->domain; | 89 | struct irq_domain *domain = d->domain; |
90 | struct irq_domain_chip_generic *dgc = domain->gc; | 90 | struct irq_domain_chip_generic *dgc = domain->gc; |
91 | struct irq_chip_generic *gc = dgc->gc[0]; | 91 | struct irq_chip_generic *bgc = dgc->gc[0]; |
92 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
92 | 93 | ||
93 | /* Disable interrupt on AIC5 */ | 94 | /* |
94 | irq_gc_lock(gc); | 95 | * Disable interrupt on AIC5. We always take the lock of the |
96 | * first irq chip as all chips share the same registers. | ||
97 | */ | ||
98 | irq_gc_lock(bgc); | ||
95 | irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR); | 99 | irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR); |
96 | irq_reg_writel(gc, 1, AT91_AIC5_IDCR); | 100 | irq_reg_writel(gc, 1, AT91_AIC5_IDCR); |
97 | gc->mask_cache &= ~d->mask; | 101 | gc->mask_cache &= ~d->mask; |
98 | irq_gc_unlock(gc); | 102 | irq_gc_unlock(bgc); |
99 | } | 103 | } |
100 | 104 | ||
101 | static void aic5_unmask(struct irq_data *d) | 105 | static void aic5_unmask(struct irq_data *d) |
102 | { | 106 | { |
103 | struct irq_domain *domain = d->domain; | 107 | struct irq_domain *domain = d->domain; |
104 | struct irq_domain_chip_generic *dgc = domain->gc; | 108 | struct irq_domain_chip_generic *dgc = domain->gc; |
105 | struct irq_chip_generic *gc = dgc->gc[0]; | 109 | struct irq_chip_generic *bgc = dgc->gc[0]; |
110 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
106 | 111 | ||
107 | /* Enable interrupt on AIC5 */ | 112 | /* |
108 | irq_gc_lock(gc); | 113 | * Enable interrupt on AIC5. We always take the lock of the |
114 | * first irq chip as all chips share the same registers. | ||
115 | */ | ||
116 | irq_gc_lock(bgc); | ||
109 | irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR); | 117 | irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR); |
110 | irq_reg_writel(gc, 1, AT91_AIC5_IECR); | 118 | irq_reg_writel(gc, 1, AT91_AIC5_IECR); |
111 | gc->mask_cache |= d->mask; | 119 | gc->mask_cache |= d->mask; |
112 | irq_gc_unlock(gc); | 120 | irq_gc_unlock(bgc); |
113 | } | 121 | } |
114 | 122 | ||
115 | static int aic5_retrigger(struct irq_data *d) | 123 | static int aic5_retrigger(struct irq_data *d) |