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