[PATCH for-rc] RDMA/erdma: Use IRQ-safe XArray helpers for QP and CQ tables
Cheng Xu <[email protected]>
| Newsgroups | org.kernel.vger.linux-rdma |
|---|---|
| Message-ID | <[email protected]> |
Locked QP and CQ lookups from EQ interrupts can deadlock with
create-path XArray updates. If an interrupt arrives while the create
path holds the plain xa_lock, the lookup spins forever trying to
acquire the same lock.
Use IRQ-safe XArray helpers for all QP and CQ create-path updates,
including the GSI QP store and error paths.
Fixes: 98df2aee1459 ("RDMA/erdma: Hold CQ references when processing EQ events")
Fixes: a52eeff32024 ("RDMA/erdma: Hold QP references for AE and CM processing")
Signed-off-by: Cheng Xu <[email protected]>
---
drivers/infiniband/hw/erdma/erdma_verbs.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c
index 65b1af1e6623..f18b88bba281 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.c
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
@@ -1021,15 +1021,15 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
init_completion(&qp->safe_free);
if (qp->ibqp.qp_type == IB_QPT_GSI) {
- old_entry = xa_store(&dev->qp_xa, 1, qp, GFP_KERNEL);
+ old_entry = xa_store_irq(&dev->qp_xa, 1, qp, GFP_KERNEL);
if (xa_is_err(old_entry))
ret = xa_err(old_entry);
else
qp->ibqp.qp_num = 1;
} else {
- ret = xa_alloc_cyclic(&dev->qp_xa, &qp->ibqp.qp_num, qp,
- XA_LIMIT(1, dev->attrs.max_qp - 1),
- &dev->next_alloc_qpn, GFP_KERNEL);
+ ret = xa_alloc_cyclic_irq(&dev->qp_xa, &qp->ibqp.qp_num, qp,
+ XA_LIMIT(1, dev->attrs.max_qp - 1),
+ &dev->next_alloc_qpn, GFP_KERNEL);
}
if (ret < 0) {
@@ -1089,7 +1089,7 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
else
free_kernel_qp(qp);
err_out_xa:
- xa_erase(&dev->qp_xa, QP_ID(qp));
+ xa_erase_irq(&dev->qp_xa, QP_ID(qp));
err_out:
return ret;
}
@@ -1993,9 +1993,9 @@ int erdma_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
refcount_set(&cq->refcount, 1);
init_completion(&cq->free);
- ret = xa_alloc_cyclic(&dev->cq_xa, &cq->cqn, cq,
- XA_LIMIT(1, dev->attrs.max_cq - 1),
- &dev->next_alloc_cqn, GFP_KERNEL);
+ ret = xa_alloc_cyclic_irq(&dev->cq_xa, &cq->cqn, cq,
+ XA_LIMIT(1, dev->attrs.max_cq - 1),
+ &dev->next_alloc_cqn, GFP_KERNEL);
if (ret < 0)
return ret;
@@ -2041,7 +2041,7 @@ int erdma_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
}
err_out_xa:
- xa_erase(&dev->cq_xa, cq->cqn);
+ xa_erase_irq(&dev->cq_xa, cq->cqn);
return ret;
}
--
2.31.1