xref: /linux/drivers/infiniband/hw/mlx5/devx.c (revision 60786f0987c0d9354e5330ee11615b16cdb448fe)
1a8b92ca1SYishai Hadas // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2a8b92ca1SYishai Hadas /*
3a8b92ca1SYishai Hadas  * Copyright (c) 2018, Mellanox Technologies inc.  All rights reserved.
4a8b92ca1SYishai Hadas  */
5a8b92ca1SYishai Hadas 
6a8b92ca1SYishai Hadas #include <rdma/ib_user_verbs.h>
7a8b92ca1SYishai Hadas #include <rdma/ib_verbs.h>
8a8b92ca1SYishai Hadas #include <rdma/uverbs_types.h>
9a8b92ca1SYishai Hadas #include <rdma/uverbs_ioctl.h>
10a8b92ca1SYishai Hadas #include <rdma/mlx5_user_ioctl_cmds.h>
11a8b92ca1SYishai Hadas #include <rdma/ib_umem.h>
12a8b92ca1SYishai Hadas #include <linux/mlx5/driver.h>
13a8b92ca1SYishai Hadas #include <linux/mlx5/fs.h>
14a8b92ca1SYishai Hadas #include "mlx5_ib.h"
15a8b92ca1SYishai Hadas 
168aa8c95cSYishai Hadas #define UVERBS_MODULE_NAME mlx5_ib
178aa8c95cSYishai Hadas #include <rdma/uverbs_named_ioctl.h>
188aa8c95cSYishai Hadas 
197efce369SYishai Hadas #define MLX5_MAX_DESTROY_INBOX_SIZE_DW MLX5_ST_SZ_DW(delete_fte_in)
207efce369SYishai Hadas struct devx_obj {
217efce369SYishai Hadas 	struct mlx5_core_dev	*mdev;
227efce369SYishai Hadas 	u32			obj_id;
237efce369SYishai Hadas 	u32			dinlen; /* destroy inbox length */
247efce369SYishai Hadas 	u32			dinbox[MLX5_MAX_DESTROY_INBOX_SIZE_DW];
257efce369SYishai Hadas };
267efce369SYishai Hadas 
27aeae9457SYishai Hadas struct devx_umem {
28aeae9457SYishai Hadas 	struct mlx5_core_dev		*mdev;
29aeae9457SYishai Hadas 	struct ib_umem			*umem;
30aeae9457SYishai Hadas 	u32				page_offset;
31aeae9457SYishai Hadas 	int				page_shift;
32aeae9457SYishai Hadas 	int				ncont;
33aeae9457SYishai Hadas 	u32				dinlen;
34aeae9457SYishai Hadas 	u32				dinbox[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)];
35aeae9457SYishai Hadas };
36aeae9457SYishai Hadas 
37aeae9457SYishai Hadas struct devx_umem_reg_cmd {
38aeae9457SYishai Hadas 	void				*in;
39aeae9457SYishai Hadas 	u32				inlen;
40aeae9457SYishai Hadas 	u32				out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
41aeae9457SYishai Hadas };
42aeae9457SYishai Hadas 
438aa8c95cSYishai Hadas static struct mlx5_ib_ucontext *devx_ufile2uctx(struct ib_uverbs_file *file)
448aa8c95cSYishai Hadas {
458aa8c95cSYishai Hadas 	return to_mucontext(ib_uverbs_get_ucontext(file));
468aa8c95cSYishai Hadas }
478aa8c95cSYishai Hadas 
48a8b92ca1SYishai Hadas int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, struct mlx5_ib_ucontext *context)
49a8b92ca1SYishai Hadas {
50a8b92ca1SYishai Hadas 	u32 in[MLX5_ST_SZ_DW(create_uctx_in)] = {0};
51a8b92ca1SYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
52a8b92ca1SYishai Hadas 	u64 general_obj_types;
53a8b92ca1SYishai Hadas 	void *hdr;
54a8b92ca1SYishai Hadas 	int err;
55a8b92ca1SYishai Hadas 
56a8b92ca1SYishai Hadas 	hdr = MLX5_ADDR_OF(create_uctx_in, in, hdr);
57a8b92ca1SYishai Hadas 
58a8b92ca1SYishai Hadas 	general_obj_types = MLX5_CAP_GEN_64(dev->mdev, general_obj_types);
59a8b92ca1SYishai Hadas 	if (!(general_obj_types & MLX5_GENERAL_OBJ_TYPES_CAP_UCTX) ||
60a8b92ca1SYishai Hadas 	    !(general_obj_types & MLX5_GENERAL_OBJ_TYPES_CAP_UMEM))
61a8b92ca1SYishai Hadas 		return -EINVAL;
62a8b92ca1SYishai Hadas 
63a8b92ca1SYishai Hadas 	if (!capable(CAP_NET_RAW))
64a8b92ca1SYishai Hadas 		return -EPERM;
65a8b92ca1SYishai Hadas 
66a8b92ca1SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, hdr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
67a8b92ca1SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_type, MLX5_OBJ_TYPE_UCTX);
68a8b92ca1SYishai Hadas 
69a8b92ca1SYishai Hadas 	err = mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
70a8b92ca1SYishai Hadas 	if (err)
71a8b92ca1SYishai Hadas 		return err;
72a8b92ca1SYishai Hadas 
73a8b92ca1SYishai Hadas 	context->devx_uid = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
74a8b92ca1SYishai Hadas 	return 0;
75a8b92ca1SYishai Hadas }
76a8b92ca1SYishai Hadas 
77a8b92ca1SYishai Hadas void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev,
78a8b92ca1SYishai Hadas 			  struct mlx5_ib_ucontext *context)
79a8b92ca1SYishai Hadas {
80a8b92ca1SYishai Hadas 	u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {0};
81a8b92ca1SYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
82a8b92ca1SYishai Hadas 
83a8b92ca1SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
84a8b92ca1SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_OBJ_TYPE_UCTX);
85a8b92ca1SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, context->devx_uid);
86a8b92ca1SYishai Hadas 
87a8b92ca1SYishai Hadas 	mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
88a8b92ca1SYishai Hadas }
898aa8c95cSYishai Hadas 
9032269441SYishai Hadas bool mlx5_ib_devx_is_flow_dest(void *obj, int *dest_id, int *dest_type)
9132269441SYishai Hadas {
9232269441SYishai Hadas 	struct devx_obj *devx_obj = obj;
9332269441SYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode);
9432269441SYishai Hadas 
9532269441SYishai Hadas 	switch (opcode) {
9632269441SYishai Hadas 	case MLX5_CMD_OP_DESTROY_TIR:
9732269441SYishai Hadas 		*dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR;
9832269441SYishai Hadas 		*dest_id = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox,
9932269441SYishai Hadas 				    obj_id);
10032269441SYishai Hadas 		return true;
10132269441SYishai Hadas 
10232269441SYishai Hadas 	case MLX5_CMD_OP_DESTROY_FLOW_TABLE:
10332269441SYishai Hadas 		*dest_type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
10432269441SYishai Hadas 		*dest_id = MLX5_GET(destroy_flow_table_in, devx_obj->dinbox,
10532269441SYishai Hadas 				    table_id);
10632269441SYishai Hadas 		return true;
10732269441SYishai Hadas 	default:
10832269441SYishai Hadas 		return false;
10932269441SYishai Hadas 	}
11032269441SYishai Hadas }
11132269441SYishai Hadas 
112e662e14dSYishai Hadas static int devx_is_valid_obj_id(struct devx_obj *obj, const void *in)
113e662e14dSYishai Hadas {
114e662e14dSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
115e662e14dSYishai Hadas 	u32 obj_id;
116e662e14dSYishai Hadas 
117e662e14dSYishai Hadas 	switch (opcode) {
118e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
119e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
120e662e14dSYishai Hadas 		obj_id = MLX5_GET(general_obj_in_cmd_hdr, in, obj_id);
121e662e14dSYishai Hadas 		break;
122e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_MKEY:
123e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_mkey_in, in, mkey_index);
124e662e14dSYishai Hadas 		break;
125e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_CQ:
126e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_cq_in, in, cqn);
127e662e14dSYishai Hadas 		break;
128e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_CQ:
129e662e14dSYishai Hadas 		obj_id = MLX5_GET(modify_cq_in, in, cqn);
130e662e14dSYishai Hadas 		break;
131e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SQ:
132e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_sq_in, in, sqn);
133e662e14dSYishai Hadas 		break;
134e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_SQ:
135e662e14dSYishai Hadas 		obj_id = MLX5_GET(modify_sq_in, in, sqn);
136e662e14dSYishai Hadas 		break;
137e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RQ:
138e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_rq_in, in, rqn);
139e662e14dSYishai Hadas 		break;
140e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RQ:
141e662e14dSYishai Hadas 		obj_id = MLX5_GET(modify_rq_in, in, rqn);
142e662e14dSYishai Hadas 		break;
143e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RMP:
144e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_rmp_in, in, rmpn);
145e662e14dSYishai Hadas 		break;
146e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RMP:
147e662e14dSYishai Hadas 		obj_id = MLX5_GET(modify_rmp_in, in, rmpn);
148e662e14dSYishai Hadas 		break;
149e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RQT:
150e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_rqt_in, in, rqtn);
151e662e14dSYishai Hadas 		break;
152e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RQT:
153e662e14dSYishai Hadas 		obj_id = MLX5_GET(modify_rqt_in, in, rqtn);
154e662e14dSYishai Hadas 		break;
155e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_TIR:
156e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_tir_in, in, tirn);
157e662e14dSYishai Hadas 		break;
158e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_TIR:
159e662e14dSYishai Hadas 		obj_id = MLX5_GET(modify_tir_in, in, tirn);
160e662e14dSYishai Hadas 		break;
161e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_TIS:
162e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_tis_in, in, tisn);
163e662e14dSYishai Hadas 		break;
164e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_TIS:
165e662e14dSYishai Hadas 		obj_id = MLX5_GET(modify_tis_in, in, tisn);
166e662e14dSYishai Hadas 		break;
167e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_TABLE:
168e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_flow_table_in, in, table_id);
169e662e14dSYishai Hadas 		break;
170e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_FLOW_TABLE:
171e662e14dSYishai Hadas 		obj_id = MLX5_GET(modify_flow_table_in, in, table_id);
172e662e14dSYishai Hadas 		break;
173e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_GROUP:
174e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_flow_group_in, in, group_id);
175e662e14dSYishai Hadas 		break;
176e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
177e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_fte_in, in, flow_index);
178e662e14dSYishai Hadas 		break;
179e662e14dSYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
180e662e14dSYishai Hadas 		obj_id = MLX5_GET(set_fte_in, in, flow_index);
181e662e14dSYishai Hadas 		break;
182e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_Q_COUNTER:
183e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_q_counter_in, in, counter_set_id);
184e662e14dSYishai Hadas 		break;
185e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
186e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_flow_counter_in, in, flow_counter_id);
187e662e14dSYishai Hadas 		break;
188e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT:
189e662e14dSYishai Hadas 		obj_id = MLX5_GET(general_obj_in_cmd_hdr, in, obj_id);
190e662e14dSYishai Hadas 		break;
191e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
192e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_scheduling_element_in, in,
193e662e14dSYishai Hadas 				  scheduling_element_id);
194e662e14dSYishai Hadas 		break;
195e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
196e662e14dSYishai Hadas 		obj_id = MLX5_GET(modify_scheduling_element_in, in,
197e662e14dSYishai Hadas 				  scheduling_element_id);
198e662e14dSYishai Hadas 		break;
199e662e14dSYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
200e662e14dSYishai Hadas 		obj_id = MLX5_GET(add_vxlan_udp_dport_in, in, vxlan_udp_port);
201e662e14dSYishai Hadas 		break;
202e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
203e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_l2_table_entry_in, in, table_index);
204e662e14dSYishai Hadas 		break;
205e662e14dSYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
206e662e14dSYishai Hadas 		obj_id = MLX5_GET(set_l2_table_entry_in, in, table_index);
207e662e14dSYishai Hadas 		break;
208e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_QP:
209e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_qp_in, in, qpn);
210e662e14dSYishai Hadas 		break;
211e662e14dSYishai Hadas 	case MLX5_CMD_OP_RST2INIT_QP:
212e662e14dSYishai Hadas 		obj_id = MLX5_GET(rst2init_qp_in, in, qpn);
213e662e14dSYishai Hadas 		break;
214e662e14dSYishai Hadas 	case MLX5_CMD_OP_INIT2RTR_QP:
215e662e14dSYishai Hadas 		obj_id = MLX5_GET(init2rtr_qp_in, in, qpn);
216e662e14dSYishai Hadas 		break;
217e662e14dSYishai Hadas 	case MLX5_CMD_OP_RTR2RTS_QP:
218e662e14dSYishai Hadas 		obj_id = MLX5_GET(rtr2rts_qp_in, in, qpn);
219e662e14dSYishai Hadas 		break;
220e662e14dSYishai Hadas 	case MLX5_CMD_OP_RTS2RTS_QP:
221e662e14dSYishai Hadas 		obj_id = MLX5_GET(rts2rts_qp_in, in, qpn);
222e662e14dSYishai Hadas 		break;
223e662e14dSYishai Hadas 	case MLX5_CMD_OP_SQERR2RTS_QP:
224e662e14dSYishai Hadas 		obj_id = MLX5_GET(sqerr2rts_qp_in, in, qpn);
225e662e14dSYishai Hadas 		break;
226e662e14dSYishai Hadas 	case MLX5_CMD_OP_2ERR_QP:
227e662e14dSYishai Hadas 		obj_id = MLX5_GET(qp_2err_in, in, qpn);
228e662e14dSYishai Hadas 		break;
229e662e14dSYishai Hadas 	case MLX5_CMD_OP_2RST_QP:
230e662e14dSYishai Hadas 		obj_id = MLX5_GET(qp_2rst_in, in, qpn);
231e662e14dSYishai Hadas 		break;
232e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_DCT:
233e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_dct_in, in, dctn);
234e662e14dSYishai Hadas 		break;
235e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ:
236e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_xrq_in, in, xrqn);
237e662e14dSYishai Hadas 		break;
238e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_XRC_SRQ:
239e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_xrc_srq_in, in, xrc_srqn);
240e662e14dSYishai Hadas 		break;
241e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_XRC_SRQ:
242e662e14dSYishai Hadas 		obj_id = MLX5_GET(arm_xrc_srq_in, in, xrc_srqn);
243e662e14dSYishai Hadas 		break;
244e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SRQ:
245e662e14dSYishai Hadas 		obj_id = MLX5_GET(query_srq_in, in, srqn);
246e662e14dSYishai Hadas 		break;
247e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_RQ:
248e662e14dSYishai Hadas 		obj_id = MLX5_GET(arm_rq_in, in, srq_number);
249e662e14dSYishai Hadas 		break;
250e662e14dSYishai Hadas 	case MLX5_CMD_OP_DRAIN_DCT:
251e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
252e662e14dSYishai Hadas 		obj_id = MLX5_GET(drain_dct_in, in, dctn);
253e662e14dSYishai Hadas 		break;
254e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_XRQ:
255e662e14dSYishai Hadas 		obj_id = MLX5_GET(arm_xrq_in, in, xrqn);
256e662e14dSYishai Hadas 		break;
257e662e14dSYishai Hadas 	default:
258e662e14dSYishai Hadas 		return false;
259e662e14dSYishai Hadas 	}
260e662e14dSYishai Hadas 
261e662e14dSYishai Hadas 	if (obj_id == obj->obj_id)
262e662e14dSYishai Hadas 		return true;
263e662e14dSYishai Hadas 
264e662e14dSYishai Hadas 	return false;
265e662e14dSYishai Hadas }
266e662e14dSYishai Hadas 
2677efce369SYishai Hadas static bool devx_is_obj_create_cmd(const void *in)
2687efce369SYishai Hadas {
2697efce369SYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
2707efce369SYishai Hadas 
2717efce369SYishai Hadas 	switch (opcode) {
2727efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
2737efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_MKEY:
2747efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_CQ:
2757efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_PD:
2767efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
2777efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RMP:
2787efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
2797efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
2807efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQT:
2817efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIR:
2827efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIS:
2837efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_Q_COUNTER:
2847efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_TABLE:
2857efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_GROUP:
2867efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
287*60786f09SMark Bloch 	case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT:
2887efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
2897efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
2907efce369SYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
2917efce369SYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
2927efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
2937efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SRQ:
2947efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
2957efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_DCT:
2967efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRQ:
2977efce369SYishai Hadas 	case MLX5_CMD_OP_ATTACH_TO_MCG:
2987efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_XRCD:
2997efce369SYishai Hadas 		return true;
3007efce369SYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
3017efce369SYishai Hadas 	{
3027efce369SYishai Hadas 		u16 op_mod = MLX5_GET(set_fte_in, in, op_mod);
3037efce369SYishai Hadas 		if (op_mod == 0)
3047efce369SYishai Hadas 			return true;
3057efce369SYishai Hadas 		return false;
3067efce369SYishai Hadas 	}
3077efce369SYishai Hadas 	default:
3087efce369SYishai Hadas 		return false;
3097efce369SYishai Hadas 	}
3107efce369SYishai Hadas }
3117efce369SYishai Hadas 
312e662e14dSYishai Hadas static bool devx_is_obj_modify_cmd(const void *in)
313e662e14dSYishai Hadas {
314e662e14dSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
315e662e14dSYishai Hadas 
316e662e14dSYishai Hadas 	switch (opcode) {
317e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
318e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_CQ:
319e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RMP:
320e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_SQ:
321e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RQ:
322e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RQT:
323e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_TIR:
324e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_TIS:
325e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_FLOW_TABLE:
326e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
327e662e14dSYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
328e662e14dSYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
329e662e14dSYishai Hadas 	case MLX5_CMD_OP_RST2INIT_QP:
330e662e14dSYishai Hadas 	case MLX5_CMD_OP_INIT2RTR_QP:
331e662e14dSYishai Hadas 	case MLX5_CMD_OP_RTR2RTS_QP:
332e662e14dSYishai Hadas 	case MLX5_CMD_OP_RTS2RTS_QP:
333e662e14dSYishai Hadas 	case MLX5_CMD_OP_SQERR2RTS_QP:
334e662e14dSYishai Hadas 	case MLX5_CMD_OP_2ERR_QP:
335e662e14dSYishai Hadas 	case MLX5_CMD_OP_2RST_QP:
336e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_XRC_SRQ:
337e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_RQ:
338e662e14dSYishai Hadas 	case MLX5_CMD_OP_DRAIN_DCT:
339e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
340e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_XRQ:
341e662e14dSYishai Hadas 		return true;
342e662e14dSYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
343e662e14dSYishai Hadas 	{
344e662e14dSYishai Hadas 		u16 op_mod = MLX5_GET(set_fte_in, in, op_mod);
345e662e14dSYishai Hadas 
346e662e14dSYishai Hadas 		if (op_mod == 1)
347e662e14dSYishai Hadas 			return true;
348e662e14dSYishai Hadas 		return false;
349e662e14dSYishai Hadas 	}
350e662e14dSYishai Hadas 	default:
351e662e14dSYishai Hadas 		return false;
352e662e14dSYishai Hadas 	}
353e662e14dSYishai Hadas }
354e662e14dSYishai Hadas 
355e662e14dSYishai Hadas static bool devx_is_obj_query_cmd(const void *in)
356e662e14dSYishai Hadas {
357e662e14dSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
358e662e14dSYishai Hadas 
359e662e14dSYishai Hadas 	switch (opcode) {
360e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
361e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_MKEY:
362e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_CQ:
363e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RMP:
364e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SQ:
365e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RQ:
366e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RQT:
367e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_TIR:
368e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_TIS:
369e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_Q_COUNTER:
370e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_TABLE:
371e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_GROUP:
372e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
373e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
374e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT:
375e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
376e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
377e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_QP:
378e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SRQ:
379e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_XRC_SRQ:
380e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_DCT:
381e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ:
382e662e14dSYishai Hadas 		return true;
383e662e14dSYishai Hadas 	default:
384e662e14dSYishai Hadas 		return false;
385e662e14dSYishai Hadas 	}
386e662e14dSYishai Hadas }
387e662e14dSYishai Hadas 
388e662e14dSYishai Hadas static bool devx_is_general_cmd(void *in)
3898aa8c95cSYishai Hadas {
3908aa8c95cSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
3918aa8c95cSYishai Hadas 
3928aa8c95cSYishai Hadas 	switch (opcode) {
3938aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_HCA_CAP:
3948aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_VPORT_STATE:
3958aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_ADAPTER:
3968aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_ISSI:
3978aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT:
3988aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_ROCE_ADDRESS:
3998aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_VNIC_ENV:
4008aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_VPORT_COUNTER:
4018aa8c95cSYishai Hadas 	case MLX5_CMD_OP_GET_DROPPED_PACKET_LOG:
4028aa8c95cSYishai Hadas 	case MLX5_CMD_OP_NOP:
4038aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_CONG_STATUS:
4048aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_CONG_PARAMS:
4058aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_CONG_STATISTICS:
4068aa8c95cSYishai Hadas 		return true;
4078aa8c95cSYishai Hadas 	default:
4088aa8c95cSYishai Hadas 		return false;
4098aa8c95cSYishai Hadas 	}
4108aa8c95cSYishai Hadas }
4118aa8c95cSYishai Hadas 
412e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_EQN)(
413e83f0ecdSJason Gunthorpe 	struct ib_uverbs_file *file, struct uverbs_attr_bundle *attrs)
414f6fe01b7SYishai Hadas {
415e83f0ecdSJason Gunthorpe 	struct mlx5_ib_ucontext *c;
416e83f0ecdSJason Gunthorpe 	struct mlx5_ib_dev *dev;
417f6fe01b7SYishai Hadas 	int user_vector;
418f6fe01b7SYishai Hadas 	int dev_eqn;
419f6fe01b7SYishai Hadas 	unsigned int irqn;
420f6fe01b7SYishai Hadas 	int err;
421f6fe01b7SYishai Hadas 
422f6fe01b7SYishai Hadas 	if (uverbs_copy_from(&user_vector, attrs,
423f6fe01b7SYishai Hadas 			     MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC))
424f6fe01b7SYishai Hadas 		return -EFAULT;
425f6fe01b7SYishai Hadas 
426e83f0ecdSJason Gunthorpe 	c = devx_ufile2uctx(file);
427e83f0ecdSJason Gunthorpe 	if (IS_ERR(c))
428e83f0ecdSJason Gunthorpe 		return PTR_ERR(c);
429e83f0ecdSJason Gunthorpe 	dev = to_mdev(c->ibucontext.device);
430e83f0ecdSJason Gunthorpe 
431f6fe01b7SYishai Hadas 	err = mlx5_vector2eqn(dev->mdev, user_vector, &dev_eqn, &irqn);
432f6fe01b7SYishai Hadas 	if (err < 0)
433f6fe01b7SYishai Hadas 		return err;
434f6fe01b7SYishai Hadas 
435f6fe01b7SYishai Hadas 	if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN,
436f6fe01b7SYishai Hadas 			   &dev_eqn, sizeof(dev_eqn)))
437f6fe01b7SYishai Hadas 		return -EFAULT;
438f6fe01b7SYishai Hadas 
439f6fe01b7SYishai Hadas 	return 0;
440f6fe01b7SYishai Hadas }
441f6fe01b7SYishai Hadas 
4427c043e90SYishai Hadas /*
4437c043e90SYishai Hadas  *Security note:
4447c043e90SYishai Hadas  * The hardware protection mechanism works like this: Each device object that
4457c043e90SYishai Hadas  * is subject to UAR doorbells (QP/SQ/CQ) gets a UAR ID (called uar_page in
4467c043e90SYishai Hadas  * the device specification manual) upon its creation. Then upon doorbell,
4477c043e90SYishai Hadas  * hardware fetches the object context for which the doorbell was rang, and
4487c043e90SYishai Hadas  * validates that the UAR through which the DB was rang matches the UAR ID
4497c043e90SYishai Hadas  * of the object.
4507c043e90SYishai Hadas  * If no match the doorbell is silently ignored by the hardware. Of course,
4517c043e90SYishai Hadas  * the user cannot ring a doorbell on a UAR that was not mapped to it.
4527c043e90SYishai Hadas  * Now in devx, as the devx kernel does not manipulate the QP/SQ/CQ command
4537c043e90SYishai Hadas  * mailboxes (except tagging them with UID), we expose to the user its UAR
4547c043e90SYishai Hadas  * ID, so it can embed it in these objects in the expected specification
4557c043e90SYishai Hadas  * format. So the only thing the user can do is hurt itself by creating a
4567c043e90SYishai Hadas  * QP/SQ/CQ with a UAR ID other than his, and then in this case other users
4577c043e90SYishai Hadas  * may ring a doorbell on its objects.
4587c043e90SYishai Hadas  * The consequence of that will be that another user can schedule a QP/SQ
4597c043e90SYishai Hadas  * of the buggy user for execution (just insert it to the hardware schedule
4607c043e90SYishai Hadas  * queue or arm its CQ for event generation), no further harm is expected.
4617c043e90SYishai Hadas  */
462e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_UAR)(
463e83f0ecdSJason Gunthorpe 	struct ib_uverbs_file *file, struct uverbs_attr_bundle *attrs)
4647c043e90SYishai Hadas {
46522fa27fbSJason Gunthorpe 	struct mlx5_ib_ucontext *c;
46622fa27fbSJason Gunthorpe 	struct mlx5_ib_dev *dev;
4677c043e90SYishai Hadas 	u32 user_idx;
4687c043e90SYishai Hadas 	s32 dev_idx;
4697c043e90SYishai Hadas 
47022fa27fbSJason Gunthorpe 	c = devx_ufile2uctx(file);
47122fa27fbSJason Gunthorpe 	if (IS_ERR(c))
47222fa27fbSJason Gunthorpe 		return PTR_ERR(c);
47322fa27fbSJason Gunthorpe 	dev = to_mdev(c->ibucontext.device);
47422fa27fbSJason Gunthorpe 
4757c043e90SYishai Hadas 	if (uverbs_copy_from(&user_idx, attrs,
4767c043e90SYishai Hadas 			     MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX))
4777c043e90SYishai Hadas 		return -EFAULT;
4787c043e90SYishai Hadas 
47922fa27fbSJason Gunthorpe 	dev_idx = bfregn_to_uar_index(dev, &c->bfregi, user_idx, true);
4807c043e90SYishai Hadas 	if (dev_idx < 0)
4817c043e90SYishai Hadas 		return dev_idx;
4827c043e90SYishai Hadas 
4837c043e90SYishai Hadas 	if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX,
4847c043e90SYishai Hadas 			   &dev_idx, sizeof(dev_idx)))
4857c043e90SYishai Hadas 		return -EFAULT;
4867c043e90SYishai Hadas 
4877c043e90SYishai Hadas 	return 0;
4887c043e90SYishai Hadas }
4897c043e90SYishai Hadas 
490e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)(
491e83f0ecdSJason Gunthorpe 	struct ib_uverbs_file *file, struct uverbs_attr_bundle *attrs)
4928aa8c95cSYishai Hadas {
49322fa27fbSJason Gunthorpe 	struct mlx5_ib_ucontext *c;
49422fa27fbSJason Gunthorpe 	struct mlx5_ib_dev *dev;
4957efce369SYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(
4967efce369SYishai Hadas 		attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN);
4978aa8c95cSYishai Hadas 	int cmd_out_len = uverbs_attr_get_len(attrs,
4988aa8c95cSYishai Hadas 					MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT);
4998aa8c95cSYishai Hadas 	void *cmd_out;
5008aa8c95cSYishai Hadas 	int err;
5018aa8c95cSYishai Hadas 
50222fa27fbSJason Gunthorpe 	c = devx_ufile2uctx(file);
50322fa27fbSJason Gunthorpe 	if (IS_ERR(c))
50422fa27fbSJason Gunthorpe 		return PTR_ERR(c);
50522fa27fbSJason Gunthorpe 	dev = to_mdev(c->ibucontext.device);
50622fa27fbSJason Gunthorpe 
5078aa8c95cSYishai Hadas 	if (!c->devx_uid)
5088aa8c95cSYishai Hadas 		return -EPERM;
5098aa8c95cSYishai Hadas 
5108aa8c95cSYishai Hadas 	/* Only white list of some general HCA commands are allowed for this method. */
5118aa8c95cSYishai Hadas 	if (!devx_is_general_cmd(cmd_in))
5128aa8c95cSYishai Hadas 		return -EINVAL;
5138aa8c95cSYishai Hadas 
514b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
515b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
516b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
5178aa8c95cSYishai Hadas 
5188aa8c95cSYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
5198aa8c95cSYishai Hadas 	err = mlx5_cmd_exec(dev->mdev, cmd_in,
5208aa8c95cSYishai Hadas 			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN),
5218aa8c95cSYishai Hadas 			    cmd_out, cmd_out_len);
5228aa8c95cSYishai Hadas 	if (err)
5238aa8c95cSYishai Hadas 		return err;
524b61815e2SJason Gunthorpe 
525b61815e2SJason Gunthorpe 	return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, cmd_out,
526b61815e2SJason Gunthorpe 			      cmd_out_len);
5278aa8c95cSYishai Hadas }
5288aa8c95cSYishai Hadas 
5297efce369SYishai Hadas static void devx_obj_build_destroy_cmd(void *in, void *out, void *din,
5307efce369SYishai Hadas 				       u32 *dinlen,
5317efce369SYishai Hadas 				       u32 *obj_id)
5327efce369SYishai Hadas {
5337efce369SYishai Hadas 	u16 obj_type = MLX5_GET(general_obj_in_cmd_hdr, in, obj_type);
5347efce369SYishai Hadas 	u16 uid = MLX5_GET(general_obj_in_cmd_hdr, in, uid);
5357efce369SYishai Hadas 
5367efce369SYishai Hadas 	*obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
5377efce369SYishai Hadas 	*dinlen = MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr);
5387efce369SYishai Hadas 
5397efce369SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, din, obj_id, *obj_id);
5407efce369SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, din, uid, uid);
5417efce369SYishai Hadas 
5427efce369SYishai Hadas 	switch (MLX5_GET(general_obj_in_cmd_hdr, in, opcode)) {
5437efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
5447efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
5457efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, obj_type, obj_type);
5467efce369SYishai Hadas 		break;
5477efce369SYishai Hadas 
5487efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_MKEY:
5497efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_MKEY);
5507efce369SYishai Hadas 		break;
5517efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_CQ:
5527efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_CQ);
5537efce369SYishai Hadas 		break;
5547efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_PD:
5557efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DEALLOC_PD);
5567efce369SYishai Hadas 		break;
5577efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
5587efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
5597efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN);
5607efce369SYishai Hadas 		break;
5617efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RMP:
5627efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RMP);
5637efce369SYishai Hadas 		break;
5647efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
5657efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_SQ);
5667efce369SYishai Hadas 		break;
5677efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
5687efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQ);
5697efce369SYishai Hadas 		break;
5707efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQT:
5717efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQT);
5727efce369SYishai Hadas 		break;
5737efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIR:
5747efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIR);
5757efce369SYishai Hadas 		break;
5767efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIS:
5777efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIS);
5787efce369SYishai Hadas 		break;
5797efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_Q_COUNTER:
5807efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
5817efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_Q_COUNTER);
5827efce369SYishai Hadas 		break;
5837efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_TABLE:
5847efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(destroy_flow_table_in);
5857efce369SYishai Hadas 		*obj_id = MLX5_GET(create_flow_table_out, out, table_id);
5867efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, other_vport,
5877efce369SYishai Hadas 			 MLX5_GET(create_flow_table_in,  in, other_vport));
5887efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, vport_number,
5897efce369SYishai Hadas 			 MLX5_GET(create_flow_table_in,  in, vport_number));
5907efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, table_type,
5917efce369SYishai Hadas 			 MLX5_GET(create_flow_table_in,  in, table_type));
5927efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, table_id, *obj_id);
5937efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
5947efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_FLOW_TABLE);
5957efce369SYishai Hadas 		break;
5967efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_GROUP:
5977efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(destroy_flow_group_in);
5987efce369SYishai Hadas 		*obj_id = MLX5_GET(create_flow_group_out, out, group_id);
5997efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, other_vport,
6007efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, other_vport));
6017efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, vport_number,
6027efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, vport_number));
6037efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, table_type,
6047efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, table_type));
6057efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, table_id,
6067efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, table_id));
6077efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, group_id, *obj_id);
6087efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
6097efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_FLOW_GROUP);
6107efce369SYishai Hadas 		break;
6117efce369SYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
6127efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(delete_fte_in);
6137efce369SYishai Hadas 		*obj_id = MLX5_GET(set_fte_in, in, flow_index);
6147efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, other_vport,
6157efce369SYishai Hadas 			 MLX5_GET(set_fte_in,  in, other_vport));
6167efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, vport_number,
6177efce369SYishai Hadas 			 MLX5_GET(set_fte_in, in, vport_number));
6187efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, table_type,
6197efce369SYishai Hadas 			 MLX5_GET(set_fte_in, in, table_type));
6207efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, table_id,
6217efce369SYishai Hadas 			 MLX5_GET(set_fte_in, in, table_id));
6227efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, flow_index, *obj_id);
6237efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
6247efce369SYishai Hadas 			 MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
6257efce369SYishai Hadas 		break;
6267efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
6277efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
6287efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_FLOW_COUNTER);
6297efce369SYishai Hadas 		break;
630*60786f09SMark Bloch 	case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT:
6317efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
632*60786f09SMark Bloch 			 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
6337efce369SYishai Hadas 		break;
6347efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
6357efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
6367efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT);
6377efce369SYishai Hadas 		break;
6387efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
6397efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(destroy_scheduling_element_in);
6407efce369SYishai Hadas 		*obj_id = MLX5_GET(create_scheduling_element_out, out,
6417efce369SYishai Hadas 				   scheduling_element_id);
6427efce369SYishai Hadas 		MLX5_SET(destroy_scheduling_element_in, din,
6437efce369SYishai Hadas 			 scheduling_hierarchy,
6447efce369SYishai Hadas 			 MLX5_GET(create_scheduling_element_in, in,
6457efce369SYishai Hadas 				  scheduling_hierarchy));
6467efce369SYishai Hadas 		MLX5_SET(destroy_scheduling_element_in, din,
6477efce369SYishai Hadas 			 scheduling_element_id, *obj_id);
6487efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
6497efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT);
6507efce369SYishai Hadas 		break;
6517efce369SYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
6527efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(delete_vxlan_udp_dport_in);
6537efce369SYishai Hadas 		*obj_id = MLX5_GET(add_vxlan_udp_dport_in, in, vxlan_udp_port);
6547efce369SYishai Hadas 		MLX5_SET(delete_vxlan_udp_dport_in, din, vxlan_udp_port, *obj_id);
6557efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
6567efce369SYishai Hadas 			 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
6577efce369SYishai Hadas 		break;
6587efce369SYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
6597efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(delete_l2_table_entry_in);
6607efce369SYishai Hadas 		*obj_id = MLX5_GET(set_l2_table_entry_in, in, table_index);
6617efce369SYishai Hadas 		MLX5_SET(delete_l2_table_entry_in, din, table_index, *obj_id);
6627efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
6637efce369SYishai Hadas 			 MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY);
6647efce369SYishai Hadas 		break;
6657efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
6667efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_QP);
6677efce369SYishai Hadas 		break;
6687efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SRQ:
6697efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_SRQ);
6707efce369SYishai Hadas 		break;
6717efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
6727efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
6737efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_XRC_SRQ);
6747efce369SYishai Hadas 		break;
6757efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_DCT:
6767efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_DCT);
6777efce369SYishai Hadas 		break;
6787efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRQ:
6797efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_XRQ);
6807efce369SYishai Hadas 		break;
6817efce369SYishai Hadas 	case MLX5_CMD_OP_ATTACH_TO_MCG:
6827efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(detach_from_mcg_in);
6837efce369SYishai Hadas 		MLX5_SET(detach_from_mcg_in, din, qpn,
6847efce369SYishai Hadas 			 MLX5_GET(attach_to_mcg_in, in, qpn));
6857efce369SYishai Hadas 		memcpy(MLX5_ADDR_OF(detach_from_mcg_in, din, multicast_gid),
6867efce369SYishai Hadas 		       MLX5_ADDR_OF(attach_to_mcg_in, in, multicast_gid),
6877efce369SYishai Hadas 		       MLX5_FLD_SZ_BYTES(attach_to_mcg_in, multicast_gid));
6887efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DETACH_FROM_MCG);
6897efce369SYishai Hadas 		break;
6907efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_XRCD:
6917efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DEALLOC_XRCD);
6927efce369SYishai Hadas 		break;
6937efce369SYishai Hadas 	default:
6947efce369SYishai Hadas 		/* The entry must match to one of the devx_is_obj_create_cmd */
6957efce369SYishai Hadas 		WARN_ON(true);
6967efce369SYishai Hadas 		break;
6977efce369SYishai Hadas 	}
6987efce369SYishai Hadas }
6997efce369SYishai Hadas 
7007efce369SYishai Hadas static int devx_obj_cleanup(struct ib_uobject *uobject,
7017efce369SYishai Hadas 			    enum rdma_remove_reason why)
7027efce369SYishai Hadas {
7037efce369SYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
7047efce369SYishai Hadas 	struct devx_obj *obj = uobject->object;
7057efce369SYishai Hadas 	int ret;
7067efce369SYishai Hadas 
7077efce369SYishai Hadas 	ret = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out));
7081c77483eSYishai Hadas 	if (ib_is_destroy_retryable(ret, why, uobject))
7097efce369SYishai Hadas 		return ret;
7107efce369SYishai Hadas 
7117efce369SYishai Hadas 	kfree(obj);
7127efce369SYishai Hadas 	return ret;
7137efce369SYishai Hadas }
7147efce369SYishai Hadas 
715e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
716e83f0ecdSJason Gunthorpe 	struct ib_uverbs_file *file, struct uverbs_attr_bundle *attrs)
7177efce369SYishai Hadas {
7187efce369SYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN);
7197efce369SYishai Hadas 	int cmd_out_len =  uverbs_attr_get_len(attrs,
7207efce369SYishai Hadas 					MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT);
7217efce369SYishai Hadas 	void *cmd_out;
722c36ee46dSJason Gunthorpe 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
723c36ee46dSJason Gunthorpe 		attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE);
724c36ee46dSJason Gunthorpe 	struct mlx5_ib_ucontext *c = to_mucontext(uobj->context);
725c36ee46dSJason Gunthorpe 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
7267efce369SYishai Hadas 	struct devx_obj *obj;
7277efce369SYishai Hadas 	int err;
7287efce369SYishai Hadas 
7297efce369SYishai Hadas 	if (!c->devx_uid)
7307efce369SYishai Hadas 		return -EPERM;
7317efce369SYishai Hadas 
7327efce369SYishai Hadas 	if (!devx_is_obj_create_cmd(cmd_in))
7337efce369SYishai Hadas 		return -EINVAL;
7347efce369SYishai Hadas 
735b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
736b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
737b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
738b61815e2SJason Gunthorpe 
7397efce369SYishai Hadas 	obj = kzalloc(sizeof(struct devx_obj), GFP_KERNEL);
7407efce369SYishai Hadas 	if (!obj)
7417efce369SYishai Hadas 		return -ENOMEM;
7427efce369SYishai Hadas 
7437efce369SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
7447efce369SYishai Hadas 	err = mlx5_cmd_exec(dev->mdev, cmd_in,
7457efce369SYishai Hadas 			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN),
7467efce369SYishai Hadas 			    cmd_out, cmd_out_len);
7477efce369SYishai Hadas 	if (err)
748b61815e2SJason Gunthorpe 		goto obj_free;
7497efce369SYishai Hadas 
7507efce369SYishai Hadas 	uobj->object = obj;
7517efce369SYishai Hadas 	obj->mdev = dev->mdev;
7527efce369SYishai Hadas 	devx_obj_build_destroy_cmd(cmd_in, cmd_out, obj->dinbox, &obj->dinlen, &obj->obj_id);
7537efce369SYishai Hadas 	WARN_ON(obj->dinlen > MLX5_MAX_DESTROY_INBOX_SIZE_DW * sizeof(u32));
7547efce369SYishai Hadas 
7557efce369SYishai Hadas 	err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, cmd_out, cmd_out_len);
7567efce369SYishai Hadas 	if (err)
757b61815e2SJason Gunthorpe 		goto obj_free;
7587efce369SYishai Hadas 
7597efce369SYishai Hadas 	return 0;
7607efce369SYishai Hadas 
7617efce369SYishai Hadas obj_free:
7627efce369SYishai Hadas 	kfree(obj);
7637efce369SYishai Hadas 	return err;
7647efce369SYishai Hadas }
7657efce369SYishai Hadas 
766e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)(
767e83f0ecdSJason Gunthorpe 	struct ib_uverbs_file *file, struct uverbs_attr_bundle *attrs)
768e662e14dSYishai Hadas {
769e662e14dSYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN);
770e662e14dSYishai Hadas 	int cmd_out_len = uverbs_attr_get_len(attrs,
771e662e14dSYishai Hadas 					MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT);
772e662e14dSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
773e662e14dSYishai Hadas 							  MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE);
774c36ee46dSJason Gunthorpe 	struct mlx5_ib_ucontext *c = to_mucontext(uobj->context);
775c36ee46dSJason Gunthorpe 	struct devx_obj *obj = uobj->object;
776e662e14dSYishai Hadas 	void *cmd_out;
777e662e14dSYishai Hadas 	int err;
778e662e14dSYishai Hadas 
779e662e14dSYishai Hadas 	if (!c->devx_uid)
780e662e14dSYishai Hadas 		return -EPERM;
781e662e14dSYishai Hadas 
782e662e14dSYishai Hadas 	if (!devx_is_obj_modify_cmd(cmd_in))
783e662e14dSYishai Hadas 		return -EINVAL;
784e662e14dSYishai Hadas 
785c36ee46dSJason Gunthorpe 	if (!devx_is_valid_obj_id(obj, cmd_in))
786e662e14dSYishai Hadas 		return -EINVAL;
787e662e14dSYishai Hadas 
788b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
789b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
790b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
791e662e14dSYishai Hadas 
792e662e14dSYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
793c36ee46dSJason Gunthorpe 	err = mlx5_cmd_exec(obj->mdev, cmd_in,
794e662e14dSYishai Hadas 			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN),
795e662e14dSYishai Hadas 			    cmd_out, cmd_out_len);
796e662e14dSYishai Hadas 	if (err)
797e662e14dSYishai Hadas 		return err;
798b61815e2SJason Gunthorpe 
799b61815e2SJason Gunthorpe 	return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
800b61815e2SJason Gunthorpe 			      cmd_out, cmd_out_len);
801e662e14dSYishai Hadas }
802e662e14dSYishai Hadas 
803e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)(
804e83f0ecdSJason Gunthorpe 	struct ib_uverbs_file *file, struct uverbs_attr_bundle *attrs)
805e662e14dSYishai Hadas {
806e662e14dSYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN);
807e662e14dSYishai Hadas 	int cmd_out_len = uverbs_attr_get_len(attrs,
808e662e14dSYishai Hadas 					      MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT);
809e662e14dSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
810e662e14dSYishai Hadas 							  MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE);
811c36ee46dSJason Gunthorpe 	struct mlx5_ib_ucontext *c = to_mucontext(uobj->context);
812c36ee46dSJason Gunthorpe 	struct devx_obj *obj = uobj->object;
813e662e14dSYishai Hadas 	void *cmd_out;
814e662e14dSYishai Hadas 	int err;
815e662e14dSYishai Hadas 
816e662e14dSYishai Hadas 	if (!c->devx_uid)
817e662e14dSYishai Hadas 		return -EPERM;
818e662e14dSYishai Hadas 
819e662e14dSYishai Hadas 	if (!devx_is_obj_query_cmd(cmd_in))
820e662e14dSYishai Hadas 		return -EINVAL;
821e662e14dSYishai Hadas 
822c36ee46dSJason Gunthorpe 	if (!devx_is_valid_obj_id(obj, cmd_in))
823e662e14dSYishai Hadas 		return -EINVAL;
824e662e14dSYishai Hadas 
825b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
826b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
827b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
828e662e14dSYishai Hadas 
829e662e14dSYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
830c36ee46dSJason Gunthorpe 	err = mlx5_cmd_exec(obj->mdev, cmd_in,
831e662e14dSYishai Hadas 			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN),
832e662e14dSYishai Hadas 			    cmd_out, cmd_out_len);
833e662e14dSYishai Hadas 	if (err)
834e662e14dSYishai Hadas 		return err;
835b61815e2SJason Gunthorpe 
836b61815e2SJason Gunthorpe 	return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
837b61815e2SJason Gunthorpe 			      cmd_out, cmd_out_len);
838e662e14dSYishai Hadas }
839e662e14dSYishai Hadas 
840aeae9457SYishai Hadas static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext,
841aeae9457SYishai Hadas 			 struct uverbs_attr_bundle *attrs,
842aeae9457SYishai Hadas 			 struct devx_umem *obj)
843aeae9457SYishai Hadas {
844aeae9457SYishai Hadas 	u64 addr;
845aeae9457SYishai Hadas 	size_t size;
846bccd0622SJason Gunthorpe 	u32 access;
847aeae9457SYishai Hadas 	int npages;
848aeae9457SYishai Hadas 	int err;
849aeae9457SYishai Hadas 	u32 page_mask;
850aeae9457SYishai Hadas 
851aeae9457SYishai Hadas 	if (uverbs_copy_from(&addr, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR) ||
852bccd0622SJason Gunthorpe 	    uverbs_copy_from(&size, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_LEN))
853aeae9457SYishai Hadas 		return -EFAULT;
854aeae9457SYishai Hadas 
855bccd0622SJason Gunthorpe 	err = uverbs_get_flags32(&access, attrs,
856bccd0622SJason Gunthorpe 				 MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
857bccd0622SJason Gunthorpe 				 IB_ACCESS_SUPPORTED);
858bccd0622SJason Gunthorpe 	if (err)
859bccd0622SJason Gunthorpe 		return err;
860bccd0622SJason Gunthorpe 
861aeae9457SYishai Hadas 	err = ib_check_mr_access(access);
862aeae9457SYishai Hadas 	if (err)
863aeae9457SYishai Hadas 		return err;
864aeae9457SYishai Hadas 
865aeae9457SYishai Hadas 	obj->umem = ib_umem_get(ucontext, addr, size, access, 0);
866aeae9457SYishai Hadas 	if (IS_ERR(obj->umem))
867aeae9457SYishai Hadas 		return PTR_ERR(obj->umem);
868aeae9457SYishai Hadas 
869aeae9457SYishai Hadas 	mlx5_ib_cont_pages(obj->umem, obj->umem->address,
870aeae9457SYishai Hadas 			   MLX5_MKEY_PAGE_SHIFT_MASK, &npages,
871aeae9457SYishai Hadas 			   &obj->page_shift, &obj->ncont, NULL);
872aeae9457SYishai Hadas 
873aeae9457SYishai Hadas 	if (!npages) {
874aeae9457SYishai Hadas 		ib_umem_release(obj->umem);
875aeae9457SYishai Hadas 		return -EINVAL;
876aeae9457SYishai Hadas 	}
877aeae9457SYishai Hadas 
878aeae9457SYishai Hadas 	page_mask = (1 << obj->page_shift) - 1;
879aeae9457SYishai Hadas 	obj->page_offset = obj->umem->address & page_mask;
880aeae9457SYishai Hadas 
881aeae9457SYishai Hadas 	return 0;
882aeae9457SYishai Hadas }
883aeae9457SYishai Hadas 
884b61815e2SJason Gunthorpe static int devx_umem_reg_cmd_alloc(struct uverbs_attr_bundle *attrs,
885b61815e2SJason Gunthorpe 				   struct devx_umem *obj,
886aeae9457SYishai Hadas 				   struct devx_umem_reg_cmd *cmd)
887aeae9457SYishai Hadas {
888aeae9457SYishai Hadas 	cmd->inlen = MLX5_ST_SZ_BYTES(create_umem_in) +
889aeae9457SYishai Hadas 		    (MLX5_ST_SZ_BYTES(mtt) * obj->ncont);
890b61815e2SJason Gunthorpe 	cmd->in = uverbs_zalloc(attrs, cmd->inlen);
891b61815e2SJason Gunthorpe 	return PTR_ERR_OR_ZERO(cmd->in);
892aeae9457SYishai Hadas }
893aeae9457SYishai Hadas 
894aeae9457SYishai Hadas static void devx_umem_reg_cmd_build(struct mlx5_ib_dev *dev,
895aeae9457SYishai Hadas 				    struct devx_umem *obj,
896aeae9457SYishai Hadas 				    struct devx_umem_reg_cmd *cmd)
897aeae9457SYishai Hadas {
898aeae9457SYishai Hadas 	void *umem;
899aeae9457SYishai Hadas 	__be64 *mtt;
900aeae9457SYishai Hadas 
901aeae9457SYishai Hadas 	umem = MLX5_ADDR_OF(create_umem_in, cmd->in, umem);
902aeae9457SYishai Hadas 	mtt = (__be64 *)MLX5_ADDR_OF(umem, umem, mtt);
903aeae9457SYishai Hadas 
904aeae9457SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd->in, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
905aeae9457SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd->in, obj_type, MLX5_OBJ_TYPE_UMEM);
906aeae9457SYishai Hadas 	MLX5_SET64(umem, umem, num_of_mtt, obj->ncont);
907aeae9457SYishai Hadas 	MLX5_SET(umem, umem, log_page_size, obj->page_shift -
908aeae9457SYishai Hadas 					    MLX5_ADAPTER_PAGE_SHIFT);
909aeae9457SYishai Hadas 	MLX5_SET(umem, umem, page_offset, obj->page_offset);
910aeae9457SYishai Hadas 	mlx5_ib_populate_pas(dev, obj->umem, obj->page_shift, mtt,
911aeae9457SYishai Hadas 			     (obj->umem->writable ? MLX5_IB_MTT_WRITE : 0) |
912aeae9457SYishai Hadas 			     MLX5_IB_MTT_READ);
913aeae9457SYishai Hadas }
914aeae9457SYishai Hadas 
915e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_REG)(
916e83f0ecdSJason Gunthorpe 	struct ib_uverbs_file *file, struct uverbs_attr_bundle *attrs)
917aeae9457SYishai Hadas {
918aeae9457SYishai Hadas 	struct devx_umem_reg_cmd cmd;
919aeae9457SYishai Hadas 	struct devx_umem *obj;
920c36ee46dSJason Gunthorpe 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
921c36ee46dSJason Gunthorpe 		attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE);
922aeae9457SYishai Hadas 	u32 obj_id;
923c36ee46dSJason Gunthorpe 	struct mlx5_ib_ucontext *c = to_mucontext(uobj->context);
924c36ee46dSJason Gunthorpe 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
925aeae9457SYishai Hadas 	int err;
926aeae9457SYishai Hadas 
927aeae9457SYishai Hadas 	if (!c->devx_uid)
928aeae9457SYishai Hadas 		return -EPERM;
929aeae9457SYishai Hadas 
930aeae9457SYishai Hadas 	obj = kzalloc(sizeof(struct devx_umem), GFP_KERNEL);
931aeae9457SYishai Hadas 	if (!obj)
932aeae9457SYishai Hadas 		return -ENOMEM;
933aeae9457SYishai Hadas 
934aeae9457SYishai Hadas 	err = devx_umem_get(dev, &c->ibucontext, attrs, obj);
935aeae9457SYishai Hadas 	if (err)
936aeae9457SYishai Hadas 		goto err_obj_free;
937aeae9457SYishai Hadas 
938b61815e2SJason Gunthorpe 	err = devx_umem_reg_cmd_alloc(attrs, obj, &cmd);
939aeae9457SYishai Hadas 	if (err)
940aeae9457SYishai Hadas 		goto err_umem_release;
941aeae9457SYishai Hadas 
942aeae9457SYishai Hadas 	devx_umem_reg_cmd_build(dev, obj, &cmd);
943aeae9457SYishai Hadas 
944aeae9457SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd.in, uid, c->devx_uid);
945aeae9457SYishai Hadas 	err = mlx5_cmd_exec(dev->mdev, cmd.in, cmd.inlen, cmd.out,
946aeae9457SYishai Hadas 			    sizeof(cmd.out));
947aeae9457SYishai Hadas 	if (err)
948b61815e2SJason Gunthorpe 		goto err_umem_release;
949aeae9457SYishai Hadas 
950aeae9457SYishai Hadas 	obj->mdev = dev->mdev;
951aeae9457SYishai Hadas 	uobj->object = obj;
952aeae9457SYishai Hadas 	devx_obj_build_destroy_cmd(cmd.in, cmd.out, obj->dinbox, &obj->dinlen, &obj_id);
953aeae9457SYishai Hadas 	err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, &obj_id, sizeof(obj_id));
954aeae9457SYishai Hadas 	if (err)
955aeae9457SYishai Hadas 		goto err_umem_destroy;
956aeae9457SYishai Hadas 
957aeae9457SYishai Hadas 	return 0;
958aeae9457SYishai Hadas 
959aeae9457SYishai Hadas err_umem_destroy:
960aeae9457SYishai Hadas 	mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, cmd.out, sizeof(cmd.out));
961aeae9457SYishai Hadas err_umem_release:
962aeae9457SYishai Hadas 	ib_umem_release(obj->umem);
963aeae9457SYishai Hadas err_obj_free:
964aeae9457SYishai Hadas 	kfree(obj);
965aeae9457SYishai Hadas 	return err;
966aeae9457SYishai Hadas }
967aeae9457SYishai Hadas 
968aeae9457SYishai Hadas static int devx_umem_cleanup(struct ib_uobject *uobject,
969aeae9457SYishai Hadas 			     enum rdma_remove_reason why)
970aeae9457SYishai Hadas {
971aeae9457SYishai Hadas 	struct devx_umem *obj = uobject->object;
972aeae9457SYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
973aeae9457SYishai Hadas 	int err;
974aeae9457SYishai Hadas 
975aeae9457SYishai Hadas 	err = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out));
9761c77483eSYishai Hadas 	if (ib_is_destroy_retryable(err, why, uobject))
977aeae9457SYishai Hadas 		return err;
978aeae9457SYishai Hadas 
979aeae9457SYishai Hadas 	ib_umem_release(obj->umem);
980aeae9457SYishai Hadas 	kfree(obj);
981aeae9457SYishai Hadas 	return 0;
982aeae9457SYishai Hadas }
983aeae9457SYishai Hadas 
9849a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
9859a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_UMEM_REG,
9869a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE,
987aeae9457SYishai Hadas 			MLX5_IB_OBJECT_DEVX_UMEM,
988aeae9457SYishai Hadas 			UVERBS_ACCESS_NEW,
98983bb4442SJason Gunthorpe 			UA_MANDATORY),
9909a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR,
9919a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u64),
99283bb4442SJason Gunthorpe 			   UA_MANDATORY),
9939a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_LEN,
9949a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u64),
99583bb4442SJason Gunthorpe 			   UA_MANDATORY),
996bccd0622SJason Gunthorpe 	UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
997bccd0622SJason Gunthorpe 			     enum ib_access_flags),
9989a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID,
9999a119cd5SJason Gunthorpe 			    UVERBS_ATTR_TYPE(u32),
100083bb4442SJason Gunthorpe 			    UA_MANDATORY));
1001aeae9457SYishai Hadas 
1002528922afSYishai Hadas DECLARE_UVERBS_NAMED_METHOD_DESTROY(
10039a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_UMEM_DEREG,
10049a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_DEREG_HANDLE,
1005aeae9457SYishai Hadas 			MLX5_IB_OBJECT_DEVX_UMEM,
1006aeae9457SYishai Hadas 			UVERBS_ACCESS_DESTROY,
100783bb4442SJason Gunthorpe 			UA_MANDATORY));
1008aeae9457SYishai Hadas 
10099a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
10109a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_QUERY_EQN,
10119a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC,
10129a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u32),
101383bb4442SJason Gunthorpe 			   UA_MANDATORY),
10149a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN,
10159a119cd5SJason Gunthorpe 			    UVERBS_ATTR_TYPE(u32),
101683bb4442SJason Gunthorpe 			    UA_MANDATORY));
1017f6fe01b7SYishai Hadas 
10189a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
10199a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_QUERY_UAR,
10209a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX,
10219a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u32),
102283bb4442SJason Gunthorpe 			   UA_MANDATORY),
10239a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX,
10249a119cd5SJason Gunthorpe 			    UVERBS_ATTR_TYPE(u32),
102583bb4442SJason Gunthorpe 			    UA_MANDATORY));
10267c043e90SYishai Hadas 
10279a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
10289a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OTHER,
10299a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
10309a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OTHER_CMD_IN,
10318aa8c95cSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
103283bb4442SJason Gunthorpe 		UA_MANDATORY,
103383bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
10349a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
10359a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT,
10367efce369SYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
1037540cd692SJason Gunthorpe 		UA_MANDATORY));
10387efce369SYishai Hadas 
10399a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
10409a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_CREATE,
10419a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE,
10429a119cd5SJason Gunthorpe 			MLX5_IB_OBJECT_DEVX_OBJ,
10439a119cd5SJason Gunthorpe 			UVERBS_ACCESS_NEW,
104483bb4442SJason Gunthorpe 			UA_MANDATORY),
10459a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
10469a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN,
10479a119cd5SJason Gunthorpe 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
104883bb4442SJason Gunthorpe 		UA_MANDATORY,
104983bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
10509a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
10519a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT,
10529a119cd5SJason Gunthorpe 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
1053540cd692SJason Gunthorpe 		UA_MANDATORY));
10549a119cd5SJason Gunthorpe 
1055528922afSYishai Hadas DECLARE_UVERBS_NAMED_METHOD_DESTROY(
10569a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_DESTROY,
10579a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_DESTROY_HANDLE,
10587efce369SYishai Hadas 			MLX5_IB_OBJECT_DEVX_OBJ,
10597efce369SYishai Hadas 			UVERBS_ACCESS_DESTROY,
106083bb4442SJason Gunthorpe 			UA_MANDATORY));
10617efce369SYishai Hadas 
10629a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
10639a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_MODIFY,
10649a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE,
1065e662e14dSYishai Hadas 			MLX5_IB_OBJECT_DEVX_OBJ,
1066e662e14dSYishai Hadas 			UVERBS_ACCESS_WRITE,
106783bb4442SJason Gunthorpe 			UA_MANDATORY),
10689a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
10699a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN,
1070e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
107183bb4442SJason Gunthorpe 		UA_MANDATORY,
107283bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
10739a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
10749a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
1075e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
1076540cd692SJason Gunthorpe 		UA_MANDATORY));
1077e662e14dSYishai Hadas 
10789a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
10799a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_QUERY,
10809a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE,
1081e662e14dSYishai Hadas 			MLX5_IB_OBJECT_DEVX_OBJ,
1082e662e14dSYishai Hadas 			UVERBS_ACCESS_READ,
108383bb4442SJason Gunthorpe 			UA_MANDATORY),
10849a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
10859a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN,
1086e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
108783bb4442SJason Gunthorpe 		UA_MANDATORY,
108883bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
10899a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
10909a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
1091e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
1092540cd692SJason Gunthorpe 		UA_MANDATORY));
1093e662e14dSYishai Hadas 
10946c61d2a5SJason Gunthorpe DECLARE_UVERBS_GLOBAL_METHODS(MLX5_IB_OBJECT_DEVX,
10957c043e90SYishai Hadas 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OTHER),
1096f6fe01b7SYishai Hadas 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR),
1097f6fe01b7SYishai Hadas 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_EQN));
10988aa8c95cSYishai Hadas 
10996c61d2a5SJason Gunthorpe DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ,
11009a119cd5SJason Gunthorpe 			    UVERBS_TYPE_ALLOC_IDR(devx_obj_cleanup),
11017efce369SYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_CREATE),
1102e662e14dSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY),
1103e662e14dSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_MODIFY),
1104e662e14dSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY));
11057efce369SYishai Hadas 
11066c61d2a5SJason Gunthorpe DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM,
11079a119cd5SJason Gunthorpe 			    UVERBS_TYPE_ALLOC_IDR(devx_umem_cleanup),
1108aeae9457SYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG),
1109aeae9457SYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG));
1110aeae9457SYishai Hadas 
11116c61d2a5SJason Gunthorpe DECLARE_UVERBS_OBJECT_TREE(devx_objects,
11127efce369SYishai Hadas 			   &UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX),
1113aeae9457SYishai Hadas 			   &UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ),
1114aeae9457SYishai Hadas 			   &UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM));
1115c59450c4SYishai Hadas 
1116c59450c4SYishai Hadas const struct uverbs_object_tree_def *mlx5_ib_get_devx_tree(void)
1117c59450c4SYishai Hadas {
1118c59450c4SYishai Hadas 	return &devx_objects;
1119c59450c4SYishai Hadas }
1120