On Fri, 2018-11-30 at 13:06 +0200, Leon Romanovsky wrote: > From: Jason Gunthorpe <jgg@xxxxxxxxxxxx> > > 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. I'm ready to merge this, and the corresponding rdma-core patch. What about you Jason? > > Signed-off-by: Jason Gunthorpe <jgg@xxxxxxxxxxxx> > Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxxxx> > --- > drivers/infiniband/core/Makefile | 2 +- > drivers/infiniband/core/rdma_core.h | 5 ++ > drivers/infiniband/core/uverbs.h | 1 - > drivers/infiniband/core/uverbs_ioctl.c | 40 +++++++------ > drivers/infiniband/core/uverbs_std_types.c | 3 - > .../infiniband/core/uverbs_std_types_device.c | 60 +++++++++++++++++++ > drivers/infiniband/core/uverbs_uapi.c | 1 + > include/uapi/rdma/ib_user_ioctl_cmds.h | 10 ++++ > include/uapi/rdma/ib_user_verbs.h | 2 +- > 9 files changed, 100 insertions(+), 24 deletions(-) > create mode 100644 drivers/infiniband/core/uverbs_std_types_device.c > > diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile > index 781b3172e596..fc1d5adfb24b 100644 > --- a/drivers/infiniband/core/Makefile > +++ b/drivers/infiniband/core/Makefile > @@ -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 > diff --git a/drivers/infiniband/core/rdma_core.h b/drivers/infiniband/core/rdma_core.h > index b3ca7457ac42..be6b8e1257d0 100644 > --- a/drivers/infiniband/core/rdma_core.h > +++ b/drivers/infiniband/core/rdma_core.h > @@ -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 */ > diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h > index 8b41c95300c6..88029f3b6853 100644 > --- a/drivers/infiniband/core/uverbs.h > +++ b/drivers/infiniband/core/uverbs.h > @@ -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 { > diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c > index e643a43dce8d..3cc46447240e 100644 > --- a/drivers/infiniband/core/uverbs_ioctl.c > +++ b/drivers/infiniband/core/uverbs_ioctl.c > @@ -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; > diff --git a/drivers/infiniband/core/uverbs_std_types.c b/drivers/infiniband/core/uverbs_std_types.c > index 063aff9e7a04..8db5d23ca087 100644 > --- a/drivers/infiniband/core/uverbs_std_types.c > +++ b/drivers/infiniband/core/uverbs_std_types.c > @@ -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 > index 000000000000..aafb251b7d37 > --- /dev/null > +++ b/drivers/infiniband/core/uverbs_std_types_device.c > @@ -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), > + {}, > +}; > diff --git a/drivers/infiniband/core/uverbs_uapi.c b/drivers/infiniband/core/uverbs_uapi.c > index 0136c1d78a0f..7097cae8d2b7 100644 > --- a/drivers/infiniband/core/uverbs_uapi.c > +++ b/drivers/infiniband/core/uverbs_uapi.c > @@ -620,6 +620,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), > diff --git a/include/uapi/rdma/ib_user_ioctl_cmds.h b/include/uapi/rdma/ib_user_ioctl_cmds.h > index 2c881aaf05c2..34e71994f4a5 100644 > --- a/include/uapi/rdma/ib_user_ioctl_cmds.h > +++ b/include/uapi/rdma/ib_user_ioctl_cmds.h > @@ -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, > diff --git a/include/uapi/rdma/ib_user_verbs.h b/include/uapi/rdma/ib_user_verbs.h > index c586fc43739c..480d9a60b68e 100644 > --- a/include/uapi/rdma/ib_user_verbs.h > +++ b/include/uapi/rdma/ib_user_verbs.h > @@ -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, -- Doug Ledford <dledford@xxxxxxxxxx> GPG KeyID: B826A3330E572FDD Key fingerprint = AE6B 1BDA 122B 23B4 265B 1274 B826 A333 0E57 2FDD
Attachment:
signature.asc
Description: This is a digitally signed message part