Skip to content

Commit a6aca2f

Browse files
author
Marc Zyngier
committed
irqchip/qcom-pdc: Fix broken locking
pdc_enable_intr() serves as a primitive to qcom_pdc_gic_{en,dis}able, and has a raw spinlock for mutual exclusion, which is uses with interruptible primitives. This means that this critical section can itself be interrupted. Should the interrupt also be a PDC interrupt, and the endpoint driver perform an irq_disable() on that interrupt, we end-up in a deadlock. Fix this by using the irqsave/irqrestore variants of the locking primitives. Signed-off-by: Marc Zyngier <[email protected]> Reviewed-by: Maulik Shah <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent d494d08 commit a6aca2f

File tree

1 file changed

+3
-2
lines changed

1 file changed

+3
-2
lines changed

drivers/irqchip/qcom-pdc.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,18 @@ static u32 pdc_reg_read(int reg, u32 i)
5555
static void pdc_enable_intr(struct irq_data *d, bool on)
5656
{
5757
int pin_out = d->hwirq;
58+
unsigned long flags;
5859
u32 index, mask;
5960
u32 enable;
6061

6162
index = pin_out / 32;
6263
mask = pin_out % 32;
6364

64-
raw_spin_lock(&pdc_lock);
65+
raw_spin_lock_irqsave(&pdc_lock, flags);
6566
enable = pdc_reg_read(IRQ_ENABLE_BANK, index);
6667
enable = on ? ENABLE_INTR(enable, mask) : CLEAR_INTR(enable, mask);
6768
pdc_reg_write(IRQ_ENABLE_BANK, index, enable);
68-
raw_spin_unlock(&pdc_lock);
69+
raw_spin_unlock_irqrestore(&pdc_lock, flags);
6970
}
7071

7172
static void qcom_pdc_gic_disable(struct irq_data *d)

0 commit comments

Comments
 (0)