blob: 162321f486ebac11cc29fc64f855945fa517f3eb [file] [log] [blame]
Yishai Hadasa8b92ca2018-06-17 12:59:57 +03001// 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/ib_user_verbs.h>
7#include <rdma/ib_verbs.h>
8#include <rdma/uverbs_types.h>
9#include <rdma/uverbs_ioctl.h>
10#include <rdma/mlx5_user_ioctl_cmds.h>
11#include <rdma/ib_umem.h>
12#include <linux/mlx5/driver.h>
13#include <linux/mlx5/fs.h>
14#include "mlx5_ib.h"
15
Yishai Hadas8aa8c952018-06-17 13:00:00 +030016#define UVERBS_MODULE_NAME mlx5_ib
17#include <rdma/uverbs_named_ioctl.h>
18
Yishai Hadas7efce362018-06-17 13:00:01 +030019#define MLX5_MAX_DESTROY_INBOX_SIZE_DW MLX5_ST_SZ_DW(delete_fte_in)
20struct devx_obj {
21 struct mlx5_core_dev *mdev;
22 u32 obj_id;
23 u32 dinlen; /* destroy inbox length */
24 u32 dinbox[MLX5_MAX_DESTROY_INBOX_SIZE_DW];
25};
26
Yishai Hadasaeae9452018-06-17 13:00:04 +030027struct devx_umem {
28 struct mlx5_core_dev *mdev;
29 struct ib_umem *umem;
30 u32 page_offset;
31 int page_shift;
32 int ncont;
33 u32 dinlen;
34 u32 dinbox[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)];
35};
36
37struct devx_umem_reg_cmd {
38 void *in;
39 u32 inlen;
40 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
41};
42
Yishai Hadas8aa8c952018-06-17 13:00:00 +030043static struct mlx5_ib_ucontext *devx_ufile2uctx(struct ib_uverbs_file *file)
44{
45 return to_mucontext(ib_uverbs_get_ucontext(file));
46}
47
Yishai Hadasa8b92ca2018-06-17 12:59:57 +030048int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, struct mlx5_ib_ucontext *context)
49{
50 u32 in[MLX5_ST_SZ_DW(create_uctx_in)] = {0};
51 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
52 u64 general_obj_types;
53 void *uctx;
54 void *hdr;
55 int err;
56
57 uctx = MLX5_ADDR_OF(create_uctx_in, in, uctx);
58 hdr = MLX5_ADDR_OF(create_uctx_in, in, hdr);
59
60 general_obj_types = MLX5_CAP_GEN_64(dev->mdev, general_obj_types);
61 if (!(general_obj_types & MLX5_GENERAL_OBJ_TYPES_CAP_UCTX) ||
62 !(general_obj_types & MLX5_GENERAL_OBJ_TYPES_CAP_UMEM))
63 return -EINVAL;
64
65 if (!capable(CAP_NET_RAW))
66 return -EPERM;
67
68 MLX5_SET(general_obj_in_cmd_hdr, hdr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
69 MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_type, MLX5_OBJ_TYPE_UCTX);
70
71 err = mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
72 if (err)
73 return err;
74
75 context->devx_uid = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
76 return 0;
77}
78
79void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev,
80 struct mlx5_ib_ucontext *context)
81{
82 u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {0};
83 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
84
85 MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
86 MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_OBJ_TYPE_UCTX);
87 MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, context->devx_uid);
88
89 mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
90}
Yishai Hadas8aa8c952018-06-17 13:00:00 +030091
Yishai Hadase662e142018-06-17 13:00:02 +030092static int devx_is_valid_obj_id(struct devx_obj *obj, const void *in)
93{
94 u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
95 u32 obj_id;
96
97 switch (opcode) {
98 case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
99 case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
100 obj_id = MLX5_GET(general_obj_in_cmd_hdr, in, obj_id);
101 break;
102 case MLX5_CMD_OP_QUERY_MKEY:
103 obj_id = MLX5_GET(query_mkey_in, in, mkey_index);
104 break;
105 case MLX5_CMD_OP_QUERY_CQ:
106 obj_id = MLX5_GET(query_cq_in, in, cqn);
107 break;
108 case MLX5_CMD_OP_MODIFY_CQ:
109 obj_id = MLX5_GET(modify_cq_in, in, cqn);
110 break;
111 case MLX5_CMD_OP_QUERY_SQ:
112 obj_id = MLX5_GET(query_sq_in, in, sqn);
113 break;
114 case MLX5_CMD_OP_MODIFY_SQ:
115 obj_id = MLX5_GET(modify_sq_in, in, sqn);
116 break;
117 case MLX5_CMD_OP_QUERY_RQ:
118 obj_id = MLX5_GET(query_rq_in, in, rqn);
119 break;
120 case MLX5_CMD_OP_MODIFY_RQ:
121 obj_id = MLX5_GET(modify_rq_in, in, rqn);
122 break;
123 case MLX5_CMD_OP_QUERY_RMP:
124 obj_id = MLX5_GET(query_rmp_in, in, rmpn);
125 break;
126 case MLX5_CMD_OP_MODIFY_RMP:
127 obj_id = MLX5_GET(modify_rmp_in, in, rmpn);
128 break;
129 case MLX5_CMD_OP_QUERY_RQT:
130 obj_id = MLX5_GET(query_rqt_in, in, rqtn);
131 break;
132 case MLX5_CMD_OP_MODIFY_RQT:
133 obj_id = MLX5_GET(modify_rqt_in, in, rqtn);
134 break;
135 case MLX5_CMD_OP_QUERY_TIR:
136 obj_id = MLX5_GET(query_tir_in, in, tirn);
137 break;
138 case MLX5_CMD_OP_MODIFY_TIR:
139 obj_id = MLX5_GET(modify_tir_in, in, tirn);
140 break;
141 case MLX5_CMD_OP_QUERY_TIS:
142 obj_id = MLX5_GET(query_tis_in, in, tisn);
143 break;
144 case MLX5_CMD_OP_MODIFY_TIS:
145 obj_id = MLX5_GET(modify_tis_in, in, tisn);
146 break;
147 case MLX5_CMD_OP_QUERY_FLOW_TABLE:
148 obj_id = MLX5_GET(query_flow_table_in, in, table_id);
149 break;
150 case MLX5_CMD_OP_MODIFY_FLOW_TABLE:
151 obj_id = MLX5_GET(modify_flow_table_in, in, table_id);
152 break;
153 case MLX5_CMD_OP_QUERY_FLOW_GROUP:
154 obj_id = MLX5_GET(query_flow_group_in, in, group_id);
155 break;
156 case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
157 obj_id = MLX5_GET(query_fte_in, in, flow_index);
158 break;
159 case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
160 obj_id = MLX5_GET(set_fte_in, in, flow_index);
161 break;
162 case MLX5_CMD_OP_QUERY_Q_COUNTER:
163 obj_id = MLX5_GET(query_q_counter_in, in, counter_set_id);
164 break;
165 case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
166 obj_id = MLX5_GET(query_flow_counter_in, in, flow_counter_id);
167 break;
168 case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT:
169 obj_id = MLX5_GET(general_obj_in_cmd_hdr, in, obj_id);
170 break;
171 case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
172 obj_id = MLX5_GET(query_scheduling_element_in, in,
173 scheduling_element_id);
174 break;
175 case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
176 obj_id = MLX5_GET(modify_scheduling_element_in, in,
177 scheduling_element_id);
178 break;
179 case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
180 obj_id = MLX5_GET(add_vxlan_udp_dport_in, in, vxlan_udp_port);
181 break;
182 case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
183 obj_id = MLX5_GET(query_l2_table_entry_in, in, table_index);
184 break;
185 case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
186 obj_id = MLX5_GET(set_l2_table_entry_in, in, table_index);
187 break;
188 case MLX5_CMD_OP_QUERY_QP:
189 obj_id = MLX5_GET(query_qp_in, in, qpn);
190 break;
191 case MLX5_CMD_OP_RST2INIT_QP:
192 obj_id = MLX5_GET(rst2init_qp_in, in, qpn);
193 break;
194 case MLX5_CMD_OP_INIT2RTR_QP:
195 obj_id = MLX5_GET(init2rtr_qp_in, in, qpn);
196 break;
197 case MLX5_CMD_OP_RTR2RTS_QP:
198 obj_id = MLX5_GET(rtr2rts_qp_in, in, qpn);
199 break;
200 case MLX5_CMD_OP_RTS2RTS_QP:
201 obj_id = MLX5_GET(rts2rts_qp_in, in, qpn);
202 break;
203 case MLX5_CMD_OP_SQERR2RTS_QP:
204 obj_id = MLX5_GET(sqerr2rts_qp_in, in, qpn);
205 break;
206 case MLX5_CMD_OP_2ERR_QP:
207 obj_id = MLX5_GET(qp_2err_in, in, qpn);
208 break;
209 case MLX5_CMD_OP_2RST_QP:
210 obj_id = MLX5_GET(qp_2rst_in, in, qpn);
211 break;
212 case MLX5_CMD_OP_QUERY_DCT:
213 obj_id = MLX5_GET(query_dct_in, in, dctn);
214 break;
215 case MLX5_CMD_OP_QUERY_XRQ:
216 obj_id = MLX5_GET(query_xrq_in, in, xrqn);
217 break;
218 case MLX5_CMD_OP_QUERY_XRC_SRQ:
219 obj_id = MLX5_GET(query_xrc_srq_in, in, xrc_srqn);
220 break;
221 case MLX5_CMD_OP_ARM_XRC_SRQ:
222 obj_id = MLX5_GET(arm_xrc_srq_in, in, xrc_srqn);
223 break;
224 case MLX5_CMD_OP_QUERY_SRQ:
225 obj_id = MLX5_GET(query_srq_in, in, srqn);
226 break;
227 case MLX5_CMD_OP_ARM_RQ:
228 obj_id = MLX5_GET(arm_rq_in, in, srq_number);
229 break;
230 case MLX5_CMD_OP_DRAIN_DCT:
231 case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
232 obj_id = MLX5_GET(drain_dct_in, in, dctn);
233 break;
234 case MLX5_CMD_OP_ARM_XRQ:
235 obj_id = MLX5_GET(arm_xrq_in, in, xrqn);
236 break;
237 default:
238 return false;
239 }
240
241 if (obj_id == obj->obj_id)
242 return true;
243
244 return false;
245}
246
Yishai Hadas7efce362018-06-17 13:00:01 +0300247static bool devx_is_obj_create_cmd(const void *in)
248{
249 u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
250
251 switch (opcode) {
252 case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
253 case MLX5_CMD_OP_CREATE_MKEY:
254 case MLX5_CMD_OP_CREATE_CQ:
255 case MLX5_CMD_OP_ALLOC_PD:
256 case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
257 case MLX5_CMD_OP_CREATE_RMP:
258 case MLX5_CMD_OP_CREATE_SQ:
259 case MLX5_CMD_OP_CREATE_RQ:
260 case MLX5_CMD_OP_CREATE_RQT:
261 case MLX5_CMD_OP_CREATE_TIR:
262 case MLX5_CMD_OP_CREATE_TIS:
263 case MLX5_CMD_OP_ALLOC_Q_COUNTER:
264 case MLX5_CMD_OP_CREATE_FLOW_TABLE:
265 case MLX5_CMD_OP_CREATE_FLOW_GROUP:
266 case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
267 case MLX5_CMD_OP_ALLOC_ENCAP_HEADER:
268 case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
269 case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
270 case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
271 case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
272 case MLX5_CMD_OP_CREATE_QP:
273 case MLX5_CMD_OP_CREATE_SRQ:
274 case MLX5_CMD_OP_CREATE_XRC_SRQ:
275 case MLX5_CMD_OP_CREATE_DCT:
276 case MLX5_CMD_OP_CREATE_XRQ:
277 case MLX5_CMD_OP_ATTACH_TO_MCG:
278 case MLX5_CMD_OP_ALLOC_XRCD:
279 return true;
280 case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
281 {
282 u16 op_mod = MLX5_GET(set_fte_in, in, op_mod);
283 if (op_mod == 0)
284 return true;
285 return false;
286 }
287 default:
288 return false;
289 }
290}
291
Yishai Hadase662e142018-06-17 13:00:02 +0300292static bool devx_is_obj_modify_cmd(const void *in)
293{
294 u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
295
296 switch (opcode) {
297 case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
298 case MLX5_CMD_OP_MODIFY_CQ:
299 case MLX5_CMD_OP_MODIFY_RMP:
300 case MLX5_CMD_OP_MODIFY_SQ:
301 case MLX5_CMD_OP_MODIFY_RQ:
302 case MLX5_CMD_OP_MODIFY_RQT:
303 case MLX5_CMD_OP_MODIFY_TIR:
304 case MLX5_CMD_OP_MODIFY_TIS:
305 case MLX5_CMD_OP_MODIFY_FLOW_TABLE:
306 case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
307 case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
308 case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
309 case MLX5_CMD_OP_RST2INIT_QP:
310 case MLX5_CMD_OP_INIT2RTR_QP:
311 case MLX5_CMD_OP_RTR2RTS_QP:
312 case MLX5_CMD_OP_RTS2RTS_QP:
313 case MLX5_CMD_OP_SQERR2RTS_QP:
314 case MLX5_CMD_OP_2ERR_QP:
315 case MLX5_CMD_OP_2RST_QP:
316 case MLX5_CMD_OP_ARM_XRC_SRQ:
317 case MLX5_CMD_OP_ARM_RQ:
318 case MLX5_CMD_OP_DRAIN_DCT:
319 case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
320 case MLX5_CMD_OP_ARM_XRQ:
321 return true;
322 case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
323 {
324 u16 op_mod = MLX5_GET(set_fte_in, in, op_mod);
325
326 if (op_mod == 1)
327 return true;
328 return false;
329 }
330 default:
331 return false;
332 }
333}
334
335static bool devx_is_obj_query_cmd(const void *in)
336{
337 u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
338
339 switch (opcode) {
340 case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
341 case MLX5_CMD_OP_QUERY_MKEY:
342 case MLX5_CMD_OP_QUERY_CQ:
343 case MLX5_CMD_OP_QUERY_RMP:
344 case MLX5_CMD_OP_QUERY_SQ:
345 case MLX5_CMD_OP_QUERY_RQ:
346 case MLX5_CMD_OP_QUERY_RQT:
347 case MLX5_CMD_OP_QUERY_TIR:
348 case MLX5_CMD_OP_QUERY_TIS:
349 case MLX5_CMD_OP_QUERY_Q_COUNTER:
350 case MLX5_CMD_OP_QUERY_FLOW_TABLE:
351 case MLX5_CMD_OP_QUERY_FLOW_GROUP:
352 case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
353 case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
354 case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT:
355 case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
356 case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
357 case MLX5_CMD_OP_QUERY_QP:
358 case MLX5_CMD_OP_QUERY_SRQ:
359 case MLX5_CMD_OP_QUERY_XRC_SRQ:
360 case MLX5_CMD_OP_QUERY_DCT:
361 case MLX5_CMD_OP_QUERY_XRQ:
362 return true;
363 default:
364 return false;
365 }
366}
367
368static bool devx_is_general_cmd(void *in)
Yishai Hadas8aa8c952018-06-17 13:00:00 +0300369{
370 u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
371
372 switch (opcode) {
373 case MLX5_CMD_OP_QUERY_HCA_CAP:
374 case MLX5_CMD_OP_QUERY_VPORT_STATE:
375 case MLX5_CMD_OP_QUERY_ADAPTER:
376 case MLX5_CMD_OP_QUERY_ISSI:
377 case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT:
378 case MLX5_CMD_OP_QUERY_ROCE_ADDRESS:
379 case MLX5_CMD_OP_QUERY_VNIC_ENV:
380 case MLX5_CMD_OP_QUERY_VPORT_COUNTER:
381 case MLX5_CMD_OP_GET_DROPPED_PACKET_LOG:
382 case MLX5_CMD_OP_NOP:
383 case MLX5_CMD_OP_QUERY_CONG_STATUS:
384 case MLX5_CMD_OP_QUERY_CONG_PARAMS:
385 case MLX5_CMD_OP_QUERY_CONG_STATISTICS:
386 return true;
387 default:
388 return false;
389 }
390}
391
Yishai Hadas7c043e92018-06-17 13:00:03 +0300392/*
393 *Security note:
394 * The hardware protection mechanism works like this: Each device object that
395 * is subject to UAR doorbells (QP/SQ/CQ) gets a UAR ID (called uar_page in
396 * the device specification manual) upon its creation. Then upon doorbell,
397 * hardware fetches the object context for which the doorbell was rang, and
398 * validates that the UAR through which the DB was rang matches the UAR ID
399 * of the object.
400 * If no match the doorbell is silently ignored by the hardware. Of course,
401 * the user cannot ring a doorbell on a UAR that was not mapped to it.
402 * Now in devx, as the devx kernel does not manipulate the QP/SQ/CQ command
403 * mailboxes (except tagging them with UID), we expose to the user its UAR
404 * ID, so it can embed it in these objects in the expected specification
405 * format. So the only thing the user can do is hurt itself by creating a
406 * QP/SQ/CQ with a UAR ID other than his, and then in this case other users
407 * may ring a doorbell on its objects.
408 * The consequence of that will be that another user can schedule a QP/SQ
409 * of the buggy user for execution (just insert it to the hardware schedule
410 * queue or arm its CQ for event generation), no further harm is expected.
411 */
412static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_UAR)(struct ib_device *ib_dev,
413 struct ib_uverbs_file *file,
414 struct uverbs_attr_bundle *attrs)
415{
416 struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
417 u32 user_idx;
418 s32 dev_idx;
419
420 if (uverbs_copy_from(&user_idx, attrs,
421 MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX))
422 return -EFAULT;
423
424 dev_idx = bfregn_to_uar_index(to_mdev(ib_dev),
425 &c->bfregi, user_idx, true);
426 if (dev_idx < 0)
427 return dev_idx;
428
429 if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX,
430 &dev_idx, sizeof(dev_idx)))
431 return -EFAULT;
432
433 return 0;
434}
435
Yishai Hadas8aa8c952018-06-17 13:00:00 +0300436static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)(struct ib_device *ib_dev,
437 struct ib_uverbs_file *file,
438 struct uverbs_attr_bundle *attrs)
439{
440 struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
441 struct mlx5_ib_dev *dev = to_mdev(ib_dev);
Yishai Hadas7efce362018-06-17 13:00:01 +0300442 void *cmd_in = uverbs_attr_get_alloced_ptr(
443 attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN);
Yishai Hadas8aa8c952018-06-17 13:00:00 +0300444 int cmd_out_len = uverbs_attr_get_len(attrs,
445 MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT);
446 void *cmd_out;
447 int err;
448
449 if (!c->devx_uid)
450 return -EPERM;
451
452 /* Only white list of some general HCA commands are allowed for this method. */
453 if (!devx_is_general_cmd(cmd_in))
454 return -EINVAL;
455
456 cmd_out = kvzalloc(cmd_out_len, GFP_KERNEL);
457 if (!cmd_out)
458 return -ENOMEM;
459
460 MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
461 err = mlx5_cmd_exec(dev->mdev, cmd_in,
462 uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN),
463 cmd_out, cmd_out_len);
464 if (err)
465 goto other_cmd_free;
466
467 err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, cmd_out, cmd_out_len);
468
469other_cmd_free:
470 kvfree(cmd_out);
471 return err;
472}
473
Yishai Hadas7efce362018-06-17 13:00:01 +0300474static void devx_obj_build_destroy_cmd(void *in, void *out, void *din,
475 u32 *dinlen,
476 u32 *obj_id)
477{
478 u16 obj_type = MLX5_GET(general_obj_in_cmd_hdr, in, obj_type);
479 u16 uid = MLX5_GET(general_obj_in_cmd_hdr, in, uid);
480
481 *obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
482 *dinlen = MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr);
483
484 MLX5_SET(general_obj_in_cmd_hdr, din, obj_id, *obj_id);
485 MLX5_SET(general_obj_in_cmd_hdr, din, uid, uid);
486
487 switch (MLX5_GET(general_obj_in_cmd_hdr, in, opcode)) {
488 case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
489 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
490 MLX5_SET(general_obj_in_cmd_hdr, din, obj_type, obj_type);
491 break;
492
493 case MLX5_CMD_OP_CREATE_MKEY:
494 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_MKEY);
495 break;
496 case MLX5_CMD_OP_CREATE_CQ:
497 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_CQ);
498 break;
499 case MLX5_CMD_OP_ALLOC_PD:
500 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DEALLOC_PD);
501 break;
502 case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
503 MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
504 MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN);
505 break;
506 case MLX5_CMD_OP_CREATE_RMP:
507 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RMP);
508 break;
509 case MLX5_CMD_OP_CREATE_SQ:
510 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_SQ);
511 break;
512 case MLX5_CMD_OP_CREATE_RQ:
513 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQ);
514 break;
515 case MLX5_CMD_OP_CREATE_RQT:
516 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQT);
517 break;
518 case MLX5_CMD_OP_CREATE_TIR:
519 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIR);
520 break;
521 case MLX5_CMD_OP_CREATE_TIS:
522 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIS);
523 break;
524 case MLX5_CMD_OP_ALLOC_Q_COUNTER:
525 MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
526 MLX5_CMD_OP_DEALLOC_Q_COUNTER);
527 break;
528 case MLX5_CMD_OP_CREATE_FLOW_TABLE:
529 *dinlen = MLX5_ST_SZ_BYTES(destroy_flow_table_in);
530 *obj_id = MLX5_GET(create_flow_table_out, out, table_id);
531 MLX5_SET(destroy_flow_table_in, din, other_vport,
532 MLX5_GET(create_flow_table_in, in, other_vport));
533 MLX5_SET(destroy_flow_table_in, din, vport_number,
534 MLX5_GET(create_flow_table_in, in, vport_number));
535 MLX5_SET(destroy_flow_table_in, din, table_type,
536 MLX5_GET(create_flow_table_in, in, table_type));
537 MLX5_SET(destroy_flow_table_in, din, table_id, *obj_id);
538 MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
539 MLX5_CMD_OP_DESTROY_FLOW_TABLE);
540 break;
541 case MLX5_CMD_OP_CREATE_FLOW_GROUP:
542 *dinlen = MLX5_ST_SZ_BYTES(destroy_flow_group_in);
543 *obj_id = MLX5_GET(create_flow_group_out, out, group_id);
544 MLX5_SET(destroy_flow_group_in, din, other_vport,
545 MLX5_GET(create_flow_group_in, in, other_vport));
546 MLX5_SET(destroy_flow_group_in, din, vport_number,
547 MLX5_GET(create_flow_group_in, in, vport_number));
548 MLX5_SET(destroy_flow_group_in, din, table_type,
549 MLX5_GET(create_flow_group_in, in, table_type));
550 MLX5_SET(destroy_flow_group_in, din, table_id,
551 MLX5_GET(create_flow_group_in, in, table_id));
552 MLX5_SET(destroy_flow_group_in, din, group_id, *obj_id);
553 MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
554 MLX5_CMD_OP_DESTROY_FLOW_GROUP);
555 break;
556 case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
557 *dinlen = MLX5_ST_SZ_BYTES(delete_fte_in);
558 *obj_id = MLX5_GET(set_fte_in, in, flow_index);
559 MLX5_SET(delete_fte_in, din, other_vport,
560 MLX5_GET(set_fte_in, in, other_vport));
561 MLX5_SET(delete_fte_in, din, vport_number,
562 MLX5_GET(set_fte_in, in, vport_number));
563 MLX5_SET(delete_fte_in, din, table_type,
564 MLX5_GET(set_fte_in, in, table_type));
565 MLX5_SET(delete_fte_in, din, table_id,
566 MLX5_GET(set_fte_in, in, table_id));
567 MLX5_SET(delete_fte_in, din, flow_index, *obj_id);
568 MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
569 MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
570 break;
571 case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
572 MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
573 MLX5_CMD_OP_DEALLOC_FLOW_COUNTER);
574 break;
575 case MLX5_CMD_OP_ALLOC_ENCAP_HEADER:
576 MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
577 MLX5_CMD_OP_DEALLOC_ENCAP_HEADER);
578 break;
579 case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
580 MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
581 MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT);
582 break;
583 case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
584 *dinlen = MLX5_ST_SZ_BYTES(destroy_scheduling_element_in);
585 *obj_id = MLX5_GET(create_scheduling_element_out, out,
586 scheduling_element_id);
587 MLX5_SET(destroy_scheduling_element_in, din,
588 scheduling_hierarchy,
589 MLX5_GET(create_scheduling_element_in, in,
590 scheduling_hierarchy));
591 MLX5_SET(destroy_scheduling_element_in, din,
592 scheduling_element_id, *obj_id);
593 MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
594 MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT);
595 break;
596 case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
597 *dinlen = MLX5_ST_SZ_BYTES(delete_vxlan_udp_dport_in);
598 *obj_id = MLX5_GET(add_vxlan_udp_dport_in, in, vxlan_udp_port);
599 MLX5_SET(delete_vxlan_udp_dport_in, din, vxlan_udp_port, *obj_id);
600 MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
601 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
602 break;
603 case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
604 *dinlen = MLX5_ST_SZ_BYTES(delete_l2_table_entry_in);
605 *obj_id = MLX5_GET(set_l2_table_entry_in, in, table_index);
606 MLX5_SET(delete_l2_table_entry_in, din, table_index, *obj_id);
607 MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
608 MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY);
609 break;
610 case MLX5_CMD_OP_CREATE_QP:
611 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_QP);
612 break;
613 case MLX5_CMD_OP_CREATE_SRQ:
614 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_SRQ);
615 break;
616 case MLX5_CMD_OP_CREATE_XRC_SRQ:
617 MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
618 MLX5_CMD_OP_DESTROY_XRC_SRQ);
619 break;
620 case MLX5_CMD_OP_CREATE_DCT:
621 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_DCT);
622 break;
623 case MLX5_CMD_OP_CREATE_XRQ:
624 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_XRQ);
625 break;
626 case MLX5_CMD_OP_ATTACH_TO_MCG:
627 *dinlen = MLX5_ST_SZ_BYTES(detach_from_mcg_in);
628 MLX5_SET(detach_from_mcg_in, din, qpn,
629 MLX5_GET(attach_to_mcg_in, in, qpn));
630 memcpy(MLX5_ADDR_OF(detach_from_mcg_in, din, multicast_gid),
631 MLX5_ADDR_OF(attach_to_mcg_in, in, multicast_gid),
632 MLX5_FLD_SZ_BYTES(attach_to_mcg_in, multicast_gid));
633 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DETACH_FROM_MCG);
634 break;
635 case MLX5_CMD_OP_ALLOC_XRCD:
636 MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DEALLOC_XRCD);
637 break;
638 default:
639 /* The entry must match to one of the devx_is_obj_create_cmd */
640 WARN_ON(true);
641 break;
642 }
643}
644
645static int devx_obj_cleanup(struct ib_uobject *uobject,
646 enum rdma_remove_reason why)
647{
648 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
649 struct devx_obj *obj = uobject->object;
650 int ret;
651
652 ret = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out));
653 if (ret && why == RDMA_REMOVE_DESTROY)
654 return ret;
655
656 kfree(obj);
657 return ret;
658}
659
660static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_DESTROY)(struct ib_device *ib_dev,
661 struct ib_uverbs_file *file,
662 struct uverbs_attr_bundle *attrs)
663{
664 return 0;
665}
666
667static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(struct ib_device *ib_dev,
668 struct ib_uverbs_file *file,
669 struct uverbs_attr_bundle *attrs)
670{
671 struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
672 struct mlx5_ib_dev *dev = to_mdev(ib_dev);
673 void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN);
674 int cmd_out_len = uverbs_attr_get_len(attrs,
675 MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT);
676 void *cmd_out;
677 struct ib_uobject *uobj;
678 struct devx_obj *obj;
679 int err;
680
681 if (!c->devx_uid)
682 return -EPERM;
683
684 if (!devx_is_obj_create_cmd(cmd_in))
685 return -EINVAL;
686
687 obj = kzalloc(sizeof(struct devx_obj), GFP_KERNEL);
688 if (!obj)
689 return -ENOMEM;
690
691 cmd_out = kvzalloc(cmd_out_len, GFP_KERNEL);
692 if (!cmd_out) {
693 err = -ENOMEM;
694 goto obj_free;
695 }
696
697 MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
698 err = mlx5_cmd_exec(dev->mdev, cmd_in,
699 uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN),
700 cmd_out, cmd_out_len);
701 if (err)
702 goto cmd_free;
703
704 uobj = uverbs_attr_get_uobject(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE);
705 uobj->object = obj;
706 obj->mdev = dev->mdev;
707 devx_obj_build_destroy_cmd(cmd_in, cmd_out, obj->dinbox, &obj->dinlen, &obj->obj_id);
708 WARN_ON(obj->dinlen > MLX5_MAX_DESTROY_INBOX_SIZE_DW * sizeof(u32));
709
710 err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, cmd_out, cmd_out_len);
711 if (err)
712 goto cmd_free;
713
714 kvfree(cmd_out);
715 return 0;
716
717cmd_free:
718 kvfree(cmd_out);
719obj_free:
720 kfree(obj);
721 return err;
722}
723
Yishai Hadase662e142018-06-17 13:00:02 +0300724static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)(struct ib_device *ib_dev,
725 struct ib_uverbs_file *file,
726 struct uverbs_attr_bundle *attrs)
727{
728 struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
729 struct mlx5_ib_dev *dev = to_mdev(ib_dev);
730 void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN);
731 int cmd_out_len = uverbs_attr_get_len(attrs,
732 MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT);
733 struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
734 MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE);
735 void *cmd_out;
736 int err;
737
738 if (!c->devx_uid)
739 return -EPERM;
740
741 if (!devx_is_obj_modify_cmd(cmd_in))
742 return -EINVAL;
743
744 if (!devx_is_valid_obj_id(uobj->object, cmd_in))
745 return -EINVAL;
746
747 cmd_out = kvzalloc(cmd_out_len, GFP_KERNEL);
748 if (!cmd_out)
749 return -ENOMEM;
750
751 MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
752 err = mlx5_cmd_exec(dev->mdev, cmd_in,
753 uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN),
754 cmd_out, cmd_out_len);
755 if (err)
756 goto other_cmd_free;
757
758 err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
759 cmd_out, cmd_out_len);
760
761other_cmd_free:
762 kvfree(cmd_out);
763 return err;
764}
765
766static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)(struct ib_device *ib_dev,
767 struct ib_uverbs_file *file,
768 struct uverbs_attr_bundle *attrs)
769{
770 struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
771 struct mlx5_ib_dev *dev = to_mdev(ib_dev);
772 void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN);
773 int cmd_out_len = uverbs_attr_get_len(attrs,
774 MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT);
775 struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
776 MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE);
777 void *cmd_out;
778 int err;
779
780 if (!c->devx_uid)
781 return -EPERM;
782
783 if (!devx_is_obj_query_cmd(cmd_in))
784 return -EINVAL;
785
786 if (!devx_is_valid_obj_id(uobj->object, cmd_in))
787 return -EINVAL;
788
789 cmd_out = kvzalloc(cmd_out_len, GFP_KERNEL);
790 if (!cmd_out)
791 return -ENOMEM;
792
793 MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
794 err = mlx5_cmd_exec(dev->mdev, cmd_in,
795 uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN),
796 cmd_out, cmd_out_len);
797 if (err)
798 goto other_cmd_free;
799
800 err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT, cmd_out, cmd_out_len);
801
802other_cmd_free:
803 kvfree(cmd_out);
804 return err;
805}
806
Yishai Hadasaeae9452018-06-17 13:00:04 +0300807static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext,
808 struct uverbs_attr_bundle *attrs,
809 struct devx_umem *obj)
810{
811 u64 addr;
812 size_t size;
813 int access;
814 int npages;
815 int err;
816 u32 page_mask;
817
818 if (uverbs_copy_from(&addr, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR) ||
819 uverbs_copy_from(&size, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_LEN) ||
820 uverbs_copy_from(&access, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS))
821 return -EFAULT;
822
823 err = ib_check_mr_access(access);
824 if (err)
825 return err;
826
827 obj->umem = ib_umem_get(ucontext, addr, size, access, 0);
828 if (IS_ERR(obj->umem))
829 return PTR_ERR(obj->umem);
830
831 mlx5_ib_cont_pages(obj->umem, obj->umem->address,
832 MLX5_MKEY_PAGE_SHIFT_MASK, &npages,
833 &obj->page_shift, &obj->ncont, NULL);
834
835 if (!npages) {
836 ib_umem_release(obj->umem);
837 return -EINVAL;
838 }
839
840 page_mask = (1 << obj->page_shift) - 1;
841 obj->page_offset = obj->umem->address & page_mask;
842
843 return 0;
844}
845
846static int devx_umem_reg_cmd_alloc(struct devx_umem *obj,
847 struct devx_umem_reg_cmd *cmd)
848{
849 cmd->inlen = MLX5_ST_SZ_BYTES(create_umem_in) +
850 (MLX5_ST_SZ_BYTES(mtt) * obj->ncont);
851 cmd->in = kvzalloc(cmd->inlen, GFP_KERNEL);
852 return cmd->in ? 0 : -ENOMEM;
853}
854
855static void devx_umem_reg_cmd_free(struct devx_umem_reg_cmd *cmd)
856{
857 kvfree(cmd->in);
858}
859
860static void devx_umem_reg_cmd_build(struct mlx5_ib_dev *dev,
861 struct devx_umem *obj,
862 struct devx_umem_reg_cmd *cmd)
863{
864 void *umem;
865 __be64 *mtt;
866
867 umem = MLX5_ADDR_OF(create_umem_in, cmd->in, umem);
868 mtt = (__be64 *)MLX5_ADDR_OF(umem, umem, mtt);
869
870 MLX5_SET(general_obj_in_cmd_hdr, cmd->in, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
871 MLX5_SET(general_obj_in_cmd_hdr, cmd->in, obj_type, MLX5_OBJ_TYPE_UMEM);
872 MLX5_SET64(umem, umem, num_of_mtt, obj->ncont);
873 MLX5_SET(umem, umem, log_page_size, obj->page_shift -
874 MLX5_ADAPTER_PAGE_SHIFT);
875 MLX5_SET(umem, umem, page_offset, obj->page_offset);
876 mlx5_ib_populate_pas(dev, obj->umem, obj->page_shift, mtt,
877 (obj->umem->writable ? MLX5_IB_MTT_WRITE : 0) |
878 MLX5_IB_MTT_READ);
879}
880
881static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_REG)(struct ib_device *ib_dev,
882 struct ib_uverbs_file *file,
883 struct uverbs_attr_bundle *attrs)
884{
885 struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
886 struct mlx5_ib_dev *dev = to_mdev(ib_dev);
887 struct devx_umem_reg_cmd cmd;
888 struct devx_umem *obj;
889 struct ib_uobject *uobj;
890 u32 obj_id;
891 int err;
892
893 if (!c->devx_uid)
894 return -EPERM;
895
896 uobj = uverbs_attr_get_uobject(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE);
897 obj = kzalloc(sizeof(struct devx_umem), GFP_KERNEL);
898 if (!obj)
899 return -ENOMEM;
900
901 err = devx_umem_get(dev, &c->ibucontext, attrs, obj);
902 if (err)
903 goto err_obj_free;
904
905 err = devx_umem_reg_cmd_alloc(obj, &cmd);
906 if (err)
907 goto err_umem_release;
908
909 devx_umem_reg_cmd_build(dev, obj, &cmd);
910
911 MLX5_SET(general_obj_in_cmd_hdr, cmd.in, uid, c->devx_uid);
912 err = mlx5_cmd_exec(dev->mdev, cmd.in, cmd.inlen, cmd.out,
913 sizeof(cmd.out));
914 if (err)
915 goto err_umem_reg_cmd_free;
916
917 obj->mdev = dev->mdev;
918 uobj->object = obj;
919 devx_obj_build_destroy_cmd(cmd.in, cmd.out, obj->dinbox, &obj->dinlen, &obj_id);
920 err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, &obj_id, sizeof(obj_id));
921 if (err)
922 goto err_umem_destroy;
923
924 devx_umem_reg_cmd_free(&cmd);
925
926 return 0;
927
928err_umem_destroy:
929 mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, cmd.out, sizeof(cmd.out));
930err_umem_reg_cmd_free:
931 devx_umem_reg_cmd_free(&cmd);
932err_umem_release:
933 ib_umem_release(obj->umem);
934err_obj_free:
935 kfree(obj);
936 return err;
937}
938
939static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_DEREG)(struct ib_device *ib_dev,
940 struct ib_uverbs_file *file,
941 struct uverbs_attr_bundle *attrs)
942{
943 return 0;
944}
945
946static int devx_umem_cleanup(struct ib_uobject *uobject,
947 enum rdma_remove_reason why)
948{
949 struct devx_umem *obj = uobject->object;
950 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
951 int err;
952
953 err = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out));
954 if (err && why == RDMA_REMOVE_DESTROY)
955 return err;
956
957 ib_umem_release(obj->umem);
958 kfree(obj);
959 return 0;
960}
961
962static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG,
963 &UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE,
964 MLX5_IB_OBJECT_DEVX_UMEM,
965 UVERBS_ACCESS_NEW,
966 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
967 &UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR, UVERBS_ATTR_TYPE(u64),
968 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
969 &UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_LEN, UVERBS_ATTR_TYPE(u64),
970 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
971 &UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS, UVERBS_ATTR_TYPE(u32),
972 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
973 &UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, UVERBS_ATTR_TYPE(u32),
974 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
975
976static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG,
977 &UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_DEREG_HANDLE,
978 MLX5_IB_OBJECT_DEVX_UMEM,
979 UVERBS_ACCESS_DESTROY,
980 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
981
Yishai Hadas7c043e92018-06-17 13:00:03 +0300982static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR,
983 &UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX, UVERBS_ATTR_TYPE(u32),
984 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
985 &UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX, UVERBS_ATTR_TYPE(u32),
986 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
987
Yishai Hadas8aa8c952018-06-17 13:00:00 +0300988static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OTHER,
989 &UVERBS_ATTR_PTR_IN_SZ(MLX5_IB_ATTR_DEVX_OTHER_CMD_IN,
990 UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
991 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
992 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO |
993 UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY)),
994 &UVERBS_ATTR_PTR_OUT_SZ(MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT,
995 UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
996 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
997 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO))
998);
999
Yishai Hadas7efce362018-06-17 13:00:01 +03001000static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OBJ_CREATE,
1001 &UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE,
1002 MLX5_IB_OBJECT_DEVX_OBJ,
1003 UVERBS_ACCESS_NEW,
1004 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
1005 &UVERBS_ATTR_PTR_IN_SZ(MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN,
1006 UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
1007 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
1008 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO |
1009 UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY)),
1010 &UVERBS_ATTR_PTR_OUT_SZ(MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT,
1011 UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
1012 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
1013 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO)));
1014
1015static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY,
1016 &UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_DESTROY_HANDLE,
1017 MLX5_IB_OBJECT_DEVX_OBJ,
1018 UVERBS_ACCESS_DESTROY,
1019 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
1020
Yishai Hadase662e142018-06-17 13:00:02 +03001021static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OBJ_MODIFY,
1022 &UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE,
1023 MLX5_IB_OBJECT_DEVX_OBJ,
1024 UVERBS_ACCESS_WRITE,
1025 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
1026 &UVERBS_ATTR_PTR_IN_SZ(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN,
1027 UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
1028 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
1029 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO |
1030 UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY)),
1031 &UVERBS_ATTR_PTR_OUT_SZ(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
1032 UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
1033 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
1034 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO)));
1035
1036static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY,
1037 &UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE,
1038 MLX5_IB_OBJECT_DEVX_OBJ,
1039 UVERBS_ACCESS_READ,
1040 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
1041 &UVERBS_ATTR_PTR_IN_SZ(MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN,
1042 UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
1043 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
1044 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO |
1045 UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY)),
1046 &UVERBS_ATTR_PTR_OUT_SZ(MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
1047 UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
1048 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
1049 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO)));
1050
Yishai Hadas8aa8c952018-06-17 13:00:00 +03001051static DECLARE_UVERBS_GLOBAL_METHODS(MLX5_IB_OBJECT_DEVX,
Yishai Hadas7c043e92018-06-17 13:00:03 +03001052 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OTHER),
1053 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR));
Yishai Hadas8aa8c952018-06-17 13:00:00 +03001054
Yishai Hadas7efce362018-06-17 13:00:01 +03001055static DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ,
1056 &UVERBS_TYPE_ALLOC_IDR(0, devx_obj_cleanup),
1057 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_CREATE),
Yishai Hadase662e142018-06-17 13:00:02 +03001058 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY),
1059 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_MODIFY),
1060 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY));
Yishai Hadas7efce362018-06-17 13:00:01 +03001061
Yishai Hadasaeae9452018-06-17 13:00:04 +03001062static DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM,
1063 &UVERBS_TYPE_ALLOC_IDR(0, devx_umem_cleanup),
1064 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG),
1065 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG));
1066
Yishai Hadas8aa8c952018-06-17 13:00:00 +03001067static DECLARE_UVERBS_OBJECT_TREE(devx_objects,
Yishai Hadas7efce362018-06-17 13:00:01 +03001068 &UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX),
Yishai Hadasaeae9452018-06-17 13:00:04 +03001069 &UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ),
1070 &UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM));