Skip to content

Commit 3d76d26

Browse files
YchameSasha Levin
authored and
Sasha Levin
committed
IB/hfi1: Fix potential deadlock on &irq_src_lock and &dd->uctxt_lock
[ Upstream commit 2f19c4b ] handle_receive_interrupt_napi_sp() running inside interrupt handler could introduce inverse lock ordering between &dd->irq_src_lock and &dd->uctxt_lock, if read_mod_write() is preempted by the isr. [CPU0] | [CPU1] hfi1_ipoib_dev_open() | --> hfi1_netdev_enable_queues() | --> enable_queues(rx) | --> hfi1_rcvctrl() | --> set_intr_bits() | --> read_mod_write() | --> spin_lock(&dd->irq_src_lock) | | hfi1_poll() | --> poll_next() | --> spin_lock_irq(&dd->uctxt_lock) | | --> hfi1_rcvctrl() | --> set_intr_bits() | --> read_mod_write() | --> spin_lock(&dd->irq_src_lock) <interrupt> | --> handle_receive_interrupt_napi_sp() | --> set_all_fastpath() | --> hfi1_rcd_get_by_index() | --> spin_lock_irqsave(&dd->uctxt_lock) | This flaw was found by an experimental static analysis tool I am developing for irq-related deadlock. To prevent the potential deadlock, the patch use spin_lock_irqsave() on &dd->irq_src_lock inside read_mod_write() to prevent the possible deadlock scenario. Signed-off-by: Chengfeng Ye <[email protected]> Link: https://lore.kernel.org/r/[email protected] Acked-by: Dennis Dalessandro <[email protected]> Signed-off-by: Leon Romanovsky <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent ee100f4 commit 3d76d26

File tree

1 file changed

+3
-2
lines changed
  • drivers/infiniband/hw/hfi1

1 file changed

+3
-2
lines changed

drivers/infiniband/hw/hfi1/chip.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13185,15 +13185,16 @@ static void read_mod_write(struct hfi1_devdata *dd, u16 src, u64 bits,
1318513185
{
1318613186
u64 reg;
1318713187
u16 idx = src / BITS_PER_REGISTER;
13188+
unsigned long flags;
1318813189

13189-
spin_lock(&dd->irq_src_lock);
13190+
spin_lock_irqsave(&dd->irq_src_lock, flags);
1319013191
reg = read_csr(dd, CCE_INT_MASK + (8 * idx));
1319113192
if (set)
1319213193
reg |= bits;
1319313194
else
1319413195
reg &= ~bits;
1319513196
write_csr(dd, CCE_INT_MASK + (8 * idx), reg);
13196-
spin_unlock(&dd->irq_src_lock);
13197+
spin_unlock_irqrestore(&dd->irq_src_lock, flags);
1319713198
}
1319813199

1319913200
/**

0 commit comments

Comments
 (0)