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.
Unified · Split
| @@ -176,6 +176,7 @@ static int aic_irq_domain_xlate(struct irq_domain *d, · 175 unmodified lines | ||
| 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; |
| @@ -194,11 +195,11 @@ static int aic_irq_domain_xlate(struct irq_domain *d, · 12 unmodified lines | ||
| 194 | 195 | |
| 195 | 196 | gc = dgc->gc[idx]; |
| 196 | 197 | |
| 197 | − irq_gc_lock(gc); | |
| 198 | + irq_gc_lock_irqsave(gc, flags); | |
| 198 | 199 | smr = irq_reg_readl(gc, AT91_AIC_SMR(*out_hwirq)); |
| 199 | 200 | aic_common_set_priority(intspec[2], &smr); |
| 200 | 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 | 204 | return ret; |
| 204 | 205 | } |
| @@ -258,6 +258,7 @@ static int aic5_irq_domain_xlate(struct irq_domain *d, · 257 unmodified lines | ||
| 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 | |
| @@ -269,12 +270,12 @@ static int aic5_irq_domain_xlate(struct irq_domain *d, · 5 unmodified lines | ||
| 269 | 270 | if (ret) |
| 270 | 271 | return ret; |
| 271 | 272 | |
| 272 | − irq_gc_lock(bgc); | |
| 273 | + irq_gc_lock_irqsave(bgc, flags); | |
| 273 | 274 | irq_reg_writel(bgc, *out_hwirq, AT91_AIC5_SSR); |
| 274 | 275 | smr = irq_reg_readl(bgc, AT91_AIC5_SMR); |
| 275 | 276 | aic_common_set_priority(intspec[2], &smr); |
| 276 | 277 | irq_reg_writel(bgc, smr, AT91_AIC5_SMR); |
| 277 | − irq_gc_unlock(bgc); | |
| 278 | + irq_gc_unlock_irqrestore(bgc, flags); | |
| 278 | 279 | |
| 279 | 280 | return ret; |
| 280 | 281 | } |