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