This patch adds support for create_qp_flags
to uverbs.

Signed-off-by: Ron Livne <[EMAIL PROTECTED]>

diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index b3ea958..5871fd0 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -194,5 +194,6 @@ IB_UVERBS_DECLARE_CMD(create_srq);
 IB_UVERBS_DECLARE_CMD(modify_srq);
 IB_UVERBS_DECLARE_CMD(query_srq);
 IB_UVERBS_DECLARE_CMD(destroy_srq);
+IB_UVERBS_DECLARE_CMD(create_qp_flags);

 #endif /* UVERBS_H */
diff --git a/drivers/infiniband/core/uverbs_cmd.c 
b/drivers/infiniband/core/uverbs_cmd.c
index 56feab6..58128a8 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -1153,6 +1153,146 @@ err_put:
        return ret;
 }

+ssize_t ib_uverbs_create_qp_flags(struct ib_uverbs_file *file,
+                           const char __user *buf, int in_len,
+                           int out_len)
+{
+       struct ib_uverbs_create_qp_flags cmd;
+       struct ib_uverbs_create_qp_resp resp;
+       struct ib_udata                 udata;
+       struct ib_uqp_object           *obj;
+       struct ib_pd                   *pd;
+       struct ib_cq                   *scq, *rcq;
+       struct ib_srq                  *srq;
+       struct ib_qp                   *qp;
+       struct ib_qp_init_attr          attr;
+       int ret;
+
+       if (out_len < sizeof resp)
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       INIT_UDATA(&udata, buf + sizeof cmd,
+                  (unsigned long) cmd.response + sizeof resp,
+                  in_len - sizeof cmd, out_len - sizeof resp);
+
+       obj = kmalloc(sizeof *obj, GFP_KERNEL);
+       if (!obj)
+               return -ENOMEM;
+
+       init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, 
&qp_lock_key);
+       down_write(&obj->uevent.uobject.mutex);
+
+       srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL;
+       pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
+       scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
+       rcq = cmd.recv_cq_handle == cmd.send_cq_handle ?
+               scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
+
+       if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) {
+               ret = -EINVAL;
+               goto err_put;
+       }
+
+       attr.event_handler = ib_uverbs_qp_event_handler;
+       attr.qp_context    = file;
+       attr.send_cq       = scq;
+       attr.recv_cq       = rcq;
+       attr.srq           = srq;
+       attr.sq_sig_type   = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : 
IB_SIGNAL_REQ_WR;
+       attr.qp_type       = cmd.qp_type;
+       attr.create_flags  = cmd.create_flags;
+       attr.cap.max_send_wr     = cmd.max_send_wr;
+       attr.cap.max_recv_wr     = cmd.max_recv_wr;
+       attr.cap.max_send_sge    = cmd.max_send_sge;
+       attr.cap.max_recv_sge    = cmd.max_recv_sge;
+       attr.cap.max_inline_data = cmd.max_inline_data;
+
+       obj->uevent.events_reported     = 0;
+       INIT_LIST_HEAD(&obj->uevent.event_list);
+       INIT_LIST_HEAD(&obj->mcast_list);
+       qp = pd->device->create_qp(pd, &attr, &udata);
+
+       if (IS_ERR(qp)) {
+               ret = PTR_ERR(qp);
+               goto err_put;
+       }
+
+       qp->device        = pd->device;
+       qp->pd            = pd;
+       qp->send_cq       = attr.send_cq;
+       qp->recv_cq       = attr.recv_cq;
+       qp->srq           = attr.srq;
+       qp->uobject       = &obj->uevent.uobject;
+       qp->event_handler = attr.event_handler;
+       qp->qp_context    = attr.qp_context;
+       qp->qp_type       = attr.qp_type;
+       atomic_inc(&pd->usecnt);
+       atomic_inc(&attr.send_cq->usecnt);
+       atomic_inc(&attr.recv_cq->usecnt);
+       if (attr.srq)
+               atomic_inc(&attr.srq->usecnt);
+
+       obj->uevent.uobject.object = qp;
+       ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
+       if (ret)
+               goto err_destroy;
+
+       memset(&resp, 0, sizeof resp);
+       resp.qpn             = qp->qp_num;
+       resp.qp_handle       = obj->uevent.uobject.id;
+       resp.max_recv_sge    = attr.cap.max_recv_sge;
+       resp.max_send_sge    = attr.cap.max_send_sge;
+       resp.max_recv_wr     = attr.cap.max_recv_wr;
+       resp.max_send_wr     = attr.cap.max_send_wr;
+       resp.max_inline_data = attr.cap.max_inline_data;
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp)) {
+               ret = -EFAULT;
+               goto err_copy;
+       }
+
+       put_pd_read(pd);
+       put_cq_read(scq);
+       if (rcq != scq)
+               put_cq_read(rcq);
+       if (srq)
+               put_srq_read(srq);
+
+       mutex_lock(&file->mutex);
+       list_add_tail(&obj->uevent.uobject.list, &file->ucontext->qp_list);
+       mutex_unlock(&file->mutex);
+
+       obj->uevent.uobject.live = 1;
+
+       up_write(&obj->uevent.uobject.mutex);
+
+       return in_len;
+
+err_copy:
+       idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
+
+err_destroy:
+       ib_destroy_qp(qp);
+
+err_put:
+       if (pd)
+               put_pd_read(pd);
+       if (scq)
+               put_cq_read(scq);
+       if (rcq && rcq != scq)
+               put_cq_read(rcq);
+       if (srq)
+               put_srq_read(srq);
+
+       put_uobj_write(&obj->uevent.uobject);
+       return ret;
+}
+
+
 ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file,
                           const char __user *buf, int in_len,
                           int out_len)
diff --git a/drivers/infiniband/core/uverbs_main.c 
b/drivers/infiniband/core/uverbs_main.c
index eb36a81..e050df4 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -108,6 +108,7 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file 
*file,
        [IB_USER_VERBS_CMD_MODIFY_SRQ]          = ib_uverbs_modify_srq,
        [IB_USER_VERBS_CMD_QUERY_SRQ]           = ib_uverbs_query_srq,
        [IB_USER_VERBS_CMD_DESTROY_SRQ]         = ib_uverbs_destroy_srq,
+       [IB_USER_VERBS_CMD_CREATE_QP_FLAGS]     = ib_uverbs_create_qp_flags,
 };

 static struct vfsmount *uverbs_event_mnt;
diff --git a/drivers/infiniband/hw/mlx4/main.c 
b/drivers/infiniband/hw/mlx4/main.c
index 2e80f8f..78c161d 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -603,7 +603,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
                (1ull << IB_USER_VERBS_CMD_CREATE_SRQ)          |
                (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ)          |
                (1ull << IB_USER_VERBS_CMD_QUERY_SRQ)           |
-               (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
+               (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ)         |
+               (1ull << IB_USER_VERBS_CMD_CREATE_QP_FLAGS);

        ibdev->ib_dev.query_device      = mlx4_ib_query_device;
        ibdev->ib_dev.query_port        = mlx4_ib_query_port;
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 39167a7..09d79ea 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -505,9 +505,6 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct 
ib_pd *pd,
        } else {
                qp->sq_no_prefetch = 0;

-               if (init_attr->create_flags & 
IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK)
-                       qp->flags |= MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK;
-
                if (init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO)
                        qp->flags |= MLX4_IB_QP_LSO;

@@ -554,6 +551,10 @@ static int create_qp_common(struct mlx4_ib_dev *dev, 
struct ib_pd *pd,
                        goto err_wrid;
        }

+       if (init_attr->create_flags &
+               IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK)
+                       qp->flags |= MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK;
+
        err = mlx4_qp_alloc(dev->dev, qpn, &qp->mqp);
        if (err)
                goto err_qpn;
@@ -697,16 +698,17 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
        struct mlx4_ib_qp *qp;
        int err;

-       /*
-        * We only support LSO and multicast loopback blocking, and
-        * only for kernel UD QPs.
-        */
-       if (init_attr->create_flags & ~(IB_QP_CREATE_IPOIB_UD_LSO |
-                                       IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK))
+/**
+ * We support creation flags only for UD type QPs.
+ */
+       if (init_attr->create_flags && init_attr->qp_type != IB_QPT_UD)
                return ERR_PTR(-EINVAL);

-       if (init_attr->create_flags &&
-           (pd->uobject || init_attr->qp_type != IB_QPT_UD))
+/**
+ * We support LSO creation flag only for kernel QPs.
+ */
+       if ((init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO) &&
+                                                               pd->uobject)
                return ERR_PTR(-EINVAL);

        switch (init_attr->qp_type) {
diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h
index a17f771..ab2e646 100644
--- a/include/rdma/ib_user_verbs.h
+++ b/include/rdma/ib_user_verbs.h
@@ -81,7 +81,8 @@ enum {
        IB_USER_VERBS_CMD_MODIFY_SRQ,
        IB_USER_VERBS_CMD_QUERY_SRQ,
        IB_USER_VERBS_CMD_DESTROY_SRQ,
-       IB_USER_VERBS_CMD_POST_SRQ_RECV
+       IB_USER_VERBS_CMD_POST_SRQ_RECV,
+       IB_USER_VERBS_CMD_CREATE_QP_FLAGS,
 };

 /*
@@ -403,6 +404,27 @@ struct ib_uverbs_create_qp {
        __u64 driver_data[0];
 };

+struct ib_uverbs_create_qp_flags {
+       __u64 response;
+       __u64 user_handle;
+       __u32 pd_handle;
+       __u32 send_cq_handle;
+       __u32 recv_cq_handle;
+       __u32 srq_handle;
+       __u32 max_send_wr;
+       __u32 max_recv_wr;
+       __u32 max_send_sge;
+       __u32 max_recv_sge;
+       __u32 max_inline_data;
+       __u8  sq_sig_all;
+       __u8  qp_type;
+       __u8  is_srq;
+       __u8  reserved;
+       __u32 reserved1;
+       __u32 create_flags;
+       __u64 driver_data[0];
+};
+
 struct ib_uverbs_create_qp_resp {
        __u32 qp_handle;
        __u32 qpn;
_______________________________________________
general mailing list
[email protected]
http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to