iw_cxgb4: add queue drain functions
authorSteve Wise <swise@opengridcomputing.com>
Wed, 17 Feb 2016 16:15:42 +0000 (08:15 -0800)
committerDoug Ledford <dledford@redhat.com>
Mon, 29 Feb 2016 22:10:27 +0000 (17:10 -0500)
Add completion objects, named sq_drained and rq_drained, to the c4iw_qp
struct.  The queue-specific completion object is signaled when the last
CQE is drained from the CQ for that queue.

Add c4iw_drain_sq() to block until qp->rq_drained is completed.

Add c4iw_drain_rq() to block until qp->sq_drained is completed.

Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/cxgb4/cq.c
drivers/infiniband/hw/cxgb4/iw_cxgb4.h
drivers/infiniband/hw/cxgb4/provider.c
drivers/infiniband/hw/cxgb4/qp.c

index cf21df4a8bf5b80da00f6f82003980650df9c522..b4eeb783573c88e50904ff20668fdcd10ee86e4c 100644 (file)
@@ -815,8 +815,15 @@ static int c4iw_poll_cq_one(struct c4iw_cq *chp, struct ib_wc *wc)
                }
        }
 out:
-       if (wq)
+       if (wq) {
+               if (unlikely(qhp->attr.state != C4IW_QP_STATE_RTS)) {
+                       if (t4_sq_empty(wq))
+                               complete(&qhp->sq_drained);
+                       if (t4_rq_empty(wq))
+                               complete(&qhp->rq_drained);
+               }
                spin_unlock(&qhp->lock);
+       }
        return ret;
 }
 
index fb2de75a039216e2f732a8f61ba387de121f1ce7..7c6a6e1a2c1db2c9f850357fb4d66b3436d0fa13 100644 (file)
@@ -476,6 +476,8 @@ struct c4iw_qp {
        wait_queue_head_t wait;
        struct timer_list timer;
        int sq_sig_all;
+       struct completion rq_drained;
+       struct completion sq_drained;
 };
 
 static inline struct c4iw_qp *to_c4iw_qp(struct ib_qp *ibqp)
@@ -1016,6 +1018,8 @@ extern int c4iw_wr_log;
 extern int db_fc_threshold;
 extern int db_coalescing_threshold;
 extern int use_dsgl;
+void c4iw_drain_rq(struct ib_qp *qp);
+void c4iw_drain_sq(struct ib_qp *qp);
 
 
 #endif
index ec04272fbdc2ffbf882318678332a506c1f1d4ec..104662d38d1eee05493505448125be78f41ea258 100644 (file)
@@ -564,6 +564,8 @@ int c4iw_register_device(struct c4iw_dev *dev)
        dev->ibdev.get_protocol_stats = c4iw_get_mib;
        dev->ibdev.uverbs_abi_ver = C4IW_UVERBS_ABI_VERSION;
        dev->ibdev.get_port_immutable = c4iw_port_immutable;
+       dev->ibdev.drain_sq = c4iw_drain_sq;
+       dev->ibdev.drain_rq = c4iw_drain_rq;
 
        dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL);
        if (!dev->ibdev.iwcm)
index e99345eb875aa286a8b962696eba9742189e660c..7b1b1e840ef1a86fe488231252253bb015202c90 100644 (file)
@@ -1697,6 +1697,8 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
        qhp->attr.max_ird = 0;
        qhp->sq_sig_all = attrs->sq_sig_type == IB_SIGNAL_ALL_WR;
        spin_lock_init(&qhp->lock);
+       init_completion(&qhp->sq_drained);
+       init_completion(&qhp->rq_drained);
        mutex_init(&qhp->mutex);
        init_waitqueue_head(&qhp->wait);
        atomic_set(&qhp->refcnt, 1);
@@ -1888,3 +1890,17 @@ int c4iw_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
        init_attr->sq_sig_type = qhp->sq_sig_all ? IB_SIGNAL_ALL_WR : 0;
        return 0;
 }
+
+void c4iw_drain_sq(struct ib_qp *ibqp)
+{
+       struct c4iw_qp *qp = to_c4iw_qp(ibqp);
+
+       wait_for_completion(&qp->sq_drained);
+}
+
+void c4iw_drain_rq(struct ib_qp *ibqp)
+{
+       struct c4iw_qp *qp = to_c4iw_qp(ibqp);
+
+       wait_for_completion(&qp->rq_drained);
+}