IB/core: Extend create QP to get indirection table
authorYishai Hadas <yishaih@mellanox.com>
Mon, 23 May 2016 12:20:54 +0000 (15:20 +0300)
committerDoug Ledford <dledford@redhat.com>
Thu, 23 Jun 2016 15:02:44 +0000 (11:02 -0400)
Extend create QP to get Receive Work Queue (WQ) indirection table.

QP can be created with external Receive Work Queue indirection table,
in that case it is ready to receive immediately.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Matan Barak <matanb@mellanox.com>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/core/verbs.c
include/rdma/ib_verbs.h

index 6b548d7f875338538d8ec12a37459992fecd7ad9..6916d5c5920b7e4b9d0575a150f9b36163319c60 100644 (file)
@@ -754,6 +754,12 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
        struct ib_qp *qp;
        int ret;
 
+       if (qp_init_attr->rwq_ind_tbl &&
+           (qp_init_attr->recv_cq ||
+           qp_init_attr->srq || qp_init_attr->cap.max_recv_wr ||
+           qp_init_attr->cap.max_recv_sge))
+               return ERR_PTR(-EINVAL);
+
        /*
         * If the callers is using the RDMA API calculate the resources
         * needed for the RDMA READ/WRITE operations.
@@ -771,6 +777,7 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
        qp->real_qp    = qp;
        qp->uobject    = NULL;
        qp->qp_type    = qp_init_attr->qp_type;
+       qp->rwq_ind_tbl = qp_init_attr->rwq_ind_tbl;
 
        atomic_set(&qp->usecnt, 0);
        qp->mrs_used = 0;
@@ -788,7 +795,8 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
                qp->srq = NULL;
        } else {
                qp->recv_cq = qp_init_attr->recv_cq;
-               atomic_inc(&qp_init_attr->recv_cq->usecnt);
+               if (qp_init_attr->recv_cq)
+                       atomic_inc(&qp_init_attr->recv_cq->usecnt);
                qp->srq = qp_init_attr->srq;
                if (qp->srq)
                        atomic_inc(&qp_init_attr->srq->usecnt);
@@ -799,7 +807,10 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
        qp->xrcd    = NULL;
 
        atomic_inc(&pd->usecnt);
-       atomic_inc(&qp_init_attr->send_cq->usecnt);
+       if (qp_init_attr->send_cq)
+               atomic_inc(&qp_init_attr->send_cq->usecnt);
+       if (qp_init_attr->rwq_ind_tbl)
+               atomic_inc(&qp->rwq_ind_tbl->usecnt);
 
        if (qp_init_attr->cap.max_rdma_ctxs) {
                ret = rdma_rw_init_mrs(qp, qp_init_attr);
@@ -1279,6 +1290,7 @@ int ib_destroy_qp(struct ib_qp *qp)
        struct ib_pd *pd;
        struct ib_cq *scq, *rcq;
        struct ib_srq *srq;
+       struct ib_rwq_ind_table *ind_tbl;
        int ret;
 
        WARN_ON_ONCE(qp->mrs_used > 0);
@@ -1293,6 +1305,7 @@ int ib_destroy_qp(struct ib_qp *qp)
        scq  = qp->send_cq;
        rcq  = qp->recv_cq;
        srq  = qp->srq;
+       ind_tbl = qp->rwq_ind_tbl;
 
        if (!qp->uobject)
                rdma_rw_cleanup_mrs(qp);
@@ -1307,6 +1320,8 @@ int ib_destroy_qp(struct ib_qp *qp)
                        atomic_dec(&rcq->usecnt);
                if (srq)
                        atomic_dec(&srq->usecnt);
+               if (ind_tbl)
+                       atomic_dec(&ind_tbl->usecnt);
        }
 
        return ret;
index e305c9a36663a0b0c6fc554165b65bfc4ed6f8e8..9b2fafe5eb382dcdfb1861dc023fa393867d291d 100644 (file)
@@ -1017,6 +1017,7 @@ struct ib_qp_init_attr {
         * Only needed for special QP types, or when using the RW API.
         */
        u8                      port_num;
+       struct ib_rwq_ind_table *rwq_ind_tbl;
 };
 
 struct ib_qp_open_attr {
@@ -1511,6 +1512,7 @@ struct ib_qp {
        void                   *qp_context;
        u32                     qp_num;
        enum ib_qp_type         qp_type;
+       struct ib_rwq_ind_table *rwq_ind_tbl;
 };
 
 struct ib_mr {