RDMA/i40iw: Adding queue drain functions
authorIsmail, Mustafa <mustafa.ismail@intel.com>
Mon, 18 Apr 2016 15:33:09 +0000 (10:33 -0500)
committerDoug Ledford <dledford@redhat.com>
Thu, 28 Apr 2016 20:32:54 +0000 (16:32 -0400)
Adding sq and rq drain functions, which block until all
previously posted wr-s in the specified queue have completed.
A completion object is signaled to unblock the thread,
when the last cqe for the corresponding queue is processed.

Signed-off-by: Mustafa Ismail <mustafa.ismail@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 196d6f006392df1ec4470994c472e32f0a23b31f..bf4e1e39dedf2eb47fa49bbb2bb50510bbd1e250 100644 (file)
@@ -789,6 +789,8 @@ static struct ib_qp *i40iw_create_qp(struct ib_pd *ibpd,
                        return ERR_PTR(err_code);
                }
        }
+       init_completion(&iwqp->sq_drained);
+       init_completion(&iwqp->rq_drained);
 
        return &iwqp->ibqp;
 error:
@@ -1581,6 +1583,32 @@ static int i40iw_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_ne
        return ib_sg_to_pages(ibmr, sg, sg_nents, i40iw_set_page);
 }
 
+/**
+ * i40iw_drain_sq - drain the send queue
+ * @ibqp: ib qp pointer
+ */
+static void i40iw_drain_sq(struct ib_qp *ibqp)
+{
+       struct i40iw_qp *iwqp = to_iwqp(ibqp);
+       struct i40iw_sc_qp *qp = &iwqp->sc_qp;
+
+       if (I40IW_RING_MORE_WORK(qp->qp_uk.sq_ring))
+               wait_for_completion(&iwqp->sq_drained);
+}
+
+/**
+ * i40iw_drain_rq - drain the receive queue
+ * @ibqp: ib qp pointer
+ */
+static void i40iw_drain_rq(struct ib_qp *ibqp)
+{
+       struct i40iw_qp *iwqp = to_iwqp(ibqp);
+       struct i40iw_sc_qp *qp = &iwqp->sc_qp;
+
+       if (I40IW_RING_MORE_WORK(qp->qp_uk.rq_ring))
+               wait_for_completion(&iwqp->rq_drained);
+}
+
 /**
  * i40iw_hwreg_mr - send cqp command for memory registration
  * @iwdev: iwarp device
@@ -2218,6 +2246,7 @@ static int i40iw_poll_cq(struct ib_cq *ibcq,
        enum i40iw_status_code ret;
        struct i40iw_cq_uk *ukcq;
        struct i40iw_sc_qp *qp;
+       struct i40iw_qp *iwqp;
        unsigned long flags;
 
        iwcq = (struct i40iw_cq *)ibcq;
@@ -2268,6 +2297,13 @@ static int i40iw_poll_cq(struct ib_cq *ibcq,
                qp = (struct i40iw_sc_qp *)cq_poll_info.qp_handle;
                entry->qp = (struct ib_qp *)qp->back_qp;
                entry->src_qp = cq_poll_info.qp_id;
+               iwqp = (struct i40iw_qp *)qp->back_qp;
+               if (iwqp->iwarp_state > I40IW_QP_STATE_RTS) {
+                       if (!I40IW_RING_MORE_WORK(qp->qp_uk.sq_ring))
+                               complete(&iwqp->sq_drained);
+                       if (!I40IW_RING_MORE_WORK(qp->qp_uk.rq_ring))
+                               complete(&iwqp->rq_drained);
+               }
                entry->byte_len = cq_poll_info.bytes_xfered;
                entry++;
                cqe_count++;
@@ -2514,6 +2550,8 @@ static struct i40iw_ib_device *i40iw_init_rdma_device(struct i40iw_device *iwdev
        iwibdev->ibdev.query_device = i40iw_query_device;
        iwibdev->ibdev.create_ah = i40iw_create_ah;
        iwibdev->ibdev.destroy_ah = i40iw_destroy_ah;
+       iwibdev->ibdev.drain_sq = i40iw_drain_sq;
+       iwibdev->ibdev.drain_rq = i40iw_drain_rq;
        iwibdev->ibdev.alloc_mr = i40iw_alloc_mr;
        iwibdev->ibdev.map_mr_sg = i40iw_map_mr_sg;
        iwibdev->ibdev.iwcm = kzalloc(sizeof(*iwibdev->ibdev.iwcm), GFP_KERNEL);
index 0acb6c8fe0f00fe83a9aafb82e9408d450fb0ac7..0069be8a5a38b77ded23699d9adf6e979435ffa6 100644 (file)
@@ -170,5 +170,7 @@ struct i40iw_qp {
        struct i40iw_pbl *iwpbl;
        struct i40iw_dma_mem q2_ctx_mem;
        struct i40iw_dma_mem ietf_mem;
+       struct completion sq_drained;
+       struct completion rq_drained;
 };
 #endif