History

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.

Boris Brezillon committed 10 years ago

Commit 5eb0d6e1 parent ebf9ff72 files · +6 −4Browse files

Unified · Split

2 files
  1. drivers/irqchip/irq-atmel-aic.c +3 −2
  2. drivers/irqchip/irq-atmel-aic5.c +3 −2
drivers/irqchip/irq-atmel-aic.c+3−2
@@ -176,6 +176,7 @@ static int aic_irq_domain_xlate(struct irq_domain *d, · 175 unmodified lines
176176 {
177177 struct irq_domain_chip_generic *dgc = d->gc;
178178 struct irq_chip_generic *gc;
179+ unsigned long flags;
179180 unsigned smr;
180181 int idx;
181182 int ret;
@@ -194,11 +195,11 @@ static int aic_irq_domain_xlate(struct irq_domain *d, · 12 unmodified lines
194195
195196 gc = dgc->gc[idx];
196197
197− irq_gc_lock(gc);
198+ irq_gc_lock_irqsave(gc, flags);
198199 smr = irq_reg_readl(gc, AT91_AIC_SMR(*out_hwirq));
199200 aic_common_set_priority(intspec[2], &smr);
200201 irq_reg_writel(gc, smr, AT91_AIC_SMR(*out_hwirq));
201− irq_gc_unlock(gc);
202+ irq_gc_unlock_irqrestore(gc, flags);
202203
203204 return ret;
204205 }
drivers/irqchip/irq-atmel-aic5.c+3−2
@@ -258,6 +258,7 @@ static int aic5_irq_domain_xlate(struct irq_domain *d, · 257 unmodified lines
258258 unsigned int *out_type)
259259 {
260260 struct irq_chip_generic *bgc = irq_get_domain_generic_chip(d, 0);
261+ unsigned long flags;
261262 unsigned smr;
262263 int ret;
263264
@@ -269,12 +270,12 @@ static int aic5_irq_domain_xlate(struct irq_domain *d, · 5 unmodified lines
269270 if (ret)
270271 return ret;
271272
272− irq_gc_lock(bgc);
273+ irq_gc_lock_irqsave(bgc, flags);
273274 irq_reg_writel(bgc, *out_hwirq, AT91_AIC5_SSR);
274275 smr = irq_reg_readl(bgc, AT91_AIC5_SMR);
275276 aic_common_set_priority(intspec[2], &smr);
276277 irq_reg_writel(bgc, smr, AT91_AIC5_SMR);
277− irq_gc_unlock(bgc);
278+ irq_gc_unlock_irqrestore(bgc, flags);
278279
279280 return ret;
280281 }