]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/infiniband/hw/i40iw/i40iw_utils.c
Merge tag 'uuid-for-4.13-2' of git://git.infradead.org/users/hch/uuid
[linux.git] / drivers / infiniband / hw / i40iw / i40iw_utils.c
index 56d986924a4c1708216684f776f4705451a65f79..e311ec559f4eb79de0e94aaa0f58861aba2882b0 100644 (file)
@@ -337,6 +337,7 @@ struct i40iw_cqp_request *i40iw_get_cqp_request(struct i40iw_cqp *cqp, bool wait
  */
 void i40iw_free_cqp_request(struct i40iw_cqp *cqp, struct i40iw_cqp_request *cqp_request)
 {
+       struct i40iw_device *iwdev = container_of(cqp, struct i40iw_device, cqp);
        unsigned long flags;
 
        if (cqp_request->dynamic) {
@@ -350,6 +351,7 @@ void i40iw_free_cqp_request(struct i40iw_cqp *cqp, struct i40iw_cqp_request *cqp
                list_add_tail(&cqp_request->list, &cqp->cqp_avail_reqs);
                spin_unlock_irqrestore(&cqp->req_lock, flags);
        }
+       wake_up(&iwdev->close_wq);
 }
 
 /**
@@ -364,6 +366,56 @@ void i40iw_put_cqp_request(struct i40iw_cqp *cqp,
                i40iw_free_cqp_request(cqp, cqp_request);
 }
 
+/**
+ * i40iw_free_pending_cqp_request -free pending cqp request objs
+ * @cqp: cqp ptr
+ * @cqp_request: to be put back in cqp list
+ */
+static void i40iw_free_pending_cqp_request(struct i40iw_cqp *cqp,
+                                          struct i40iw_cqp_request *cqp_request)
+{
+       struct i40iw_device *iwdev = container_of(cqp, struct i40iw_device, cqp);
+
+       if (cqp_request->waiting) {
+               cqp_request->compl_info.error = true;
+               cqp_request->request_done = true;
+               wake_up(&cqp_request->waitq);
+       }
+       i40iw_put_cqp_request(cqp, cqp_request);
+       wait_event_timeout(iwdev->close_wq,
+                          !atomic_read(&cqp_request->refcount),
+                          1000);
+}
+
+/**
+ * i40iw_cleanup_pending_cqp_op - clean-up cqp with no completions
+ * @iwdev: iwarp device
+ */
+void i40iw_cleanup_pending_cqp_op(struct i40iw_device *iwdev)
+{
+       struct i40iw_sc_dev *dev = &iwdev->sc_dev;
+       struct i40iw_cqp *cqp = &iwdev->cqp;
+       struct i40iw_cqp_request *cqp_request = NULL;
+       struct cqp_commands_info *pcmdinfo = NULL;
+       u32 i, pending_work, wqe_idx;
+
+       pending_work = I40IW_RING_WORK_AVAILABLE(cqp->sc_cqp.sq_ring);
+       wqe_idx = I40IW_RING_GETCURRENT_TAIL(cqp->sc_cqp.sq_ring);
+       for (i = 0; i < pending_work; i++) {
+               cqp_request = (struct i40iw_cqp_request *)(unsigned long)cqp->scratch_array[wqe_idx];
+               if (cqp_request)
+                       i40iw_free_pending_cqp_request(cqp, cqp_request);
+               wqe_idx = (wqe_idx + 1) % I40IW_RING_GETSIZE(cqp->sc_cqp.sq_ring);
+       }
+
+       while (!list_empty(&dev->cqp_cmd_head)) {
+               pcmdinfo = (struct cqp_commands_info *)i40iw_remove_head(&dev->cqp_cmd_head);
+               cqp_request = container_of(pcmdinfo, struct i40iw_cqp_request, info);
+               if (cqp_request)
+                       i40iw_free_pending_cqp_request(cqp, cqp_request);
+       }
+}
+
 /**
  * i40iw_free_qp - callback after destroy cqp completes
  * @cqp_request: cqp request for destroy qp
@@ -546,8 +598,12 @@ void i40iw_rem_ref(struct ib_qp *ibqp)
        cqp_info->in.u.qp_destroy.scratch = (uintptr_t)cqp_request;
        cqp_info->in.u.qp_destroy.remove_hash_idx = true;
        status = i40iw_handle_cqp_op(iwdev, cqp_request);
-       if (status)
-               i40iw_pr_err("CQP-OP Destroy QP fail");
+       if (!status)
+               return;
+
+       i40iw_rem_pdusecount(iwqp->iwpd, iwdev);
+       i40iw_free_qp_resources(iwdev, iwqp, qp_num);
+       i40iw_rem_devusecount(iwdev);
 }
 
 /**