xref: /linux/drivers/infiniband/hw/mlx5/devx.c (revision c5ae1954c47d3fd8815bd5a592aba18702c93f33)
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>
11a124edbaSYishai Hadas #include <rdma/mlx5_user_ioctl_verbs.h>
12a8b92ca1SYishai Hadas #include <rdma/ib_umem.h>
1334613eb1SYishai Hadas #include <rdma/uverbs_std_types.h>
14a8b92ca1SYishai Hadas #include <linux/mlx5/driver.h>
15a8b92ca1SYishai Hadas #include <linux/mlx5/fs.h>
16a8b92ca1SYishai Hadas #include "mlx5_ib.h"
17a8b92ca1SYishai Hadas 
188aa8c95cSYishai Hadas #define UVERBS_MODULE_NAME mlx5_ib
198aa8c95cSYishai Hadas #include <rdma/uverbs_named_ioctl.h>
208aa8c95cSYishai Hadas 
21534fd7aaSYishai Hadas enum devx_obj_flags {
22534fd7aaSYishai Hadas 	DEVX_OBJ_FLAGS_INDIRECT_MKEY = 1 << 0,
23*c5ae1954SYishai Hadas 	DEVX_OBJ_FLAGS_DCT = 1 << 1,
24534fd7aaSYishai Hadas };
25534fd7aaSYishai Hadas 
26a124edbaSYishai Hadas struct devx_async_data {
27a124edbaSYishai Hadas 	struct mlx5_ib_dev *mdev;
28a124edbaSYishai Hadas 	struct list_head list;
29a124edbaSYishai Hadas 	struct ib_uobject *fd_uobj;
30a124edbaSYishai Hadas 	struct mlx5_async_work cb_work;
31a124edbaSYishai Hadas 	u16 cmd_out_len;
32a124edbaSYishai Hadas 	/* must be last field in this structure */
33a124edbaSYishai Hadas 	struct mlx5_ib_uapi_devx_async_cmd_hdr hdr;
34a124edbaSYishai Hadas };
35a124edbaSYishai Hadas 
367efce369SYishai Hadas #define MLX5_MAX_DESTROY_INBOX_SIZE_DW MLX5_ST_SZ_DW(delete_fte_in)
377efce369SYishai Hadas struct devx_obj {
387efce369SYishai Hadas 	struct mlx5_core_dev	*mdev;
392351776eSYishai Hadas 	u64			obj_id;
407efce369SYishai Hadas 	u32			dinlen; /* destroy inbox length */
417efce369SYishai Hadas 	u32			dinbox[MLX5_MAX_DESTROY_INBOX_SIZE_DW];
42534fd7aaSYishai Hadas 	u32			flags;
43*c5ae1954SYishai Hadas 	union {
44534fd7aaSYishai Hadas 		struct mlx5_ib_devx_mr	devx_mr;
45*c5ae1954SYishai Hadas 		struct mlx5_core_dct	core_dct;
46*c5ae1954SYishai Hadas 	};
477efce369SYishai Hadas };
487efce369SYishai Hadas 
49aeae9457SYishai Hadas struct devx_umem {
50aeae9457SYishai Hadas 	struct mlx5_core_dev		*mdev;
51aeae9457SYishai Hadas 	struct ib_umem			*umem;
52aeae9457SYishai Hadas 	u32				page_offset;
53aeae9457SYishai Hadas 	int				page_shift;
54aeae9457SYishai Hadas 	int				ncont;
55aeae9457SYishai Hadas 	u32				dinlen;
56aeae9457SYishai Hadas 	u32				dinbox[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)];
57aeae9457SYishai Hadas };
58aeae9457SYishai Hadas 
59aeae9457SYishai Hadas struct devx_umem_reg_cmd {
60aeae9457SYishai Hadas 	void				*in;
61aeae9457SYishai Hadas 	u32				inlen;
62aeae9457SYishai Hadas 	u32				out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
63aeae9457SYishai Hadas };
64aeae9457SYishai Hadas 
6515a1b4beSJason Gunthorpe static struct mlx5_ib_ucontext *
6615a1b4beSJason Gunthorpe devx_ufile2uctx(const struct uverbs_attr_bundle *attrs)
678aa8c95cSYishai Hadas {
6815a1b4beSJason Gunthorpe 	return to_mucontext(ib_uverbs_get_ucontext(attrs));
698aa8c95cSYishai Hadas }
708aa8c95cSYishai Hadas 
71fb98153bSYishai Hadas int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user)
72a8b92ca1SYishai Hadas {
73a8b92ca1SYishai Hadas 	u32 in[MLX5_ST_SZ_DW(create_uctx_in)] = {0};
74a8b92ca1SYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
756e3722baSYishai Hadas 	void *uctx;
76a8b92ca1SYishai Hadas 	int err;
7776dc5a84SYishai Hadas 	u16 uid;
78fb98153bSYishai Hadas 	u32 cap = 0;
79a8b92ca1SYishai Hadas 
806e3722baSYishai Hadas 	/* 0 means not supported */
816e3722baSYishai Hadas 	if (!MLX5_CAP_GEN(dev->mdev, log_max_uctx))
82a8b92ca1SYishai Hadas 		return -EINVAL;
83a8b92ca1SYishai Hadas 
846e3722baSYishai Hadas 	uctx = MLX5_ADDR_OF(create_uctx_in, in, uctx);
85fb98153bSYishai Hadas 	if (is_user && capable(CAP_NET_RAW) &&
86fb98153bSYishai Hadas 	    (MLX5_CAP_GEN(dev->mdev, uctx_cap) & MLX5_UCTX_CAP_RAW_TX))
87fb98153bSYishai Hadas 		cap |= MLX5_UCTX_CAP_RAW_TX;
88fb98153bSYishai Hadas 
896e3722baSYishai Hadas 	MLX5_SET(create_uctx_in, in, opcode, MLX5_CMD_OP_CREATE_UCTX);
90fb98153bSYishai Hadas 	MLX5_SET(uctx, uctx, cap, cap);
91a8b92ca1SYishai Hadas 
92a8b92ca1SYishai Hadas 	err = mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
93a8b92ca1SYishai Hadas 	if (err)
94a8b92ca1SYishai Hadas 		return err;
95a8b92ca1SYishai Hadas 
9676dc5a84SYishai Hadas 	uid = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
9776dc5a84SYishai Hadas 	return uid;
98a8b92ca1SYishai Hadas }
99a8b92ca1SYishai Hadas 
10076dc5a84SYishai Hadas void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev, u16 uid)
101a8b92ca1SYishai Hadas {
1026e3722baSYishai Hadas 	u32 in[MLX5_ST_SZ_DW(destroy_uctx_in)] = {0};
103a8b92ca1SYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
104a8b92ca1SYishai Hadas 
1056e3722baSYishai Hadas 	MLX5_SET(destroy_uctx_in, in, opcode, MLX5_CMD_OP_DESTROY_UCTX);
1066e3722baSYishai Hadas 	MLX5_SET(destroy_uctx_in, in, uid, uid);
107a8b92ca1SYishai Hadas 
108a8b92ca1SYishai Hadas 	mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
109a8b92ca1SYishai Hadas }
1108aa8c95cSYishai Hadas 
11132269441SYishai Hadas bool mlx5_ib_devx_is_flow_dest(void *obj, int *dest_id, int *dest_type)
11232269441SYishai Hadas {
11332269441SYishai Hadas 	struct devx_obj *devx_obj = obj;
11432269441SYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode);
11532269441SYishai Hadas 
11632269441SYishai Hadas 	switch (opcode) {
11732269441SYishai Hadas 	case MLX5_CMD_OP_DESTROY_TIR:
11832269441SYishai Hadas 		*dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR;
11932269441SYishai Hadas 		*dest_id = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox,
12032269441SYishai Hadas 				    obj_id);
12132269441SYishai Hadas 		return true;
12232269441SYishai Hadas 
12332269441SYishai Hadas 	case MLX5_CMD_OP_DESTROY_FLOW_TABLE:
12432269441SYishai Hadas 		*dest_type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
12532269441SYishai Hadas 		*dest_id = MLX5_GET(destroy_flow_table_in, devx_obj->dinbox,
12632269441SYishai Hadas 				    table_id);
12732269441SYishai Hadas 		return true;
12832269441SYishai Hadas 	default:
12932269441SYishai Hadas 		return false;
13032269441SYishai Hadas 	}
13132269441SYishai Hadas }
13232269441SYishai Hadas 
133bfc5d839SMark Bloch bool mlx5_ib_devx_is_flow_counter(void *obj, u32 *counter_id)
134bfc5d839SMark Bloch {
135bfc5d839SMark Bloch 	struct devx_obj *devx_obj = obj;
136bfc5d839SMark Bloch 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode);
137bfc5d839SMark Bloch 
138bfc5d839SMark Bloch 	if (opcode == MLX5_CMD_OP_DEALLOC_FLOW_COUNTER) {
139bfc5d839SMark Bloch 		*counter_id = MLX5_GET(dealloc_flow_counter_in,
140bfc5d839SMark Bloch 				       devx_obj->dinbox,
141bfc5d839SMark Bloch 				       flow_counter_id);
142bfc5d839SMark Bloch 		return true;
143bfc5d839SMark Bloch 	}
144bfc5d839SMark Bloch 
145bfc5d839SMark Bloch 	return false;
146bfc5d839SMark Bloch }
147bfc5d839SMark Bloch 
1482351776eSYishai Hadas /*
1492351776eSYishai Hadas  * As the obj_id in the firmware is not globally unique the object type
1502351776eSYishai Hadas  * must be considered upon checking for a valid object id.
1512351776eSYishai Hadas  * For that the opcode of the creator command is encoded as part of the obj_id.
1522351776eSYishai Hadas  */
1532351776eSYishai Hadas static u64 get_enc_obj_id(u16 opcode, u32 obj_id)
1542351776eSYishai Hadas {
1552351776eSYishai Hadas 	return ((u64)opcode << 32) | obj_id;
1562351776eSYishai Hadas }
1572351776eSYishai Hadas 
15834613eb1SYishai Hadas static u64 devx_get_obj_id(const void *in)
159e662e14dSYishai Hadas {
160e662e14dSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
1612351776eSYishai Hadas 	u64 obj_id;
162e662e14dSYishai Hadas 
163e662e14dSYishai Hadas 	switch (opcode) {
164e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
165e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
1662351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_GENERAL_OBJECT,
1672351776eSYishai Hadas 					MLX5_GET(general_obj_in_cmd_hdr, in,
1682351776eSYishai Hadas 						 obj_id));
169e662e14dSYishai Hadas 		break;
170e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_MKEY:
1712351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_MKEY,
1722351776eSYishai Hadas 					MLX5_GET(query_mkey_in, in,
1732351776eSYishai Hadas 						 mkey_index));
174e662e14dSYishai Hadas 		break;
175e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_CQ:
1762351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ,
1772351776eSYishai Hadas 					MLX5_GET(query_cq_in, in, cqn));
178e662e14dSYishai Hadas 		break;
179e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_CQ:
1802351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ,
1812351776eSYishai Hadas 					MLX5_GET(modify_cq_in, in, cqn));
182e662e14dSYishai Hadas 		break;
183e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SQ:
1842351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ,
1852351776eSYishai Hadas 					MLX5_GET(query_sq_in, in, sqn));
186e662e14dSYishai Hadas 		break;
187e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_SQ:
1882351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ,
1892351776eSYishai Hadas 					MLX5_GET(modify_sq_in, in, sqn));
190e662e14dSYishai Hadas 		break;
191e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RQ:
1922351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
1932351776eSYishai Hadas 					MLX5_GET(query_rq_in, in, rqn));
194e662e14dSYishai Hadas 		break;
195e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RQ:
1962351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
1972351776eSYishai Hadas 					MLX5_GET(modify_rq_in, in, rqn));
198e662e14dSYishai Hadas 		break;
199e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RMP:
2002351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RMP,
2012351776eSYishai Hadas 					MLX5_GET(query_rmp_in, in, rmpn));
202e662e14dSYishai Hadas 		break;
203e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RMP:
2042351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RMP,
2052351776eSYishai Hadas 					MLX5_GET(modify_rmp_in, in, rmpn));
206e662e14dSYishai Hadas 		break;
207e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RQT:
2082351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT,
2092351776eSYishai Hadas 					MLX5_GET(query_rqt_in, in, rqtn));
210e662e14dSYishai Hadas 		break;
211e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RQT:
2122351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT,
2132351776eSYishai Hadas 					MLX5_GET(modify_rqt_in, in, rqtn));
214e662e14dSYishai Hadas 		break;
215e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_TIR:
2162351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR,
2172351776eSYishai Hadas 					MLX5_GET(query_tir_in, in, tirn));
218e662e14dSYishai Hadas 		break;
219e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_TIR:
2202351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR,
2212351776eSYishai Hadas 					MLX5_GET(modify_tir_in, in, tirn));
222e662e14dSYishai Hadas 		break;
223e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_TIS:
2242351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS,
2252351776eSYishai Hadas 					MLX5_GET(query_tis_in, in, tisn));
226e662e14dSYishai Hadas 		break;
227e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_TIS:
2282351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS,
2292351776eSYishai Hadas 					MLX5_GET(modify_tis_in, in, tisn));
230e662e14dSYishai Hadas 		break;
231e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_TABLE:
2322351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_TABLE,
2332351776eSYishai Hadas 					MLX5_GET(query_flow_table_in, in,
2342351776eSYishai Hadas 						 table_id));
235e662e14dSYishai Hadas 		break;
236e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_FLOW_TABLE:
2372351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_TABLE,
2382351776eSYishai Hadas 					MLX5_GET(modify_flow_table_in, in,
2392351776eSYishai Hadas 						 table_id));
240e662e14dSYishai Hadas 		break;
241e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_GROUP:
2422351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_GROUP,
2432351776eSYishai Hadas 					MLX5_GET(query_flow_group_in, in,
2442351776eSYishai Hadas 						 group_id));
245e662e14dSYishai Hadas 		break;
246e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
2472351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY,
2482351776eSYishai Hadas 					MLX5_GET(query_fte_in, in,
2492351776eSYishai Hadas 						 flow_index));
250e662e14dSYishai Hadas 		break;
251e662e14dSYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
2522351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY,
2532351776eSYishai Hadas 					MLX5_GET(set_fte_in, in, flow_index));
254e662e14dSYishai Hadas 		break;
255e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_Q_COUNTER:
2562351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_Q_COUNTER,
2572351776eSYishai Hadas 					MLX5_GET(query_q_counter_in, in,
2582351776eSYishai Hadas 						 counter_set_id));
259e662e14dSYishai Hadas 		break;
260e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
2612351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_FLOW_COUNTER,
2622351776eSYishai Hadas 					MLX5_GET(query_flow_counter_in, in,
2632351776eSYishai Hadas 						 flow_counter_id));
264e662e14dSYishai Hadas 		break;
265e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT:
2662351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT,
2672351776eSYishai Hadas 					MLX5_GET(general_obj_in_cmd_hdr, in,
2682351776eSYishai Hadas 						 obj_id));
269e662e14dSYishai Hadas 		break;
270e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
2712351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT,
2722351776eSYishai Hadas 					MLX5_GET(query_scheduling_element_in,
2732351776eSYishai Hadas 						 in, scheduling_element_id));
274e662e14dSYishai Hadas 		break;
275e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
2762351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT,
2772351776eSYishai Hadas 					MLX5_GET(modify_scheduling_element_in,
2782351776eSYishai Hadas 						 in, scheduling_element_id));
279e662e14dSYishai Hadas 		break;
280e662e14dSYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
2812351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT,
2822351776eSYishai Hadas 					MLX5_GET(add_vxlan_udp_dport_in, in,
2832351776eSYishai Hadas 						 vxlan_udp_port));
284e662e14dSYishai Hadas 		break;
285e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
2862351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_L2_TABLE_ENTRY,
2872351776eSYishai Hadas 					MLX5_GET(query_l2_table_entry_in, in,
2882351776eSYishai Hadas 						 table_index));
289e662e14dSYishai Hadas 		break;
290e662e14dSYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
2912351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_L2_TABLE_ENTRY,
2922351776eSYishai Hadas 					MLX5_GET(set_l2_table_entry_in, in,
2932351776eSYishai Hadas 						 table_index));
294e662e14dSYishai Hadas 		break;
295e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_QP:
2962351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
2972351776eSYishai Hadas 					MLX5_GET(query_qp_in, in, qpn));
298e662e14dSYishai Hadas 		break;
299e662e14dSYishai Hadas 	case MLX5_CMD_OP_RST2INIT_QP:
3002351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
3012351776eSYishai Hadas 					MLX5_GET(rst2init_qp_in, in, qpn));
302e662e14dSYishai Hadas 		break;
303e662e14dSYishai Hadas 	case MLX5_CMD_OP_INIT2RTR_QP:
3042351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
3052351776eSYishai Hadas 					MLX5_GET(init2rtr_qp_in, in, qpn));
306e662e14dSYishai Hadas 		break;
307e662e14dSYishai Hadas 	case MLX5_CMD_OP_RTR2RTS_QP:
3082351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
3092351776eSYishai Hadas 					MLX5_GET(rtr2rts_qp_in, in, qpn));
310e662e14dSYishai Hadas 		break;
311e662e14dSYishai Hadas 	case MLX5_CMD_OP_RTS2RTS_QP:
3122351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
3132351776eSYishai Hadas 					MLX5_GET(rts2rts_qp_in, in, qpn));
314e662e14dSYishai Hadas 		break;
315e662e14dSYishai Hadas 	case MLX5_CMD_OP_SQERR2RTS_QP:
3162351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
3172351776eSYishai Hadas 					MLX5_GET(sqerr2rts_qp_in, in, qpn));
318e662e14dSYishai Hadas 		break;
319e662e14dSYishai Hadas 	case MLX5_CMD_OP_2ERR_QP:
3202351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
3212351776eSYishai Hadas 					MLX5_GET(qp_2err_in, in, qpn));
322e662e14dSYishai Hadas 		break;
323e662e14dSYishai Hadas 	case MLX5_CMD_OP_2RST_QP:
3242351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
3252351776eSYishai Hadas 					MLX5_GET(qp_2rst_in, in, qpn));
326e662e14dSYishai Hadas 		break;
327e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_DCT:
3282351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT,
3292351776eSYishai Hadas 					MLX5_GET(query_dct_in, in, dctn));
330e662e14dSYishai Hadas 		break;
331e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ:
332719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY:
333719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS:
3342351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRQ,
3352351776eSYishai Hadas 					MLX5_GET(query_xrq_in, in, xrqn));
336e662e14dSYishai Hadas 		break;
337e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_XRC_SRQ:
3382351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRC_SRQ,
3392351776eSYishai Hadas 					MLX5_GET(query_xrc_srq_in, in,
3402351776eSYishai Hadas 						 xrc_srqn));
341e662e14dSYishai Hadas 		break;
342e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_XRC_SRQ:
3432351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRC_SRQ,
3442351776eSYishai Hadas 					MLX5_GET(arm_xrc_srq_in, in, xrc_srqn));
345e662e14dSYishai Hadas 		break;
346e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SRQ:
3472351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SRQ,
3482351776eSYishai Hadas 					MLX5_GET(query_srq_in, in, srqn));
349e662e14dSYishai Hadas 		break;
350e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_RQ:
3512351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
3522351776eSYishai Hadas 					MLX5_GET(arm_rq_in, in, srq_number));
353e662e14dSYishai Hadas 		break;
354e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
3552351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT,
3562351776eSYishai Hadas 					MLX5_GET(drain_dct_in, in, dctn));
357e662e14dSYishai Hadas 		break;
358e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_XRQ:
359719598c9SYishai Hadas 	case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY:
3602351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRQ,
3612351776eSYishai Hadas 					MLX5_GET(arm_xrq_in, in, xrqn));
362e662e14dSYishai Hadas 		break;
363719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT:
364719598c9SYishai Hadas 		obj_id = get_enc_obj_id
365719598c9SYishai Hadas 				(MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT,
366719598c9SYishai Hadas 				 MLX5_GET(query_packet_reformat_context_in,
367719598c9SYishai Hadas 					  in, packet_reformat_id));
368719598c9SYishai Hadas 		break;
369e662e14dSYishai Hadas 	default:
37034613eb1SYishai Hadas 		obj_id = 0;
371e662e14dSYishai Hadas 	}
372e662e14dSYishai Hadas 
37334613eb1SYishai Hadas 	return obj_id;
37434613eb1SYishai Hadas }
375e662e14dSYishai Hadas 
37634613eb1SYishai Hadas static bool devx_is_valid_obj_id(struct ib_uobject *uobj, const void *in)
37734613eb1SYishai Hadas {
37834613eb1SYishai Hadas 	u64 obj_id = devx_get_obj_id(in);
37934613eb1SYishai Hadas 
38034613eb1SYishai Hadas 	if (!obj_id)
381e662e14dSYishai Hadas 		return false;
38234613eb1SYishai Hadas 
38334613eb1SYishai Hadas 	switch (uobj_get_object_id(uobj)) {
38434613eb1SYishai Hadas 	case UVERBS_OBJECT_CQ:
38534613eb1SYishai Hadas 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ,
38634613eb1SYishai Hadas 				      to_mcq(uobj->object)->mcq.cqn) ==
38734613eb1SYishai Hadas 				      obj_id;
38834613eb1SYishai Hadas 
38934613eb1SYishai Hadas 	case UVERBS_OBJECT_SRQ:
39034613eb1SYishai Hadas 	{
39134613eb1SYishai Hadas 		struct mlx5_core_srq *srq = &(to_msrq(uobj->object)->msrq);
39234613eb1SYishai Hadas 		struct mlx5_ib_dev *dev = to_mdev(uobj->context->device);
39334613eb1SYishai Hadas 		u16 opcode;
39434613eb1SYishai Hadas 
39534613eb1SYishai Hadas 		switch (srq->common.res) {
39634613eb1SYishai Hadas 		case MLX5_RES_XSRQ:
39734613eb1SYishai Hadas 			opcode = MLX5_CMD_OP_CREATE_XRC_SRQ;
39834613eb1SYishai Hadas 			break;
39934613eb1SYishai Hadas 		case MLX5_RES_XRQ:
40034613eb1SYishai Hadas 			opcode = MLX5_CMD_OP_CREATE_XRQ;
40134613eb1SYishai Hadas 			break;
40234613eb1SYishai Hadas 		default:
40334613eb1SYishai Hadas 			if (!dev->mdev->issi)
40434613eb1SYishai Hadas 				opcode = MLX5_CMD_OP_CREATE_SRQ;
40534613eb1SYishai Hadas 			else
40634613eb1SYishai Hadas 				opcode = MLX5_CMD_OP_CREATE_RMP;
40734613eb1SYishai Hadas 		}
40834613eb1SYishai Hadas 
40934613eb1SYishai Hadas 		return get_enc_obj_id(opcode,
41034613eb1SYishai Hadas 				      to_msrq(uobj->object)->msrq.srqn) ==
41134613eb1SYishai Hadas 				      obj_id;
41234613eb1SYishai Hadas 	}
41334613eb1SYishai Hadas 
41434613eb1SYishai Hadas 	case UVERBS_OBJECT_QP:
41534613eb1SYishai Hadas 	{
41634613eb1SYishai Hadas 		struct mlx5_ib_qp *qp = to_mqp(uobj->object);
41734613eb1SYishai Hadas 		enum ib_qp_type	qp_type = qp->ibqp.qp_type;
41834613eb1SYishai Hadas 
41934613eb1SYishai Hadas 		if (qp_type == IB_QPT_RAW_PACKET ||
42034613eb1SYishai Hadas 		    (qp->flags & MLX5_IB_QP_UNDERLAY)) {
42134613eb1SYishai Hadas 			struct mlx5_ib_raw_packet_qp *raw_packet_qp =
42234613eb1SYishai Hadas 							 &qp->raw_packet_qp;
42334613eb1SYishai Hadas 			struct mlx5_ib_rq *rq = &raw_packet_qp->rq;
42434613eb1SYishai Hadas 			struct mlx5_ib_sq *sq = &raw_packet_qp->sq;
42534613eb1SYishai Hadas 
42634613eb1SYishai Hadas 			return (get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
42734613eb1SYishai Hadas 					       rq->base.mqp.qpn) == obj_id ||
42834613eb1SYishai Hadas 				get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ,
42934613eb1SYishai Hadas 					       sq->base.mqp.qpn) == obj_id ||
43034613eb1SYishai Hadas 				get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR,
43134613eb1SYishai Hadas 					       rq->tirn) == obj_id ||
43234613eb1SYishai Hadas 				get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS,
43334613eb1SYishai Hadas 					       sq->tisn) == obj_id);
43434613eb1SYishai Hadas 		}
43534613eb1SYishai Hadas 
43634613eb1SYishai Hadas 		if (qp_type == MLX5_IB_QPT_DCT)
43734613eb1SYishai Hadas 			return get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT,
43834613eb1SYishai Hadas 					      qp->dct.mdct.mqp.qpn) == obj_id;
43934613eb1SYishai Hadas 
44034613eb1SYishai Hadas 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
44134613eb1SYishai Hadas 				      qp->ibqp.qp_num) == obj_id;
44234613eb1SYishai Hadas 	}
44334613eb1SYishai Hadas 
44434613eb1SYishai Hadas 	case UVERBS_OBJECT_WQ:
44534613eb1SYishai Hadas 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
44634613eb1SYishai Hadas 				      to_mrwq(uobj->object)->core_qp.qpn) ==
44734613eb1SYishai Hadas 				      obj_id;
44834613eb1SYishai Hadas 
44934613eb1SYishai Hadas 	case UVERBS_OBJECT_RWQ_IND_TBL:
45034613eb1SYishai Hadas 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT,
45134613eb1SYishai Hadas 				      to_mrwq_ind_table(uobj->object)->rqtn) ==
45234613eb1SYishai Hadas 				      obj_id;
45334613eb1SYishai Hadas 
45434613eb1SYishai Hadas 	case MLX5_IB_OBJECT_DEVX_OBJ:
45534613eb1SYishai Hadas 		return ((struct devx_obj *)uobj->object)->obj_id == obj_id;
45634613eb1SYishai Hadas 
457e662e14dSYishai Hadas 	default:
458e662e14dSYishai Hadas 		return false;
459e662e14dSYishai Hadas 	}
460e662e14dSYishai Hadas }
461e662e14dSYishai Hadas 
462ba1a057dSYishai Hadas static void devx_set_umem_valid(const void *in)
463ba1a057dSYishai Hadas {
464ba1a057dSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
465ba1a057dSYishai Hadas 
466ba1a057dSYishai Hadas 	switch (opcode) {
467ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_MKEY:
468ba1a057dSYishai Hadas 		MLX5_SET(create_mkey_in, in, mkey_umem_valid, 1);
469ba1a057dSYishai Hadas 		break;
470ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_CQ:
471ba1a057dSYishai Hadas 	{
472ba1a057dSYishai Hadas 		void *cqc;
473ba1a057dSYishai Hadas 
474ba1a057dSYishai Hadas 		MLX5_SET(create_cq_in, in, cq_umem_valid, 1);
475ba1a057dSYishai Hadas 		cqc = MLX5_ADDR_OF(create_cq_in, in, cq_context);
476ba1a057dSYishai Hadas 		MLX5_SET(cqc, cqc, dbr_umem_valid, 1);
477ba1a057dSYishai Hadas 		break;
478ba1a057dSYishai Hadas 	}
479ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
480ba1a057dSYishai Hadas 	{
481ba1a057dSYishai Hadas 		void *qpc;
482ba1a057dSYishai Hadas 
483ba1a057dSYishai Hadas 		qpc = MLX5_ADDR_OF(create_qp_in, in, qpc);
484ba1a057dSYishai Hadas 		MLX5_SET(qpc, qpc, dbr_umem_valid, 1);
485ba1a057dSYishai Hadas 		MLX5_SET(create_qp_in, in, wq_umem_valid, 1);
486ba1a057dSYishai Hadas 		break;
487ba1a057dSYishai Hadas 	}
488ba1a057dSYishai Hadas 
489ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
490ba1a057dSYishai Hadas 	{
491ba1a057dSYishai Hadas 		void *rqc, *wq;
492ba1a057dSYishai Hadas 
493ba1a057dSYishai Hadas 		rqc = MLX5_ADDR_OF(create_rq_in, in, ctx);
494ba1a057dSYishai Hadas 		wq  = MLX5_ADDR_OF(rqc, rqc, wq);
495ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
496ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, wq_umem_valid, 1);
497ba1a057dSYishai Hadas 		break;
498ba1a057dSYishai Hadas 	}
499ba1a057dSYishai Hadas 
500ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
501ba1a057dSYishai Hadas 	{
502ba1a057dSYishai Hadas 		void *sqc, *wq;
503ba1a057dSYishai Hadas 
504ba1a057dSYishai Hadas 		sqc = MLX5_ADDR_OF(create_sq_in, in, ctx);
505ba1a057dSYishai Hadas 		wq = MLX5_ADDR_OF(sqc, sqc, wq);
506ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
507ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, wq_umem_valid, 1);
508ba1a057dSYishai Hadas 		break;
509ba1a057dSYishai Hadas 	}
510ba1a057dSYishai Hadas 
511ba1a057dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_CQ:
512ba1a057dSYishai Hadas 		MLX5_SET(modify_cq_in, in, cq_umem_valid, 1);
513ba1a057dSYishai Hadas 		break;
514ba1a057dSYishai Hadas 
515ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_RMP:
516ba1a057dSYishai Hadas 	{
517ba1a057dSYishai Hadas 		void *rmpc, *wq;
518ba1a057dSYishai Hadas 
519ba1a057dSYishai Hadas 		rmpc = MLX5_ADDR_OF(create_rmp_in, in, ctx);
520ba1a057dSYishai Hadas 		wq = MLX5_ADDR_OF(rmpc, rmpc, wq);
521ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
522ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, wq_umem_valid, 1);
523ba1a057dSYishai Hadas 		break;
524ba1a057dSYishai Hadas 	}
525ba1a057dSYishai Hadas 
526ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_XRQ:
527ba1a057dSYishai Hadas 	{
528ba1a057dSYishai Hadas 		void *xrqc, *wq;
529ba1a057dSYishai Hadas 
530ba1a057dSYishai Hadas 		xrqc = MLX5_ADDR_OF(create_xrq_in, in, xrq_context);
531ba1a057dSYishai Hadas 		wq = MLX5_ADDR_OF(xrqc, xrqc, wq);
532ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
533ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, wq_umem_valid, 1);
534ba1a057dSYishai Hadas 		break;
535ba1a057dSYishai Hadas 	}
536ba1a057dSYishai Hadas 
537ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
538ba1a057dSYishai Hadas 	{
539ba1a057dSYishai Hadas 		void *xrc_srqc;
540ba1a057dSYishai Hadas 
541ba1a057dSYishai Hadas 		MLX5_SET(create_xrc_srq_in, in, xrc_srq_umem_valid, 1);
542ba1a057dSYishai Hadas 		xrc_srqc = MLX5_ADDR_OF(create_xrc_srq_in, in,
543ba1a057dSYishai Hadas 					xrc_srq_context_entry);
544ba1a057dSYishai Hadas 		MLX5_SET(xrc_srqc, xrc_srqc, dbr_umem_valid, 1);
545ba1a057dSYishai Hadas 		break;
546ba1a057dSYishai Hadas 	}
547ba1a057dSYishai Hadas 
548ba1a057dSYishai Hadas 	default:
549ba1a057dSYishai Hadas 		return;
550ba1a057dSYishai Hadas 	}
551ba1a057dSYishai Hadas }
552ba1a057dSYishai Hadas 
5532351776eSYishai Hadas static bool devx_is_obj_create_cmd(const void *in, u16 *opcode)
5547efce369SYishai Hadas {
5552351776eSYishai Hadas 	*opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
5567efce369SYishai Hadas 
5572351776eSYishai Hadas 	switch (*opcode) {
5587efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
5597efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_MKEY:
5607efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_CQ:
5617efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_PD:
5627efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
5637efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RMP:
5647efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
5657efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
5667efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQT:
5677efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIR:
5687efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIS:
5697efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_Q_COUNTER:
5707efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_TABLE:
5717efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_GROUP:
5727efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
57360786f09SMark Bloch 	case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT:
5747efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
5757efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
5767efce369SYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
5777efce369SYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
5787efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
5797efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SRQ:
5807efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
5817efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_DCT:
5827efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRQ:
5837efce369SYishai Hadas 	case MLX5_CMD_OP_ATTACH_TO_MCG:
5847efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_XRCD:
5857efce369SYishai Hadas 		return true;
5867efce369SYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
5877efce369SYishai Hadas 	{
5887efce369SYishai Hadas 		u16 op_mod = MLX5_GET(set_fte_in, in, op_mod);
5897efce369SYishai Hadas 		if (op_mod == 0)
5907efce369SYishai Hadas 			return true;
5917efce369SYishai Hadas 		return false;
5927efce369SYishai Hadas 	}
5937efce369SYishai Hadas 	default:
5947efce369SYishai Hadas 		return false;
5957efce369SYishai Hadas 	}
5967efce369SYishai Hadas }
5977efce369SYishai Hadas 
598e662e14dSYishai Hadas static bool devx_is_obj_modify_cmd(const void *in)
599e662e14dSYishai Hadas {
600e662e14dSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
601e662e14dSYishai Hadas 
602e662e14dSYishai Hadas 	switch (opcode) {
603e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
604e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_CQ:
605e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RMP:
606e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_SQ:
607e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RQ:
608e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RQT:
609e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_TIR:
610e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_TIS:
611e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_FLOW_TABLE:
612e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
613e662e14dSYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
614e662e14dSYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
615e662e14dSYishai Hadas 	case MLX5_CMD_OP_RST2INIT_QP:
616e662e14dSYishai Hadas 	case MLX5_CMD_OP_INIT2RTR_QP:
617e662e14dSYishai Hadas 	case MLX5_CMD_OP_RTR2RTS_QP:
618e662e14dSYishai Hadas 	case MLX5_CMD_OP_RTS2RTS_QP:
619e662e14dSYishai Hadas 	case MLX5_CMD_OP_SQERR2RTS_QP:
620e662e14dSYishai Hadas 	case MLX5_CMD_OP_2ERR_QP:
621e662e14dSYishai Hadas 	case MLX5_CMD_OP_2RST_QP:
622e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_XRC_SRQ:
623e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_RQ:
624e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
625e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_XRQ:
626719598c9SYishai Hadas 	case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY:
627e662e14dSYishai Hadas 		return true;
628e662e14dSYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
629e662e14dSYishai Hadas 	{
630e662e14dSYishai Hadas 		u16 op_mod = MLX5_GET(set_fte_in, in, op_mod);
631e662e14dSYishai Hadas 
632e662e14dSYishai Hadas 		if (op_mod == 1)
633e662e14dSYishai Hadas 			return true;
634e662e14dSYishai Hadas 		return false;
635e662e14dSYishai Hadas 	}
636e662e14dSYishai Hadas 	default:
637e662e14dSYishai Hadas 		return false;
638e662e14dSYishai Hadas 	}
639e662e14dSYishai Hadas }
640e662e14dSYishai Hadas 
641e662e14dSYishai Hadas static bool devx_is_obj_query_cmd(const void *in)
642e662e14dSYishai Hadas {
643e662e14dSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
644e662e14dSYishai Hadas 
645e662e14dSYishai Hadas 	switch (opcode) {
646e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
647e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_MKEY:
648e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_CQ:
649e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RMP:
650e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SQ:
651e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RQ:
652e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RQT:
653e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_TIR:
654e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_TIS:
655e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_Q_COUNTER:
656e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_TABLE:
657e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_GROUP:
658e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
659e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
660e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT:
661e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
662e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
663e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_QP:
664e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SRQ:
665e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_XRC_SRQ:
666e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_DCT:
667e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ:
668719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY:
669719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS:
670719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT:
671e662e14dSYishai Hadas 		return true;
672e662e14dSYishai Hadas 	default:
673e662e14dSYishai Hadas 		return false;
674e662e14dSYishai Hadas 	}
675e662e14dSYishai Hadas }
676e662e14dSYishai Hadas 
6777e1335a7SYishai Hadas static bool devx_is_whitelist_cmd(void *in)
6787e1335a7SYishai Hadas {
6797e1335a7SYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
6807e1335a7SYishai Hadas 
6817e1335a7SYishai Hadas 	switch (opcode) {
6827e1335a7SYishai Hadas 	case MLX5_CMD_OP_QUERY_HCA_CAP:
6837e1335a7SYishai Hadas 	case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT:
6847e1335a7SYishai Hadas 		return true;
6857e1335a7SYishai Hadas 	default:
6867e1335a7SYishai Hadas 		return false;
6877e1335a7SYishai Hadas 	}
6887e1335a7SYishai Hadas }
6897e1335a7SYishai Hadas 
6907e1335a7SYishai Hadas static int devx_get_uid(struct mlx5_ib_ucontext *c, void *cmd_in)
6917e1335a7SYishai Hadas {
6927e1335a7SYishai Hadas 	if (devx_is_whitelist_cmd(cmd_in)) {
6937e1335a7SYishai Hadas 		struct mlx5_ib_dev *dev;
6947e1335a7SYishai Hadas 
6957e1335a7SYishai Hadas 		if (c->devx_uid)
6967e1335a7SYishai Hadas 			return c->devx_uid;
6977e1335a7SYishai Hadas 
6987e1335a7SYishai Hadas 		dev = to_mdev(c->ibucontext.device);
6997e1335a7SYishai Hadas 		if (dev->devx_whitelist_uid)
7007e1335a7SYishai Hadas 			return dev->devx_whitelist_uid;
7017e1335a7SYishai Hadas 
7027e1335a7SYishai Hadas 		return -EOPNOTSUPP;
7037e1335a7SYishai Hadas 	}
7047e1335a7SYishai Hadas 
7057e1335a7SYishai Hadas 	if (!c->devx_uid)
7067e1335a7SYishai Hadas 		return -EINVAL;
7077e1335a7SYishai Hadas 
7087e1335a7SYishai Hadas 	return c->devx_uid;
7097e1335a7SYishai Hadas }
710e662e14dSYishai Hadas static bool devx_is_general_cmd(void *in)
7118aa8c95cSYishai Hadas {
7128aa8c95cSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
7138aa8c95cSYishai Hadas 
714719598c9SYishai Hadas 	if (opcode >= MLX5_CMD_OP_GENERAL_START &&
715719598c9SYishai Hadas 	    opcode < MLX5_CMD_OP_GENERAL_END)
716719598c9SYishai Hadas 		return true;
717719598c9SYishai Hadas 
7188aa8c95cSYishai Hadas 	switch (opcode) {
7198aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_HCA_CAP:
7207e1335a7SYishai Hadas 	case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT:
7218aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_VPORT_STATE:
7228aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_ADAPTER:
7238aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_ISSI:
7248aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT:
7258aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_ROCE_ADDRESS:
7268aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_VNIC_ENV:
7278aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_VPORT_COUNTER:
7288aa8c95cSYishai Hadas 	case MLX5_CMD_OP_GET_DROPPED_PACKET_LOG:
7298aa8c95cSYishai Hadas 	case MLX5_CMD_OP_NOP:
7308aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_CONG_STATUS:
7318aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_CONG_PARAMS:
7328aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_CONG_STATISTICS:
7338aa8c95cSYishai Hadas 		return true;
7348aa8c95cSYishai Hadas 	default:
7358aa8c95cSYishai Hadas 		return false;
7368aa8c95cSYishai Hadas 	}
7378aa8c95cSYishai Hadas }
7388aa8c95cSYishai Hadas 
739e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_EQN)(
74015a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
741f6fe01b7SYishai Hadas {
742e83f0ecdSJason Gunthorpe 	struct mlx5_ib_ucontext *c;
743e83f0ecdSJason Gunthorpe 	struct mlx5_ib_dev *dev;
744f6fe01b7SYishai Hadas 	int user_vector;
745f6fe01b7SYishai Hadas 	int dev_eqn;
746f6fe01b7SYishai Hadas 	unsigned int irqn;
747f6fe01b7SYishai Hadas 	int err;
748f6fe01b7SYishai Hadas 
749f6fe01b7SYishai Hadas 	if (uverbs_copy_from(&user_vector, attrs,
750f6fe01b7SYishai Hadas 			     MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC))
751f6fe01b7SYishai Hadas 		return -EFAULT;
752f6fe01b7SYishai Hadas 
75315a1b4beSJason Gunthorpe 	c = devx_ufile2uctx(attrs);
754e83f0ecdSJason Gunthorpe 	if (IS_ERR(c))
755e83f0ecdSJason Gunthorpe 		return PTR_ERR(c);
756e83f0ecdSJason Gunthorpe 	dev = to_mdev(c->ibucontext.device);
757e83f0ecdSJason Gunthorpe 
758f6fe01b7SYishai Hadas 	err = mlx5_vector2eqn(dev->mdev, user_vector, &dev_eqn, &irqn);
759f6fe01b7SYishai Hadas 	if (err < 0)
760f6fe01b7SYishai Hadas 		return err;
761f6fe01b7SYishai Hadas 
762f6fe01b7SYishai Hadas 	if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN,
763f6fe01b7SYishai Hadas 			   &dev_eqn, sizeof(dev_eqn)))
764f6fe01b7SYishai Hadas 		return -EFAULT;
765f6fe01b7SYishai Hadas 
766f6fe01b7SYishai Hadas 	return 0;
767f6fe01b7SYishai Hadas }
768f6fe01b7SYishai Hadas 
7697c043e90SYishai Hadas /*
7707c043e90SYishai Hadas  *Security note:
7717c043e90SYishai Hadas  * The hardware protection mechanism works like this: Each device object that
7727c043e90SYishai Hadas  * is subject to UAR doorbells (QP/SQ/CQ) gets a UAR ID (called uar_page in
7737c043e90SYishai Hadas  * the device specification manual) upon its creation. Then upon doorbell,
7747c043e90SYishai Hadas  * hardware fetches the object context for which the doorbell was rang, and
7757c043e90SYishai Hadas  * validates that the UAR through which the DB was rang matches the UAR ID
7767c043e90SYishai Hadas  * of the object.
7777c043e90SYishai Hadas  * If no match the doorbell is silently ignored by the hardware. Of course,
7787c043e90SYishai Hadas  * the user cannot ring a doorbell on a UAR that was not mapped to it.
7797c043e90SYishai Hadas  * Now in devx, as the devx kernel does not manipulate the QP/SQ/CQ command
7807c043e90SYishai Hadas  * mailboxes (except tagging them with UID), we expose to the user its UAR
7817c043e90SYishai Hadas  * ID, so it can embed it in these objects in the expected specification
7827c043e90SYishai Hadas  * format. So the only thing the user can do is hurt itself by creating a
7837c043e90SYishai Hadas  * QP/SQ/CQ with a UAR ID other than his, and then in this case other users
7847c043e90SYishai Hadas  * may ring a doorbell on its objects.
7857c043e90SYishai Hadas  * The consequence of that will be that another user can schedule a QP/SQ
7867c043e90SYishai Hadas  * of the buggy user for execution (just insert it to the hardware schedule
7877c043e90SYishai Hadas  * queue or arm its CQ for event generation), no further harm is expected.
7887c043e90SYishai Hadas  */
789e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_UAR)(
79015a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
7917c043e90SYishai Hadas {
79222fa27fbSJason Gunthorpe 	struct mlx5_ib_ucontext *c;
79322fa27fbSJason Gunthorpe 	struct mlx5_ib_dev *dev;
7947c043e90SYishai Hadas 	u32 user_idx;
7957c043e90SYishai Hadas 	s32 dev_idx;
7967c043e90SYishai Hadas 
79715a1b4beSJason Gunthorpe 	c = devx_ufile2uctx(attrs);
79822fa27fbSJason Gunthorpe 	if (IS_ERR(c))
79922fa27fbSJason Gunthorpe 		return PTR_ERR(c);
80022fa27fbSJason Gunthorpe 	dev = to_mdev(c->ibucontext.device);
80122fa27fbSJason Gunthorpe 
8027c043e90SYishai Hadas 	if (uverbs_copy_from(&user_idx, attrs,
8037c043e90SYishai Hadas 			     MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX))
8047c043e90SYishai Hadas 		return -EFAULT;
8057c043e90SYishai Hadas 
80622fa27fbSJason Gunthorpe 	dev_idx = bfregn_to_uar_index(dev, &c->bfregi, user_idx, true);
8077c043e90SYishai Hadas 	if (dev_idx < 0)
8087c043e90SYishai Hadas 		return dev_idx;
8097c043e90SYishai Hadas 
8107c043e90SYishai Hadas 	if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX,
8117c043e90SYishai Hadas 			   &dev_idx, sizeof(dev_idx)))
8127c043e90SYishai Hadas 		return -EFAULT;
8137c043e90SYishai Hadas 
8147c043e90SYishai Hadas 	return 0;
8157c043e90SYishai Hadas }
8167c043e90SYishai Hadas 
817e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)(
81815a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
8198aa8c95cSYishai Hadas {
82022fa27fbSJason Gunthorpe 	struct mlx5_ib_ucontext *c;
82122fa27fbSJason Gunthorpe 	struct mlx5_ib_dev *dev;
8227efce369SYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(
8237efce369SYishai Hadas 		attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN);
8248aa8c95cSYishai Hadas 	int cmd_out_len = uverbs_attr_get_len(attrs,
8258aa8c95cSYishai Hadas 					MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT);
8268aa8c95cSYishai Hadas 	void *cmd_out;
8278aa8c95cSYishai Hadas 	int err;
8287e1335a7SYishai Hadas 	int uid;
8298aa8c95cSYishai Hadas 
83015a1b4beSJason Gunthorpe 	c = devx_ufile2uctx(attrs);
83122fa27fbSJason Gunthorpe 	if (IS_ERR(c))
83222fa27fbSJason Gunthorpe 		return PTR_ERR(c);
83322fa27fbSJason Gunthorpe 	dev = to_mdev(c->ibucontext.device);
83422fa27fbSJason Gunthorpe 
8357e1335a7SYishai Hadas 	uid = devx_get_uid(c, cmd_in);
8367e1335a7SYishai Hadas 	if (uid < 0)
8377e1335a7SYishai Hadas 		return uid;
8388aa8c95cSYishai Hadas 
8398aa8c95cSYishai Hadas 	/* Only white list of some general HCA commands are allowed for this method. */
8408aa8c95cSYishai Hadas 	if (!devx_is_general_cmd(cmd_in))
8418aa8c95cSYishai Hadas 		return -EINVAL;
8428aa8c95cSYishai Hadas 
843b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
844b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
845b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
8468aa8c95cSYishai Hadas 
8477e1335a7SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
8488aa8c95cSYishai Hadas 	err = mlx5_cmd_exec(dev->mdev, cmd_in,
8498aa8c95cSYishai Hadas 			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN),
8508aa8c95cSYishai Hadas 			    cmd_out, cmd_out_len);
8518aa8c95cSYishai Hadas 	if (err)
8528aa8c95cSYishai Hadas 		return err;
853b61815e2SJason Gunthorpe 
854b61815e2SJason Gunthorpe 	return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, cmd_out,
855b61815e2SJason Gunthorpe 			      cmd_out_len);
8568aa8c95cSYishai Hadas }
8578aa8c95cSYishai Hadas 
8587efce369SYishai Hadas static void devx_obj_build_destroy_cmd(void *in, void *out, void *din,
8597efce369SYishai Hadas 				       u32 *dinlen,
8607efce369SYishai Hadas 				       u32 *obj_id)
8617efce369SYishai Hadas {
8627efce369SYishai Hadas 	u16 obj_type = MLX5_GET(general_obj_in_cmd_hdr, in, obj_type);
8637efce369SYishai Hadas 	u16 uid = MLX5_GET(general_obj_in_cmd_hdr, in, uid);
8647efce369SYishai Hadas 
8657efce369SYishai Hadas 	*obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
8667efce369SYishai Hadas 	*dinlen = MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr);
8677efce369SYishai Hadas 
8687efce369SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, din, obj_id, *obj_id);
8697efce369SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, din, uid, uid);
8707efce369SYishai Hadas 
8717efce369SYishai Hadas 	switch (MLX5_GET(general_obj_in_cmd_hdr, in, opcode)) {
8727efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
8737efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
8747efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, obj_type, obj_type);
8757efce369SYishai Hadas 		break;
8767efce369SYishai Hadas 
8776e3722baSYishai Hadas 	case MLX5_CMD_OP_CREATE_UMEM:
8786e3722baSYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
8796e3722baSYishai Hadas 			 MLX5_CMD_OP_DESTROY_UMEM);
8806e3722baSYishai Hadas 		break;
8817efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_MKEY:
8827efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_MKEY);
8837efce369SYishai Hadas 		break;
8847efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_CQ:
8857efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_CQ);
8867efce369SYishai Hadas 		break;
8877efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_PD:
8887efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DEALLOC_PD);
8897efce369SYishai Hadas 		break;
8907efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
8917efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
8927efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN);
8937efce369SYishai Hadas 		break;
8947efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RMP:
8957efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RMP);
8967efce369SYishai Hadas 		break;
8977efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
8987efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_SQ);
8997efce369SYishai Hadas 		break;
9007efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
9017efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQ);
9027efce369SYishai Hadas 		break;
9037efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQT:
9047efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQT);
9057efce369SYishai Hadas 		break;
9067efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIR:
9077efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIR);
9087efce369SYishai Hadas 		break;
9097efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIS:
9107efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIS);
9117efce369SYishai Hadas 		break;
9127efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_Q_COUNTER:
9137efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
9147efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_Q_COUNTER);
9157efce369SYishai Hadas 		break;
9167efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_TABLE:
9177efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(destroy_flow_table_in);
9187efce369SYishai Hadas 		*obj_id = MLX5_GET(create_flow_table_out, out, table_id);
9197efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, other_vport,
9207efce369SYishai Hadas 			 MLX5_GET(create_flow_table_in,  in, other_vport));
9217efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, vport_number,
9227efce369SYishai Hadas 			 MLX5_GET(create_flow_table_in,  in, vport_number));
9237efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, table_type,
9247efce369SYishai Hadas 			 MLX5_GET(create_flow_table_in,  in, table_type));
9257efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, table_id, *obj_id);
9267efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
9277efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_FLOW_TABLE);
9287efce369SYishai Hadas 		break;
9297efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_GROUP:
9307efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(destroy_flow_group_in);
9317efce369SYishai Hadas 		*obj_id = MLX5_GET(create_flow_group_out, out, group_id);
9327efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, other_vport,
9337efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, other_vport));
9347efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, vport_number,
9357efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, vport_number));
9367efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, table_type,
9377efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, table_type));
9387efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, table_id,
9397efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, table_id));
9407efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, group_id, *obj_id);
9417efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
9427efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_FLOW_GROUP);
9437efce369SYishai Hadas 		break;
9447efce369SYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
9457efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(delete_fte_in);
9467efce369SYishai Hadas 		*obj_id = MLX5_GET(set_fte_in, in, flow_index);
9477efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, other_vport,
9487efce369SYishai Hadas 			 MLX5_GET(set_fte_in,  in, other_vport));
9497efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, vport_number,
9507efce369SYishai Hadas 			 MLX5_GET(set_fte_in, in, vport_number));
9517efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, table_type,
9527efce369SYishai Hadas 			 MLX5_GET(set_fte_in, in, table_type));
9537efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, table_id,
9547efce369SYishai Hadas 			 MLX5_GET(set_fte_in, in, table_id));
9557efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, flow_index, *obj_id);
9567efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
9577efce369SYishai Hadas 			 MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
9587efce369SYishai Hadas 		break;
9597efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
9607efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
9617efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_FLOW_COUNTER);
9627efce369SYishai Hadas 		break;
96360786f09SMark Bloch 	case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT:
9647efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
96560786f09SMark Bloch 			 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
9667efce369SYishai Hadas 		break;
9677efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
9687efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
9697efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT);
9707efce369SYishai Hadas 		break;
9717efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
9727efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(destroy_scheduling_element_in);
9737efce369SYishai Hadas 		*obj_id = MLX5_GET(create_scheduling_element_out, out,
9747efce369SYishai Hadas 				   scheduling_element_id);
9757efce369SYishai Hadas 		MLX5_SET(destroy_scheduling_element_in, din,
9767efce369SYishai Hadas 			 scheduling_hierarchy,
9777efce369SYishai Hadas 			 MLX5_GET(create_scheduling_element_in, in,
9787efce369SYishai Hadas 				  scheduling_hierarchy));
9797efce369SYishai Hadas 		MLX5_SET(destroy_scheduling_element_in, din,
9807efce369SYishai Hadas 			 scheduling_element_id, *obj_id);
9817efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
9827efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT);
9837efce369SYishai Hadas 		break;
9847efce369SYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
9857efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(delete_vxlan_udp_dport_in);
9867efce369SYishai Hadas 		*obj_id = MLX5_GET(add_vxlan_udp_dport_in, in, vxlan_udp_port);
9877efce369SYishai Hadas 		MLX5_SET(delete_vxlan_udp_dport_in, din, vxlan_udp_port, *obj_id);
9887efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
9897efce369SYishai Hadas 			 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
9907efce369SYishai Hadas 		break;
9917efce369SYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
9927efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(delete_l2_table_entry_in);
9937efce369SYishai Hadas 		*obj_id = MLX5_GET(set_l2_table_entry_in, in, table_index);
9947efce369SYishai Hadas 		MLX5_SET(delete_l2_table_entry_in, din, table_index, *obj_id);
9957efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
9967efce369SYishai Hadas 			 MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY);
9977efce369SYishai Hadas 		break;
9987efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
9997efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_QP);
10007efce369SYishai Hadas 		break;
10017efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SRQ:
10027efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_SRQ);
10037efce369SYishai Hadas 		break;
10047efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
10057efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
10067efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_XRC_SRQ);
10077efce369SYishai Hadas 		break;
10087efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_DCT:
10097efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_DCT);
10107efce369SYishai Hadas 		break;
10117efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRQ:
10127efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_XRQ);
10137efce369SYishai Hadas 		break;
10147efce369SYishai Hadas 	case MLX5_CMD_OP_ATTACH_TO_MCG:
10157efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(detach_from_mcg_in);
10167efce369SYishai Hadas 		MLX5_SET(detach_from_mcg_in, din, qpn,
10177efce369SYishai Hadas 			 MLX5_GET(attach_to_mcg_in, in, qpn));
10187efce369SYishai Hadas 		memcpy(MLX5_ADDR_OF(detach_from_mcg_in, din, multicast_gid),
10197efce369SYishai Hadas 		       MLX5_ADDR_OF(attach_to_mcg_in, in, multicast_gid),
10207efce369SYishai Hadas 		       MLX5_FLD_SZ_BYTES(attach_to_mcg_in, multicast_gid));
10217efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DETACH_FROM_MCG);
10227efce369SYishai Hadas 		break;
10237efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_XRCD:
10247efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DEALLOC_XRCD);
10257efce369SYishai Hadas 		break;
10267efce369SYishai Hadas 	default:
10277efce369SYishai Hadas 		/* The entry must match to one of the devx_is_obj_create_cmd */
10287efce369SYishai Hadas 		WARN_ON(true);
10297efce369SYishai Hadas 		break;
10307efce369SYishai Hadas 	}
10317efce369SYishai Hadas }
10327efce369SYishai Hadas 
1033534fd7aaSYishai Hadas static int devx_handle_mkey_indirect(struct devx_obj *obj,
1034534fd7aaSYishai Hadas 				     struct mlx5_ib_dev *dev,
1035534fd7aaSYishai Hadas 				     void *in, void *out)
1036534fd7aaSYishai Hadas {
1037534fd7aaSYishai Hadas 	struct mlx5_mkey_table *table = &dev->mdev->priv.mkey_table;
1038534fd7aaSYishai Hadas 	struct mlx5_ib_devx_mr *devx_mr = &obj->devx_mr;
1039534fd7aaSYishai Hadas 	unsigned long flags;
1040534fd7aaSYishai Hadas 	struct mlx5_core_mkey *mkey;
1041534fd7aaSYishai Hadas 	void *mkc;
1042534fd7aaSYishai Hadas 	u8 key;
1043534fd7aaSYishai Hadas 	int err;
1044534fd7aaSYishai Hadas 
1045534fd7aaSYishai Hadas 	mkey = &devx_mr->mmkey;
1046534fd7aaSYishai Hadas 	mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
1047534fd7aaSYishai Hadas 	key = MLX5_GET(mkc, mkc, mkey_7_0);
1048534fd7aaSYishai Hadas 	mkey->key = mlx5_idx_to_mkey(
1049534fd7aaSYishai Hadas 			MLX5_GET(create_mkey_out, out, mkey_index)) | key;
1050534fd7aaSYishai Hadas 	mkey->type = MLX5_MKEY_INDIRECT_DEVX;
1051534fd7aaSYishai Hadas 	mkey->iova = MLX5_GET64(mkc, mkc, start_addr);
1052534fd7aaSYishai Hadas 	mkey->size = MLX5_GET64(mkc, mkc, len);
1053534fd7aaSYishai Hadas 	mkey->pd = MLX5_GET(mkc, mkc, pd);
1054534fd7aaSYishai Hadas 	devx_mr->ndescs = MLX5_GET(mkc, mkc, translations_octword_size);
1055534fd7aaSYishai Hadas 
1056534fd7aaSYishai Hadas 	write_lock_irqsave(&table->lock, flags);
1057534fd7aaSYishai Hadas 	err = radix_tree_insert(&table->tree, mlx5_base_mkey(mkey->key),
1058534fd7aaSYishai Hadas 				mkey);
1059534fd7aaSYishai Hadas 	write_unlock_irqrestore(&table->lock, flags);
1060534fd7aaSYishai Hadas 	return err;
1061534fd7aaSYishai Hadas }
1062534fd7aaSYishai Hadas 
1063fa31f143SYishai Hadas static int devx_handle_mkey_create(struct mlx5_ib_dev *dev,
1064fa31f143SYishai Hadas 				   struct devx_obj *obj,
1065fa31f143SYishai Hadas 				   void *in, int in_len)
1066fa31f143SYishai Hadas {
1067fa31f143SYishai Hadas 	int min_len = MLX5_BYTE_OFF(create_mkey_in, memory_key_mkey_entry) +
1068fa31f143SYishai Hadas 			MLX5_FLD_SZ_BYTES(create_mkey_in,
1069fa31f143SYishai Hadas 			memory_key_mkey_entry);
1070fa31f143SYishai Hadas 	void *mkc;
1071fa31f143SYishai Hadas 	u8 access_mode;
1072fa31f143SYishai Hadas 
1073fa31f143SYishai Hadas 	if (in_len < min_len)
1074fa31f143SYishai Hadas 		return -EINVAL;
1075fa31f143SYishai Hadas 
1076fa31f143SYishai Hadas 	mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
1077fa31f143SYishai Hadas 
1078fa31f143SYishai Hadas 	access_mode = MLX5_GET(mkc, mkc, access_mode_1_0);
1079fa31f143SYishai Hadas 	access_mode |= MLX5_GET(mkc, mkc, access_mode_4_2) << 2;
1080fa31f143SYishai Hadas 
1081fa31f143SYishai Hadas 	if (access_mode == MLX5_MKC_ACCESS_MODE_KLMS ||
1082534fd7aaSYishai Hadas 		access_mode == MLX5_MKC_ACCESS_MODE_KSM) {
1083534fd7aaSYishai Hadas 		if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING))
1084534fd7aaSYishai Hadas 			obj->flags |= DEVX_OBJ_FLAGS_INDIRECT_MKEY;
1085fa31f143SYishai Hadas 		return 0;
1086534fd7aaSYishai Hadas 	}
1087fa31f143SYishai Hadas 
1088fa31f143SYishai Hadas 	MLX5_SET(create_mkey_in, in, mkey_umem_valid, 1);
1089fa31f143SYishai Hadas 	return 0;
1090fa31f143SYishai Hadas }
1091fa31f143SYishai Hadas 
1092534fd7aaSYishai Hadas static void devx_free_indirect_mkey(struct rcu_head *rcu)
1093534fd7aaSYishai Hadas {
1094534fd7aaSYishai Hadas 	kfree(container_of(rcu, struct devx_obj, devx_mr.rcu));
1095534fd7aaSYishai Hadas }
1096534fd7aaSYishai Hadas 
1097534fd7aaSYishai Hadas /* This function to delete from the radix tree needs to be called before
1098534fd7aaSYishai Hadas  * destroying the underlying mkey. Otherwise a race might occur in case that
1099534fd7aaSYishai Hadas  * other thread will get the same mkey before this one will be deleted,
1100534fd7aaSYishai Hadas  * in that case it will fail via inserting to the tree its own data.
1101534fd7aaSYishai Hadas  *
1102534fd7aaSYishai Hadas  * Note:
1103534fd7aaSYishai Hadas  * An error in the destroy is not expected unless there is some other indirect
1104534fd7aaSYishai Hadas  * mkey which points to this one. In a kernel cleanup flow it will be just
1105534fd7aaSYishai Hadas  * destroyed in the iterative destruction call. In a user flow, in case
1106534fd7aaSYishai Hadas  * the application didn't close in the expected order it's its own problem,
1107534fd7aaSYishai Hadas  * the mkey won't be part of the tree, in both cases the kernel is safe.
1108534fd7aaSYishai Hadas  */
1109534fd7aaSYishai Hadas static void devx_cleanup_mkey(struct devx_obj *obj)
1110534fd7aaSYishai Hadas {
1111534fd7aaSYishai Hadas 	struct mlx5_mkey_table *table = &obj->mdev->priv.mkey_table;
1112534fd7aaSYishai Hadas 	unsigned long flags;
1113534fd7aaSYishai Hadas 
1114534fd7aaSYishai Hadas 	write_lock_irqsave(&table->lock, flags);
1115e5c1bb47SKamal Heib 	radix_tree_delete(&table->tree, mlx5_base_mkey(obj->devx_mr.mmkey.key));
1116534fd7aaSYishai Hadas 	write_unlock_irqrestore(&table->lock, flags);
1117534fd7aaSYishai Hadas }
1118534fd7aaSYishai Hadas 
11197efce369SYishai Hadas static int devx_obj_cleanup(struct ib_uobject *uobject,
11207efce369SYishai Hadas 			    enum rdma_remove_reason why)
11217efce369SYishai Hadas {
11227efce369SYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
11237efce369SYishai Hadas 	struct devx_obj *obj = uobject->object;
11247efce369SYishai Hadas 	int ret;
11257efce369SYishai Hadas 
1126534fd7aaSYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY)
1127534fd7aaSYishai Hadas 		devx_cleanup_mkey(obj);
1128534fd7aaSYishai Hadas 
1129*c5ae1954SYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_DCT)
1130*c5ae1954SYishai Hadas 		ret = mlx5_core_destroy_dct(obj->mdev, &obj->core_dct);
1131*c5ae1954SYishai Hadas 	else
1132*c5ae1954SYishai Hadas 		ret = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out,
1133*c5ae1954SYishai Hadas 				    sizeof(out));
11341c77483eSYishai Hadas 	if (ib_is_destroy_retryable(ret, why, uobject))
11357efce369SYishai Hadas 		return ret;
11367efce369SYishai Hadas 
1137534fd7aaSYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY) {
1138534fd7aaSYishai Hadas 		struct mlx5_ib_dev *dev = to_mdev(uobject->context->device);
1139534fd7aaSYishai Hadas 
1140534fd7aaSYishai Hadas 		call_srcu(&dev->mr_srcu, &obj->devx_mr.rcu,
1141534fd7aaSYishai Hadas 			  devx_free_indirect_mkey);
1142534fd7aaSYishai Hadas 		return ret;
1143534fd7aaSYishai Hadas 	}
1144534fd7aaSYishai Hadas 
11457efce369SYishai Hadas 	kfree(obj);
11467efce369SYishai Hadas 	return ret;
11477efce369SYishai Hadas }
11487efce369SYishai Hadas 
1149e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
115015a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
11517efce369SYishai Hadas {
11527efce369SYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN);
11537efce369SYishai Hadas 	int cmd_out_len =  uverbs_attr_get_len(attrs,
11547efce369SYishai Hadas 					MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT);
1155fa31f143SYishai Hadas 	int cmd_in_len = uverbs_attr_get_len(attrs,
1156fa31f143SYishai Hadas 					MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN);
11577efce369SYishai Hadas 	void *cmd_out;
1158c36ee46dSJason Gunthorpe 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
1159c36ee46dSJason Gunthorpe 		attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE);
116089944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
116189944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1162c36ee46dSJason Gunthorpe 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
1163e8ef090aSYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
11647efce369SYishai Hadas 	struct devx_obj *obj;
11657efce369SYishai Hadas 	int err;
11667e1335a7SYishai Hadas 	int uid;
11672351776eSYishai Hadas 	u32 obj_id;
11682351776eSYishai Hadas 	u16 opcode;
11697efce369SYishai Hadas 
11707e1335a7SYishai Hadas 	uid = devx_get_uid(c, cmd_in);
11717e1335a7SYishai Hadas 	if (uid < 0)
11727e1335a7SYishai Hadas 		return uid;
11737efce369SYishai Hadas 
11742351776eSYishai Hadas 	if (!devx_is_obj_create_cmd(cmd_in, &opcode))
11757efce369SYishai Hadas 		return -EINVAL;
11767efce369SYishai Hadas 
1177b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
1178b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
1179b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
1180b61815e2SJason Gunthorpe 
11817efce369SYishai Hadas 	obj = kzalloc(sizeof(struct devx_obj), GFP_KERNEL);
11827efce369SYishai Hadas 	if (!obj)
11837efce369SYishai Hadas 		return -ENOMEM;
11847efce369SYishai Hadas 
11857e1335a7SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1186fa31f143SYishai Hadas 	if (opcode == MLX5_CMD_OP_CREATE_MKEY) {
1187fa31f143SYishai Hadas 		err = devx_handle_mkey_create(dev, obj, cmd_in, cmd_in_len);
1188fa31f143SYishai Hadas 		if (err)
1189fa31f143SYishai Hadas 			goto obj_free;
1190fa31f143SYishai Hadas 	} else {
1191ba1a057dSYishai Hadas 		devx_set_umem_valid(cmd_in);
1192fa31f143SYishai Hadas 	}
1193ba1a057dSYishai Hadas 
1194*c5ae1954SYishai Hadas 	if (opcode == MLX5_CMD_OP_CREATE_DCT) {
1195*c5ae1954SYishai Hadas 		obj->flags |= DEVX_OBJ_FLAGS_DCT;
1196*c5ae1954SYishai Hadas 		err = mlx5_core_create_dct(dev->mdev, &obj->core_dct,
1197*c5ae1954SYishai Hadas 					   cmd_in, cmd_in_len,
1198*c5ae1954SYishai Hadas 					   cmd_out, cmd_out_len);
1199*c5ae1954SYishai Hadas 	} else {
12007efce369SYishai Hadas 		err = mlx5_cmd_exec(dev->mdev, cmd_in,
1201fa31f143SYishai Hadas 				    cmd_in_len,
12027efce369SYishai Hadas 				    cmd_out, cmd_out_len);
1203*c5ae1954SYishai Hadas 	}
1204*c5ae1954SYishai Hadas 
12057efce369SYishai Hadas 	if (err)
1206b61815e2SJason Gunthorpe 		goto obj_free;
12077efce369SYishai Hadas 
12087efce369SYishai Hadas 	uobj->object = obj;
12097efce369SYishai Hadas 	obj->mdev = dev->mdev;
12102351776eSYishai Hadas 	devx_obj_build_destroy_cmd(cmd_in, cmd_out, obj->dinbox, &obj->dinlen,
12112351776eSYishai Hadas 				   &obj_id);
12127efce369SYishai Hadas 	WARN_ON(obj->dinlen > MLX5_MAX_DESTROY_INBOX_SIZE_DW * sizeof(u32));
12137efce369SYishai Hadas 
1214534fd7aaSYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY) {
1215534fd7aaSYishai Hadas 		err = devx_handle_mkey_indirect(obj, dev, cmd_in, cmd_out);
1216534fd7aaSYishai Hadas 		if (err)
1217534fd7aaSYishai Hadas 			goto obj_destroy;
1218534fd7aaSYishai Hadas 	}
1219534fd7aaSYishai Hadas 
12207efce369SYishai Hadas 	err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, cmd_out, cmd_out_len);
12217efce369SYishai Hadas 	if (err)
12220da4d48dSYishai Hadas 		goto err_copy;
12237efce369SYishai Hadas 
12242351776eSYishai Hadas 	obj->obj_id = get_enc_obj_id(opcode, obj_id);
12257efce369SYishai Hadas 	return 0;
12267efce369SYishai Hadas 
12270da4d48dSYishai Hadas err_copy:
1228534fd7aaSYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY)
1229534fd7aaSYishai Hadas 		devx_cleanup_mkey(obj);
12300da4d48dSYishai Hadas obj_destroy:
1231*c5ae1954SYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_DCT)
1232*c5ae1954SYishai Hadas 		mlx5_core_destroy_dct(obj->mdev, &obj->core_dct);
1233*c5ae1954SYishai Hadas 	else
1234*c5ae1954SYishai Hadas 		mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out,
1235*c5ae1954SYishai Hadas 			      sizeof(out));
12367efce369SYishai Hadas obj_free:
12377efce369SYishai Hadas 	kfree(obj);
12387efce369SYishai Hadas 	return err;
12397efce369SYishai Hadas }
12407efce369SYishai Hadas 
1241e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)(
124215a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
1243e662e14dSYishai Hadas {
1244e662e14dSYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN);
1245e662e14dSYishai Hadas 	int cmd_out_len = uverbs_attr_get_len(attrs,
1246e662e14dSYishai Hadas 					MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT);
1247e662e14dSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
1248e662e14dSYishai Hadas 							  MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE);
124989944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
125089944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
125189944450SShamir Rabinovitch 	struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device);
1252e662e14dSYishai Hadas 	void *cmd_out;
1253e662e14dSYishai Hadas 	int err;
12547e1335a7SYishai Hadas 	int uid;
1255e662e14dSYishai Hadas 
12567e1335a7SYishai Hadas 	uid = devx_get_uid(c, cmd_in);
12577e1335a7SYishai Hadas 	if (uid < 0)
12587e1335a7SYishai Hadas 		return uid;
1259e662e14dSYishai Hadas 
1260e662e14dSYishai Hadas 	if (!devx_is_obj_modify_cmd(cmd_in))
1261e662e14dSYishai Hadas 		return -EINVAL;
1262e662e14dSYishai Hadas 
126334613eb1SYishai Hadas 	if (!devx_is_valid_obj_id(uobj, cmd_in))
1264e662e14dSYishai Hadas 		return -EINVAL;
1265e662e14dSYishai Hadas 
1266b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
1267b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
1268b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
1269e662e14dSYishai Hadas 
12707e1335a7SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1271ba1a057dSYishai Hadas 	devx_set_umem_valid(cmd_in);
1272ba1a057dSYishai Hadas 
127334613eb1SYishai Hadas 	err = mlx5_cmd_exec(mdev->mdev, cmd_in,
1274e662e14dSYishai Hadas 			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN),
1275e662e14dSYishai Hadas 			    cmd_out, cmd_out_len);
1276e662e14dSYishai Hadas 	if (err)
1277e662e14dSYishai Hadas 		return err;
1278b61815e2SJason Gunthorpe 
1279b61815e2SJason Gunthorpe 	return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
1280b61815e2SJason Gunthorpe 			      cmd_out, cmd_out_len);
1281e662e14dSYishai Hadas }
1282e662e14dSYishai Hadas 
1283e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)(
128415a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
1285e662e14dSYishai Hadas {
1286e662e14dSYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN);
1287e662e14dSYishai Hadas 	int cmd_out_len = uverbs_attr_get_len(attrs,
1288e662e14dSYishai Hadas 					      MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT);
1289e662e14dSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
1290e662e14dSYishai Hadas 							  MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE);
129189944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
129289944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1293e662e14dSYishai Hadas 	void *cmd_out;
1294e662e14dSYishai Hadas 	int err;
12957e1335a7SYishai Hadas 	int uid;
129689944450SShamir Rabinovitch 	struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device);
1297e662e14dSYishai Hadas 
12987e1335a7SYishai Hadas 	uid = devx_get_uid(c, cmd_in);
12997e1335a7SYishai Hadas 	if (uid < 0)
13007e1335a7SYishai Hadas 		return uid;
1301e662e14dSYishai Hadas 
1302e662e14dSYishai Hadas 	if (!devx_is_obj_query_cmd(cmd_in))
1303e662e14dSYishai Hadas 		return -EINVAL;
1304e662e14dSYishai Hadas 
130534613eb1SYishai Hadas 	if (!devx_is_valid_obj_id(uobj, cmd_in))
1306e662e14dSYishai Hadas 		return -EINVAL;
1307e662e14dSYishai Hadas 
1308b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
1309b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
1310b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
1311e662e14dSYishai Hadas 
13127e1335a7SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
131334613eb1SYishai Hadas 	err = mlx5_cmd_exec(mdev->mdev, cmd_in,
1314e662e14dSYishai Hadas 			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN),
1315e662e14dSYishai Hadas 			    cmd_out, cmd_out_len);
1316e662e14dSYishai Hadas 	if (err)
1317e662e14dSYishai Hadas 		return err;
1318b61815e2SJason Gunthorpe 
1319b61815e2SJason Gunthorpe 	return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
1320b61815e2SJason Gunthorpe 			      cmd_out, cmd_out_len);
1321e662e14dSYishai Hadas }
1322e662e14dSYishai Hadas 
13236bf8f22aSYishai Hadas struct devx_async_event_queue {
13246bf8f22aSYishai Hadas 	spinlock_t		lock;
13256bf8f22aSYishai Hadas 	wait_queue_head_t	poll_wait;
13266bf8f22aSYishai Hadas 	struct list_head	event_list;
1327a124edbaSYishai Hadas 	atomic_t		bytes_in_use;
1328eaebaf77SYishai Hadas 	u8			is_destroyed:1;
13296bf8f22aSYishai Hadas };
13306bf8f22aSYishai Hadas 
13316bf8f22aSYishai Hadas struct devx_async_cmd_event_file {
13326bf8f22aSYishai Hadas 	struct ib_uobject		uobj;
13336bf8f22aSYishai Hadas 	struct devx_async_event_queue	ev_queue;
1334a124edbaSYishai Hadas 	struct mlx5_async_ctx		async_ctx;
13356bf8f22aSYishai Hadas };
13366bf8f22aSYishai Hadas 
13376bf8f22aSYishai Hadas static void devx_init_event_queue(struct devx_async_event_queue *ev_queue)
13386bf8f22aSYishai Hadas {
13396bf8f22aSYishai Hadas 	spin_lock_init(&ev_queue->lock);
13406bf8f22aSYishai Hadas 	INIT_LIST_HEAD(&ev_queue->event_list);
13416bf8f22aSYishai Hadas 	init_waitqueue_head(&ev_queue->poll_wait);
1342a124edbaSYishai Hadas 	atomic_set(&ev_queue->bytes_in_use, 0);
1343eaebaf77SYishai Hadas 	ev_queue->is_destroyed = 0;
13446bf8f22aSYishai Hadas }
13456bf8f22aSYishai Hadas 
13466bf8f22aSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC)(
13476bf8f22aSYishai Hadas 	struct uverbs_attr_bundle *attrs)
13486bf8f22aSYishai Hadas {
13496bf8f22aSYishai Hadas 	struct devx_async_cmd_event_file *ev_file;
13506bf8f22aSYishai Hadas 
13516bf8f22aSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
13526bf8f22aSYishai Hadas 		attrs, MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE);
1353a124edbaSYishai Hadas 	struct mlx5_ib_dev *mdev = to_mdev(uobj->context->device);
13546bf8f22aSYishai Hadas 
13556bf8f22aSYishai Hadas 	ev_file = container_of(uobj, struct devx_async_cmd_event_file,
13566bf8f22aSYishai Hadas 			       uobj);
13576bf8f22aSYishai Hadas 	devx_init_event_queue(&ev_file->ev_queue);
1358a124edbaSYishai Hadas 	mlx5_cmd_init_async_ctx(mdev->mdev, &ev_file->async_ctx);
13596bf8f22aSYishai Hadas 	return 0;
13606bf8f22aSYishai Hadas }
13616bf8f22aSYishai Hadas 
1362a124edbaSYishai Hadas static void devx_query_callback(int status, struct mlx5_async_work *context)
1363a124edbaSYishai Hadas {
1364a124edbaSYishai Hadas 	struct devx_async_data *async_data =
1365a124edbaSYishai Hadas 		container_of(context, struct devx_async_data, cb_work);
1366a124edbaSYishai Hadas 	struct ib_uobject *fd_uobj = async_data->fd_uobj;
1367a124edbaSYishai Hadas 	struct devx_async_cmd_event_file *ev_file;
1368a124edbaSYishai Hadas 	struct devx_async_event_queue *ev_queue;
1369a124edbaSYishai Hadas 	unsigned long flags;
1370a124edbaSYishai Hadas 
1371a124edbaSYishai Hadas 	ev_file = container_of(fd_uobj, struct devx_async_cmd_event_file,
1372a124edbaSYishai Hadas 			       uobj);
1373a124edbaSYishai Hadas 	ev_queue = &ev_file->ev_queue;
1374a124edbaSYishai Hadas 
1375a124edbaSYishai Hadas 	spin_lock_irqsave(&ev_queue->lock, flags);
1376a124edbaSYishai Hadas 	list_add_tail(&async_data->list, &ev_queue->event_list);
1377a124edbaSYishai Hadas 	spin_unlock_irqrestore(&ev_queue->lock, flags);
1378a124edbaSYishai Hadas 
1379a124edbaSYishai Hadas 	wake_up_interruptible(&ev_queue->poll_wait);
1380a124edbaSYishai Hadas 	fput(fd_uobj->object);
1381a124edbaSYishai Hadas }
1382a124edbaSYishai Hadas 
1383a124edbaSYishai Hadas #define MAX_ASYNC_BYTES_IN_USE (1024 * 1024) /* 1MB */
1384a124edbaSYishai Hadas 
1385a124edbaSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY)(
1386a124edbaSYishai Hadas 	struct uverbs_attr_bundle *attrs)
1387a124edbaSYishai Hadas {
1388a124edbaSYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs,
1389a124edbaSYishai Hadas 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN);
1390a124edbaSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
1391a124edbaSYishai Hadas 				attrs,
1392a124edbaSYishai Hadas 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_HANDLE);
1393a124edbaSYishai Hadas 	u16 cmd_out_len;
139489944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
139589944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1396a124edbaSYishai Hadas 	struct ib_uobject *fd_uobj;
1397a124edbaSYishai Hadas 	int err;
1398a124edbaSYishai Hadas 	int uid;
139989944450SShamir Rabinovitch 	struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device);
1400a124edbaSYishai Hadas 	struct devx_async_cmd_event_file *ev_file;
1401a124edbaSYishai Hadas 	struct devx_async_data *async_data;
1402a124edbaSYishai Hadas 
1403a124edbaSYishai Hadas 	uid = devx_get_uid(c, cmd_in);
1404a124edbaSYishai Hadas 	if (uid < 0)
1405a124edbaSYishai Hadas 		return uid;
1406a124edbaSYishai Hadas 
1407a124edbaSYishai Hadas 	if (!devx_is_obj_query_cmd(cmd_in))
1408a124edbaSYishai Hadas 		return -EINVAL;
1409a124edbaSYishai Hadas 
1410a124edbaSYishai Hadas 	err = uverbs_get_const(&cmd_out_len, attrs,
1411a124edbaSYishai Hadas 			       MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_OUT_LEN);
1412a124edbaSYishai Hadas 	if (err)
1413a124edbaSYishai Hadas 		return err;
1414a124edbaSYishai Hadas 
1415a124edbaSYishai Hadas 	if (!devx_is_valid_obj_id(uobj, cmd_in))
1416a124edbaSYishai Hadas 		return -EINVAL;
1417a124edbaSYishai Hadas 
1418a124edbaSYishai Hadas 	fd_uobj = uverbs_attr_get_uobject(attrs,
1419a124edbaSYishai Hadas 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_FD);
1420a124edbaSYishai Hadas 	if (IS_ERR(fd_uobj))
1421a124edbaSYishai Hadas 		return PTR_ERR(fd_uobj);
1422a124edbaSYishai Hadas 
1423a124edbaSYishai Hadas 	ev_file = container_of(fd_uobj, struct devx_async_cmd_event_file,
1424a124edbaSYishai Hadas 			       uobj);
1425a124edbaSYishai Hadas 
1426a124edbaSYishai Hadas 	if (atomic_add_return(cmd_out_len, &ev_file->ev_queue.bytes_in_use) >
1427a124edbaSYishai Hadas 			MAX_ASYNC_BYTES_IN_USE) {
1428a124edbaSYishai Hadas 		atomic_sub(cmd_out_len, &ev_file->ev_queue.bytes_in_use);
1429a124edbaSYishai Hadas 		return -EAGAIN;
1430a124edbaSYishai Hadas 	}
1431a124edbaSYishai Hadas 
1432a124edbaSYishai Hadas 	async_data = kvzalloc(struct_size(async_data, hdr.out_data,
1433a124edbaSYishai Hadas 					  cmd_out_len), GFP_KERNEL);
1434a124edbaSYishai Hadas 	if (!async_data) {
1435a124edbaSYishai Hadas 		err = -ENOMEM;
1436a124edbaSYishai Hadas 		goto sub_bytes;
1437a124edbaSYishai Hadas 	}
1438a124edbaSYishai Hadas 
1439a124edbaSYishai Hadas 	err = uverbs_copy_from(&async_data->hdr.wr_id, attrs,
1440a124edbaSYishai Hadas 			       MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_WR_ID);
1441a124edbaSYishai Hadas 	if (err)
1442a124edbaSYishai Hadas 		goto free_async;
1443a124edbaSYishai Hadas 
1444a124edbaSYishai Hadas 	async_data->cmd_out_len = cmd_out_len;
1445a124edbaSYishai Hadas 	async_data->mdev = mdev;
1446a124edbaSYishai Hadas 	async_data->fd_uobj = fd_uobj;
1447a124edbaSYishai Hadas 
1448a124edbaSYishai Hadas 	get_file(fd_uobj->object);
1449a124edbaSYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1450a124edbaSYishai Hadas 	err = mlx5_cmd_exec_cb(&ev_file->async_ctx, cmd_in,
1451a124edbaSYishai Hadas 		    uverbs_attr_get_len(attrs,
1452a124edbaSYishai Hadas 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN),
1453a124edbaSYishai Hadas 		    async_data->hdr.out_data,
1454a124edbaSYishai Hadas 		    async_data->cmd_out_len,
1455a124edbaSYishai Hadas 		    devx_query_callback, &async_data->cb_work);
1456a124edbaSYishai Hadas 
1457a124edbaSYishai Hadas 	if (err)
1458a124edbaSYishai Hadas 		goto cb_err;
1459a124edbaSYishai Hadas 
1460a124edbaSYishai Hadas 	return 0;
1461a124edbaSYishai Hadas 
1462a124edbaSYishai Hadas cb_err:
1463a124edbaSYishai Hadas 	fput(fd_uobj->object);
1464a124edbaSYishai Hadas free_async:
1465a124edbaSYishai Hadas 	kvfree(async_data);
1466a124edbaSYishai Hadas sub_bytes:
1467a124edbaSYishai Hadas 	atomic_sub(cmd_out_len, &ev_file->ev_queue.bytes_in_use);
1468a124edbaSYishai Hadas 	return err;
1469a124edbaSYishai Hadas }
1470a124edbaSYishai Hadas 
1471aeae9457SYishai Hadas static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext,
1472aeae9457SYishai Hadas 			 struct uverbs_attr_bundle *attrs,
1473aeae9457SYishai Hadas 			 struct devx_umem *obj)
1474aeae9457SYishai Hadas {
1475aeae9457SYishai Hadas 	u64 addr;
1476aeae9457SYishai Hadas 	size_t size;
1477bccd0622SJason Gunthorpe 	u32 access;
1478aeae9457SYishai Hadas 	int npages;
1479aeae9457SYishai Hadas 	int err;
1480aeae9457SYishai Hadas 	u32 page_mask;
1481aeae9457SYishai Hadas 
1482aeae9457SYishai Hadas 	if (uverbs_copy_from(&addr, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR) ||
1483bccd0622SJason Gunthorpe 	    uverbs_copy_from(&size, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_LEN))
1484aeae9457SYishai Hadas 		return -EFAULT;
1485aeae9457SYishai Hadas 
1486bccd0622SJason Gunthorpe 	err = uverbs_get_flags32(&access, attrs,
1487bccd0622SJason Gunthorpe 				 MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
148847f07f03SYishai Hadas 				 IB_ACCESS_LOCAL_WRITE |
148947f07f03SYishai Hadas 				 IB_ACCESS_REMOTE_WRITE |
149047f07f03SYishai Hadas 				 IB_ACCESS_REMOTE_READ);
1491bccd0622SJason Gunthorpe 	if (err)
1492bccd0622SJason Gunthorpe 		return err;
1493bccd0622SJason Gunthorpe 
1494aeae9457SYishai Hadas 	err = ib_check_mr_access(access);
1495aeae9457SYishai Hadas 	if (err)
1496aeae9457SYishai Hadas 		return err;
1497aeae9457SYishai Hadas 
1498b0ea0fa5SJason Gunthorpe 	obj->umem = ib_umem_get(&attrs->driver_udata, addr, size, access, 0);
1499aeae9457SYishai Hadas 	if (IS_ERR(obj->umem))
1500aeae9457SYishai Hadas 		return PTR_ERR(obj->umem);
1501aeae9457SYishai Hadas 
1502aeae9457SYishai Hadas 	mlx5_ib_cont_pages(obj->umem, obj->umem->address,
1503aeae9457SYishai Hadas 			   MLX5_MKEY_PAGE_SHIFT_MASK, &npages,
1504aeae9457SYishai Hadas 			   &obj->page_shift, &obj->ncont, NULL);
1505aeae9457SYishai Hadas 
1506aeae9457SYishai Hadas 	if (!npages) {
1507aeae9457SYishai Hadas 		ib_umem_release(obj->umem);
1508aeae9457SYishai Hadas 		return -EINVAL;
1509aeae9457SYishai Hadas 	}
1510aeae9457SYishai Hadas 
1511aeae9457SYishai Hadas 	page_mask = (1 << obj->page_shift) - 1;
1512aeae9457SYishai Hadas 	obj->page_offset = obj->umem->address & page_mask;
1513aeae9457SYishai Hadas 
1514aeae9457SYishai Hadas 	return 0;
1515aeae9457SYishai Hadas }
1516aeae9457SYishai Hadas 
1517b61815e2SJason Gunthorpe static int devx_umem_reg_cmd_alloc(struct uverbs_attr_bundle *attrs,
1518b61815e2SJason Gunthorpe 				   struct devx_umem *obj,
1519aeae9457SYishai Hadas 				   struct devx_umem_reg_cmd *cmd)
1520aeae9457SYishai Hadas {
1521aeae9457SYishai Hadas 	cmd->inlen = MLX5_ST_SZ_BYTES(create_umem_in) +
1522aeae9457SYishai Hadas 		    (MLX5_ST_SZ_BYTES(mtt) * obj->ncont);
1523b61815e2SJason Gunthorpe 	cmd->in = uverbs_zalloc(attrs, cmd->inlen);
1524b61815e2SJason Gunthorpe 	return PTR_ERR_OR_ZERO(cmd->in);
1525aeae9457SYishai Hadas }
1526aeae9457SYishai Hadas 
1527aeae9457SYishai Hadas static void devx_umem_reg_cmd_build(struct mlx5_ib_dev *dev,
1528aeae9457SYishai Hadas 				    struct devx_umem *obj,
1529aeae9457SYishai Hadas 				    struct devx_umem_reg_cmd *cmd)
1530aeae9457SYishai Hadas {
1531aeae9457SYishai Hadas 	void *umem;
1532aeae9457SYishai Hadas 	__be64 *mtt;
1533aeae9457SYishai Hadas 
1534aeae9457SYishai Hadas 	umem = MLX5_ADDR_OF(create_umem_in, cmd->in, umem);
1535aeae9457SYishai Hadas 	mtt = (__be64 *)MLX5_ADDR_OF(umem, umem, mtt);
1536aeae9457SYishai Hadas 
15376e3722baSYishai Hadas 	MLX5_SET(create_umem_in, cmd->in, opcode, MLX5_CMD_OP_CREATE_UMEM);
1538aeae9457SYishai Hadas 	MLX5_SET64(umem, umem, num_of_mtt, obj->ncont);
1539aeae9457SYishai Hadas 	MLX5_SET(umem, umem, log_page_size, obj->page_shift -
1540aeae9457SYishai Hadas 					    MLX5_ADAPTER_PAGE_SHIFT);
1541aeae9457SYishai Hadas 	MLX5_SET(umem, umem, page_offset, obj->page_offset);
1542aeae9457SYishai Hadas 	mlx5_ib_populate_pas(dev, obj->umem, obj->page_shift, mtt,
1543aeae9457SYishai Hadas 			     (obj->umem->writable ? MLX5_IB_MTT_WRITE : 0) |
1544aeae9457SYishai Hadas 			     MLX5_IB_MTT_READ);
1545aeae9457SYishai Hadas }
1546aeae9457SYishai Hadas 
1547e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_REG)(
154815a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
1549aeae9457SYishai Hadas {
1550aeae9457SYishai Hadas 	struct devx_umem_reg_cmd cmd;
1551aeae9457SYishai Hadas 	struct devx_umem *obj;
1552c36ee46dSJason Gunthorpe 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
1553c36ee46dSJason Gunthorpe 		attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE);
1554aeae9457SYishai Hadas 	u32 obj_id;
155589944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
155689944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1557c36ee46dSJason Gunthorpe 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
1558aeae9457SYishai Hadas 	int err;
1559aeae9457SYishai Hadas 
1560aeae9457SYishai Hadas 	if (!c->devx_uid)
15617e1335a7SYishai Hadas 		return -EINVAL;
15627e1335a7SYishai Hadas 
1563aeae9457SYishai Hadas 	obj = kzalloc(sizeof(struct devx_umem), GFP_KERNEL);
1564aeae9457SYishai Hadas 	if (!obj)
1565aeae9457SYishai Hadas 		return -ENOMEM;
1566aeae9457SYishai Hadas 
1567aeae9457SYishai Hadas 	err = devx_umem_get(dev, &c->ibucontext, attrs, obj);
1568aeae9457SYishai Hadas 	if (err)
1569aeae9457SYishai Hadas 		goto err_obj_free;
1570aeae9457SYishai Hadas 
1571b61815e2SJason Gunthorpe 	err = devx_umem_reg_cmd_alloc(attrs, obj, &cmd);
1572aeae9457SYishai Hadas 	if (err)
1573aeae9457SYishai Hadas 		goto err_umem_release;
1574aeae9457SYishai Hadas 
1575aeae9457SYishai Hadas 	devx_umem_reg_cmd_build(dev, obj, &cmd);
1576aeae9457SYishai Hadas 
15776e3722baSYishai Hadas 	MLX5_SET(create_umem_in, cmd.in, uid, c->devx_uid);
1578aeae9457SYishai Hadas 	err = mlx5_cmd_exec(dev->mdev, cmd.in, cmd.inlen, cmd.out,
1579aeae9457SYishai Hadas 			    sizeof(cmd.out));
1580aeae9457SYishai Hadas 	if (err)
1581b61815e2SJason Gunthorpe 		goto err_umem_release;
1582aeae9457SYishai Hadas 
1583aeae9457SYishai Hadas 	obj->mdev = dev->mdev;
1584aeae9457SYishai Hadas 	uobj->object = obj;
1585aeae9457SYishai Hadas 	devx_obj_build_destroy_cmd(cmd.in, cmd.out, obj->dinbox, &obj->dinlen, &obj_id);
1586aeae9457SYishai Hadas 	err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, &obj_id, sizeof(obj_id));
1587aeae9457SYishai Hadas 	if (err)
1588aeae9457SYishai Hadas 		goto err_umem_destroy;
1589aeae9457SYishai Hadas 
1590aeae9457SYishai Hadas 	return 0;
1591aeae9457SYishai Hadas 
1592aeae9457SYishai Hadas err_umem_destroy:
1593aeae9457SYishai Hadas 	mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, cmd.out, sizeof(cmd.out));
1594aeae9457SYishai Hadas err_umem_release:
1595aeae9457SYishai Hadas 	ib_umem_release(obj->umem);
1596aeae9457SYishai Hadas err_obj_free:
1597aeae9457SYishai Hadas 	kfree(obj);
1598aeae9457SYishai Hadas 	return err;
1599aeae9457SYishai Hadas }
1600aeae9457SYishai Hadas 
1601aeae9457SYishai Hadas static int devx_umem_cleanup(struct ib_uobject *uobject,
1602aeae9457SYishai Hadas 			     enum rdma_remove_reason why)
1603aeae9457SYishai Hadas {
1604aeae9457SYishai Hadas 	struct devx_umem *obj = uobject->object;
1605aeae9457SYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
1606aeae9457SYishai Hadas 	int err;
1607aeae9457SYishai Hadas 
1608aeae9457SYishai Hadas 	err = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out));
16091c77483eSYishai Hadas 	if (ib_is_destroy_retryable(err, why, uobject))
1610aeae9457SYishai Hadas 		return err;
1611aeae9457SYishai Hadas 
1612aeae9457SYishai Hadas 	ib_umem_release(obj->umem);
1613aeae9457SYishai Hadas 	kfree(obj);
1614aeae9457SYishai Hadas 	return 0;
1615aeae9457SYishai Hadas }
1616aeae9457SYishai Hadas 
16176bf8f22aSYishai Hadas static ssize_t devx_async_cmd_event_read(struct file *filp, char __user *buf,
16186bf8f22aSYishai Hadas 					 size_t count, loff_t *pos)
16196bf8f22aSYishai Hadas {
16204accbb3fSYishai Hadas 	struct devx_async_cmd_event_file *comp_ev_file = filp->private_data;
16214accbb3fSYishai Hadas 	struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue;
16224accbb3fSYishai Hadas 	struct devx_async_data *event;
16234accbb3fSYishai Hadas 	int ret = 0;
16244accbb3fSYishai Hadas 	size_t eventsz;
16254accbb3fSYishai Hadas 
16264accbb3fSYishai Hadas 	spin_lock_irq(&ev_queue->lock);
16274accbb3fSYishai Hadas 
16284accbb3fSYishai Hadas 	while (list_empty(&ev_queue->event_list)) {
16294accbb3fSYishai Hadas 		spin_unlock_irq(&ev_queue->lock);
16304accbb3fSYishai Hadas 
16314accbb3fSYishai Hadas 		if (filp->f_flags & O_NONBLOCK)
16324accbb3fSYishai Hadas 			return -EAGAIN;
16334accbb3fSYishai Hadas 
16344accbb3fSYishai Hadas 		if (wait_event_interruptible(
16354accbb3fSYishai Hadas 			    ev_queue->poll_wait,
1636eaebaf77SYishai Hadas 			    (!list_empty(&ev_queue->event_list) ||
1637eaebaf77SYishai Hadas 			     ev_queue->is_destroyed))) {
16384accbb3fSYishai Hadas 			return -ERESTARTSYS;
16394accbb3fSYishai Hadas 		}
1640eaebaf77SYishai Hadas 
1641eaebaf77SYishai Hadas 		if (list_empty(&ev_queue->event_list) &&
1642eaebaf77SYishai Hadas 		    ev_queue->is_destroyed)
1643eaebaf77SYishai Hadas 			return -EIO;
1644eaebaf77SYishai Hadas 
16454accbb3fSYishai Hadas 		spin_lock_irq(&ev_queue->lock);
16464accbb3fSYishai Hadas 	}
16474accbb3fSYishai Hadas 
16484accbb3fSYishai Hadas 	event = list_entry(ev_queue->event_list.next,
16494accbb3fSYishai Hadas 			   struct devx_async_data, list);
16504accbb3fSYishai Hadas 	eventsz = event->cmd_out_len +
16514accbb3fSYishai Hadas 			sizeof(struct mlx5_ib_uapi_devx_async_cmd_hdr);
16524accbb3fSYishai Hadas 
16534accbb3fSYishai Hadas 	if (eventsz > count) {
16544accbb3fSYishai Hadas 		spin_unlock_irq(&ev_queue->lock);
16554accbb3fSYishai Hadas 		return -ENOSPC;
16564accbb3fSYishai Hadas 	}
16574accbb3fSYishai Hadas 
16584accbb3fSYishai Hadas 	list_del(ev_queue->event_list.next);
16594accbb3fSYishai Hadas 	spin_unlock_irq(&ev_queue->lock);
16604accbb3fSYishai Hadas 
16614accbb3fSYishai Hadas 	if (copy_to_user(buf, &event->hdr, eventsz))
16624accbb3fSYishai Hadas 		ret = -EFAULT;
16634accbb3fSYishai Hadas 	else
16644accbb3fSYishai Hadas 		ret = eventsz;
16654accbb3fSYishai Hadas 
16664accbb3fSYishai Hadas 	atomic_sub(event->cmd_out_len, &ev_queue->bytes_in_use);
16674accbb3fSYishai Hadas 	kvfree(event);
16684accbb3fSYishai Hadas 	return ret;
16696bf8f22aSYishai Hadas }
16706bf8f22aSYishai Hadas 
16716bf8f22aSYishai Hadas static int devx_async_cmd_event_close(struct inode *inode, struct file *filp)
16726bf8f22aSYishai Hadas {
1673a124edbaSYishai Hadas 	struct ib_uobject *uobj = filp->private_data;
1674a124edbaSYishai Hadas 	struct devx_async_cmd_event_file *comp_ev_file = container_of(
1675a124edbaSYishai Hadas 		uobj, struct devx_async_cmd_event_file, uobj);
1676a124edbaSYishai Hadas 	struct devx_async_data *entry, *tmp;
1677a124edbaSYishai Hadas 
1678a124edbaSYishai Hadas 	spin_lock_irq(&comp_ev_file->ev_queue.lock);
1679a124edbaSYishai Hadas 	list_for_each_entry_safe(entry, tmp,
1680a124edbaSYishai Hadas 				 &comp_ev_file->ev_queue.event_list, list)
1681a124edbaSYishai Hadas 		kvfree(entry);
1682a124edbaSYishai Hadas 	spin_unlock_irq(&comp_ev_file->ev_queue.lock);
1683a124edbaSYishai Hadas 
16846bf8f22aSYishai Hadas 	uverbs_close_fd(filp);
16856bf8f22aSYishai Hadas 	return 0;
16866bf8f22aSYishai Hadas }
16876bf8f22aSYishai Hadas 
16886bf8f22aSYishai Hadas static __poll_t devx_async_cmd_event_poll(struct file *filp,
16896bf8f22aSYishai Hadas 					      struct poll_table_struct *wait)
16906bf8f22aSYishai Hadas {
16914accbb3fSYishai Hadas 	struct devx_async_cmd_event_file *comp_ev_file = filp->private_data;
16924accbb3fSYishai Hadas 	struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue;
16934accbb3fSYishai Hadas 	__poll_t pollflags = 0;
16944accbb3fSYishai Hadas 
16954accbb3fSYishai Hadas 	poll_wait(filp, &ev_queue->poll_wait, wait);
16964accbb3fSYishai Hadas 
16974accbb3fSYishai Hadas 	spin_lock_irq(&ev_queue->lock);
1698eaebaf77SYishai Hadas 	if (ev_queue->is_destroyed)
1699eaebaf77SYishai Hadas 		pollflags = EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
1700eaebaf77SYishai Hadas 	else if (!list_empty(&ev_queue->event_list))
17014accbb3fSYishai Hadas 		pollflags = EPOLLIN | EPOLLRDNORM;
17024accbb3fSYishai Hadas 	spin_unlock_irq(&ev_queue->lock);
17034accbb3fSYishai Hadas 
17044accbb3fSYishai Hadas 	return pollflags;
17056bf8f22aSYishai Hadas }
17066bf8f22aSYishai Hadas 
17076bf8f22aSYishai Hadas const struct file_operations devx_async_cmd_event_fops = {
17086bf8f22aSYishai Hadas 	.owner	 = THIS_MODULE,
17096bf8f22aSYishai Hadas 	.read	 = devx_async_cmd_event_read,
17106bf8f22aSYishai Hadas 	.poll    = devx_async_cmd_event_poll,
17116bf8f22aSYishai Hadas 	.release = devx_async_cmd_event_close,
17126bf8f22aSYishai Hadas 	.llseek	 = no_llseek,
17136bf8f22aSYishai Hadas };
17146bf8f22aSYishai Hadas 
17156bf8f22aSYishai Hadas static int devx_hot_unplug_async_cmd_event_file(struct ib_uobject *uobj,
17166bf8f22aSYishai Hadas 						   enum rdma_remove_reason why)
17176bf8f22aSYishai Hadas {
1718a124edbaSYishai Hadas 	struct devx_async_cmd_event_file *comp_ev_file =
1719a124edbaSYishai Hadas 		container_of(uobj, struct devx_async_cmd_event_file,
1720a124edbaSYishai Hadas 			     uobj);
1721eaebaf77SYishai Hadas 	struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue;
1722eaebaf77SYishai Hadas 
1723eaebaf77SYishai Hadas 	spin_lock_irq(&ev_queue->lock);
1724eaebaf77SYishai Hadas 	ev_queue->is_destroyed = 1;
1725eaebaf77SYishai Hadas 	spin_unlock_irq(&ev_queue->lock);
1726eaebaf77SYishai Hadas 
1727eaebaf77SYishai Hadas 	if (why == RDMA_REMOVE_DRIVER_REMOVE)
1728eaebaf77SYishai Hadas 		wake_up_interruptible(&ev_queue->poll_wait);
1729a124edbaSYishai Hadas 
1730a124edbaSYishai Hadas 	mlx5_cmd_cleanup_async_ctx(&comp_ev_file->async_ctx);
17316bf8f22aSYishai Hadas 	return 0;
17326bf8f22aSYishai Hadas };
17336bf8f22aSYishai Hadas 
17349a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
17359a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_UMEM_REG,
17369a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE,
1737aeae9457SYishai Hadas 			MLX5_IB_OBJECT_DEVX_UMEM,
1738aeae9457SYishai Hadas 			UVERBS_ACCESS_NEW,
173983bb4442SJason Gunthorpe 			UA_MANDATORY),
17409a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR,
17419a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u64),
174283bb4442SJason Gunthorpe 			   UA_MANDATORY),
17439a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_LEN,
17449a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u64),
174583bb4442SJason Gunthorpe 			   UA_MANDATORY),
1746bccd0622SJason Gunthorpe 	UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
1747bccd0622SJason Gunthorpe 			     enum ib_access_flags),
17489a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID,
17499a119cd5SJason Gunthorpe 			    UVERBS_ATTR_TYPE(u32),
175083bb4442SJason Gunthorpe 			    UA_MANDATORY));
1751aeae9457SYishai Hadas 
1752528922afSYishai Hadas DECLARE_UVERBS_NAMED_METHOD_DESTROY(
17539a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_UMEM_DEREG,
17549a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_DEREG_HANDLE,
1755aeae9457SYishai Hadas 			MLX5_IB_OBJECT_DEVX_UMEM,
1756aeae9457SYishai Hadas 			UVERBS_ACCESS_DESTROY,
175783bb4442SJason Gunthorpe 			UA_MANDATORY));
1758aeae9457SYishai Hadas 
17599a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
17609a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_QUERY_EQN,
17619a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC,
17629a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u32),
176383bb4442SJason Gunthorpe 			   UA_MANDATORY),
17649a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN,
17659a119cd5SJason Gunthorpe 			    UVERBS_ATTR_TYPE(u32),
176683bb4442SJason Gunthorpe 			    UA_MANDATORY));
1767f6fe01b7SYishai Hadas 
17689a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
17699a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_QUERY_UAR,
17709a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX,
17719a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u32),
177283bb4442SJason Gunthorpe 			   UA_MANDATORY),
17739a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX,
17749a119cd5SJason Gunthorpe 			    UVERBS_ATTR_TYPE(u32),
177583bb4442SJason Gunthorpe 			    UA_MANDATORY));
17767c043e90SYishai Hadas 
17779a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
17789a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OTHER,
17799a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
17809a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OTHER_CMD_IN,
17818aa8c95cSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
178283bb4442SJason Gunthorpe 		UA_MANDATORY,
178383bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
17849a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
17859a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT,
17867efce369SYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
1787540cd692SJason Gunthorpe 		UA_MANDATORY));
17887efce369SYishai Hadas 
17899a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
17909a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_CREATE,
17919a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE,
17929a119cd5SJason Gunthorpe 			MLX5_IB_OBJECT_DEVX_OBJ,
17939a119cd5SJason Gunthorpe 			UVERBS_ACCESS_NEW,
179483bb4442SJason Gunthorpe 			UA_MANDATORY),
17959a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
17969a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN,
17979a119cd5SJason Gunthorpe 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
179883bb4442SJason Gunthorpe 		UA_MANDATORY,
179983bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
18009a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
18019a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT,
18029a119cd5SJason Gunthorpe 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
1803540cd692SJason Gunthorpe 		UA_MANDATORY));
18049a119cd5SJason Gunthorpe 
1805528922afSYishai Hadas DECLARE_UVERBS_NAMED_METHOD_DESTROY(
18069a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_DESTROY,
18079a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_DESTROY_HANDLE,
18087efce369SYishai Hadas 			MLX5_IB_OBJECT_DEVX_OBJ,
18097efce369SYishai Hadas 			UVERBS_ACCESS_DESTROY,
181083bb4442SJason Gunthorpe 			UA_MANDATORY));
18117efce369SYishai Hadas 
18129a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
18139a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_MODIFY,
18149a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE,
181534613eb1SYishai Hadas 			UVERBS_IDR_ANY_OBJECT,
1816e662e14dSYishai Hadas 			UVERBS_ACCESS_WRITE,
181783bb4442SJason Gunthorpe 			UA_MANDATORY),
18189a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
18199a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN,
1820e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
182183bb4442SJason Gunthorpe 		UA_MANDATORY,
182283bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
18239a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
18249a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
1825e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
1826540cd692SJason Gunthorpe 		UA_MANDATORY));
1827e662e14dSYishai Hadas 
18289a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
18299a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_QUERY,
18309a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE,
183134613eb1SYishai Hadas 			UVERBS_IDR_ANY_OBJECT,
1832e662e14dSYishai Hadas 			UVERBS_ACCESS_READ,
183383bb4442SJason Gunthorpe 			UA_MANDATORY),
18349a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
18359a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN,
1836e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
183783bb4442SJason Gunthorpe 		UA_MANDATORY,
183883bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
18399a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
18409a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
1841e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
1842540cd692SJason Gunthorpe 		UA_MANDATORY));
1843e662e14dSYishai Hadas 
1844a124edbaSYishai Hadas DECLARE_UVERBS_NAMED_METHOD(
1845a124edbaSYishai Hadas 	MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY,
1846a124edbaSYishai Hadas 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE,
1847a124edbaSYishai Hadas 			UVERBS_IDR_ANY_OBJECT,
1848a124edbaSYishai Hadas 			UVERBS_ACCESS_READ,
1849a124edbaSYishai Hadas 			UA_MANDATORY),
1850a124edbaSYishai Hadas 	UVERBS_ATTR_PTR_IN(
1851a124edbaSYishai Hadas 		MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN,
1852a124edbaSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
1853a124edbaSYishai Hadas 		UA_MANDATORY,
1854a124edbaSYishai Hadas 		UA_ALLOC_AND_COPY),
1855a124edbaSYishai Hadas 	UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_OUT_LEN,
1856a124edbaSYishai Hadas 		u16, UA_MANDATORY),
1857a124edbaSYishai Hadas 	UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_FD,
1858a124edbaSYishai Hadas 		MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
1859a124edbaSYishai Hadas 		UVERBS_ACCESS_READ,
1860a124edbaSYishai Hadas 		UA_MANDATORY),
1861a124edbaSYishai Hadas 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_WR_ID,
1862a124edbaSYishai Hadas 		UVERBS_ATTR_TYPE(u64),
1863a124edbaSYishai Hadas 		UA_MANDATORY));
1864a124edbaSYishai Hadas 
18656c61d2a5SJason Gunthorpe DECLARE_UVERBS_GLOBAL_METHODS(MLX5_IB_OBJECT_DEVX,
18667c043e90SYishai Hadas 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OTHER),
1867f6fe01b7SYishai Hadas 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR),
1868f6fe01b7SYishai Hadas 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_EQN));
18698aa8c95cSYishai Hadas 
18706c61d2a5SJason Gunthorpe DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ,
18719a119cd5SJason Gunthorpe 			    UVERBS_TYPE_ALLOC_IDR(devx_obj_cleanup),
18727efce369SYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_CREATE),
1873e662e14dSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY),
1874e662e14dSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_MODIFY),
1875a124edbaSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY),
1876a124edbaSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY));
18777efce369SYishai Hadas 
18786c61d2a5SJason Gunthorpe DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM,
18799a119cd5SJason Gunthorpe 			    UVERBS_TYPE_ALLOC_IDR(devx_umem_cleanup),
1880aeae9457SYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG),
1881aeae9457SYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG));
1882aeae9457SYishai Hadas 
18836bf8f22aSYishai Hadas 
18846bf8f22aSYishai Hadas DECLARE_UVERBS_NAMED_METHOD(
18856bf8f22aSYishai Hadas 	MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC,
18866bf8f22aSYishai Hadas 	UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE,
18876bf8f22aSYishai Hadas 			MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
18886bf8f22aSYishai Hadas 			UVERBS_ACCESS_NEW,
18896bf8f22aSYishai Hadas 			UA_MANDATORY));
18906bf8f22aSYishai Hadas 
18916bf8f22aSYishai Hadas DECLARE_UVERBS_NAMED_OBJECT(
18926bf8f22aSYishai Hadas 	MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
18936bf8f22aSYishai Hadas 	UVERBS_TYPE_ALLOC_FD(sizeof(struct devx_async_cmd_event_file),
18946bf8f22aSYishai Hadas 			     devx_hot_unplug_async_cmd_event_file,
18956bf8f22aSYishai Hadas 			     &devx_async_cmd_event_fops, "[devx_async_cmd]",
18966bf8f22aSYishai Hadas 			     O_RDONLY),
18976bf8f22aSYishai Hadas 	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC));
18986bf8f22aSYishai Hadas 
189936e235c8SJason Gunthorpe static bool devx_is_supported(struct ib_device *device)
1900c59450c4SYishai Hadas {
190136e235c8SJason Gunthorpe 	struct mlx5_ib_dev *dev = to_mdev(device);
190236e235c8SJason Gunthorpe 
19036e3722baSYishai Hadas 	return !dev->rep && MLX5_CAP_GEN(dev->mdev, log_max_uctx);
1904c59450c4SYishai Hadas }
190536e235c8SJason Gunthorpe 
19060cbf432dSJason Gunthorpe const struct uapi_definition mlx5_ib_devx_defs[] = {
190736e235c8SJason Gunthorpe 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
190836e235c8SJason Gunthorpe 		MLX5_IB_OBJECT_DEVX,
190936e235c8SJason Gunthorpe 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
191036e235c8SJason Gunthorpe 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
191136e235c8SJason Gunthorpe 		MLX5_IB_OBJECT_DEVX_OBJ,
191236e235c8SJason Gunthorpe 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
191336e235c8SJason Gunthorpe 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
191436e235c8SJason Gunthorpe 		MLX5_IB_OBJECT_DEVX_UMEM,
191536e235c8SJason Gunthorpe 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
19166bf8f22aSYishai Hadas 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
19176bf8f22aSYishai Hadas 		MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
19186bf8f22aSYishai Hadas 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
19190cbf432dSJason Gunthorpe 	{},
19200cbf432dSJason Gunthorpe };
1921