]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
RDMA/uverbs: Implement an ioctl that can call write and write_ex handlers
authorJason Gunthorpe <jgg@mellanox.com>
Fri, 30 Nov 2018 11:06:21 +0000 (13:06 +0200)
committerDoug Ledford <dledford@redhat.com>
Tue, 18 Dec 2018 19:12:48 +0000 (14:12 -0500)
Now that the handlers do not process their own udata we can make a
sensible ioctl that wrappers them. The ioctl follows the same format as
the write_ex() and has the user explicitly specify the core and driver
in/out opaque structures and a command number.

This works for all forms of write commands.

Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/core/Makefile
drivers/infiniband/core/rdma_core.h
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_ioctl.c
drivers/infiniband/core/uverbs_std_types.c
drivers/infiniband/core/uverbs_std_types_device.c [new file with mode: 0644]
drivers/infiniband/core/uverbs_uapi.c
include/uapi/rdma/ib_user_ioctl_cmds.h
include/uapi/rdma/ib_user_verbs.h

index 867cee5e27b2220d9e4bcaddf8c648acebaf6650..69dee36e0e89f489d3d0b0ce9024a75f4e31f56a 100644 (file)
@@ -38,4 +38,4 @@ ib_uverbs-y :=                        uverbs_main.o uverbs_cmd.o uverbs_marshall.o \
                                uverbs_std_types_cq.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_uapi.o uverbs_std_types_device.o
index b3ca7457ac42669929bc766f37ad75d0e9b23a5a..be6b8e1257d07e64d5729a114c482b071713f1fe 100644 (file)
@@ -188,6 +188,7 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile);
 
 extern const struct uapi_definition uverbs_def_obj_counters[];
 extern const struct uapi_definition uverbs_def_obj_cq[];
+extern const struct uapi_definition uverbs_def_obj_device[];
 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[];
@@ -214,4 +215,8 @@ uapi_get_method(const struct uverbs_api *uapi, u32 command)
        return uapi->write_methods[cmd_idx];
 }
 
+void uverbs_fill_udata(struct uverbs_attr_bundle *bundle,
+                      struct ib_udata *udata, unsigned int attr_in,
+                      unsigned int attr_out);
+
 #endif /* RDMA_CORE_H */
index 8b41c95300c62dff4ef6d873c93b5ad97352988a..88029f3b685384e0daafea76b23895ed120569bc 100644 (file)
@@ -246,7 +246,6 @@ int uverbs_dealloc_mw(struct ib_mw *mw);
 void ib_uverbs_detach_umcast(struct ib_qp *qp,
                             struct ib_uqp_object *uobj);
 
-void create_udata(struct uverbs_attr_bundle *ctx, struct ib_udata *udata);
 long ib_uverbs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
 
 struct ib_uverbs_flow_spec {
index e643a43dce8d61715dd653da4395a4e425e5e5a2..3cc46447240e23aeef978b860e891f2bc297b7ad 100644 (file)
@@ -436,7 +436,9 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
                return -EINVAL;
 
        if (pbundle->method_elm->has_udata)
-               create_udata(&pbundle->bundle, &pbundle->bundle.driver_udata);
+               uverbs_fill_udata(&pbundle->bundle,
+                                 &pbundle->bundle.driver_udata,
+                                 UVERBS_ATTR_UHW_IN, UVERBS_ATTR_UHW_OUT);
 
        if (destroy_bkey != UVERBS_API_ATTR_BKEY_LEN) {
                struct uverbs_obj_attr *destroy_attr =
@@ -664,35 +666,37 @@ int uverbs_get_flags32(u32 *to, const struct uverbs_attr_bundle *attrs_bundle,
 EXPORT_SYMBOL(uverbs_get_flags32);
 
 /*
- * This is for ease of conversion. The purpose is to convert all drivers to
- * use uverbs_attr_bundle instead of ib_udata.  Assume attr == 0 is input and
- * attr == 1 is output.
+ * Fill a ib_udata struct (core or uhw) using the given attribute IDs.
+ * This is primarily used to convert the UVERBS_ATTR_UHW() into the
+ * ib_udata format used by the drivers.
  */
-void create_udata(struct uverbs_attr_bundle *bundle, struct ib_udata *udata)
+void uverbs_fill_udata(struct uverbs_attr_bundle *bundle,
+                      struct ib_udata *udata, unsigned int attr_in,
+                      unsigned int attr_out)
 {
        struct bundle_priv *pbundle =
                container_of(bundle, struct bundle_priv, bundle);
-       const struct uverbs_attr *uhw_in =
-               uverbs_attr_get(bundle, UVERBS_ATTR_UHW_IN);
-       const struct uverbs_attr *uhw_out =
-               uverbs_attr_get(bundle, UVERBS_ATTR_UHW_OUT);
-
-       if (!IS_ERR(uhw_in)) {
-               udata->inlen = uhw_in->ptr_attr.len;
-               if (uverbs_attr_ptr_is_inline(uhw_in))
+       const struct uverbs_attr *in =
+               uverbs_attr_get(&pbundle->bundle, attr_in);
+       const struct uverbs_attr *out =
+               uverbs_attr_get(&pbundle->bundle, attr_out);
+
+       if (!IS_ERR(in)) {
+               udata->inlen = in->ptr_attr.len;
+               if (uverbs_attr_ptr_is_inline(in))
                        udata->inbuf =
-                               &pbundle->user_attrs[uhw_in->ptr_attr.uattr_idx]
+                               &pbundle->user_attrs[in->ptr_attr.uattr_idx]
                                         .data;
                else
-                       udata->inbuf = u64_to_user_ptr(uhw_in->ptr_attr.data);
+                       udata->inbuf = u64_to_user_ptr(in->ptr_attr.data);
        } else {
                udata->inbuf = NULL;
                udata->inlen = 0;
        }
 
-       if (!IS_ERR(uhw_out)) {
-               udata->outbuf = u64_to_user_ptr(uhw_out->ptr_attr.data);
-               udata->outlen = uhw_out->ptr_attr.len;
+       if (!IS_ERR(out)) {
+               udata->outbuf = u64_to_user_ptr(out->ptr_attr.data);
+               udata->outlen = out->ptr_attr.len;
        } else {
                udata->outbuf = NULL;
                udata->outlen = 0;
index 424f325f8cba632c7dde03d3233bdb3be20c0376..e3df1e342e2f6b714c117051fd1c64a63a220067 100644 (file)
@@ -259,10 +259,7 @@ DECLARE_UVERBS_NAMED_OBJECT(
 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_PD,
                            UVERBS_TYPE_ALLOC_IDR(uverbs_free_pd));
 
-DECLARE_UVERBS_GLOBAL_METHODS(UVERBS_OBJECT_DEVICE);
-
 const struct uapi_definition uverbs_def_obj_intf[] = {
-       UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_DEVICE),
        UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_PD,
                                      UAPI_DEF_OBJ_NEEDS_FN(dealloc_pd)),
        UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_COMP_CHANNEL,
diff --git a/drivers/infiniband/core/uverbs_std_types_device.c b/drivers/infiniband/core/uverbs_std_types_device.c
new file mode 100644 (file)
index 0000000..aafb251
--- /dev/null
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/*
+ * Copyright (c) 2018, Mellanox Technologies inc.  All rights reserved.
+ */
+
+#include <rdma/uverbs_std_types.h>
+#include "rdma_core.h"
+#include "uverbs.h"
+
+/*
+ * This ioctl method allows calling any defined write or write_ex
+ * handler. This essentially replaces the hdr/ex_hdr system with the ioctl
+ * marshalling, and brings the non-ex path into the same marshalling as the ex
+ * path.
+ */
+static int UVERBS_HANDLER(UVERBS_METHOD_INVOKE_WRITE)(
+       struct uverbs_attr_bundle *attrs)
+{
+       struct uverbs_api *uapi = attrs->ufile->device->uapi;
+       const struct uverbs_api_write_method *method_elm;
+       u32 cmd;
+       int rc;
+
+       rc = uverbs_get_const(&cmd, attrs, UVERBS_ATTR_WRITE_CMD);
+       if (rc)
+               return rc;
+
+       method_elm = uapi_get_method(uapi, cmd);
+       if (IS_ERR(method_elm))
+               return PTR_ERR(method_elm);
+
+       uverbs_fill_udata(attrs, &attrs->ucore, UVERBS_ATTR_CORE_IN,
+                         UVERBS_ATTR_CORE_OUT);
+
+       if (attrs->ucore.inlen < method_elm->req_size ||
+           attrs->ucore.outlen < method_elm->resp_size)
+               return -ENOSPC;
+
+       return method_elm->handler(attrs);
+}
+
+DECLARE_UVERBS_NAMED_METHOD(UVERBS_METHOD_INVOKE_WRITE,
+                           UVERBS_ATTR_CONST_IN(UVERBS_ATTR_WRITE_CMD,
+                                                enum ib_uverbs_write_cmds,
+                                                UA_MANDATORY),
+                           UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CORE_IN,
+                                              UVERBS_ATTR_MIN_SIZE(sizeof(u32)),
+                                              UA_OPTIONAL),
+                           UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CORE_OUT,
+                                               UVERBS_ATTR_MIN_SIZE(0),
+                                               UA_OPTIONAL),
+                           UVERBS_ATTR_UHW());
+
+DECLARE_UVERBS_GLOBAL_METHODS(UVERBS_OBJECT_DEVICE,
+                             &UVERBS_METHOD(UVERBS_METHOD_INVOKE_WRITE));
+
+const struct uapi_definition uverbs_def_obj_device[] = {
+       UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_DEVICE),
+       {},
+};
index 830e48fe5e65f9a9afe2bc29d4900e0a92ed205e..9ae08e4b78a301f36714a65f86b3afd5a0d216ea 100644 (file)
@@ -621,6 +621,7 @@ void uverbs_destroy_api(struct uverbs_api *uapi)
 static const struct uapi_definition uverbs_core_api[] = {
        UAPI_DEF_CHAIN(uverbs_def_obj_counters),
        UAPI_DEF_CHAIN(uverbs_def_obj_cq),
+       UAPI_DEF_CHAIN(uverbs_def_obj_device),
        UAPI_DEF_CHAIN(uverbs_def_obj_dm),
        UAPI_DEF_CHAIN(uverbs_def_obj_flow_action),
        UAPI_DEF_CHAIN(uverbs_def_obj_intf),
index 2c881aaf05c2a63e1e16beea023524637b099415..34e71994f4a559fd790805e5f0f683c01768a9a6 100644 (file)
@@ -63,6 +63,16 @@ enum {
        UVERBS_ATTR_UHW_OUT,
 };
 
+enum uverbs_methods_device {
+       UVERBS_METHOD_INVOKE_WRITE,
+};
+
+enum uverbs_attrs_invoke_write_cmd_attr_ids {
+       UVERBS_ATTR_CORE_IN,
+       UVERBS_ATTR_CORE_OUT,
+       UVERBS_ATTR_WRITE_CMD,
+};
+
 enum uverbs_attrs_create_cq_cmd_attr_ids {
        UVERBS_ATTR_CREATE_CQ_HANDLE,
        UVERBS_ATTR_CREATE_CQ_CQE,
index c586fc43739cdfd4ebb765aaeba4b04f6540a391..480d9a60b68e475a7dcd20fe326cbe9706ba11c2 100644 (file)
@@ -46,7 +46,7 @@
 #define IB_USER_VERBS_ABI_VERSION      6
 #define IB_USER_VERBS_CMD_THRESHOLD    50
 
-enum {
+enum ib_uverbs_write_cmds {
        IB_USER_VERBS_CMD_GET_CONTEXT,
        IB_USER_VERBS_CMD_QUERY_DEVICE,
        IB_USER_VERBS_CMD_QUERY_PORT,