1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /*
3 * Copyright (c) 2020, 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
uverbs_free_wq(struct ib_uobject * uobject,enum rdma_remove_reason why,struct uverbs_attr_bundle * attrs)10 static int uverbs_free_wq(struct ib_uobject *uobject,
11 enum rdma_remove_reason why,
12 struct uverbs_attr_bundle *attrs)
13 {
14 struct ib_wq *wq = uobject->object;
15 struct ib_uwq_object *uwq =
16 container_of(uobject, struct ib_uwq_object, uevent.uobject);
17 int ret;
18
19 ret = ib_destroy_wq_user(wq, &attrs->driver_udata);
20 if (ret)
21 return ret;
22
23 ib_uverbs_release_uevent(&uwq->uevent);
24 return 0;
25 }
26
UVERBS_HANDLER(UVERBS_METHOD_WQ_CREATE)27 static int UVERBS_HANDLER(UVERBS_METHOD_WQ_CREATE)(
28 struct uverbs_attr_bundle *attrs)
29 {
30 struct ib_uwq_object *obj = container_of(
31 uverbs_attr_get_uobject(attrs, UVERBS_ATTR_CREATE_WQ_HANDLE),
32 typeof(*obj), uevent.uobject);
33 struct ib_pd *pd =
34 uverbs_attr_get_obj(attrs, UVERBS_ATTR_CREATE_WQ_PD_HANDLE);
35 struct ib_cq *cq =
36 uverbs_attr_get_obj(attrs, UVERBS_ATTR_CREATE_WQ_CQ_HANDLE);
37 struct ib_wq_init_attr wq_init_attr = {};
38 struct ib_wq *wq;
39 u64 user_handle;
40 int ret;
41
42 ret = uverbs_get_flags32(&wq_init_attr.create_flags, attrs,
43 UVERBS_ATTR_CREATE_WQ_FLAGS,
44 IB_UVERBS_WQ_FLAGS_CVLAN_STRIPPING |
45 IB_UVERBS_WQ_FLAGS_SCATTER_FCS |
46 IB_UVERBS_WQ_FLAGS_DELAY_DROP |
47 IB_UVERBS_WQ_FLAGS_PCI_WRITE_END_PADDING);
48 if (!ret)
49 ret = uverbs_copy_from(&wq_init_attr.max_sge, attrs,
50 UVERBS_ATTR_CREATE_WQ_MAX_SGE);
51 if (!ret)
52 ret = uverbs_copy_from(&wq_init_attr.max_wr, attrs,
53 UVERBS_ATTR_CREATE_WQ_MAX_WR);
54 if (!ret)
55 ret = uverbs_copy_from(&user_handle, attrs,
56 UVERBS_ATTR_CREATE_WQ_USER_HANDLE);
57 if (!ret)
58 ret = uverbs_get_const(&wq_init_attr.wq_type, attrs,
59 UVERBS_ATTR_CREATE_WQ_TYPE);
60 if (ret)
61 return ret;
62
63 if (wq_init_attr.wq_type != IB_WQT_RQ)
64 return -EINVAL;
65
66 obj->uevent.event_file = ib_uverbs_get_async_event(attrs,
67 UVERBS_ATTR_CREATE_WQ_EVENT_FD);
68 obj->uevent.uobject.user_handle = user_handle;
69 INIT_LIST_HEAD(&obj->uevent.event_list);
70 wq_init_attr.event_handler = ib_uverbs_wq_event_handler;
71 wq_init_attr.wq_context = attrs->ufile;
72 wq_init_attr.cq = cq;
73
74 wq = pd->device->ops.create_wq(pd, &wq_init_attr, &attrs->driver_udata);
75 if (IS_ERR(wq)) {
76 ret = PTR_ERR(wq);
77 goto err;
78 }
79
80 obj->uevent.uobject.object = wq;
81 wq->wq_type = wq_init_attr.wq_type;
82 wq->cq = cq;
83 wq->pd = pd;
84 wq->device = pd->device;
85 wq->wq_context = wq_init_attr.wq_context;
86 atomic_set(&wq->usecnt, 0);
87 atomic_inc(&pd->usecnt);
88 atomic_inc(&cq->usecnt);
89 wq->uobject = obj;
90 uverbs_finalize_uobj_create(attrs, UVERBS_ATTR_CREATE_WQ_HANDLE);
91
92 ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_WQ_RESP_MAX_WR,
93 &wq_init_attr.max_wr,
94 sizeof(wq_init_attr.max_wr));
95 if (ret)
96 return ret;
97
98 ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_WQ_RESP_MAX_SGE,
99 &wq_init_attr.max_sge,
100 sizeof(wq_init_attr.max_sge));
101 if (ret)
102 return ret;
103
104 ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_WQ_RESP_WQ_NUM,
105 &wq->wq_num,
106 sizeof(wq->wq_num));
107 return ret;
108
109 err:
110 if (obj->uevent.event_file)
111 uverbs_uobject_put(&obj->uevent.event_file->uobj);
112 return ret;
113 };
114
115 DECLARE_UVERBS_NAMED_METHOD(
116 UVERBS_METHOD_WQ_CREATE,
117 UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_WQ_HANDLE,
118 UVERBS_OBJECT_WQ,
119 UVERBS_ACCESS_NEW,
120 UA_MANDATORY),
121 UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_WQ_PD_HANDLE,
122 UVERBS_OBJECT_PD,
123 UVERBS_ACCESS_READ,
124 UA_MANDATORY),
125 UVERBS_ATTR_CONST_IN(UVERBS_ATTR_CREATE_WQ_TYPE,
126 enum ib_wq_type,
127 UA_MANDATORY),
128 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_WQ_USER_HANDLE,
129 UVERBS_ATTR_TYPE(u64),
130 UA_MANDATORY),
131 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_WQ_MAX_WR,
132 UVERBS_ATTR_TYPE(u32),
133 UA_MANDATORY),
134 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_WQ_MAX_SGE,
135 UVERBS_ATTR_TYPE(u32),
136 UA_MANDATORY),
137 UVERBS_ATTR_FLAGS_IN(UVERBS_ATTR_CREATE_WQ_FLAGS,
138 enum ib_uverbs_wq_flags,
139 UA_MANDATORY),
140 UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_WQ_CQ_HANDLE,
141 UVERBS_OBJECT_CQ,
142 UVERBS_ACCESS_READ,
143 UA_OPTIONAL),
144 UVERBS_ATTR_FD(UVERBS_ATTR_CREATE_WQ_EVENT_FD,
145 UVERBS_OBJECT_ASYNC_EVENT,
146 UVERBS_ACCESS_READ,
147 UA_OPTIONAL),
148 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_WQ_RESP_MAX_WR,
149 UVERBS_ATTR_TYPE(u32),
150 UA_MANDATORY),
151 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_WQ_RESP_MAX_SGE,
152 UVERBS_ATTR_TYPE(u32),
153 UA_MANDATORY),
154 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_WQ_RESP_WQ_NUM,
155 UVERBS_ATTR_TYPE(u32),
156 UA_OPTIONAL),
157 UVERBS_ATTR_UHW());
158
UVERBS_HANDLER(UVERBS_METHOD_WQ_DESTROY)159 static int UVERBS_HANDLER(UVERBS_METHOD_WQ_DESTROY)(
160 struct uverbs_attr_bundle *attrs)
161 {
162 struct ib_uobject *uobj =
163 uverbs_attr_get_uobject(attrs, UVERBS_ATTR_DESTROY_WQ_HANDLE);
164 struct ib_uwq_object *obj =
165 container_of(uobj, struct ib_uwq_object, uevent.uobject);
166
167 return uverbs_copy_to(attrs, UVERBS_ATTR_DESTROY_WQ_RESP,
168 &obj->uevent.events_reported,
169 sizeof(obj->uevent.events_reported));
170 }
171
172 DECLARE_UVERBS_NAMED_METHOD(
173 UVERBS_METHOD_WQ_DESTROY,
174 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_WQ_HANDLE,
175 UVERBS_OBJECT_WQ,
176 UVERBS_ACCESS_DESTROY,
177 UA_MANDATORY),
178 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_DESTROY_WQ_RESP,
179 UVERBS_ATTR_TYPE(u32),
180 UA_MANDATORY));
181
182
183 DECLARE_UVERBS_NAMED_OBJECT(
184 UVERBS_OBJECT_WQ,
185 UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uwq_object), uverbs_free_wq),
186 &UVERBS_METHOD(UVERBS_METHOD_WQ_CREATE),
187 &UVERBS_METHOD(UVERBS_METHOD_WQ_DESTROY)
188 );
189
190 const struct uapi_definition uverbs_def_obj_wq[] = {
191 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_WQ,
192 UAPI_DEF_OBJ_NEEDS_FN(destroy_wq)),
193 {}
194 };
195