Skip to content

Commit aaed4d0

Browse files
committed
Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq fixes from Thomas Gleixner: "Two patches from Boris which address a potential deadlock in the atmel irq chip driver" * 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: irqchip/atmel-aic: Fix potential deadlock in ->xlate() genirq: Provide irq_gc_{lock_irqsave,unlock_irqrestore}() helpers
2 parents d4690f1 + 5eb0d6e commit aaed4d0

File tree

3 files changed

+16
-4
lines changed

3 files changed

+16
-4
lines changed

drivers/irqchip/irq-atmel-aic.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ static int aic_irq_domain_xlate(struct irq_domain *d,
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,
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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ static int aic5_irq_domain_xlate(struct irq_domain *d,
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,
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
}

include/linux/irq.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,16 @@ static inline void irq_gc_lock(struct irq_chip_generic *gc) { }
945945
static inline void irq_gc_unlock(struct irq_chip_generic *gc) { }
946946
#endif
947947

948+
/*
949+
* The irqsave variants are for usage in non interrupt code. Do not use
950+
* them in irq_chip callbacks. Use irq_gc_lock() instead.
951+
*/
952+
#define irq_gc_lock_irqsave(gc, flags) \
953+
raw_spin_lock_irqsave(&(gc)->lock, flags)
954+
955+
#define irq_gc_unlock_irqrestore(gc, flags) \
956+
raw_spin_unlock_irqrestore(&(gc)->lock, flags)
957+
948958
static inline void irq_reg_writel(struct irq_chip_generic *gc,
949959
u32 val, int reg_offset)
950960
{

0 commit comments

Comments
 (0)