From: Selvin Xavier <[email protected]>

[ Upstream commit 097a9d23b7250355b182c5fd47dd4c55b22b1c33 ]

Driver crashes when destroy_qp is re-tried because of an error
returned. This is because the qp entry was removed from the qp list during
the first call.

Remove qp from the list only if destroy_qp returns success.

The driver will still trigger a WARN_ON due to the memory leaking, but at
least it isn't corrupting memory too.

Fixes: 8dae419f9ec7 ("RDMA/bnxt_re: Refactor queue pair creation code")
Link: 
https://lore.kernel.org/r/[email protected]
Signed-off-by: Selvin Xavier <[email protected]>
Signed-off-by: Jason Gunthorpe <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
---
 drivers/infiniband/hw/bnxt_re/ib_verbs.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c 
b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index dad38aa06403d..cb6e873039df5 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -752,12 +752,6 @@ static int bnxt_re_destroy_gsi_sqp(struct bnxt_re_qp *qp)
        gsi_sqp = rdev->gsi_ctx.gsi_sqp;
        gsi_sah = rdev->gsi_ctx.gsi_sah;
 
-       /* remove from active qp list */
-       mutex_lock(&rdev->qp_lock);
-       list_del(&gsi_sqp->list);
-       mutex_unlock(&rdev->qp_lock);
-       atomic_dec(&rdev->qp_count);
-
        ibdev_dbg(&rdev->ibdev, "Destroy the shadow AH\n");
        bnxt_qplib_destroy_ah(&rdev->qplib_res,
                              &gsi_sah->qplib_ah,
@@ -772,6 +766,12 @@ static int bnxt_re_destroy_gsi_sqp(struct bnxt_re_qp *qp)
        }
        bnxt_qplib_free_qp_res(&rdev->qplib_res, &gsi_sqp->qplib_qp);
 
+       /* remove from active qp list */
+       mutex_lock(&rdev->qp_lock);
+       list_del(&gsi_sqp->list);
+       mutex_unlock(&rdev->qp_lock);
+       atomic_dec(&rdev->qp_count);
+
        kfree(rdev->gsi_ctx.sqp_tbl);
        kfree(gsi_sah);
        kfree(gsi_sqp);
@@ -792,11 +792,6 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct 
ib_udata *udata)
        unsigned int flags;
        int rc;
 
-       mutex_lock(&rdev->qp_lock);
-       list_del(&qp->list);
-       mutex_unlock(&rdev->qp_lock);
-       atomic_dec(&rdev->qp_count);
-
        bnxt_qplib_flush_cqn_wq(&qp->qplib_qp);
 
        rc = bnxt_qplib_destroy_qp(&rdev->qplib_res, &qp->qplib_qp);
@@ -819,6 +814,11 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct 
ib_udata *udata)
                        goto sh_fail;
        }
 
+       mutex_lock(&rdev->qp_lock);
+       list_del(&qp->list);
+       mutex_unlock(&rdev->qp_lock);
+       atomic_dec(&rdev->qp_count);
+
        ib_umem_release(qp->rumem);
        ib_umem_release(qp->sumem);
 
-- 
2.25.1



Reply via email to