]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
RDMA/efa: Fix wrong resources deallocation order
authorYonatan Nachum <ynachum@amazon.com>
Tue, 22 Aug 2023 08:27:25 +0000 (08:27 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Sep 2023 07:42:57 +0000 (09:42 +0200)
[ Upstream commit dc202c57e9a1423aed528e4b8dc949509cd32191 ]

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: ff6629f88c52 ("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>
drivers/infiniband/hw/efa/efa_verbs.c

index f9526a4c75b26bd9775d458b4d420f850902602d..90d5f1a96f3e5cc94bbfb4c59bae4c3308c9b22f 100644 (file)
@@ -443,12 +443,12 @@ int efa_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
 
        ibdev_dbg(&dev->ibdev, "Destroy qp[%u]\n", ibqp->qp_num);
 
-       efa_qp_user_mmap_entries_remove(qp);
-
        err = efa_destroy_qp_handle(dev, qp->qp_handle);
        if (err)
                return err;
 
+       efa_qp_user_mmap_entries_remove(qp);
+
        if (qp->rq_cpu_addr) {
                ibdev_dbg(&dev->ibdev,
                          "qp->cpu_addr[0x%p] freed: size[%lu], dma[%pad]\n",
@@ -1007,8 +1007,8 @@ int efa_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata)
                  "Destroy cq[%d] virt[0x%p] freed: size[%lu], dma[%pad]\n",
                  cq->cq_idx, cq->cpu_addr, cq->size, &cq->dma_addr);
 
-       efa_cq_user_mmap_entries_remove(cq);
        efa_destroy_cq_idx(dev, cq->cq_idx);
+       efa_cq_user_mmap_entries_remove(cq);
        if (cq->eq) {
                xa_erase(&dev->cqs_xa, cq->cq_idx);
                synchronize_irq(cq->eq->irq.irqn);