Skip to content

Commit 4785860

Browse files
jgunthorpedledford
authored andcommitted
RDMA/uverbs: Implement an ioctl that can call write and write_ex handlers
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>
1 parent 2414149 commit 4785860

File tree

9 files changed

+100
-24
lines changed

9 files changed

+100
-24
lines changed

drivers/infiniband/core/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,4 @@ ib_uverbs-y := uverbs_main.o uverbs_cmd.o uverbs_marshall.o \
3838
uverbs_std_types_cq.o \
3939
uverbs_std_types_flow_action.o uverbs_std_types_dm.o \
4040
uverbs_std_types_mr.o uverbs_std_types_counters.o \
41-
uverbs_uapi.o
41+
uverbs_uapi.o uverbs_std_types_device.o

drivers/infiniband/core/rdma_core.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile);
188188

189189
extern const struct uapi_definition uverbs_def_obj_counters[];
190190
extern const struct uapi_definition uverbs_def_obj_cq[];
191+
extern const struct uapi_definition uverbs_def_obj_device[];
191192
extern const struct uapi_definition uverbs_def_obj_dm[];
192193
extern const struct uapi_definition uverbs_def_obj_flow_action[];
193194
extern const struct uapi_definition uverbs_def_obj_intf[];
@@ -214,4 +215,8 @@ uapi_get_method(const struct uverbs_api *uapi, u32 command)
214215
return uapi->write_methods[cmd_idx];
215216
}
216217

218+
void uverbs_fill_udata(struct uverbs_attr_bundle *bundle,
219+
struct ib_udata *udata, unsigned int attr_in,
220+
unsigned int attr_out);
221+
217222
#endif /* RDMA_CORE_H */

drivers/infiniband/core/uverbs.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,6 @@ int uverbs_dealloc_mw(struct ib_mw *mw);
246246
void ib_uverbs_detach_umcast(struct ib_qp *qp,
247247
struct ib_uqp_object *uobj);
248248

249-
void create_udata(struct uverbs_attr_bundle *ctx, struct ib_udata *udata);
250249
long ib_uverbs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
251250

252251
struct ib_uverbs_flow_spec {

drivers/infiniband/core/uverbs_ioctl.c

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,9 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
436436
return -EINVAL;
437437

438438
if (pbundle->method_elm->has_udata)
439-
create_udata(&pbundle->bundle, &pbundle->bundle.driver_udata);
439+
uverbs_fill_udata(&pbundle->bundle,
440+
&pbundle->bundle.driver_udata,
441+
UVERBS_ATTR_UHW_IN, UVERBS_ATTR_UHW_OUT);
440442

441443
if (destroy_bkey != UVERBS_API_ATTR_BKEY_LEN) {
442444
struct uverbs_obj_attr *destroy_attr =
@@ -664,35 +666,37 @@ int uverbs_get_flags32(u32 *to, const struct uverbs_attr_bundle *attrs_bundle,
664666
EXPORT_SYMBOL(uverbs_get_flags32);
665667

666668
/*
667-
* This is for ease of conversion. The purpose is to convert all drivers to
668-
* use uverbs_attr_bundle instead of ib_udata. Assume attr == 0 is input and
669-
* attr == 1 is output.
669+
* Fill a ib_udata struct (core or uhw) using the given attribute IDs.
670+
* This is primarily used to convert the UVERBS_ATTR_UHW() into the
671+
* ib_udata format used by the drivers.
670672
*/
671-
void create_udata(struct uverbs_attr_bundle *bundle, struct ib_udata *udata)
673+
void uverbs_fill_udata(struct uverbs_attr_bundle *bundle,
674+
struct ib_udata *udata, unsigned int attr_in,
675+
unsigned int attr_out)
672676
{
673677
struct bundle_priv *pbundle =
674678
container_of(bundle, struct bundle_priv, bundle);
675-
const struct uverbs_attr *uhw_in =
676-
uverbs_attr_get(bundle, UVERBS_ATTR_UHW_IN);
677-
const struct uverbs_attr *uhw_out =
678-
uverbs_attr_get(bundle, UVERBS_ATTR_UHW_OUT);
679-
680-
if (!IS_ERR(uhw_in)) {
681-
udata->inlen = uhw_in->ptr_attr.len;
682-
if (uverbs_attr_ptr_is_inline(uhw_in))
679+
const struct uverbs_attr *in =
680+
uverbs_attr_get(&pbundle->bundle, attr_in);
681+
const struct uverbs_attr *out =
682+
uverbs_attr_get(&pbundle->bundle, attr_out);
683+
684+
if (!IS_ERR(in)) {
685+
udata->inlen = in->ptr_attr.len;
686+
if (uverbs_attr_ptr_is_inline(in))
683687
udata->inbuf =
684-
&pbundle->user_attrs[uhw_in->ptr_attr.uattr_idx]
688+
&pbundle->user_attrs[in->ptr_attr.uattr_idx]
685689
.data;
686690
else
687-
udata->inbuf = u64_to_user_ptr(uhw_in->ptr_attr.data);
691+
udata->inbuf = u64_to_user_ptr(in->ptr_attr.data);
688692
} else {
689693
udata->inbuf = NULL;
690694
udata->inlen = 0;
691695
}
692696

693-
if (!IS_ERR(uhw_out)) {
694-
udata->outbuf = u64_to_user_ptr(uhw_out->ptr_attr.data);
695-
udata->outlen = uhw_out->ptr_attr.len;
697+
if (!IS_ERR(out)) {
698+
udata->outbuf = u64_to_user_ptr(out->ptr_attr.data);
699+
udata->outlen = out->ptr_attr.len;
696700
} else {
697701
udata->outbuf = NULL;
698702
udata->outlen = 0;

drivers/infiniband/core/uverbs_std_types.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,7 @@ DECLARE_UVERBS_NAMED_OBJECT(
259259
DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_PD,
260260
UVERBS_TYPE_ALLOC_IDR(uverbs_free_pd));
261261

262-
DECLARE_UVERBS_GLOBAL_METHODS(UVERBS_OBJECT_DEVICE);
263-
264262
const struct uapi_definition uverbs_def_obj_intf[] = {
265-
UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_DEVICE),
266263
UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_PD,
267264
UAPI_DEF_OBJ_NEEDS_FN(dealloc_pd)),
268265
UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_COMP_CHANNEL,
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2+
/*
3+
* Copyright (c) 2018, Mellanox Technologies inc. All rights reserved.
4+
*/
5+
6+
#include <rdma/uverbs_std_types.h>
7+
#include "rdma_core.h"
8+
#include "uverbs.h"
9+
10+
/*
11+
* This ioctl method allows calling any defined write or write_ex
12+
* handler. This essentially replaces the hdr/ex_hdr system with the ioctl
13+
* marshalling, and brings the non-ex path into the same marshalling as the ex
14+
* path.
15+
*/
16+
static int UVERBS_HANDLER(UVERBS_METHOD_INVOKE_WRITE)(
17+
struct uverbs_attr_bundle *attrs)
18+
{
19+
struct uverbs_api *uapi = attrs->ufile->device->uapi;
20+
const struct uverbs_api_write_method *method_elm;
21+
u32 cmd;
22+
int rc;
23+
24+
rc = uverbs_get_const(&cmd, attrs, UVERBS_ATTR_WRITE_CMD);
25+
if (rc)
26+
return rc;
27+
28+
method_elm = uapi_get_method(uapi, cmd);
29+
if (IS_ERR(method_elm))
30+
return PTR_ERR(method_elm);
31+
32+
uverbs_fill_udata(attrs, &attrs->ucore, UVERBS_ATTR_CORE_IN,
33+
UVERBS_ATTR_CORE_OUT);
34+
35+
if (attrs->ucore.inlen < method_elm->req_size ||
36+
attrs->ucore.outlen < method_elm->resp_size)
37+
return -ENOSPC;
38+
39+
return method_elm->handler(attrs);
40+
}
41+
42+
DECLARE_UVERBS_NAMED_METHOD(UVERBS_METHOD_INVOKE_WRITE,
43+
UVERBS_ATTR_CONST_IN(UVERBS_ATTR_WRITE_CMD,
44+
enum ib_uverbs_write_cmds,
45+
UA_MANDATORY),
46+
UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CORE_IN,
47+
UVERBS_ATTR_MIN_SIZE(sizeof(u32)),
48+
UA_OPTIONAL),
49+
UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CORE_OUT,
50+
UVERBS_ATTR_MIN_SIZE(0),
51+
UA_OPTIONAL),
52+
UVERBS_ATTR_UHW());
53+
54+
DECLARE_UVERBS_GLOBAL_METHODS(UVERBS_OBJECT_DEVICE,
55+
&UVERBS_METHOD(UVERBS_METHOD_INVOKE_WRITE));
56+
57+
const struct uapi_definition uverbs_def_obj_device[] = {
58+
UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_DEVICE),
59+
{},
60+
};

drivers/infiniband/core/uverbs_uapi.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,7 @@ void uverbs_destroy_api(struct uverbs_api *uapi)
621621
static const struct uapi_definition uverbs_core_api[] = {
622622
UAPI_DEF_CHAIN(uverbs_def_obj_counters),
623623
UAPI_DEF_CHAIN(uverbs_def_obj_cq),
624+
UAPI_DEF_CHAIN(uverbs_def_obj_device),
624625
UAPI_DEF_CHAIN(uverbs_def_obj_dm),
625626
UAPI_DEF_CHAIN(uverbs_def_obj_flow_action),
626627
UAPI_DEF_CHAIN(uverbs_def_obj_intf),

include/uapi/rdma/ib_user_ioctl_cmds.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ enum {
6363
UVERBS_ATTR_UHW_OUT,
6464
};
6565

66+
enum uverbs_methods_device {
67+
UVERBS_METHOD_INVOKE_WRITE,
68+
};
69+
70+
enum uverbs_attrs_invoke_write_cmd_attr_ids {
71+
UVERBS_ATTR_CORE_IN,
72+
UVERBS_ATTR_CORE_OUT,
73+
UVERBS_ATTR_WRITE_CMD,
74+
};
75+
6676
enum uverbs_attrs_create_cq_cmd_attr_ids {
6777
UVERBS_ATTR_CREATE_CQ_HANDLE,
6878
UVERBS_ATTR_CREATE_CQ_CQE,

include/uapi/rdma/ib_user_verbs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
#define IB_USER_VERBS_ABI_VERSION 6
4747
#define IB_USER_VERBS_CMD_THRESHOLD 50
4848

49-
enum {
49+
enum ib_uverbs_write_cmds {
5050
IB_USER_VERBS_CMD_GET_CONTEXT,
5151
IB_USER_VERBS_CMD_QUERY_DEVICE,
5252
IB_USER_VERBS_CMD_QUERY_PORT,

0 commit comments

Comments
 (0)