IB/uverbs: Introduce create/destroy SRQ commands over ioctl
authorYishai Hadas <yishaih@mellanox.com>
Tue, 19 May 2020 07:27:09 +0000 (10:27 +0300)
committerJason Gunthorpe <jgg@mellanox.com>
Thu, 21 May 2020 23:39:35 +0000 (20:39 -0300)
Introduce create/destroy SRQ commands over the ioctl interface to let it
be extended to get an asynchronous event FD.

Link: https://lore.kernel.org/r/20200519072711.257271-6-leon@kernel.org
Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/infiniband/core/Makefile
drivers/infiniband/core/rdma_core.h
drivers/infiniband/core/uverbs_std_types.c
drivers/infiniband/core/uverbs_std_types_srq.c [new file with mode: 0644]
drivers/infiniband/core/uverbs_uapi.c
include/uapi/rdma/ib_user_ioctl_cmds.h

index 870f0fc..d7b46a7 100644 (file)
@@ -36,6 +36,7 @@ ib_uverbs-y :=                        uverbs_main.o uverbs_cmd.o uverbs_marshall.o \
                                uverbs_std_types_flow_action.o uverbs_std_types_dm.o \
                                uverbs_std_types_mr.o uverbs_std_types_counters.o \
                                uverbs_uapi.o uverbs_std_types_device.o \
-                               uverbs_std_types_async_fd.o
+                               uverbs_std_types_async_fd.o \
+                               uverbs_std_types_srq.o
 ib_uverbs-$(CONFIG_INFINIBAND_USER_MEM) += umem.o
 ib_uverbs-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += umem_odp.o
index 2b52923..d623f91 100644 (file)
@@ -159,6 +159,7 @@ extern const struct uapi_definition uverbs_def_obj_dm[];
 extern const struct uapi_definition uverbs_def_obj_flow_action[];
 extern const struct uapi_definition uverbs_def_obj_intf[];
 extern const struct uapi_definition uverbs_def_obj_mr[];
+extern const struct uapi_definition uverbs_def_obj_srq[];
 extern const struct uapi_definition uverbs_def_write_intf[];
 
 static inline const struct uverbs_api_write_method *
index 3abfc63..d9b6912 100644 (file)
@@ -142,31 +142,6 @@ static int uverbs_free_wq(struct ib_uobject *uobject,
        return ret;
 }
 
-static int uverbs_free_srq(struct ib_uobject *uobject,
-                          enum rdma_remove_reason why,
-                          struct uverbs_attr_bundle *attrs)
-{
-       struct ib_srq *srq = uobject->object;
-       struct ib_uevent_object *uevent =
-               container_of(uobject, struct ib_uevent_object, uobject);
-       enum ib_srq_type  srq_type = srq->srq_type;
-       int ret;
-
-       ret = ib_destroy_srq_user(srq, &attrs->driver_udata);
-       if (ib_is_destroy_retryable(ret, why, uobject))
-               return ret;
-
-       if (srq_type == IB_SRQT_XRC) {
-               struct ib_usrq_object *us =
-                       container_of(uevent, struct ib_usrq_object, uevent);
-
-               atomic_dec(&us->uxrcd->refcnt);
-       }
-
-       ib_uverbs_release_uevent(uevent);
-       return ret;
-}
-
 static int uverbs_free_xrcd(struct ib_uobject *uobject,
                            enum rdma_remove_reason why,
                            struct uverbs_attr_bundle *attrs)
@@ -267,11 +242,6 @@ DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_MW,
                            UVERBS_TYPE_ALLOC_IDR(uverbs_free_mw),
                            &UVERBS_METHOD(UVERBS_METHOD_MW_DESTROY));
 
-DECLARE_UVERBS_NAMED_OBJECT(
-       UVERBS_OBJECT_SRQ,
-       UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_usrq_object),
-                                uverbs_free_srq));
-
 DECLARE_UVERBS_NAMED_METHOD_DESTROY(
        UVERBS_METHOD_AH_DESTROY,
        UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_AH_HANDLE,
@@ -346,8 +316,6 @@ const struct uapi_definition uverbs_def_obj_intf[] = {
                                      UAPI_DEF_OBJ_NEEDS_FN(destroy_ah)),
        UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_MW,
                                      UAPI_DEF_OBJ_NEEDS_FN(dealloc_mw)),
-       UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_SRQ,
-                                     UAPI_DEF_OBJ_NEEDS_FN(destroy_srq)),
        UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_FLOW,
                                      UAPI_DEF_OBJ_NEEDS_FN(destroy_flow)),
        UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_WQ,
diff --git a/drivers/infiniband/core/uverbs_std_types_srq.c b/drivers/infiniband/core/uverbs_std_types_srq.c
new file mode 100644 (file)
index 0000000..c0ecbba
--- /dev/null
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/*
+ * Copyright (c) 2020, Mellanox Technologies inc.  All rights reserved.
+ */
+
+#include <rdma/uverbs_std_types.h>
+#include "rdma_core.h"
+#include "uverbs.h"
+
+static int uverbs_free_srq(struct ib_uobject *uobject,
+                   enum rdma_remove_reason why,
+                   struct uverbs_attr_bundle *attrs)
+{
+       struct ib_srq *srq = uobject->object;
+       struct ib_uevent_object *uevent =
+               container_of(uobject, struct ib_uevent_object, uobject);
+       enum ib_srq_type srq_type = srq->srq_type;
+       int ret;
+
+       ret = ib_destroy_srq_user(srq, &attrs->driver_udata);
+       if (ib_is_destroy_retryable(ret, why, uobject))
+               return ret;
+
+       if (srq_type == IB_SRQT_XRC) {
+               struct ib_usrq_object *us =
+                       container_of(uobject, struct ib_usrq_object,
+                                    uevent.uobject);
+
+               atomic_dec(&us->uxrcd->refcnt);
+       }
+
+       ib_uverbs_release_uevent(uevent);
+       return ret;
+}
+
+static int UVERBS_HANDLER(UVERBS_METHOD_SRQ_CREATE)(
+       struct uverbs_attr_bundle *attrs)
+{
+       struct ib_usrq_object *obj = container_of(
+               uverbs_attr_get_uobject(attrs, UVERBS_ATTR_CREATE_SRQ_HANDLE),
+               typeof(*obj), uevent.uobject);
+       struct ib_pd *pd =
+               uverbs_attr_get_obj(attrs, UVERBS_ATTR_CREATE_SRQ_PD_HANDLE);
+       struct ib_srq_init_attr attr = {};
+       struct ib_uobject *xrcd_uobj;
+       struct ib_srq *srq;
+       u64 user_handle;
+       int ret;
+
+       ret = uverbs_copy_from(&attr.attr.max_sge, attrs,
+                              UVERBS_ATTR_CREATE_SRQ_MAX_SGE);
+       if (!ret)
+               ret = uverbs_copy_from(&attr.attr.max_wr, attrs,
+                                      UVERBS_ATTR_CREATE_SRQ_MAX_WR);
+       if (!ret)
+               ret = uverbs_copy_from(&attr.attr.srq_limit, attrs,
+                                      UVERBS_ATTR_CREATE_SRQ_LIMIT);
+       if (!ret)
+               ret = uverbs_copy_from(&user_handle, attrs,
+                                      UVERBS_ATTR_CREATE_SRQ_USER_HANDLE);
+       if (!ret)
+               ret = uverbs_get_const(&attr.srq_type, attrs,
+                                      UVERBS_ATTR_CREATE_SRQ_TYPE);
+       if (ret)
+               return ret;
+
+       if (ib_srq_has_cq(attr.srq_type)) {
+               attr.ext.cq = uverbs_attr_get_obj(attrs,
+                                       UVERBS_ATTR_CREATE_SRQ_CQ_HANDLE);
+               if (IS_ERR(attr.ext.cq))
+                       return PTR_ERR(attr.ext.cq);
+       }
+
+       switch (attr.srq_type) {
+       case IB_UVERBS_SRQT_XRC:
+               xrcd_uobj = uverbs_attr_get_uobject(attrs,
+                                       UVERBS_ATTR_CREATE_SRQ_XRCD_HANDLE);
+               if (IS_ERR(xrcd_uobj))
+                       return PTR_ERR(xrcd_uobj);
+
+               attr.ext.xrc.xrcd = (struct ib_xrcd *)xrcd_uobj->object;
+               if (!attr.ext.xrc.xrcd)
+                       return -EINVAL;
+               obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object,
+                                         uobject);
+               atomic_inc(&obj->uxrcd->refcnt);
+               break;
+       case IB_UVERBS_SRQT_TM:
+               ret = uverbs_copy_from(&attr.ext.tag_matching.max_num_tags,
+                                      attrs,
+                                      UVERBS_ATTR_CREATE_SRQ_MAX_NUM_TAGS);
+               if (ret)
+                       return ret;
+               break;
+       case IB_UVERBS_SRQT_BASIC:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       obj->uevent.event_file = ib_uverbs_get_async_event(attrs,
+                                       UVERBS_ATTR_CREATE_SRQ_EVENT_FD);
+       INIT_LIST_HEAD(&obj->uevent.event_list);
+       attr.event_handler = ib_uverbs_srq_event_handler;
+       obj->uevent.uobject.user_handle = user_handle;
+
+       srq = ib_create_srq_user(pd, &attr, obj, &attrs->driver_udata);
+       if (IS_ERR(srq)) {
+               ret = PTR_ERR(srq);
+               goto err;
+       }
+
+       obj->uevent.uobject.object = srq;
+       uverbs_finalize_uobj_create(attrs, UVERBS_ATTR_CREATE_SRQ_HANDLE);
+
+       ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_SRQ_RESP_MAX_WR,
+                            &attr.attr.max_wr,
+                            sizeof(attr.attr.max_wr));
+       if (ret)
+               return ret;
+
+       ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_SRQ_RESP_MAX_SGE,
+                            &attr.attr.max_sge,
+                            sizeof(attr.attr.max_sge));
+       if (ret)
+               return ret;
+
+       if (attr.srq_type == IB_SRQT_XRC) {
+               ret = uverbs_copy_to(attrs,
+                                    UVERBS_ATTR_CREATE_SRQ_RESP_SRQ_NUM,
+                                    &srq->ext.xrc.srq_num,
+                                    sizeof(srq->ext.xrc.srq_num));
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+err:
+       if (obj->uevent.event_file)
+               uverbs_uobject_put(&obj->uevent.event_file->uobj);
+       if (attr.srq_type == IB_SRQT_XRC)
+               atomic_dec(&obj->uxrcd->refcnt);
+       return ret;
+};
+
+DECLARE_UVERBS_NAMED_METHOD(
+       UVERBS_METHOD_SRQ_CREATE,
+       UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_SRQ_HANDLE,
+                       UVERBS_OBJECT_SRQ,
+                       UVERBS_ACCESS_NEW,
+                       UA_MANDATORY),
+       UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_SRQ_PD_HANDLE,
+                       UVERBS_OBJECT_PD,
+                       UVERBS_ACCESS_READ,
+                       UA_MANDATORY),
+       UVERBS_ATTR_CONST_IN(UVERBS_ATTR_CREATE_SRQ_TYPE,
+                            enum ib_uverbs_srq_type,
+                            UA_MANDATORY),
+       UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_USER_HANDLE,
+                          UVERBS_ATTR_TYPE(u64),
+                          UA_MANDATORY),
+       UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_MAX_WR,
+                          UVERBS_ATTR_TYPE(u32),
+                          UA_MANDATORY),
+       UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_MAX_SGE,
+                          UVERBS_ATTR_TYPE(u32),
+                          UA_MANDATORY),
+       UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_LIMIT,
+                          UVERBS_ATTR_TYPE(u32),
+                          UA_MANDATORY),
+       UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_SRQ_XRCD_HANDLE,
+                       UVERBS_OBJECT_XRCD,
+                       UVERBS_ACCESS_READ,
+                       UA_OPTIONAL),
+       UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_SRQ_CQ_HANDLE,
+                       UVERBS_OBJECT_CQ,
+                       UVERBS_ACCESS_READ,
+                       UA_OPTIONAL),
+       UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_MAX_NUM_TAGS,
+                          UVERBS_ATTR_TYPE(u32),
+                          UA_OPTIONAL),
+       UVERBS_ATTR_FD(UVERBS_ATTR_CREATE_SRQ_EVENT_FD,
+                      UVERBS_OBJECT_ASYNC_EVENT,
+                      UVERBS_ACCESS_READ,
+                      UA_OPTIONAL),
+       UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_SRQ_RESP_MAX_WR,
+                           UVERBS_ATTR_TYPE(u32),
+                           UA_MANDATORY),
+       UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_SRQ_RESP_MAX_SGE,
+                           UVERBS_ATTR_TYPE(u32),
+                           UA_MANDATORY),
+       UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_SRQ_RESP_SRQ_NUM,
+                          UVERBS_ATTR_TYPE(u32),
+                          UA_OPTIONAL),
+       UVERBS_ATTR_UHW());
+
+static int UVERBS_HANDLER(UVERBS_METHOD_SRQ_DESTROY)(
+       struct uverbs_attr_bundle *attrs)
+{
+       struct ib_uobject *uobj =
+               uverbs_attr_get_uobject(attrs, UVERBS_ATTR_DESTROY_SRQ_HANDLE);
+       struct ib_usrq_object *obj =
+               container_of(uobj, struct ib_usrq_object, uevent.uobject);
+       struct ib_uverbs_destroy_srq_resp resp = {
+               .events_reported = obj->uevent.events_reported
+       };
+
+       return uverbs_copy_to(attrs, UVERBS_ATTR_DESTROY_SRQ_RESP, &resp,
+                             sizeof(resp));
+}
+
+DECLARE_UVERBS_NAMED_METHOD(
+       UVERBS_METHOD_SRQ_DESTROY,
+       UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_SRQ_HANDLE,
+                       UVERBS_OBJECT_SRQ,
+                       UVERBS_ACCESS_DESTROY,
+                       UA_MANDATORY),
+       UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_DESTROY_SRQ_RESP,
+                           UVERBS_ATTR_TYPE(struct ib_uverbs_destroy_srq_resp),
+                           UA_MANDATORY));
+
+DECLARE_UVERBS_NAMED_OBJECT(
+       UVERBS_OBJECT_SRQ,
+       UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_usrq_object),
+                                uverbs_free_srq),
+       &UVERBS_METHOD(UVERBS_METHOD_SRQ_CREATE),
+       &UVERBS_METHOD(UVERBS_METHOD_SRQ_DESTROY)
+);
+
+const struct uapi_definition uverbs_def_obj_srq[] = {
+       UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_SRQ,
+                                     UAPI_DEF_OBJ_NEEDS_FN(destroy_srq)),
+       {}
+};
index 3f121ac..3f56279 100644 (file)
@@ -634,6 +634,7 @@ static const struct uapi_definition uverbs_core_api[] = {
        UAPI_DEF_CHAIN(uverbs_def_obj_flow_action),
        UAPI_DEF_CHAIN(uverbs_def_obj_intf),
        UAPI_DEF_CHAIN(uverbs_def_obj_mr),
+       UAPI_DEF_CHAIN(uverbs_def_obj_srq),
        UAPI_DEF_CHAIN(uverbs_def_write_intf),
        {},
 };
index 286fdc1..c07af46 100644 (file)
@@ -121,6 +121,33 @@ enum uverbs_attrs_destroy_flow_action_esp {
        UVERBS_ATTR_DESTROY_FLOW_ACTION_HANDLE,
 };
 
+enum uverbs_attrs_create_srq_cmd_attr_ids {
+       UVERBS_ATTR_CREATE_SRQ_HANDLE,
+       UVERBS_ATTR_CREATE_SRQ_PD_HANDLE,
+       UVERBS_ATTR_CREATE_SRQ_XRCD_HANDLE,
+       UVERBS_ATTR_CREATE_SRQ_CQ_HANDLE,
+       UVERBS_ATTR_CREATE_SRQ_USER_HANDLE,
+       UVERBS_ATTR_CREATE_SRQ_MAX_WR,
+       UVERBS_ATTR_CREATE_SRQ_MAX_SGE,
+       UVERBS_ATTR_CREATE_SRQ_LIMIT,
+       UVERBS_ATTR_CREATE_SRQ_MAX_NUM_TAGS,
+       UVERBS_ATTR_CREATE_SRQ_TYPE,
+       UVERBS_ATTR_CREATE_SRQ_EVENT_FD,
+       UVERBS_ATTR_CREATE_SRQ_RESP_MAX_WR,
+       UVERBS_ATTR_CREATE_SRQ_RESP_MAX_SGE,
+       UVERBS_ATTR_CREATE_SRQ_RESP_SRQ_NUM,
+};
+
+enum uverbs_attrs_destroy_srq_cmd_attr_ids {
+       UVERBS_ATTR_DESTROY_SRQ_HANDLE,
+       UVERBS_ATTR_DESTROY_SRQ_RESP,
+};
+
+enum uverbs_methods_srq {
+       UVERBS_METHOD_SRQ_CREATE,
+       UVERBS_METHOD_SRQ_DESTROY,
+};
+
 enum uverbs_methods_cq {
        UVERBS_METHOD_CQ_CREATE,
        UVERBS_METHOD_CQ_DESTROY,