i40iw: Free QP PBLEs when the QP is destroyed
authorTatyana Nikolova <Tatyana.E.Nikolova@intel.com>
Thu, 6 Jul 2017 02:25:33 +0000 (21:25 -0500)
committerDoug Ledford <dledford@redhat.com>
Thu, 20 Jul 2017 15:20:49 +0000 (11:20 -0400)
If the physical buffer list entries (PBLEs) of a QP are freed
up at i40iw_dereg_mr, they can be assigned to a newly
created QP before the previous QP is destroyed. Fix this
by freeing PBLEs only when the QP is destroyed.

Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
Signed-off-by: Faisal Latif <faisal.latif@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/i40iw/i40iw_verbs.c
drivers/infiniband/hw/i40iw/i40iw_verbs.h

index 4dbe61ec7a77caa87ad7eacc66b859c3412fd708..4aa0264ccb3ab4486b01b45feb226386894e9bcd 100644 (file)
@@ -426,9 +426,13 @@ void i40iw_free_qp_resources(struct i40iw_device *iwdev,
                             struct i40iw_qp *iwqp,
                             u32 qp_num)
 {
+       struct i40iw_pbl *iwpbl = &iwqp->iwpbl;
+
        i40iw_dealloc_push_page(iwdev, &iwqp->sc_qp);
        if (qp_num)
                i40iw_free_resource(iwdev, iwdev->allocated_qps, qp_num);
+       if (iwpbl->pbl_allocated)
+               i40iw_free_pble(iwdev->pble_rsrc, &iwpbl->pble_alloc);
        i40iw_free_dma_mem(iwdev->sc_dev.hw, &iwqp->q2_ctx_mem);
        i40iw_free_dma_mem(iwdev->sc_dev.hw, &iwqp->kqp.dma_mem);
        kfree(iwqp->kqp.wrid_mem);
@@ -483,7 +487,7 @@ static int i40iw_setup_virt_qp(struct i40iw_device *iwdev,
                               struct i40iw_qp *iwqp,
                               struct i40iw_qp_init_info *init_info)
 {
-       struct i40iw_pbl *iwpbl = iwqp->iwpbl;
+       struct i40iw_pbl *iwpbl = &iwqp->iwpbl;
        struct i40iw_qp_mr *qpmr = &iwpbl->qp_mr;
 
        iwqp->page = qpmr->sq_page;
@@ -688,19 +692,22 @@ static struct ib_qp *i40iw_create_qp(struct ib_pd *ibpd,
                        ucontext = to_ucontext(ibpd->uobject->context);
 
                        if (req.user_wqe_buffers) {
+                               struct i40iw_pbl *iwpbl;
+
                                spin_lock_irqsave(
                                    &ucontext->qp_reg_mem_list_lock, flags);
-                               iwqp->iwpbl = i40iw_get_pbl(
+                               iwpbl = i40iw_get_pbl(
                                    (unsigned long)req.user_wqe_buffers,
                                    &ucontext->qp_reg_mem_list);
                                spin_unlock_irqrestore(
                                    &ucontext->qp_reg_mem_list_lock, flags);
 
-                               if (!iwqp->iwpbl) {
+                               if (!iwpbl) {
                                        err_code = -ENODATA;
                                        i40iw_pr_err("no pbl info\n");
                                        goto error;
                                }
+                               memcpy(&iwqp->iwpbl, iwpbl, sizeof(iwqp->iwpbl));
                        }
                }
                err_code = i40iw_setup_virt_qp(iwdev, iwqp, &init_info);
@@ -2063,7 +2070,7 @@ static int i40iw_dereg_mr(struct ib_mr *ib_mr)
                        ucontext = to_ucontext(ibpd->uobject->context);
                        i40iw_del_memlist(iwmr, ucontext);
                }
-               if (iwpbl->pbl_allocated)
+               if (iwpbl->pbl_allocated && iwmr->type != IW_MEMREG_TYPE_QP)
                        i40iw_free_pble(iwdev->pble_rsrc, palloc);
                kfree(iwmr);
                return 0;
index 07c3fec77de6a1fcbb3a52a95e4937b6e23ea8aa..9067443cd31151bb501a505e74b06bb56265f1b5 100644 (file)
@@ -170,7 +170,7 @@ struct i40iw_qp {
        struct i40iw_qp_kmode kqp;
        struct i40iw_dma_mem host_ctx;
        struct timer_list terminate_timer;
-       struct i40iw_pbl *iwpbl;
+       struct i40iw_pbl iwpbl;
        struct i40iw_dma_mem q2_ctx_mem;
        struct i40iw_dma_mem ietf_mem;
        struct completion sq_drained;