irqchip/atmel-aic: Fix potential deadlock in ->xlate()

aic5_irq_domain_xlate() and aic_irq_domain_xlate() take the generic chip
lock without disabling interrupts, which can lead to a deadlock if an
interrupt occurs while the lock is held in one of these functions.

Replace irq_gc_{lock,unlock}() calls by
irq_gc_{lock_irqsave,unlock_irqrestore}() ones to prevent this bug from
happening.

Fixes: b1479ebb7720 ("irqchip: atmel-aic: Add atmel AIC/AIC5 drivers")
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
Cc: stable@vger.kernel.org
Cc: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Link: http://lkml.kernel.org/r/1473775109-4192-2-git-send-email-boris.brezillon@free-electrons.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

authored by Boris Brezillon and committed by Thomas Gleixner 5eb0d6eb ebf9ff75

+6 -4
+3 -2
drivers/irqchip/irq-atmel-aic.c
··· 176 { 177 struct irq_domain_chip_generic *dgc = d->gc; 178 struct irq_chip_generic *gc; 179 unsigned smr; 180 int idx; 181 int ret; ··· 195 196 gc = dgc->gc[idx]; 197 198 - irq_gc_lock(gc); 199 smr = irq_reg_readl(gc, AT91_AIC_SMR(*out_hwirq)); 200 aic_common_set_priority(intspec[2], &smr); 201 irq_reg_writel(gc, smr, AT91_AIC_SMR(*out_hwirq)); 202 - irq_gc_unlock(gc); 203 204 return ret; 205 }
··· 176 { 177 struct irq_domain_chip_generic *dgc = d->gc; 178 struct irq_chip_generic *gc; 179 + unsigned long flags; 180 unsigned smr; 181 int idx; 182 int ret; ··· 194 195 gc = dgc->gc[idx]; 196 197 + irq_gc_lock_irqsave(gc, flags); 198 smr = irq_reg_readl(gc, AT91_AIC_SMR(*out_hwirq)); 199 aic_common_set_priority(intspec[2], &smr); 200 irq_reg_writel(gc, smr, AT91_AIC_SMR(*out_hwirq)); 201 + irq_gc_unlock_irqrestore(gc, flags); 202 203 return ret; 204 }
+3 -2
drivers/irqchip/irq-atmel-aic5.c
··· 258 unsigned int *out_type) 259 { 260 struct irq_chip_generic *bgc = irq_get_domain_generic_chip(d, 0); 261 unsigned smr; 262 int ret; 263 ··· 270 if (ret) 271 return ret; 272 273 - irq_gc_lock(bgc); 274 irq_reg_writel(bgc, *out_hwirq, AT91_AIC5_SSR); 275 smr = irq_reg_readl(bgc, AT91_AIC5_SMR); 276 aic_common_set_priority(intspec[2], &smr); 277 irq_reg_writel(bgc, smr, AT91_AIC5_SMR); 278 - irq_gc_unlock(bgc); 279 280 return ret; 281 }
··· 258 unsigned int *out_type) 259 { 260 struct irq_chip_generic *bgc = irq_get_domain_generic_chip(d, 0); 261 + unsigned long flags; 262 unsigned smr; 263 int ret; 264 ··· 269 if (ret) 270 return ret; 271 272 + irq_gc_lock_irqsave(bgc, flags); 273 irq_reg_writel(bgc, *out_hwirq, AT91_AIC5_SSR); 274 smr = irq_reg_readl(bgc, AT91_AIC5_SMR); 275 aic_common_set_priority(intspec[2], &smr); 276 irq_reg_writel(bgc, smr, AT91_AIC5_SMR); 277 + irq_gc_unlock_irqrestore(bgc, flags); 278 279 return ret; 280 }