diff mbox

[RDMA,16/16] i40iw: Adding queue drain functions

Message ID 1460046664-552-17-git-send-email-mustafa.ismail@intel.com (mailing list archive)
State Superseded
Headers show

Commit Message

Ismail, Mustafa April 7, 2016, 4:31 p.m. UTC
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>
---
 drivers/infiniband/hw/i40iw/i40iw_verbs.c | 38 +++++++++++++++++++++++++++++++
 drivers/infiniband/hw/i40iw/i40iw_verbs.h |  2 ++
 2 files changed, 40 insertions(+)

Comments

Leon Romanovsky April 8, 2016, 12:46 a.m. UTC | #1
On Thu, Apr 07, 2016 at 11:31:04AM -0500, Mustafa Ismail wrote:
> 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>

I want to bring back last conversation about need special function to
drain QPs for iWARP devices.
Come on guys, it is already third place there is the same implementation
is introduced in last 2 months.
Ismail, Mustafa April 8, 2016, 6:44 p.m. UTC | #2
On Thu, Apr 07, 2016 at 05:46:38PM -0700, Leon Romanovsky wrote:
> On Thu, Apr 07, 2016 at 11:31:04AM -0500, Mustafa Ismail wrote:
> > 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>
> 
> I want to bring back last conversation about need special function to
> drain QPs for iWARP devices.
> Come on guys, it is already third place there is the same implementation
> is introduced in last 2 months.

In order to move this into core, the core would need to determine if the
sq and rq are empty. To do this it will need the driver's internal sq and
rq information such as head and tail. Then if not empty it will need
more information about the qp's cq processing. All this is device specific.

It is just a few lines of code in each driver to check if its hw sq and rq
are empty and if not, handle it from its cq processing.

For this reason, it seems best left to each iWARP driver to handle.

Thanks,

Mustafa
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Steve Wise April 8, 2016, 10:15 p.m. UTC | #3
> On Thu, Apr 07, 2016 at 05:46:38PM -0700, Leon Romanovsky wrote:
> > On Thu, Apr 07, 2016 at 11:31:04AM -0500, Mustafa Ismail wrote:
> > > 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>
> >
> > I want to bring back last conversation about need special function to
> > drain QPs for iWARP devices.
> > Come on guys, it is already third place there is the same implementation
> > is introduced in last 2 months.
> 
> In order to move this into core, the core would need to determine if the
> sq and rq are empty. To do this it will need the driver's internal sq and
> rq information such as head and tail. Then if not empty it will need
> more information about the qp's cq processing. All this is device specific.
> 
> It is just a few lines of code in each driver to check if its hw sq and rq
> are empty and if not, handle it from its cq processing.
> 
> For this reason, it seems best left to each iWARP driver to handle.
> 
> Thanks,

I agree.  My cxgb4 drain functions need to check if the sq/rq are empty as well.
And for cxgb4, that will require holding the qp spinlock.  (I need to post this
patch soon).

So while they are all very similar, the guts for looking at the sq/rq are
device-specific.

Steve.
 

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sagi Grimberg April 10, 2016, 7:26 p.m. UTC | #4
>>> I want to bring back last conversation about need special function to
>>> drain QPs for iWARP devices.
>>> Come on guys, it is already third place there is the same implementation
>>> is introduced in last 2 months.
>>
>> In order to move this into core, the core would need to determine if the
>> sq and rq are empty. To do this it will need the driver's internal sq and
>> rq information such as head and tail. Then if not empty it will need
>> more information about the qp's cq processing. All this is device specific.
>>
>> It is just a few lines of code in each driver to check if its hw sq and rq
>> are empty and if not, handle it from its cq processing.
>>
>> For this reason, it seems best left to each iWARP driver to handle.
>>
>> Thanks,
>
> I agree.  My cxgb4 drain functions need to check if the sq/rq are empty as well.
> And for cxgb4, that will require holding the qp spinlock.  (I need to post this
> patch soon).
>
> So while they are all very similar, the guts for looking at the sq/rq are
> device-specific.

I actually agree here too.

The iWARP folks needs some driver specific logic to get the QP drained
correctly so I'm all for them having the freedom to do whats best
for them.

I do understand Leon when he sees 3 copies of this code, but all these
copies are looking into the raw queue so I'm fine with it.

Cheers,
Sagi.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Leon Romanovsky April 11, 2016, 4:50 a.m. UTC | #5
On Sun, Apr 10, 2016 at 10:26:08PM +0300, Sagi Grimberg wrote:
> I do understand Leon when he sees 3 copies of this code, but all these
> copies are looking into the raw queue so I'm fine with it.

Despite the fact that I understand the reasoning behind this specific
implementation, it makes me wonder when will we see common implementation
for this type of queues?

We saw 3 similar implementations, in near future, we will get another
one and I believe that it won't stop there.
diff mbox

Patch

diff --git a/drivers/infiniband/hw/i40iw/i40iw_verbs.c b/drivers/infiniband/hw/i40iw/i40iw_verbs.c
index 9da5361..fc0bace 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_verbs.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_verbs.c
@@ -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:
@@ -1582,6 +1584,32 @@  static int i40iw_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_ne
 }
 
 /**
+ * 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
  * @iwmr: iwarp mr pointer
@@ -2216,6 +2244,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;
@@ -2266,6 +2295,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++;
@@ -2512,6 +2548,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);
diff --git a/drivers/infiniband/hw/i40iw/i40iw_verbs.h b/drivers/infiniband/hw/i40iw/i40iw_verbs.h
index 0acb6c8..0069be8 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_verbs.h
+++ b/drivers/infiniband/hw/i40iw/i40iw_verbs.h
@@ -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