Skip to content

Commit e79db2f

Browse files
YonatanNachumgregkh
authored andcommitted
RDMA/efa: Fix wrong resources deallocation order
[ Upstream commit dc202c5 ] When trying to destroy QP or CQ, we first decrease the refcount and potentially free memory regions allocated for the object and then request the device to destroy the object. If the device fails, the object isn't fully destroyed so the user/IB core can try to destroy the object again which will lead to underflow when trying to decrease an already zeroed refcount. Deallocate resources in reverse order of allocating them to safely free them. Fixes: ff6629f ("RDMA/efa: Do not delay freeing of DMA pages") Reviewed-by: Michael Margolin <mrgolin@amazon.com> Reviewed-by: Yossi Leybovich <sleybo@amazon.com> Signed-off-by: Yonatan Nachum <ynachum@amazon.com> Link: https://lore.kernel.org/r/20230822082725.31719-1-ynachum@amazon.com Signed-off-by: Leon Romanovsky <leon@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent a1ceb30 commit e79db2f

1 file changed

Lines changed: 3 additions & 3 deletions

File tree

drivers/infiniband/hw/efa/efa_verbs.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -449,12 +449,12 @@ int efa_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
449449

450450
ibdev_dbg(&dev->ibdev, "Destroy qp[%u]\n", ibqp->qp_num);
451451

452-
efa_qp_user_mmap_entries_remove(qp);
453-
454452
err = efa_destroy_qp_handle(dev, qp->qp_handle);
455453
if (err)
456454
return err;
457455

456+
efa_qp_user_mmap_entries_remove(qp);
457+
458458
if (qp->rq_cpu_addr) {
459459
ibdev_dbg(&dev->ibdev,
460460
"qp->cpu_addr[0x%p] freed: size[%lu], dma[%pad]\n",
@@ -1013,8 +1013,8 @@ int efa_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata)
10131013
"Destroy cq[%d] virt[0x%p] freed: size[%lu], dma[%pad]\n",
10141014
cq->cq_idx, cq->cpu_addr, cq->size, &cq->dma_addr);
10151015

1016-
efa_cq_user_mmap_entries_remove(cq);
10171016
efa_destroy_cq_idx(dev, cq->cq_idx);
1017+
efa_cq_user_mmap_entries_remove(cq);
10181018
if (cq->eq) {
10191019
xa_erase(&dev->cqs_xa, cq->cq_idx);
10201020
synchronize_irq(cq->eq->irq.irqn);

0 commit comments

Comments
 (0)