xref: /linux/drivers/infiniband/hw/mlx5/devx.c (revision 7597385371425febdaa8c6a1da3625d4ffff16f5)
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"
17*75973853SYishai Hadas #include <linux/xarray.h>
18a8b92ca1SYishai Hadas 
198aa8c95cSYishai Hadas #define UVERBS_MODULE_NAME mlx5_ib
208aa8c95cSYishai Hadas #include <rdma/uverbs_named_ioctl.h>
218aa8c95cSYishai Hadas 
22534fd7aaSYishai Hadas enum devx_obj_flags {
23534fd7aaSYishai Hadas 	DEVX_OBJ_FLAGS_INDIRECT_MKEY = 1 << 0,
24c5ae1954SYishai Hadas 	DEVX_OBJ_FLAGS_DCT = 1 << 1,
25534fd7aaSYishai Hadas };
26534fd7aaSYishai Hadas 
27a124edbaSYishai Hadas struct devx_async_data {
28a124edbaSYishai Hadas 	struct mlx5_ib_dev *mdev;
29a124edbaSYishai Hadas 	struct list_head list;
30a124edbaSYishai Hadas 	struct ib_uobject *fd_uobj;
31a124edbaSYishai Hadas 	struct mlx5_async_work cb_work;
32a124edbaSYishai Hadas 	u16 cmd_out_len;
33a124edbaSYishai Hadas 	/* must be last field in this structure */
34a124edbaSYishai Hadas 	struct mlx5_ib_uapi_devx_async_cmd_hdr hdr;
35a124edbaSYishai Hadas };
36a124edbaSYishai Hadas 
37*75973853SYishai Hadas /* first level XA value data structure */
38*75973853SYishai Hadas struct devx_event {
39*75973853SYishai Hadas 	struct xarray object_ids; /* second XA level, Key = object id */
40*75973853SYishai Hadas 	struct list_head unaffiliated_list;
41*75973853SYishai Hadas };
42*75973853SYishai Hadas 
43*75973853SYishai Hadas /* second level XA value data structure */
44*75973853SYishai Hadas struct devx_obj_event {
45*75973853SYishai Hadas 	struct rcu_head rcu;
46*75973853SYishai Hadas 	struct list_head obj_sub_list;
47*75973853SYishai Hadas };
48*75973853SYishai Hadas 
49*75973853SYishai Hadas struct devx_event_subscription {
50*75973853SYishai Hadas 	struct list_head file_list; /* headed in ev_file->
51*75973853SYishai Hadas 				     * subscribed_events_list
52*75973853SYishai Hadas 				     */
53*75973853SYishai Hadas 	struct list_head xa_list; /* headed in devx_event->unaffiliated_list or
54*75973853SYishai Hadas 				   * devx_obj_event->obj_sub_list
55*75973853SYishai Hadas 				   */
56*75973853SYishai Hadas 	struct list_head obj_list; /* headed in devx_object */
57*75973853SYishai Hadas 	struct list_head event_list; /* headed in ev_file->event_list or in
58*75973853SYishai Hadas 				      * temp list via subscription
59*75973853SYishai Hadas 				      */
60*75973853SYishai Hadas 
61*75973853SYishai Hadas 	u8 is_cleaned:1;
62*75973853SYishai Hadas 	u32 xa_key_level1;
63*75973853SYishai Hadas 	u32 xa_key_level2;
64*75973853SYishai Hadas 	struct rcu_head	rcu;
65*75973853SYishai Hadas 	u64 cookie;
66*75973853SYishai Hadas 	struct devx_async_event_file *ev_file;
67*75973853SYishai Hadas 	struct file *filp; /* Upon hot unplug we need a direct access to */
68*75973853SYishai Hadas 	struct eventfd_ctx *eventfd;
69*75973853SYishai Hadas };
70*75973853SYishai Hadas 
712afc5e1bSYishai Hadas struct devx_async_event_file {
722afc5e1bSYishai Hadas 	struct ib_uobject uobj;
732afc5e1bSYishai Hadas 	/* Head of events that are subscribed to this FD */
742afc5e1bSYishai Hadas 	struct list_head subscribed_events_list;
752afc5e1bSYishai Hadas 	spinlock_t lock;
762afc5e1bSYishai Hadas 	wait_queue_head_t poll_wait;
772afc5e1bSYishai Hadas 	struct list_head event_list;
782afc5e1bSYishai Hadas 	struct mlx5_ib_dev *dev;
792afc5e1bSYishai Hadas 	u8 omit_data:1;
802afc5e1bSYishai Hadas };
812afc5e1bSYishai Hadas 
827efce369SYishai Hadas #define MLX5_MAX_DESTROY_INBOX_SIZE_DW MLX5_ST_SZ_DW(delete_fte_in)
837efce369SYishai Hadas struct devx_obj {
847efce369SYishai Hadas 	struct mlx5_core_dev	*mdev;
852351776eSYishai Hadas 	u64			obj_id;
867efce369SYishai Hadas 	u32			dinlen; /* destroy inbox length */
877efce369SYishai Hadas 	u32			dinbox[MLX5_MAX_DESTROY_INBOX_SIZE_DW];
88534fd7aaSYishai Hadas 	u32			flags;
89c5ae1954SYishai Hadas 	union {
90534fd7aaSYishai Hadas 		struct mlx5_ib_devx_mr	devx_mr;
91c5ae1954SYishai Hadas 		struct mlx5_core_dct	core_dct;
92c5ae1954SYishai Hadas 	};
93*75973853SYishai Hadas 	struct list_head event_sub; /* holds devx_event_subscription entries */
947efce369SYishai Hadas };
957efce369SYishai Hadas 
96aeae9457SYishai Hadas struct devx_umem {
97aeae9457SYishai Hadas 	struct mlx5_core_dev		*mdev;
98aeae9457SYishai Hadas 	struct ib_umem			*umem;
99aeae9457SYishai Hadas 	u32				page_offset;
100aeae9457SYishai Hadas 	int				page_shift;
101aeae9457SYishai Hadas 	int				ncont;
102aeae9457SYishai Hadas 	u32				dinlen;
103aeae9457SYishai Hadas 	u32				dinbox[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)];
104aeae9457SYishai Hadas };
105aeae9457SYishai Hadas 
106aeae9457SYishai Hadas struct devx_umem_reg_cmd {
107aeae9457SYishai Hadas 	void				*in;
108aeae9457SYishai Hadas 	u32				inlen;
109aeae9457SYishai Hadas 	u32				out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
110aeae9457SYishai Hadas };
111aeae9457SYishai Hadas 
11215a1b4beSJason Gunthorpe static struct mlx5_ib_ucontext *
11315a1b4beSJason Gunthorpe devx_ufile2uctx(const struct uverbs_attr_bundle *attrs)
1148aa8c95cSYishai Hadas {
11515a1b4beSJason Gunthorpe 	return to_mucontext(ib_uverbs_get_ucontext(attrs));
1168aa8c95cSYishai Hadas }
1178aa8c95cSYishai Hadas 
118fb98153bSYishai Hadas int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user)
119a8b92ca1SYishai Hadas {
120a8b92ca1SYishai Hadas 	u32 in[MLX5_ST_SZ_DW(create_uctx_in)] = {0};
121a8b92ca1SYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
1226e3722baSYishai Hadas 	void *uctx;
123a8b92ca1SYishai Hadas 	int err;
12476dc5a84SYishai Hadas 	u16 uid;
125fb98153bSYishai Hadas 	u32 cap = 0;
126a8b92ca1SYishai Hadas 
1276e3722baSYishai Hadas 	/* 0 means not supported */
1286e3722baSYishai Hadas 	if (!MLX5_CAP_GEN(dev->mdev, log_max_uctx))
129a8b92ca1SYishai Hadas 		return -EINVAL;
130a8b92ca1SYishai Hadas 
1316e3722baSYishai Hadas 	uctx = MLX5_ADDR_OF(create_uctx_in, in, uctx);
132fb98153bSYishai Hadas 	if (is_user && capable(CAP_NET_RAW) &&
133fb98153bSYishai Hadas 	    (MLX5_CAP_GEN(dev->mdev, uctx_cap) & MLX5_UCTX_CAP_RAW_TX))
134fb98153bSYishai Hadas 		cap |= MLX5_UCTX_CAP_RAW_TX;
13533cde96fSAriel Levkovich 	if (is_user && capable(CAP_SYS_RAWIO) &&
13633cde96fSAriel Levkovich 	    (MLX5_CAP_GEN(dev->mdev, uctx_cap) &
13733cde96fSAriel Levkovich 	     MLX5_UCTX_CAP_INTERNAL_DEV_RES))
13833cde96fSAriel Levkovich 		cap |= MLX5_UCTX_CAP_INTERNAL_DEV_RES;
139fb98153bSYishai Hadas 
1406e3722baSYishai Hadas 	MLX5_SET(create_uctx_in, in, opcode, MLX5_CMD_OP_CREATE_UCTX);
141fb98153bSYishai Hadas 	MLX5_SET(uctx, uctx, cap, cap);
142a8b92ca1SYishai Hadas 
143a8b92ca1SYishai Hadas 	err = mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
144a8b92ca1SYishai Hadas 	if (err)
145a8b92ca1SYishai Hadas 		return err;
146a8b92ca1SYishai Hadas 
14776dc5a84SYishai Hadas 	uid = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
14876dc5a84SYishai Hadas 	return uid;
149a8b92ca1SYishai Hadas }
150a8b92ca1SYishai Hadas 
15176dc5a84SYishai Hadas void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev, u16 uid)
152a8b92ca1SYishai Hadas {
1536e3722baSYishai Hadas 	u32 in[MLX5_ST_SZ_DW(destroy_uctx_in)] = {0};
154a8b92ca1SYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
155a8b92ca1SYishai Hadas 
1566e3722baSYishai Hadas 	MLX5_SET(destroy_uctx_in, in, opcode, MLX5_CMD_OP_DESTROY_UCTX);
1576e3722baSYishai Hadas 	MLX5_SET(destroy_uctx_in, in, uid, uid);
158a8b92ca1SYishai Hadas 
159a8b92ca1SYishai Hadas 	mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
160a8b92ca1SYishai Hadas }
1618aa8c95cSYishai Hadas 
16232269441SYishai Hadas bool mlx5_ib_devx_is_flow_dest(void *obj, int *dest_id, int *dest_type)
16332269441SYishai Hadas {
16432269441SYishai Hadas 	struct devx_obj *devx_obj = obj;
16532269441SYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode);
16632269441SYishai Hadas 
16732269441SYishai Hadas 	switch (opcode) {
16832269441SYishai Hadas 	case MLX5_CMD_OP_DESTROY_TIR:
16932269441SYishai Hadas 		*dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR;
17032269441SYishai Hadas 		*dest_id = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox,
17132269441SYishai Hadas 				    obj_id);
17232269441SYishai Hadas 		return true;
17332269441SYishai Hadas 
17432269441SYishai Hadas 	case MLX5_CMD_OP_DESTROY_FLOW_TABLE:
17532269441SYishai Hadas 		*dest_type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
17632269441SYishai Hadas 		*dest_id = MLX5_GET(destroy_flow_table_in, devx_obj->dinbox,
17732269441SYishai Hadas 				    table_id);
17832269441SYishai Hadas 		return true;
17932269441SYishai Hadas 	default:
18032269441SYishai Hadas 		return false;
18132269441SYishai Hadas 	}
18232269441SYishai Hadas }
18332269441SYishai Hadas 
184bfc5d839SMark Bloch bool mlx5_ib_devx_is_flow_counter(void *obj, u32 *counter_id)
185bfc5d839SMark Bloch {
186bfc5d839SMark Bloch 	struct devx_obj *devx_obj = obj;
187bfc5d839SMark Bloch 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode);
188bfc5d839SMark Bloch 
189bfc5d839SMark Bloch 	if (opcode == MLX5_CMD_OP_DEALLOC_FLOW_COUNTER) {
190bfc5d839SMark Bloch 		*counter_id = MLX5_GET(dealloc_flow_counter_in,
191bfc5d839SMark Bloch 				       devx_obj->dinbox,
192bfc5d839SMark Bloch 				       flow_counter_id);
193bfc5d839SMark Bloch 		return true;
194bfc5d839SMark Bloch 	}
195bfc5d839SMark Bloch 
196bfc5d839SMark Bloch 	return false;
197bfc5d839SMark Bloch }
198bfc5d839SMark Bloch 
199*75973853SYishai Hadas static bool is_legacy_unaffiliated_event_num(u16 event_num)
200*75973853SYishai Hadas {
201*75973853SYishai Hadas 	switch (event_num) {
202*75973853SYishai Hadas 	case MLX5_EVENT_TYPE_PORT_CHANGE:
203*75973853SYishai Hadas 		return true;
204*75973853SYishai Hadas 	default:
205*75973853SYishai Hadas 		return false;
206*75973853SYishai Hadas 	}
207*75973853SYishai Hadas }
208*75973853SYishai Hadas 
209*75973853SYishai Hadas static bool is_legacy_obj_event_num(u16 event_num)
210*75973853SYishai Hadas {
211*75973853SYishai Hadas 	switch (event_num) {
212*75973853SYishai Hadas 	case MLX5_EVENT_TYPE_PATH_MIG:
213*75973853SYishai Hadas 	case MLX5_EVENT_TYPE_COMM_EST:
214*75973853SYishai Hadas 	case MLX5_EVENT_TYPE_SQ_DRAINED:
215*75973853SYishai Hadas 	case MLX5_EVENT_TYPE_SRQ_LAST_WQE:
216*75973853SYishai Hadas 	case MLX5_EVENT_TYPE_SRQ_RQ_LIMIT:
217*75973853SYishai Hadas 	case MLX5_EVENT_TYPE_CQ_ERROR:
218*75973853SYishai Hadas 	case MLX5_EVENT_TYPE_WQ_CATAS_ERROR:
219*75973853SYishai Hadas 	case MLX5_EVENT_TYPE_PATH_MIG_FAILED:
220*75973853SYishai Hadas 	case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR:
221*75973853SYishai Hadas 	case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR:
222*75973853SYishai Hadas 	case MLX5_EVENT_TYPE_SRQ_CATAS_ERROR:
223*75973853SYishai Hadas 	case MLX5_EVENT_TYPE_DCT_DRAINED:
224*75973853SYishai Hadas 	case MLX5_EVENT_TYPE_COMP:
225*75973853SYishai Hadas 		return true;
226*75973853SYishai Hadas 	default:
227*75973853SYishai Hadas 		return false;
228*75973853SYishai Hadas 	}
229*75973853SYishai Hadas }
230*75973853SYishai Hadas 
231*75973853SYishai Hadas static u16 get_legacy_obj_type(u16 opcode)
232*75973853SYishai Hadas {
233*75973853SYishai Hadas 	switch (opcode) {
234*75973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
235*75973853SYishai Hadas 		return MLX5_EVENT_QUEUE_TYPE_RQ;
236*75973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
237*75973853SYishai Hadas 		return MLX5_EVENT_QUEUE_TYPE_QP;
238*75973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
239*75973853SYishai Hadas 		return MLX5_EVENT_QUEUE_TYPE_SQ;
240*75973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_DCT:
241*75973853SYishai Hadas 		return MLX5_EVENT_QUEUE_TYPE_DCT;
242*75973853SYishai Hadas 	default:
243*75973853SYishai Hadas 		return 0;
244*75973853SYishai Hadas 	}
245*75973853SYishai Hadas }
246*75973853SYishai Hadas 
247*75973853SYishai Hadas static u16 get_dec_obj_type(struct devx_obj *obj, u16 event_num)
248*75973853SYishai Hadas {
249*75973853SYishai Hadas 	u16 opcode;
250*75973853SYishai Hadas 
251*75973853SYishai Hadas 	opcode = (obj->obj_id >> 32) & 0xffff;
252*75973853SYishai Hadas 
253*75973853SYishai Hadas 	if (is_legacy_obj_event_num(event_num))
254*75973853SYishai Hadas 		return get_legacy_obj_type(opcode);
255*75973853SYishai Hadas 
256*75973853SYishai Hadas 	switch (opcode) {
257*75973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
258*75973853SYishai Hadas 		return (obj->obj_id >> 48);
259*75973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
260*75973853SYishai Hadas 		return MLX5_OBJ_TYPE_RQ;
261*75973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
262*75973853SYishai Hadas 		return MLX5_OBJ_TYPE_QP;
263*75973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
264*75973853SYishai Hadas 		return MLX5_OBJ_TYPE_SQ;
265*75973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_DCT:
266*75973853SYishai Hadas 		return MLX5_OBJ_TYPE_DCT;
267*75973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIR:
268*75973853SYishai Hadas 		return MLX5_OBJ_TYPE_TIR;
269*75973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIS:
270*75973853SYishai Hadas 		return MLX5_OBJ_TYPE_TIS;
271*75973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_PSV:
272*75973853SYishai Hadas 		return MLX5_OBJ_TYPE_PSV;
273*75973853SYishai Hadas 	case MLX5_OBJ_TYPE_MKEY:
274*75973853SYishai Hadas 		return MLX5_OBJ_TYPE_MKEY;
275*75973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_RMP:
276*75973853SYishai Hadas 		return MLX5_OBJ_TYPE_RMP;
277*75973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
278*75973853SYishai Hadas 		return MLX5_OBJ_TYPE_XRC_SRQ;
279*75973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRQ:
280*75973853SYishai Hadas 		return MLX5_OBJ_TYPE_XRQ;
281*75973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQT:
282*75973853SYishai Hadas 		return MLX5_OBJ_TYPE_RQT;
283*75973853SYishai Hadas 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
284*75973853SYishai Hadas 		return MLX5_OBJ_TYPE_FLOW_COUNTER;
285*75973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_CQ:
286*75973853SYishai Hadas 		return MLX5_OBJ_TYPE_CQ;
287*75973853SYishai Hadas 	default:
288*75973853SYishai Hadas 		return 0;
289*75973853SYishai Hadas 	}
290*75973853SYishai Hadas }
291*75973853SYishai Hadas 
292*75973853SYishai Hadas static u32 get_dec_obj_id(u64 obj_id)
293*75973853SYishai Hadas {
294*75973853SYishai Hadas 	return (obj_id & 0xffffffff);
295*75973853SYishai Hadas }
296*75973853SYishai Hadas 
2972351776eSYishai Hadas /*
2982351776eSYishai Hadas  * As the obj_id in the firmware is not globally unique the object type
2992351776eSYishai Hadas  * must be considered upon checking for a valid object id.
3002351776eSYishai Hadas  * For that the opcode of the creator command is encoded as part of the obj_id.
3012351776eSYishai Hadas  */
302cd5d20f1SYishai Hadas static u64 get_enc_obj_id(u32 opcode, u32 obj_id)
3032351776eSYishai Hadas {
3042351776eSYishai Hadas 	return ((u64)opcode << 32) | obj_id;
3052351776eSYishai Hadas }
3062351776eSYishai Hadas 
30734613eb1SYishai Hadas static u64 devx_get_obj_id(const void *in)
308e662e14dSYishai Hadas {
309e662e14dSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
3102351776eSYishai Hadas 	u64 obj_id;
311e662e14dSYishai Hadas 
312e662e14dSYishai Hadas 	switch (opcode) {
313e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
314e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
315cd5d20f1SYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_GENERAL_OBJECT |
316cd5d20f1SYishai Hadas 					MLX5_GET(general_obj_in_cmd_hdr, in,
317cd5d20f1SYishai Hadas 						 obj_type) << 16,
3182351776eSYishai Hadas 					MLX5_GET(general_obj_in_cmd_hdr, in,
3192351776eSYishai Hadas 						 obj_id));
320e662e14dSYishai Hadas 		break;
321e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_MKEY:
3222351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_MKEY,
3232351776eSYishai Hadas 					MLX5_GET(query_mkey_in, in,
3242351776eSYishai Hadas 						 mkey_index));
325e662e14dSYishai Hadas 		break;
326e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_CQ:
3272351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ,
3282351776eSYishai Hadas 					MLX5_GET(query_cq_in, in, cqn));
329e662e14dSYishai Hadas 		break;
330e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_CQ:
3312351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ,
3322351776eSYishai Hadas 					MLX5_GET(modify_cq_in, in, cqn));
333e662e14dSYishai Hadas 		break;
334e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SQ:
3352351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ,
3362351776eSYishai Hadas 					MLX5_GET(query_sq_in, in, sqn));
337e662e14dSYishai Hadas 		break;
338e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_SQ:
3392351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ,
3402351776eSYishai Hadas 					MLX5_GET(modify_sq_in, in, sqn));
341e662e14dSYishai Hadas 		break;
342e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RQ:
3432351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
3442351776eSYishai Hadas 					MLX5_GET(query_rq_in, in, rqn));
345e662e14dSYishai Hadas 		break;
346e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RQ:
3472351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
3482351776eSYishai Hadas 					MLX5_GET(modify_rq_in, in, rqn));
349e662e14dSYishai Hadas 		break;
350e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RMP:
3512351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RMP,
3522351776eSYishai Hadas 					MLX5_GET(query_rmp_in, in, rmpn));
353e662e14dSYishai Hadas 		break;
354e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RMP:
3552351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RMP,
3562351776eSYishai Hadas 					MLX5_GET(modify_rmp_in, in, rmpn));
357e662e14dSYishai Hadas 		break;
358e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RQT:
3592351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT,
3602351776eSYishai Hadas 					MLX5_GET(query_rqt_in, in, rqtn));
361e662e14dSYishai Hadas 		break;
362e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RQT:
3632351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT,
3642351776eSYishai Hadas 					MLX5_GET(modify_rqt_in, in, rqtn));
365e662e14dSYishai Hadas 		break;
366e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_TIR:
3672351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR,
3682351776eSYishai Hadas 					MLX5_GET(query_tir_in, in, tirn));
369e662e14dSYishai Hadas 		break;
370e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_TIR:
3712351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR,
3722351776eSYishai Hadas 					MLX5_GET(modify_tir_in, in, tirn));
373e662e14dSYishai Hadas 		break;
374e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_TIS:
3752351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS,
3762351776eSYishai Hadas 					MLX5_GET(query_tis_in, in, tisn));
377e662e14dSYishai Hadas 		break;
378e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_TIS:
3792351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS,
3802351776eSYishai Hadas 					MLX5_GET(modify_tis_in, in, tisn));
381e662e14dSYishai Hadas 		break;
382e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_TABLE:
3832351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_TABLE,
3842351776eSYishai Hadas 					MLX5_GET(query_flow_table_in, in,
3852351776eSYishai Hadas 						 table_id));
386e662e14dSYishai Hadas 		break;
387e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_FLOW_TABLE:
3882351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_TABLE,
3892351776eSYishai Hadas 					MLX5_GET(modify_flow_table_in, in,
3902351776eSYishai Hadas 						 table_id));
391e662e14dSYishai Hadas 		break;
392e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_GROUP:
3932351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_GROUP,
3942351776eSYishai Hadas 					MLX5_GET(query_flow_group_in, in,
3952351776eSYishai Hadas 						 group_id));
396e662e14dSYishai Hadas 		break;
397e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
3982351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY,
3992351776eSYishai Hadas 					MLX5_GET(query_fte_in, in,
4002351776eSYishai Hadas 						 flow_index));
401e662e14dSYishai Hadas 		break;
402e662e14dSYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
4032351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY,
4042351776eSYishai Hadas 					MLX5_GET(set_fte_in, in, flow_index));
405e662e14dSYishai Hadas 		break;
406e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_Q_COUNTER:
4072351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_Q_COUNTER,
4082351776eSYishai Hadas 					MLX5_GET(query_q_counter_in, in,
4092351776eSYishai Hadas 						 counter_set_id));
410e662e14dSYishai Hadas 		break;
411e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
4122351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_FLOW_COUNTER,
4132351776eSYishai Hadas 					MLX5_GET(query_flow_counter_in, in,
4142351776eSYishai Hadas 						 flow_counter_id));
415e662e14dSYishai Hadas 		break;
416e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT:
4172351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT,
4182351776eSYishai Hadas 					MLX5_GET(general_obj_in_cmd_hdr, in,
4192351776eSYishai Hadas 						 obj_id));
420e662e14dSYishai Hadas 		break;
421e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
4222351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT,
4232351776eSYishai Hadas 					MLX5_GET(query_scheduling_element_in,
4242351776eSYishai Hadas 						 in, scheduling_element_id));
425e662e14dSYishai Hadas 		break;
426e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
4272351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT,
4282351776eSYishai Hadas 					MLX5_GET(modify_scheduling_element_in,
4292351776eSYishai Hadas 						 in, scheduling_element_id));
430e662e14dSYishai Hadas 		break;
431e662e14dSYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
4322351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT,
4332351776eSYishai Hadas 					MLX5_GET(add_vxlan_udp_dport_in, in,
4342351776eSYishai Hadas 						 vxlan_udp_port));
435e662e14dSYishai Hadas 		break;
436e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
4372351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_L2_TABLE_ENTRY,
4382351776eSYishai Hadas 					MLX5_GET(query_l2_table_entry_in, in,
4392351776eSYishai Hadas 						 table_index));
440e662e14dSYishai Hadas 		break;
441e662e14dSYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
4422351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_L2_TABLE_ENTRY,
4432351776eSYishai Hadas 					MLX5_GET(set_l2_table_entry_in, in,
4442351776eSYishai Hadas 						 table_index));
445e662e14dSYishai Hadas 		break;
446e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_QP:
4472351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
4482351776eSYishai Hadas 					MLX5_GET(query_qp_in, in, qpn));
449e662e14dSYishai Hadas 		break;
450e662e14dSYishai Hadas 	case MLX5_CMD_OP_RST2INIT_QP:
4512351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
4522351776eSYishai Hadas 					MLX5_GET(rst2init_qp_in, in, qpn));
453e662e14dSYishai Hadas 		break;
454e662e14dSYishai Hadas 	case MLX5_CMD_OP_INIT2RTR_QP:
4552351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
4562351776eSYishai Hadas 					MLX5_GET(init2rtr_qp_in, in, qpn));
457e662e14dSYishai Hadas 		break;
458e662e14dSYishai Hadas 	case MLX5_CMD_OP_RTR2RTS_QP:
4592351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
4602351776eSYishai Hadas 					MLX5_GET(rtr2rts_qp_in, in, qpn));
461e662e14dSYishai Hadas 		break;
462e662e14dSYishai Hadas 	case MLX5_CMD_OP_RTS2RTS_QP:
4632351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
4642351776eSYishai Hadas 					MLX5_GET(rts2rts_qp_in, in, qpn));
465e662e14dSYishai Hadas 		break;
466e662e14dSYishai Hadas 	case MLX5_CMD_OP_SQERR2RTS_QP:
4672351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
4682351776eSYishai Hadas 					MLX5_GET(sqerr2rts_qp_in, in, qpn));
469e662e14dSYishai Hadas 		break;
470e662e14dSYishai Hadas 	case MLX5_CMD_OP_2ERR_QP:
4712351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
4722351776eSYishai Hadas 					MLX5_GET(qp_2err_in, in, qpn));
473e662e14dSYishai Hadas 		break;
474e662e14dSYishai Hadas 	case MLX5_CMD_OP_2RST_QP:
4752351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
4762351776eSYishai Hadas 					MLX5_GET(qp_2rst_in, in, qpn));
477e662e14dSYishai Hadas 		break;
478e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_DCT:
4792351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT,
4802351776eSYishai Hadas 					MLX5_GET(query_dct_in, in, dctn));
481e662e14dSYishai Hadas 		break;
482e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ:
483719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY:
484719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS:
4852351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRQ,
4862351776eSYishai Hadas 					MLX5_GET(query_xrq_in, in, xrqn));
487e662e14dSYishai Hadas 		break;
488e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_XRC_SRQ:
4892351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRC_SRQ,
4902351776eSYishai Hadas 					MLX5_GET(query_xrc_srq_in, in,
4912351776eSYishai Hadas 						 xrc_srqn));
492e662e14dSYishai Hadas 		break;
493e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_XRC_SRQ:
4942351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRC_SRQ,
4952351776eSYishai Hadas 					MLX5_GET(arm_xrc_srq_in, in, xrc_srqn));
496e662e14dSYishai Hadas 		break;
497e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SRQ:
4982351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SRQ,
4992351776eSYishai Hadas 					MLX5_GET(query_srq_in, in, srqn));
500e662e14dSYishai Hadas 		break;
501e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_RQ:
5022351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
5032351776eSYishai Hadas 					MLX5_GET(arm_rq_in, in, srq_number));
504e662e14dSYishai Hadas 		break;
505e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
5062351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT,
5072351776eSYishai Hadas 					MLX5_GET(drain_dct_in, in, dctn));
508e662e14dSYishai Hadas 		break;
509e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_XRQ:
510719598c9SYishai Hadas 	case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY:
5112351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRQ,
5122351776eSYishai Hadas 					MLX5_GET(arm_xrq_in, in, xrqn));
513e662e14dSYishai Hadas 		break;
514719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT:
515719598c9SYishai Hadas 		obj_id = get_enc_obj_id
516719598c9SYishai Hadas 				(MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT,
517719598c9SYishai Hadas 				 MLX5_GET(query_packet_reformat_context_in,
518719598c9SYishai Hadas 					  in, packet_reformat_id));
519719598c9SYishai Hadas 		break;
520e662e14dSYishai Hadas 	default:
52134613eb1SYishai Hadas 		obj_id = 0;
522e662e14dSYishai Hadas 	}
523e662e14dSYishai Hadas 
52434613eb1SYishai Hadas 	return obj_id;
52534613eb1SYishai Hadas }
526e662e14dSYishai Hadas 
527e79c9c60SJason Gunthorpe static bool devx_is_valid_obj_id(struct uverbs_attr_bundle *attrs,
528e79c9c60SJason Gunthorpe 				 struct ib_uobject *uobj, const void *in)
52934613eb1SYishai Hadas {
530e79c9c60SJason Gunthorpe 	struct mlx5_ib_dev *dev = mlx5_udata_to_mdev(&attrs->driver_udata);
53134613eb1SYishai Hadas 	u64 obj_id = devx_get_obj_id(in);
53234613eb1SYishai Hadas 
53334613eb1SYishai Hadas 	if (!obj_id)
534e662e14dSYishai Hadas 		return false;
53534613eb1SYishai Hadas 
53634613eb1SYishai Hadas 	switch (uobj_get_object_id(uobj)) {
53734613eb1SYishai Hadas 	case UVERBS_OBJECT_CQ:
53834613eb1SYishai Hadas 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ,
53934613eb1SYishai Hadas 				      to_mcq(uobj->object)->mcq.cqn) ==
54034613eb1SYishai Hadas 				      obj_id;
54134613eb1SYishai Hadas 
54234613eb1SYishai Hadas 	case UVERBS_OBJECT_SRQ:
54334613eb1SYishai Hadas 	{
54434613eb1SYishai Hadas 		struct mlx5_core_srq *srq = &(to_msrq(uobj->object)->msrq);
54534613eb1SYishai Hadas 		u16 opcode;
54634613eb1SYishai Hadas 
54734613eb1SYishai Hadas 		switch (srq->common.res) {
54834613eb1SYishai Hadas 		case MLX5_RES_XSRQ:
54934613eb1SYishai Hadas 			opcode = MLX5_CMD_OP_CREATE_XRC_SRQ;
55034613eb1SYishai Hadas 			break;
55134613eb1SYishai Hadas 		case MLX5_RES_XRQ:
55234613eb1SYishai Hadas 			opcode = MLX5_CMD_OP_CREATE_XRQ;
55334613eb1SYishai Hadas 			break;
55434613eb1SYishai Hadas 		default:
55534613eb1SYishai Hadas 			if (!dev->mdev->issi)
55634613eb1SYishai Hadas 				opcode = MLX5_CMD_OP_CREATE_SRQ;
55734613eb1SYishai Hadas 			else
55834613eb1SYishai Hadas 				opcode = MLX5_CMD_OP_CREATE_RMP;
55934613eb1SYishai Hadas 		}
56034613eb1SYishai Hadas 
56134613eb1SYishai Hadas 		return get_enc_obj_id(opcode,
56234613eb1SYishai Hadas 				      to_msrq(uobj->object)->msrq.srqn) ==
56334613eb1SYishai Hadas 				      obj_id;
56434613eb1SYishai Hadas 	}
56534613eb1SYishai Hadas 
56634613eb1SYishai Hadas 	case UVERBS_OBJECT_QP:
56734613eb1SYishai Hadas 	{
56834613eb1SYishai Hadas 		struct mlx5_ib_qp *qp = to_mqp(uobj->object);
56934613eb1SYishai Hadas 		enum ib_qp_type	qp_type = qp->ibqp.qp_type;
57034613eb1SYishai Hadas 
57134613eb1SYishai Hadas 		if (qp_type == IB_QPT_RAW_PACKET ||
57234613eb1SYishai Hadas 		    (qp->flags & MLX5_IB_QP_UNDERLAY)) {
57334613eb1SYishai Hadas 			struct mlx5_ib_raw_packet_qp *raw_packet_qp =
57434613eb1SYishai Hadas 							 &qp->raw_packet_qp;
57534613eb1SYishai Hadas 			struct mlx5_ib_rq *rq = &raw_packet_qp->rq;
57634613eb1SYishai Hadas 			struct mlx5_ib_sq *sq = &raw_packet_qp->sq;
57734613eb1SYishai Hadas 
57834613eb1SYishai Hadas 			return (get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
57934613eb1SYishai Hadas 					       rq->base.mqp.qpn) == obj_id ||
58034613eb1SYishai Hadas 				get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ,
58134613eb1SYishai Hadas 					       sq->base.mqp.qpn) == obj_id ||
58234613eb1SYishai Hadas 				get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR,
58334613eb1SYishai Hadas 					       rq->tirn) == obj_id ||
58434613eb1SYishai Hadas 				get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS,
58534613eb1SYishai Hadas 					       sq->tisn) == obj_id);
58634613eb1SYishai Hadas 		}
58734613eb1SYishai Hadas 
58834613eb1SYishai Hadas 		if (qp_type == MLX5_IB_QPT_DCT)
58934613eb1SYishai Hadas 			return get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT,
59034613eb1SYishai Hadas 					      qp->dct.mdct.mqp.qpn) == obj_id;
59134613eb1SYishai Hadas 
59234613eb1SYishai Hadas 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
59334613eb1SYishai Hadas 				      qp->ibqp.qp_num) == obj_id;
59434613eb1SYishai Hadas 	}
59534613eb1SYishai Hadas 
59634613eb1SYishai Hadas 	case UVERBS_OBJECT_WQ:
59734613eb1SYishai Hadas 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
59834613eb1SYishai Hadas 				      to_mrwq(uobj->object)->core_qp.qpn) ==
59934613eb1SYishai Hadas 				      obj_id;
60034613eb1SYishai Hadas 
60134613eb1SYishai Hadas 	case UVERBS_OBJECT_RWQ_IND_TBL:
60234613eb1SYishai Hadas 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT,
60334613eb1SYishai Hadas 				      to_mrwq_ind_table(uobj->object)->rqtn) ==
60434613eb1SYishai Hadas 				      obj_id;
60534613eb1SYishai Hadas 
60634613eb1SYishai Hadas 	case MLX5_IB_OBJECT_DEVX_OBJ:
60734613eb1SYishai Hadas 		return ((struct devx_obj *)uobj->object)->obj_id == obj_id;
60834613eb1SYishai Hadas 
609e662e14dSYishai Hadas 	default:
610e662e14dSYishai Hadas 		return false;
611e662e14dSYishai Hadas 	}
612e662e14dSYishai Hadas }
613e662e14dSYishai Hadas 
614ba1a057dSYishai Hadas static void devx_set_umem_valid(const void *in)
615ba1a057dSYishai Hadas {
616ba1a057dSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
617ba1a057dSYishai Hadas 
618ba1a057dSYishai Hadas 	switch (opcode) {
619ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_MKEY:
620ba1a057dSYishai Hadas 		MLX5_SET(create_mkey_in, in, mkey_umem_valid, 1);
621ba1a057dSYishai Hadas 		break;
622ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_CQ:
623ba1a057dSYishai Hadas 	{
624ba1a057dSYishai Hadas 		void *cqc;
625ba1a057dSYishai Hadas 
626ba1a057dSYishai Hadas 		MLX5_SET(create_cq_in, in, cq_umem_valid, 1);
627ba1a057dSYishai Hadas 		cqc = MLX5_ADDR_OF(create_cq_in, in, cq_context);
628ba1a057dSYishai Hadas 		MLX5_SET(cqc, cqc, dbr_umem_valid, 1);
629ba1a057dSYishai Hadas 		break;
630ba1a057dSYishai Hadas 	}
631ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
632ba1a057dSYishai Hadas 	{
633ba1a057dSYishai Hadas 		void *qpc;
634ba1a057dSYishai Hadas 
635ba1a057dSYishai Hadas 		qpc = MLX5_ADDR_OF(create_qp_in, in, qpc);
636ba1a057dSYishai Hadas 		MLX5_SET(qpc, qpc, dbr_umem_valid, 1);
637ba1a057dSYishai Hadas 		MLX5_SET(create_qp_in, in, wq_umem_valid, 1);
638ba1a057dSYishai Hadas 		break;
639ba1a057dSYishai Hadas 	}
640ba1a057dSYishai Hadas 
641ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
642ba1a057dSYishai Hadas 	{
643ba1a057dSYishai Hadas 		void *rqc, *wq;
644ba1a057dSYishai Hadas 
645ba1a057dSYishai Hadas 		rqc = MLX5_ADDR_OF(create_rq_in, in, ctx);
646ba1a057dSYishai Hadas 		wq  = MLX5_ADDR_OF(rqc, rqc, wq);
647ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
648ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, wq_umem_valid, 1);
649ba1a057dSYishai Hadas 		break;
650ba1a057dSYishai Hadas 	}
651ba1a057dSYishai Hadas 
652ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
653ba1a057dSYishai Hadas 	{
654ba1a057dSYishai Hadas 		void *sqc, *wq;
655ba1a057dSYishai Hadas 
656ba1a057dSYishai Hadas 		sqc = MLX5_ADDR_OF(create_sq_in, in, ctx);
657ba1a057dSYishai Hadas 		wq = MLX5_ADDR_OF(sqc, sqc, wq);
658ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
659ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, wq_umem_valid, 1);
660ba1a057dSYishai Hadas 		break;
661ba1a057dSYishai Hadas 	}
662ba1a057dSYishai Hadas 
663ba1a057dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_CQ:
664ba1a057dSYishai Hadas 		MLX5_SET(modify_cq_in, in, cq_umem_valid, 1);
665ba1a057dSYishai Hadas 		break;
666ba1a057dSYishai Hadas 
667ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_RMP:
668ba1a057dSYishai Hadas 	{
669ba1a057dSYishai Hadas 		void *rmpc, *wq;
670ba1a057dSYishai Hadas 
671ba1a057dSYishai Hadas 		rmpc = MLX5_ADDR_OF(create_rmp_in, in, ctx);
672ba1a057dSYishai Hadas 		wq = MLX5_ADDR_OF(rmpc, rmpc, wq);
673ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
674ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, wq_umem_valid, 1);
675ba1a057dSYishai Hadas 		break;
676ba1a057dSYishai Hadas 	}
677ba1a057dSYishai Hadas 
678ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_XRQ:
679ba1a057dSYishai Hadas 	{
680ba1a057dSYishai Hadas 		void *xrqc, *wq;
681ba1a057dSYishai Hadas 
682ba1a057dSYishai Hadas 		xrqc = MLX5_ADDR_OF(create_xrq_in, in, xrq_context);
683ba1a057dSYishai Hadas 		wq = MLX5_ADDR_OF(xrqc, xrqc, wq);
684ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
685ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, wq_umem_valid, 1);
686ba1a057dSYishai Hadas 		break;
687ba1a057dSYishai Hadas 	}
688ba1a057dSYishai Hadas 
689ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
690ba1a057dSYishai Hadas 	{
691ba1a057dSYishai Hadas 		void *xrc_srqc;
692ba1a057dSYishai Hadas 
693ba1a057dSYishai Hadas 		MLX5_SET(create_xrc_srq_in, in, xrc_srq_umem_valid, 1);
694ba1a057dSYishai Hadas 		xrc_srqc = MLX5_ADDR_OF(create_xrc_srq_in, in,
695ba1a057dSYishai Hadas 					xrc_srq_context_entry);
696ba1a057dSYishai Hadas 		MLX5_SET(xrc_srqc, xrc_srqc, dbr_umem_valid, 1);
697ba1a057dSYishai Hadas 		break;
698ba1a057dSYishai Hadas 	}
699ba1a057dSYishai Hadas 
700ba1a057dSYishai Hadas 	default:
701ba1a057dSYishai Hadas 		return;
702ba1a057dSYishai Hadas 	}
703ba1a057dSYishai Hadas }
704ba1a057dSYishai Hadas 
7052351776eSYishai Hadas static bool devx_is_obj_create_cmd(const void *in, u16 *opcode)
7067efce369SYishai Hadas {
7072351776eSYishai Hadas 	*opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
7087efce369SYishai Hadas 
7092351776eSYishai Hadas 	switch (*opcode) {
7107efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
7117efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_MKEY:
7127efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_CQ:
7137efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_PD:
7147efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
7157efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RMP:
7167efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
7177efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
7187efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQT:
7197efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIR:
7207efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIS:
7217efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_Q_COUNTER:
7227efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_TABLE:
7237efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_GROUP:
7247efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
72560786f09SMark Bloch 	case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT:
7267efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
7277efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
7287efce369SYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
7297efce369SYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
7307efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
7317efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SRQ:
7327efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
7337efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_DCT:
7347efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRQ:
7357efce369SYishai Hadas 	case MLX5_CMD_OP_ATTACH_TO_MCG:
7367efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_XRCD:
7377efce369SYishai Hadas 		return true;
7387efce369SYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
7397efce369SYishai Hadas 	{
7407efce369SYishai Hadas 		u16 op_mod = MLX5_GET(set_fte_in, in, op_mod);
7417efce369SYishai Hadas 		if (op_mod == 0)
7427efce369SYishai Hadas 			return true;
7437efce369SYishai Hadas 		return false;
7447efce369SYishai Hadas 	}
7457efce369SYishai Hadas 	default:
7467efce369SYishai Hadas 		return false;
7477efce369SYishai Hadas 	}
7487efce369SYishai Hadas }
7497efce369SYishai Hadas 
750e662e14dSYishai Hadas static bool devx_is_obj_modify_cmd(const void *in)
751e662e14dSYishai Hadas {
752e662e14dSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
753e662e14dSYishai Hadas 
754e662e14dSYishai Hadas 	switch (opcode) {
755e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
756e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_CQ:
757e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RMP:
758e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_SQ:
759e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RQ:
760e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RQT:
761e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_TIR:
762e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_TIS:
763e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_FLOW_TABLE:
764e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
765e662e14dSYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
766e662e14dSYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
767e662e14dSYishai Hadas 	case MLX5_CMD_OP_RST2INIT_QP:
768e662e14dSYishai Hadas 	case MLX5_CMD_OP_INIT2RTR_QP:
769e662e14dSYishai Hadas 	case MLX5_CMD_OP_RTR2RTS_QP:
770e662e14dSYishai Hadas 	case MLX5_CMD_OP_RTS2RTS_QP:
771e662e14dSYishai Hadas 	case MLX5_CMD_OP_SQERR2RTS_QP:
772e662e14dSYishai Hadas 	case MLX5_CMD_OP_2ERR_QP:
773e662e14dSYishai Hadas 	case MLX5_CMD_OP_2RST_QP:
774e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_XRC_SRQ:
775e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_RQ:
776e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
777e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_XRQ:
778719598c9SYishai Hadas 	case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY:
779e662e14dSYishai Hadas 		return true;
780e662e14dSYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
781e662e14dSYishai Hadas 	{
782e662e14dSYishai Hadas 		u16 op_mod = MLX5_GET(set_fte_in, in, op_mod);
783e662e14dSYishai Hadas 
784e662e14dSYishai Hadas 		if (op_mod == 1)
785e662e14dSYishai Hadas 			return true;
786e662e14dSYishai Hadas 		return false;
787e662e14dSYishai Hadas 	}
788e662e14dSYishai Hadas 	default:
789e662e14dSYishai Hadas 		return false;
790e662e14dSYishai Hadas 	}
791e662e14dSYishai Hadas }
792e662e14dSYishai Hadas 
793e662e14dSYishai Hadas static bool devx_is_obj_query_cmd(const void *in)
794e662e14dSYishai Hadas {
795e662e14dSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
796e662e14dSYishai Hadas 
797e662e14dSYishai Hadas 	switch (opcode) {
798e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
799e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_MKEY:
800e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_CQ:
801e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RMP:
802e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SQ:
803e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RQ:
804e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RQT:
805e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_TIR:
806e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_TIS:
807e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_Q_COUNTER:
808e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_TABLE:
809e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_GROUP:
810e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
811e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
812e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT:
813e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
814e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
815e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_QP:
816e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SRQ:
817e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_XRC_SRQ:
818e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_DCT:
819e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ:
820719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY:
821719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS:
822719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT:
823e662e14dSYishai Hadas 		return true;
824e662e14dSYishai Hadas 	default:
825e662e14dSYishai Hadas 		return false;
826e662e14dSYishai Hadas 	}
827e662e14dSYishai Hadas }
828e662e14dSYishai Hadas 
8297e1335a7SYishai Hadas static bool devx_is_whitelist_cmd(void *in)
8307e1335a7SYishai Hadas {
8317e1335a7SYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
8327e1335a7SYishai Hadas 
8337e1335a7SYishai Hadas 	switch (opcode) {
8347e1335a7SYishai Hadas 	case MLX5_CMD_OP_QUERY_HCA_CAP:
8357e1335a7SYishai Hadas 	case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT:
83656e5acd4SMaor Gottlieb 	case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT:
8377e1335a7SYishai Hadas 		return true;
8387e1335a7SYishai Hadas 	default:
8397e1335a7SYishai Hadas 		return false;
8407e1335a7SYishai Hadas 	}
8417e1335a7SYishai Hadas }
8427e1335a7SYishai Hadas 
8437e1335a7SYishai Hadas static int devx_get_uid(struct mlx5_ib_ucontext *c, void *cmd_in)
8447e1335a7SYishai Hadas {
8457e1335a7SYishai Hadas 	if (devx_is_whitelist_cmd(cmd_in)) {
8467e1335a7SYishai Hadas 		struct mlx5_ib_dev *dev;
8477e1335a7SYishai Hadas 
8487e1335a7SYishai Hadas 		if (c->devx_uid)
8497e1335a7SYishai Hadas 			return c->devx_uid;
8507e1335a7SYishai Hadas 
8517e1335a7SYishai Hadas 		dev = to_mdev(c->ibucontext.device);
8527e1335a7SYishai Hadas 		if (dev->devx_whitelist_uid)
8537e1335a7SYishai Hadas 			return dev->devx_whitelist_uid;
8547e1335a7SYishai Hadas 
8557e1335a7SYishai Hadas 		return -EOPNOTSUPP;
8567e1335a7SYishai Hadas 	}
8577e1335a7SYishai Hadas 
8587e1335a7SYishai Hadas 	if (!c->devx_uid)
8597e1335a7SYishai Hadas 		return -EINVAL;
8607e1335a7SYishai Hadas 
8617e1335a7SYishai Hadas 	return c->devx_uid;
8627e1335a7SYishai Hadas }
863e662e14dSYishai Hadas static bool devx_is_general_cmd(void *in)
8648aa8c95cSYishai Hadas {
8658aa8c95cSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
8668aa8c95cSYishai Hadas 
867719598c9SYishai Hadas 	if (opcode >= MLX5_CMD_OP_GENERAL_START &&
868719598c9SYishai Hadas 	    opcode < MLX5_CMD_OP_GENERAL_END)
869719598c9SYishai Hadas 		return true;
870719598c9SYishai Hadas 
8718aa8c95cSYishai Hadas 	switch (opcode) {
8728aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_HCA_CAP:
8737e1335a7SYishai Hadas 	case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT:
87456e5acd4SMaor Gottlieb 	case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT:
8758aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_VPORT_STATE:
8768aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_ADAPTER:
8778aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_ISSI:
8788aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT:
8798aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_ROCE_ADDRESS:
8808aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_VNIC_ENV:
8818aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_VPORT_COUNTER:
8828aa8c95cSYishai Hadas 	case MLX5_CMD_OP_GET_DROPPED_PACKET_LOG:
8838aa8c95cSYishai Hadas 	case MLX5_CMD_OP_NOP:
8848aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_CONG_STATUS:
8858aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_CONG_PARAMS:
8868aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_CONG_STATISTICS:
8878aa8c95cSYishai Hadas 		return true;
8888aa8c95cSYishai Hadas 	default:
8898aa8c95cSYishai Hadas 		return false;
8908aa8c95cSYishai Hadas 	}
8918aa8c95cSYishai Hadas }
8928aa8c95cSYishai Hadas 
893e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_EQN)(
89415a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
895f6fe01b7SYishai Hadas {
896e83f0ecdSJason Gunthorpe 	struct mlx5_ib_ucontext *c;
897e83f0ecdSJason Gunthorpe 	struct mlx5_ib_dev *dev;
898f6fe01b7SYishai Hadas 	int user_vector;
899f6fe01b7SYishai Hadas 	int dev_eqn;
900f6fe01b7SYishai Hadas 	unsigned int irqn;
901f6fe01b7SYishai Hadas 	int err;
902f6fe01b7SYishai Hadas 
903f6fe01b7SYishai Hadas 	if (uverbs_copy_from(&user_vector, attrs,
904f6fe01b7SYishai Hadas 			     MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC))
905f6fe01b7SYishai Hadas 		return -EFAULT;
906f6fe01b7SYishai Hadas 
90715a1b4beSJason Gunthorpe 	c = devx_ufile2uctx(attrs);
908e83f0ecdSJason Gunthorpe 	if (IS_ERR(c))
909e83f0ecdSJason Gunthorpe 		return PTR_ERR(c);
910e83f0ecdSJason Gunthorpe 	dev = to_mdev(c->ibucontext.device);
911e83f0ecdSJason Gunthorpe 
912f6fe01b7SYishai Hadas 	err = mlx5_vector2eqn(dev->mdev, user_vector, &dev_eqn, &irqn);
913f6fe01b7SYishai Hadas 	if (err < 0)
914f6fe01b7SYishai Hadas 		return err;
915f6fe01b7SYishai Hadas 
916f6fe01b7SYishai Hadas 	if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN,
917f6fe01b7SYishai Hadas 			   &dev_eqn, sizeof(dev_eqn)))
918f6fe01b7SYishai Hadas 		return -EFAULT;
919f6fe01b7SYishai Hadas 
920f6fe01b7SYishai Hadas 	return 0;
921f6fe01b7SYishai Hadas }
922f6fe01b7SYishai Hadas 
9237c043e90SYishai Hadas /*
9247c043e90SYishai Hadas  *Security note:
9257c043e90SYishai Hadas  * The hardware protection mechanism works like this: Each device object that
9267c043e90SYishai Hadas  * is subject to UAR doorbells (QP/SQ/CQ) gets a UAR ID (called uar_page in
9277c043e90SYishai Hadas  * the device specification manual) upon its creation. Then upon doorbell,
9287c043e90SYishai Hadas  * hardware fetches the object context for which the doorbell was rang, and
9297c043e90SYishai Hadas  * validates that the UAR through which the DB was rang matches the UAR ID
9307c043e90SYishai Hadas  * of the object.
9317c043e90SYishai Hadas  * If no match the doorbell is silently ignored by the hardware. Of course,
9327c043e90SYishai Hadas  * the user cannot ring a doorbell on a UAR that was not mapped to it.
9337c043e90SYishai Hadas  * Now in devx, as the devx kernel does not manipulate the QP/SQ/CQ command
9347c043e90SYishai Hadas  * mailboxes (except tagging them with UID), we expose to the user its UAR
9357c043e90SYishai Hadas  * ID, so it can embed it in these objects in the expected specification
9367c043e90SYishai Hadas  * format. So the only thing the user can do is hurt itself by creating a
9377c043e90SYishai Hadas  * QP/SQ/CQ with a UAR ID other than his, and then in this case other users
9387c043e90SYishai Hadas  * may ring a doorbell on its objects.
9397c043e90SYishai Hadas  * The consequence of that will be that another user can schedule a QP/SQ
9407c043e90SYishai Hadas  * of the buggy user for execution (just insert it to the hardware schedule
9417c043e90SYishai Hadas  * queue or arm its CQ for event generation), no further harm is expected.
9427c043e90SYishai Hadas  */
943e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_UAR)(
94415a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
9457c043e90SYishai Hadas {
94622fa27fbSJason Gunthorpe 	struct mlx5_ib_ucontext *c;
94722fa27fbSJason Gunthorpe 	struct mlx5_ib_dev *dev;
9487c043e90SYishai Hadas 	u32 user_idx;
9497c043e90SYishai Hadas 	s32 dev_idx;
9507c043e90SYishai Hadas 
95115a1b4beSJason Gunthorpe 	c = devx_ufile2uctx(attrs);
95222fa27fbSJason Gunthorpe 	if (IS_ERR(c))
95322fa27fbSJason Gunthorpe 		return PTR_ERR(c);
95422fa27fbSJason Gunthorpe 	dev = to_mdev(c->ibucontext.device);
95522fa27fbSJason Gunthorpe 
9567c043e90SYishai Hadas 	if (uverbs_copy_from(&user_idx, attrs,
9577c043e90SYishai Hadas 			     MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX))
9587c043e90SYishai Hadas 		return -EFAULT;
9597c043e90SYishai Hadas 
96022fa27fbSJason Gunthorpe 	dev_idx = bfregn_to_uar_index(dev, &c->bfregi, user_idx, true);
9617c043e90SYishai Hadas 	if (dev_idx < 0)
9627c043e90SYishai Hadas 		return dev_idx;
9637c043e90SYishai Hadas 
9647c043e90SYishai Hadas 	if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX,
9657c043e90SYishai Hadas 			   &dev_idx, sizeof(dev_idx)))
9667c043e90SYishai Hadas 		return -EFAULT;
9677c043e90SYishai Hadas 
9687c043e90SYishai Hadas 	return 0;
9697c043e90SYishai Hadas }
9707c043e90SYishai Hadas 
971e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)(
97215a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
9738aa8c95cSYishai Hadas {
97422fa27fbSJason Gunthorpe 	struct mlx5_ib_ucontext *c;
97522fa27fbSJason Gunthorpe 	struct mlx5_ib_dev *dev;
9767efce369SYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(
9777efce369SYishai Hadas 		attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN);
9788aa8c95cSYishai Hadas 	int cmd_out_len = uverbs_attr_get_len(attrs,
9798aa8c95cSYishai Hadas 					MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT);
9808aa8c95cSYishai Hadas 	void *cmd_out;
9818aa8c95cSYishai Hadas 	int err;
9827e1335a7SYishai Hadas 	int uid;
9838aa8c95cSYishai Hadas 
98415a1b4beSJason Gunthorpe 	c = devx_ufile2uctx(attrs);
98522fa27fbSJason Gunthorpe 	if (IS_ERR(c))
98622fa27fbSJason Gunthorpe 		return PTR_ERR(c);
98722fa27fbSJason Gunthorpe 	dev = to_mdev(c->ibucontext.device);
98822fa27fbSJason Gunthorpe 
9897e1335a7SYishai Hadas 	uid = devx_get_uid(c, cmd_in);
9907e1335a7SYishai Hadas 	if (uid < 0)
9917e1335a7SYishai Hadas 		return uid;
9928aa8c95cSYishai Hadas 
9938aa8c95cSYishai Hadas 	/* Only white list of some general HCA commands are allowed for this method. */
9948aa8c95cSYishai Hadas 	if (!devx_is_general_cmd(cmd_in))
9958aa8c95cSYishai Hadas 		return -EINVAL;
9968aa8c95cSYishai Hadas 
997b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
998b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
999b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
10008aa8c95cSYishai Hadas 
10017e1335a7SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
10028aa8c95cSYishai Hadas 	err = mlx5_cmd_exec(dev->mdev, cmd_in,
10038aa8c95cSYishai Hadas 			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN),
10048aa8c95cSYishai Hadas 			    cmd_out, cmd_out_len);
10058aa8c95cSYishai Hadas 	if (err)
10068aa8c95cSYishai Hadas 		return err;
1007b61815e2SJason Gunthorpe 
1008b61815e2SJason Gunthorpe 	return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, cmd_out,
1009b61815e2SJason Gunthorpe 			      cmd_out_len);
10108aa8c95cSYishai Hadas }
10118aa8c95cSYishai Hadas 
10127efce369SYishai Hadas static void devx_obj_build_destroy_cmd(void *in, void *out, void *din,
10137efce369SYishai Hadas 				       u32 *dinlen,
10147efce369SYishai Hadas 				       u32 *obj_id)
10157efce369SYishai Hadas {
10167efce369SYishai Hadas 	u16 obj_type = MLX5_GET(general_obj_in_cmd_hdr, in, obj_type);
10177efce369SYishai Hadas 	u16 uid = MLX5_GET(general_obj_in_cmd_hdr, in, uid);
10187efce369SYishai Hadas 
10197efce369SYishai Hadas 	*obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
10207efce369SYishai Hadas 	*dinlen = MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr);
10217efce369SYishai Hadas 
10227efce369SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, din, obj_id, *obj_id);
10237efce369SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, din, uid, uid);
10247efce369SYishai Hadas 
10257efce369SYishai Hadas 	switch (MLX5_GET(general_obj_in_cmd_hdr, in, opcode)) {
10267efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
10277efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
10287efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, obj_type, obj_type);
10297efce369SYishai Hadas 		break;
10307efce369SYishai Hadas 
10316e3722baSYishai Hadas 	case MLX5_CMD_OP_CREATE_UMEM:
10326e3722baSYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
10336e3722baSYishai Hadas 			 MLX5_CMD_OP_DESTROY_UMEM);
10346e3722baSYishai Hadas 		break;
10357efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_MKEY:
10367efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_MKEY);
10377efce369SYishai Hadas 		break;
10387efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_CQ:
10397efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_CQ);
10407efce369SYishai Hadas 		break;
10417efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_PD:
10427efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DEALLOC_PD);
10437efce369SYishai Hadas 		break;
10447efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
10457efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
10467efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN);
10477efce369SYishai Hadas 		break;
10487efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RMP:
10497efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RMP);
10507efce369SYishai Hadas 		break;
10517efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
10527efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_SQ);
10537efce369SYishai Hadas 		break;
10547efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
10557efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQ);
10567efce369SYishai Hadas 		break;
10577efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQT:
10587efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQT);
10597efce369SYishai Hadas 		break;
10607efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIR:
10617efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIR);
10627efce369SYishai Hadas 		break;
10637efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIS:
10647efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIS);
10657efce369SYishai Hadas 		break;
10667efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_Q_COUNTER:
10677efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
10687efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_Q_COUNTER);
10697efce369SYishai Hadas 		break;
10707efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_TABLE:
10717efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(destroy_flow_table_in);
10727efce369SYishai Hadas 		*obj_id = MLX5_GET(create_flow_table_out, out, table_id);
10737efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, other_vport,
10747efce369SYishai Hadas 			 MLX5_GET(create_flow_table_in,  in, other_vport));
10757efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, vport_number,
10767efce369SYishai Hadas 			 MLX5_GET(create_flow_table_in,  in, vport_number));
10777efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, table_type,
10787efce369SYishai Hadas 			 MLX5_GET(create_flow_table_in,  in, table_type));
10797efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, table_id, *obj_id);
10807efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
10817efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_FLOW_TABLE);
10827efce369SYishai Hadas 		break;
10837efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_GROUP:
10847efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(destroy_flow_group_in);
10857efce369SYishai Hadas 		*obj_id = MLX5_GET(create_flow_group_out, out, group_id);
10867efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, other_vport,
10877efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, other_vport));
10887efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, vport_number,
10897efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, vport_number));
10907efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, table_type,
10917efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, table_type));
10927efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, table_id,
10937efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, table_id));
10947efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, group_id, *obj_id);
10957efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
10967efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_FLOW_GROUP);
10977efce369SYishai Hadas 		break;
10987efce369SYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
10997efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(delete_fte_in);
11007efce369SYishai Hadas 		*obj_id = MLX5_GET(set_fte_in, in, flow_index);
11017efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, other_vport,
11027efce369SYishai Hadas 			 MLX5_GET(set_fte_in,  in, other_vport));
11037efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, vport_number,
11047efce369SYishai Hadas 			 MLX5_GET(set_fte_in, in, vport_number));
11057efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, table_type,
11067efce369SYishai Hadas 			 MLX5_GET(set_fte_in, in, table_type));
11077efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, table_id,
11087efce369SYishai Hadas 			 MLX5_GET(set_fte_in, in, table_id));
11097efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, flow_index, *obj_id);
11107efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
11117efce369SYishai Hadas 			 MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
11127efce369SYishai Hadas 		break;
11137efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
11147efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
11157efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_FLOW_COUNTER);
11167efce369SYishai Hadas 		break;
111760786f09SMark Bloch 	case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT:
11187efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
111960786f09SMark Bloch 			 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
11207efce369SYishai Hadas 		break;
11217efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
11227efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
11237efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT);
11247efce369SYishai Hadas 		break;
11257efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
11267efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(destroy_scheduling_element_in);
11277efce369SYishai Hadas 		*obj_id = MLX5_GET(create_scheduling_element_out, out,
11287efce369SYishai Hadas 				   scheduling_element_id);
11297efce369SYishai Hadas 		MLX5_SET(destroy_scheduling_element_in, din,
11307efce369SYishai Hadas 			 scheduling_hierarchy,
11317efce369SYishai Hadas 			 MLX5_GET(create_scheduling_element_in, in,
11327efce369SYishai Hadas 				  scheduling_hierarchy));
11337efce369SYishai Hadas 		MLX5_SET(destroy_scheduling_element_in, din,
11347efce369SYishai Hadas 			 scheduling_element_id, *obj_id);
11357efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
11367efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT);
11377efce369SYishai Hadas 		break;
11387efce369SYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
11397efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(delete_vxlan_udp_dport_in);
11407efce369SYishai Hadas 		*obj_id = MLX5_GET(add_vxlan_udp_dport_in, in, vxlan_udp_port);
11417efce369SYishai Hadas 		MLX5_SET(delete_vxlan_udp_dport_in, din, vxlan_udp_port, *obj_id);
11427efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
11437efce369SYishai Hadas 			 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
11447efce369SYishai Hadas 		break;
11457efce369SYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
11467efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(delete_l2_table_entry_in);
11477efce369SYishai Hadas 		*obj_id = MLX5_GET(set_l2_table_entry_in, in, table_index);
11487efce369SYishai Hadas 		MLX5_SET(delete_l2_table_entry_in, din, table_index, *obj_id);
11497efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
11507efce369SYishai Hadas 			 MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY);
11517efce369SYishai Hadas 		break;
11527efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
11537efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_QP);
11547efce369SYishai Hadas 		break;
11557efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SRQ:
11567efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_SRQ);
11577efce369SYishai Hadas 		break;
11587efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
11597efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
11607efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_XRC_SRQ);
11617efce369SYishai Hadas 		break;
11627efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_DCT:
11637efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_DCT);
11647efce369SYishai Hadas 		break;
11657efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRQ:
11667efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_XRQ);
11677efce369SYishai Hadas 		break;
11687efce369SYishai Hadas 	case MLX5_CMD_OP_ATTACH_TO_MCG:
11697efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(detach_from_mcg_in);
11707efce369SYishai Hadas 		MLX5_SET(detach_from_mcg_in, din, qpn,
11717efce369SYishai Hadas 			 MLX5_GET(attach_to_mcg_in, in, qpn));
11727efce369SYishai Hadas 		memcpy(MLX5_ADDR_OF(detach_from_mcg_in, din, multicast_gid),
11737efce369SYishai Hadas 		       MLX5_ADDR_OF(attach_to_mcg_in, in, multicast_gid),
11747efce369SYishai Hadas 		       MLX5_FLD_SZ_BYTES(attach_to_mcg_in, multicast_gid));
11757efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DETACH_FROM_MCG);
11767efce369SYishai Hadas 		break;
11777efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_XRCD:
11787efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DEALLOC_XRCD);
11797efce369SYishai Hadas 		break;
11807efce369SYishai Hadas 	default:
11817efce369SYishai Hadas 		/* The entry must match to one of the devx_is_obj_create_cmd */
11827efce369SYishai Hadas 		WARN_ON(true);
11837efce369SYishai Hadas 		break;
11847efce369SYishai Hadas 	}
11857efce369SYishai Hadas }
11867efce369SYishai Hadas 
1187534fd7aaSYishai Hadas static int devx_handle_mkey_indirect(struct devx_obj *obj,
1188534fd7aaSYishai Hadas 				     struct mlx5_ib_dev *dev,
1189534fd7aaSYishai Hadas 				     void *in, void *out)
1190534fd7aaSYishai Hadas {
1191534fd7aaSYishai Hadas 	struct mlx5_ib_devx_mr *devx_mr = &obj->devx_mr;
1192534fd7aaSYishai Hadas 	struct mlx5_core_mkey *mkey;
1193534fd7aaSYishai Hadas 	void *mkc;
1194534fd7aaSYishai Hadas 	u8 key;
1195534fd7aaSYishai Hadas 
1196534fd7aaSYishai Hadas 	mkey = &devx_mr->mmkey;
1197534fd7aaSYishai Hadas 	mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
1198534fd7aaSYishai Hadas 	key = MLX5_GET(mkc, mkc, mkey_7_0);
1199534fd7aaSYishai Hadas 	mkey->key = mlx5_idx_to_mkey(
1200534fd7aaSYishai Hadas 			MLX5_GET(create_mkey_out, out, mkey_index)) | key;
1201534fd7aaSYishai Hadas 	mkey->type = MLX5_MKEY_INDIRECT_DEVX;
1202534fd7aaSYishai Hadas 	mkey->iova = MLX5_GET64(mkc, mkc, start_addr);
1203534fd7aaSYishai Hadas 	mkey->size = MLX5_GET64(mkc, mkc, len);
1204534fd7aaSYishai Hadas 	mkey->pd = MLX5_GET(mkc, mkc, pd);
1205534fd7aaSYishai Hadas 	devx_mr->ndescs = MLX5_GET(mkc, mkc, translations_octword_size);
1206534fd7aaSYishai Hadas 
1207792c4e9dSMatthew Wilcox 	return xa_err(xa_store(&dev->mdev->priv.mkey_table,
1208792c4e9dSMatthew Wilcox 			       mlx5_base_mkey(mkey->key), mkey, GFP_KERNEL));
1209534fd7aaSYishai Hadas }
1210534fd7aaSYishai Hadas 
1211fa31f143SYishai Hadas static int devx_handle_mkey_create(struct mlx5_ib_dev *dev,
1212fa31f143SYishai Hadas 				   struct devx_obj *obj,
1213fa31f143SYishai Hadas 				   void *in, int in_len)
1214fa31f143SYishai Hadas {
1215fa31f143SYishai Hadas 	int min_len = MLX5_BYTE_OFF(create_mkey_in, memory_key_mkey_entry) +
1216fa31f143SYishai Hadas 			MLX5_FLD_SZ_BYTES(create_mkey_in,
1217fa31f143SYishai Hadas 			memory_key_mkey_entry);
1218fa31f143SYishai Hadas 	void *mkc;
1219fa31f143SYishai Hadas 	u8 access_mode;
1220fa31f143SYishai Hadas 
1221fa31f143SYishai Hadas 	if (in_len < min_len)
1222fa31f143SYishai Hadas 		return -EINVAL;
1223fa31f143SYishai Hadas 
1224fa31f143SYishai Hadas 	mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
1225fa31f143SYishai Hadas 
1226fa31f143SYishai Hadas 	access_mode = MLX5_GET(mkc, mkc, access_mode_1_0);
1227fa31f143SYishai Hadas 	access_mode |= MLX5_GET(mkc, mkc, access_mode_4_2) << 2;
1228fa31f143SYishai Hadas 
1229fa31f143SYishai Hadas 	if (access_mode == MLX5_MKC_ACCESS_MODE_KLMS ||
1230534fd7aaSYishai Hadas 		access_mode == MLX5_MKC_ACCESS_MODE_KSM) {
1231534fd7aaSYishai Hadas 		if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING))
1232534fd7aaSYishai Hadas 			obj->flags |= DEVX_OBJ_FLAGS_INDIRECT_MKEY;
1233fa31f143SYishai Hadas 		return 0;
1234534fd7aaSYishai Hadas 	}
1235fa31f143SYishai Hadas 
1236fa31f143SYishai Hadas 	MLX5_SET(create_mkey_in, in, mkey_umem_valid, 1);
1237fa31f143SYishai Hadas 	return 0;
1238fa31f143SYishai Hadas }
1239fa31f143SYishai Hadas 
1240534fd7aaSYishai Hadas static void devx_free_indirect_mkey(struct rcu_head *rcu)
1241534fd7aaSYishai Hadas {
1242534fd7aaSYishai Hadas 	kfree(container_of(rcu, struct devx_obj, devx_mr.rcu));
1243534fd7aaSYishai Hadas }
1244534fd7aaSYishai Hadas 
1245534fd7aaSYishai Hadas /* This function to delete from the radix tree needs to be called before
1246534fd7aaSYishai Hadas  * destroying the underlying mkey. Otherwise a race might occur in case that
1247534fd7aaSYishai Hadas  * other thread will get the same mkey before this one will be deleted,
1248534fd7aaSYishai Hadas  * in that case it will fail via inserting to the tree its own data.
1249534fd7aaSYishai Hadas  *
1250534fd7aaSYishai Hadas  * Note:
1251534fd7aaSYishai Hadas  * An error in the destroy is not expected unless there is some other indirect
1252534fd7aaSYishai Hadas  * mkey which points to this one. In a kernel cleanup flow it will be just
1253534fd7aaSYishai Hadas  * destroyed in the iterative destruction call. In a user flow, in case
1254534fd7aaSYishai Hadas  * the application didn't close in the expected order it's its own problem,
1255534fd7aaSYishai Hadas  * the mkey won't be part of the tree, in both cases the kernel is safe.
1256534fd7aaSYishai Hadas  */
1257534fd7aaSYishai Hadas static void devx_cleanup_mkey(struct devx_obj *obj)
1258534fd7aaSYishai Hadas {
1259792c4e9dSMatthew Wilcox 	xa_erase(&obj->mdev->priv.mkey_table,
1260792c4e9dSMatthew Wilcox 		 mlx5_base_mkey(obj->devx_mr.mmkey.key));
1261534fd7aaSYishai Hadas }
1262534fd7aaSYishai Hadas 
1263*75973853SYishai Hadas static void devx_cleanup_subscription(struct mlx5_ib_dev *dev,
1264*75973853SYishai Hadas 				      struct devx_event_subscription *sub)
1265*75973853SYishai Hadas {
1266*75973853SYishai Hadas 	struct devx_event *event;
1267*75973853SYishai Hadas 	struct devx_obj_event *xa_val_level2;
1268*75973853SYishai Hadas 
1269*75973853SYishai Hadas 	if (sub->is_cleaned)
1270*75973853SYishai Hadas 		return;
1271*75973853SYishai Hadas 
1272*75973853SYishai Hadas 	sub->is_cleaned = 1;
1273*75973853SYishai Hadas 	list_del_rcu(&sub->xa_list);
1274*75973853SYishai Hadas 
1275*75973853SYishai Hadas 	if (list_empty(&sub->obj_list))
1276*75973853SYishai Hadas 		return;
1277*75973853SYishai Hadas 
1278*75973853SYishai Hadas 	list_del_rcu(&sub->obj_list);
1279*75973853SYishai Hadas 	/* check whether key level 1 for this obj_sub_list is empty */
1280*75973853SYishai Hadas 	event = xa_load(&dev->devx_event_table.event_xa,
1281*75973853SYishai Hadas 			sub->xa_key_level1);
1282*75973853SYishai Hadas 	WARN_ON(!event);
1283*75973853SYishai Hadas 
1284*75973853SYishai Hadas 	xa_val_level2 = xa_load(&event->object_ids, sub->xa_key_level2);
1285*75973853SYishai Hadas 	if (list_empty(&xa_val_level2->obj_sub_list)) {
1286*75973853SYishai Hadas 		xa_erase(&event->object_ids,
1287*75973853SYishai Hadas 			 sub->xa_key_level2);
1288*75973853SYishai Hadas 		kfree_rcu(xa_val_level2, rcu);
1289*75973853SYishai Hadas 	}
1290*75973853SYishai Hadas }
1291*75973853SYishai Hadas 
12927efce369SYishai Hadas static int devx_obj_cleanup(struct ib_uobject *uobject,
1293a6a3797dSShamir Rabinovitch 			    enum rdma_remove_reason why,
1294a6a3797dSShamir Rabinovitch 			    struct uverbs_attr_bundle *attrs)
12957efce369SYishai Hadas {
12967efce369SYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
1297*75973853SYishai Hadas 	struct mlx5_devx_event_table *devx_event_table;
12987efce369SYishai Hadas 	struct devx_obj *obj = uobject->object;
1299*75973853SYishai Hadas 	struct devx_event_subscription *sub_entry, *tmp;
1300*75973853SYishai Hadas 	struct mlx5_ib_dev *dev;
13017efce369SYishai Hadas 	int ret;
13027efce369SYishai Hadas 
1303*75973853SYishai Hadas 	dev = mlx5_udata_to_mdev(&attrs->driver_udata);
1304534fd7aaSYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY)
1305534fd7aaSYishai Hadas 		devx_cleanup_mkey(obj);
1306534fd7aaSYishai Hadas 
1307c5ae1954SYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_DCT)
1308c5ae1954SYishai Hadas 		ret = mlx5_core_destroy_dct(obj->mdev, &obj->core_dct);
1309c5ae1954SYishai Hadas 	else
1310c5ae1954SYishai Hadas 		ret = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out,
1311c5ae1954SYishai Hadas 				    sizeof(out));
13121c77483eSYishai Hadas 	if (ib_is_destroy_retryable(ret, why, uobject))
13137efce369SYishai Hadas 		return ret;
13147efce369SYishai Hadas 
1315*75973853SYishai Hadas 	devx_event_table = &dev->devx_event_table;
1316534fd7aaSYishai Hadas 
1317*75973853SYishai Hadas 	mutex_lock(&devx_event_table->event_xa_lock);
1318*75973853SYishai Hadas 	list_for_each_entry_safe(sub_entry, tmp, &obj->event_sub, obj_list)
1319*75973853SYishai Hadas 		devx_cleanup_subscription(dev, sub_entry);
1320*75973853SYishai Hadas 	mutex_unlock(&devx_event_table->event_xa_lock);
1321*75973853SYishai Hadas 
1322*75973853SYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY) {
1323534fd7aaSYishai Hadas 		call_srcu(&dev->mr_srcu, &obj->devx_mr.rcu,
1324534fd7aaSYishai Hadas 			  devx_free_indirect_mkey);
1325534fd7aaSYishai Hadas 		return ret;
1326534fd7aaSYishai Hadas 	}
1327534fd7aaSYishai Hadas 
13287efce369SYishai Hadas 	kfree(obj);
13297efce369SYishai Hadas 	return ret;
13307efce369SYishai Hadas }
13317efce369SYishai Hadas 
1332e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
133315a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
13347efce369SYishai Hadas {
13357efce369SYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN);
13367efce369SYishai Hadas 	int cmd_out_len =  uverbs_attr_get_len(attrs,
13377efce369SYishai Hadas 					MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT);
1338fa31f143SYishai Hadas 	int cmd_in_len = uverbs_attr_get_len(attrs,
1339fa31f143SYishai Hadas 					MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN);
13407efce369SYishai Hadas 	void *cmd_out;
1341c36ee46dSJason Gunthorpe 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
1342c36ee46dSJason Gunthorpe 		attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE);
134389944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
134489944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1345c36ee46dSJason Gunthorpe 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
1346e8ef090aSYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
13477efce369SYishai Hadas 	struct devx_obj *obj;
1348cd5d20f1SYishai Hadas 	u16 obj_type = 0;
13497efce369SYishai Hadas 	int err;
13507e1335a7SYishai Hadas 	int uid;
13512351776eSYishai Hadas 	u32 obj_id;
13522351776eSYishai Hadas 	u16 opcode;
13537efce369SYishai Hadas 
13547e1335a7SYishai Hadas 	uid = devx_get_uid(c, cmd_in);
13557e1335a7SYishai Hadas 	if (uid < 0)
13567e1335a7SYishai Hadas 		return uid;
13577efce369SYishai Hadas 
13582351776eSYishai Hadas 	if (!devx_is_obj_create_cmd(cmd_in, &opcode))
13597efce369SYishai Hadas 		return -EINVAL;
13607efce369SYishai Hadas 
1361b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
1362b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
1363b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
1364b61815e2SJason Gunthorpe 
13657efce369SYishai Hadas 	obj = kzalloc(sizeof(struct devx_obj), GFP_KERNEL);
13667efce369SYishai Hadas 	if (!obj)
13677efce369SYishai Hadas 		return -ENOMEM;
13687efce369SYishai Hadas 
13697e1335a7SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1370fa31f143SYishai Hadas 	if (opcode == MLX5_CMD_OP_CREATE_MKEY) {
1371fa31f143SYishai Hadas 		err = devx_handle_mkey_create(dev, obj, cmd_in, cmd_in_len);
1372fa31f143SYishai Hadas 		if (err)
1373fa31f143SYishai Hadas 			goto obj_free;
1374fa31f143SYishai Hadas 	} else {
1375ba1a057dSYishai Hadas 		devx_set_umem_valid(cmd_in);
1376fa31f143SYishai Hadas 	}
1377ba1a057dSYishai Hadas 
1378c5ae1954SYishai Hadas 	if (opcode == MLX5_CMD_OP_CREATE_DCT) {
1379c5ae1954SYishai Hadas 		obj->flags |= DEVX_OBJ_FLAGS_DCT;
1380c5ae1954SYishai Hadas 		err = mlx5_core_create_dct(dev->mdev, &obj->core_dct,
1381c5ae1954SYishai Hadas 					   cmd_in, cmd_in_len,
1382c5ae1954SYishai Hadas 					   cmd_out, cmd_out_len);
1383c5ae1954SYishai Hadas 	} else {
13847efce369SYishai Hadas 		err = mlx5_cmd_exec(dev->mdev, cmd_in,
1385fa31f143SYishai Hadas 				    cmd_in_len,
13867efce369SYishai Hadas 				    cmd_out, cmd_out_len);
1387c5ae1954SYishai Hadas 	}
1388c5ae1954SYishai Hadas 
13897efce369SYishai Hadas 	if (err)
1390b61815e2SJason Gunthorpe 		goto obj_free;
13917efce369SYishai Hadas 
13927efce369SYishai Hadas 	uobj->object = obj;
13937efce369SYishai Hadas 	obj->mdev = dev->mdev;
1394*75973853SYishai Hadas 	INIT_LIST_HEAD(&obj->event_sub);
13952351776eSYishai Hadas 	devx_obj_build_destroy_cmd(cmd_in, cmd_out, obj->dinbox, &obj->dinlen,
13962351776eSYishai Hadas 				   &obj_id);
13977efce369SYishai Hadas 	WARN_ON(obj->dinlen > MLX5_MAX_DESTROY_INBOX_SIZE_DW * sizeof(u32));
13987efce369SYishai Hadas 
1399534fd7aaSYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY) {
1400534fd7aaSYishai Hadas 		err = devx_handle_mkey_indirect(obj, dev, cmd_in, cmd_out);
1401534fd7aaSYishai Hadas 		if (err)
1402534fd7aaSYishai Hadas 			goto obj_destroy;
1403534fd7aaSYishai Hadas 	}
1404534fd7aaSYishai Hadas 
14057efce369SYishai Hadas 	err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, cmd_out, cmd_out_len);
14067efce369SYishai Hadas 	if (err)
14070da4d48dSYishai Hadas 		goto err_copy;
14087efce369SYishai Hadas 
1409cd5d20f1SYishai Hadas 	if (opcode == MLX5_CMD_OP_CREATE_GENERAL_OBJECT)
1410cd5d20f1SYishai Hadas 		obj_type = MLX5_GET(general_obj_in_cmd_hdr, cmd_in, obj_type);
1411cd5d20f1SYishai Hadas 
1412cd5d20f1SYishai Hadas 	obj->obj_id = get_enc_obj_id(opcode | obj_type << 16, obj_id);
1413cd5d20f1SYishai Hadas 
14147efce369SYishai Hadas 	return 0;
14157efce369SYishai Hadas 
14160da4d48dSYishai Hadas err_copy:
1417534fd7aaSYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY)
1418534fd7aaSYishai Hadas 		devx_cleanup_mkey(obj);
14190da4d48dSYishai Hadas obj_destroy:
1420c5ae1954SYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_DCT)
1421c5ae1954SYishai Hadas 		mlx5_core_destroy_dct(obj->mdev, &obj->core_dct);
1422c5ae1954SYishai Hadas 	else
1423c5ae1954SYishai Hadas 		mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out,
1424c5ae1954SYishai Hadas 			      sizeof(out));
14257efce369SYishai Hadas obj_free:
14267efce369SYishai Hadas 	kfree(obj);
14277efce369SYishai Hadas 	return err;
14287efce369SYishai Hadas }
14297efce369SYishai Hadas 
1430e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)(
143115a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
1432e662e14dSYishai Hadas {
1433e662e14dSYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN);
1434e662e14dSYishai Hadas 	int cmd_out_len = uverbs_attr_get_len(attrs,
1435e662e14dSYishai Hadas 					MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT);
1436e662e14dSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
1437e662e14dSYishai Hadas 							  MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE);
143889944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
143989944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
144089944450SShamir Rabinovitch 	struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device);
1441e662e14dSYishai Hadas 	void *cmd_out;
1442e662e14dSYishai Hadas 	int err;
14437e1335a7SYishai Hadas 	int uid;
1444e662e14dSYishai Hadas 
14457e1335a7SYishai Hadas 	uid = devx_get_uid(c, cmd_in);
14467e1335a7SYishai Hadas 	if (uid < 0)
14477e1335a7SYishai Hadas 		return uid;
1448e662e14dSYishai Hadas 
1449e662e14dSYishai Hadas 	if (!devx_is_obj_modify_cmd(cmd_in))
1450e662e14dSYishai Hadas 		return -EINVAL;
1451e662e14dSYishai Hadas 
1452e79c9c60SJason Gunthorpe 	if (!devx_is_valid_obj_id(attrs, uobj, cmd_in))
1453e662e14dSYishai Hadas 		return -EINVAL;
1454e662e14dSYishai Hadas 
1455b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
1456b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
1457b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
1458e662e14dSYishai Hadas 
14597e1335a7SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1460ba1a057dSYishai Hadas 	devx_set_umem_valid(cmd_in);
1461ba1a057dSYishai Hadas 
146234613eb1SYishai Hadas 	err = mlx5_cmd_exec(mdev->mdev, cmd_in,
1463e662e14dSYishai Hadas 			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN),
1464e662e14dSYishai Hadas 			    cmd_out, cmd_out_len);
1465e662e14dSYishai Hadas 	if (err)
1466e662e14dSYishai Hadas 		return err;
1467b61815e2SJason Gunthorpe 
1468b61815e2SJason Gunthorpe 	return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
1469b61815e2SJason Gunthorpe 			      cmd_out, cmd_out_len);
1470e662e14dSYishai Hadas }
1471e662e14dSYishai Hadas 
1472e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)(
147315a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
1474e662e14dSYishai Hadas {
1475e662e14dSYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN);
1476e662e14dSYishai Hadas 	int cmd_out_len = uverbs_attr_get_len(attrs,
1477e662e14dSYishai Hadas 					      MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT);
1478e662e14dSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
1479e662e14dSYishai Hadas 							  MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE);
148089944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
148189944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1482e662e14dSYishai Hadas 	void *cmd_out;
1483e662e14dSYishai Hadas 	int err;
14847e1335a7SYishai Hadas 	int uid;
148589944450SShamir Rabinovitch 	struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device);
1486e662e14dSYishai Hadas 
14877e1335a7SYishai Hadas 	uid = devx_get_uid(c, cmd_in);
14887e1335a7SYishai Hadas 	if (uid < 0)
14897e1335a7SYishai Hadas 		return uid;
1490e662e14dSYishai Hadas 
1491e662e14dSYishai Hadas 	if (!devx_is_obj_query_cmd(cmd_in))
1492e662e14dSYishai Hadas 		return -EINVAL;
1493e662e14dSYishai Hadas 
1494e79c9c60SJason Gunthorpe 	if (!devx_is_valid_obj_id(attrs, uobj, cmd_in))
1495e662e14dSYishai Hadas 		return -EINVAL;
1496e662e14dSYishai Hadas 
1497b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
1498b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
1499b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
1500e662e14dSYishai Hadas 
15017e1335a7SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
150234613eb1SYishai Hadas 	err = mlx5_cmd_exec(mdev->mdev, cmd_in,
1503e662e14dSYishai Hadas 			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN),
1504e662e14dSYishai Hadas 			    cmd_out, cmd_out_len);
1505e662e14dSYishai Hadas 	if (err)
1506e662e14dSYishai Hadas 		return err;
1507b61815e2SJason Gunthorpe 
1508b61815e2SJason Gunthorpe 	return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
1509b61815e2SJason Gunthorpe 			      cmd_out, cmd_out_len);
1510e662e14dSYishai Hadas }
1511e662e14dSYishai Hadas 
15126bf8f22aSYishai Hadas struct devx_async_event_queue {
15136bf8f22aSYishai Hadas 	spinlock_t		lock;
15146bf8f22aSYishai Hadas 	wait_queue_head_t	poll_wait;
15156bf8f22aSYishai Hadas 	struct list_head	event_list;
1516a124edbaSYishai Hadas 	atomic_t		bytes_in_use;
1517eaebaf77SYishai Hadas 	u8			is_destroyed:1;
15186bf8f22aSYishai Hadas };
15196bf8f22aSYishai Hadas 
15206bf8f22aSYishai Hadas struct devx_async_cmd_event_file {
15216bf8f22aSYishai Hadas 	struct ib_uobject		uobj;
15226bf8f22aSYishai Hadas 	struct devx_async_event_queue	ev_queue;
1523a124edbaSYishai Hadas 	struct mlx5_async_ctx		async_ctx;
15246bf8f22aSYishai Hadas };
15256bf8f22aSYishai Hadas 
15266bf8f22aSYishai Hadas static void devx_init_event_queue(struct devx_async_event_queue *ev_queue)
15276bf8f22aSYishai Hadas {
15286bf8f22aSYishai Hadas 	spin_lock_init(&ev_queue->lock);
15296bf8f22aSYishai Hadas 	INIT_LIST_HEAD(&ev_queue->event_list);
15306bf8f22aSYishai Hadas 	init_waitqueue_head(&ev_queue->poll_wait);
1531a124edbaSYishai Hadas 	atomic_set(&ev_queue->bytes_in_use, 0);
1532eaebaf77SYishai Hadas 	ev_queue->is_destroyed = 0;
15336bf8f22aSYishai Hadas }
15346bf8f22aSYishai Hadas 
15356bf8f22aSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC)(
15366bf8f22aSYishai Hadas 	struct uverbs_attr_bundle *attrs)
15376bf8f22aSYishai Hadas {
15386bf8f22aSYishai Hadas 	struct devx_async_cmd_event_file *ev_file;
15396bf8f22aSYishai Hadas 
15406bf8f22aSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
15416bf8f22aSYishai Hadas 		attrs, MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE);
1542e79c9c60SJason Gunthorpe 	struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata);
15436bf8f22aSYishai Hadas 
15446bf8f22aSYishai Hadas 	ev_file = container_of(uobj, struct devx_async_cmd_event_file,
15456bf8f22aSYishai Hadas 			       uobj);
15466bf8f22aSYishai Hadas 	devx_init_event_queue(&ev_file->ev_queue);
1547a124edbaSYishai Hadas 	mlx5_cmd_init_async_ctx(mdev->mdev, &ev_file->async_ctx);
15486bf8f22aSYishai Hadas 	return 0;
15496bf8f22aSYishai Hadas }
15506bf8f22aSYishai Hadas 
15512afc5e1bSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC)(
15522afc5e1bSYishai Hadas 	struct uverbs_attr_bundle *attrs)
15532afc5e1bSYishai Hadas {
15542afc5e1bSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
15552afc5e1bSYishai Hadas 		attrs, MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_HANDLE);
15562afc5e1bSYishai Hadas 	struct devx_async_event_file *ev_file;
15572afc5e1bSYishai Hadas 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
15582afc5e1bSYishai Hadas 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
15592afc5e1bSYishai Hadas 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
15602afc5e1bSYishai Hadas 	u32 flags;
15612afc5e1bSYishai Hadas 	int err;
15622afc5e1bSYishai Hadas 
15632afc5e1bSYishai Hadas 	err = uverbs_get_flags32(&flags, attrs,
15642afc5e1bSYishai Hadas 		MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_FLAGS,
15652afc5e1bSYishai Hadas 		MLX5_IB_UAPI_DEVX_CR_EV_CH_FLAGS_OMIT_DATA);
15662afc5e1bSYishai Hadas 
15672afc5e1bSYishai Hadas 	if (err)
15682afc5e1bSYishai Hadas 		return err;
15692afc5e1bSYishai Hadas 
15702afc5e1bSYishai Hadas 	ev_file = container_of(uobj, struct devx_async_event_file,
15712afc5e1bSYishai Hadas 			       uobj);
15722afc5e1bSYishai Hadas 	spin_lock_init(&ev_file->lock);
15732afc5e1bSYishai Hadas 	INIT_LIST_HEAD(&ev_file->event_list);
15742afc5e1bSYishai Hadas 	init_waitqueue_head(&ev_file->poll_wait);
15752afc5e1bSYishai Hadas 	if (flags & MLX5_IB_UAPI_DEVX_CR_EV_CH_FLAGS_OMIT_DATA)
15762afc5e1bSYishai Hadas 		ev_file->omit_data = 1;
15772afc5e1bSYishai Hadas 	INIT_LIST_HEAD(&ev_file->subscribed_events_list);
15782afc5e1bSYishai Hadas 	ev_file->dev = dev;
1579*75973853SYishai Hadas 	get_device(&dev->ib_dev.dev);
15802afc5e1bSYishai Hadas 	return 0;
15812afc5e1bSYishai Hadas }
15822afc5e1bSYishai Hadas 
1583a124edbaSYishai Hadas static void devx_query_callback(int status, struct mlx5_async_work *context)
1584a124edbaSYishai Hadas {
1585a124edbaSYishai Hadas 	struct devx_async_data *async_data =
1586a124edbaSYishai Hadas 		container_of(context, struct devx_async_data, cb_work);
1587a124edbaSYishai Hadas 	struct ib_uobject *fd_uobj = async_data->fd_uobj;
1588a124edbaSYishai Hadas 	struct devx_async_cmd_event_file *ev_file;
1589a124edbaSYishai Hadas 	struct devx_async_event_queue *ev_queue;
1590a124edbaSYishai Hadas 	unsigned long flags;
1591a124edbaSYishai Hadas 
1592a124edbaSYishai Hadas 	ev_file = container_of(fd_uobj, struct devx_async_cmd_event_file,
1593a124edbaSYishai Hadas 			       uobj);
1594a124edbaSYishai Hadas 	ev_queue = &ev_file->ev_queue;
1595a124edbaSYishai Hadas 
1596a124edbaSYishai Hadas 	spin_lock_irqsave(&ev_queue->lock, flags);
1597a124edbaSYishai Hadas 	list_add_tail(&async_data->list, &ev_queue->event_list);
1598a124edbaSYishai Hadas 	spin_unlock_irqrestore(&ev_queue->lock, flags);
1599a124edbaSYishai Hadas 
1600a124edbaSYishai Hadas 	wake_up_interruptible(&ev_queue->poll_wait);
1601a124edbaSYishai Hadas 	fput(fd_uobj->object);
1602a124edbaSYishai Hadas }
1603a124edbaSYishai Hadas 
1604a124edbaSYishai Hadas #define MAX_ASYNC_BYTES_IN_USE (1024 * 1024) /* 1MB */
1605a124edbaSYishai Hadas 
1606a124edbaSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY)(
1607a124edbaSYishai Hadas 	struct uverbs_attr_bundle *attrs)
1608a124edbaSYishai Hadas {
1609a124edbaSYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs,
1610a124edbaSYishai Hadas 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN);
1611a124edbaSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
1612a124edbaSYishai Hadas 				attrs,
1613a124edbaSYishai Hadas 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_HANDLE);
1614a124edbaSYishai Hadas 	u16 cmd_out_len;
161589944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
161689944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1617a124edbaSYishai Hadas 	struct ib_uobject *fd_uobj;
1618a124edbaSYishai Hadas 	int err;
1619a124edbaSYishai Hadas 	int uid;
162089944450SShamir Rabinovitch 	struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device);
1621a124edbaSYishai Hadas 	struct devx_async_cmd_event_file *ev_file;
1622a124edbaSYishai Hadas 	struct devx_async_data *async_data;
1623a124edbaSYishai Hadas 
1624a124edbaSYishai Hadas 	uid = devx_get_uid(c, cmd_in);
1625a124edbaSYishai Hadas 	if (uid < 0)
1626a124edbaSYishai Hadas 		return uid;
1627a124edbaSYishai Hadas 
1628a124edbaSYishai Hadas 	if (!devx_is_obj_query_cmd(cmd_in))
1629a124edbaSYishai Hadas 		return -EINVAL;
1630a124edbaSYishai Hadas 
1631a124edbaSYishai Hadas 	err = uverbs_get_const(&cmd_out_len, attrs,
1632a124edbaSYishai Hadas 			       MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_OUT_LEN);
1633a124edbaSYishai Hadas 	if (err)
1634a124edbaSYishai Hadas 		return err;
1635a124edbaSYishai Hadas 
1636e79c9c60SJason Gunthorpe 	if (!devx_is_valid_obj_id(attrs, uobj, cmd_in))
1637a124edbaSYishai Hadas 		return -EINVAL;
1638a124edbaSYishai Hadas 
1639a124edbaSYishai Hadas 	fd_uobj = uverbs_attr_get_uobject(attrs,
1640a124edbaSYishai Hadas 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_FD);
1641a124edbaSYishai Hadas 	if (IS_ERR(fd_uobj))
1642a124edbaSYishai Hadas 		return PTR_ERR(fd_uobj);
1643a124edbaSYishai Hadas 
1644a124edbaSYishai Hadas 	ev_file = container_of(fd_uobj, struct devx_async_cmd_event_file,
1645a124edbaSYishai Hadas 			       uobj);
1646a124edbaSYishai Hadas 
1647a124edbaSYishai Hadas 	if (atomic_add_return(cmd_out_len, &ev_file->ev_queue.bytes_in_use) >
1648a124edbaSYishai Hadas 			MAX_ASYNC_BYTES_IN_USE) {
1649a124edbaSYishai Hadas 		atomic_sub(cmd_out_len, &ev_file->ev_queue.bytes_in_use);
1650a124edbaSYishai Hadas 		return -EAGAIN;
1651a124edbaSYishai Hadas 	}
1652a124edbaSYishai Hadas 
1653a124edbaSYishai Hadas 	async_data = kvzalloc(struct_size(async_data, hdr.out_data,
1654a124edbaSYishai Hadas 					  cmd_out_len), GFP_KERNEL);
1655a124edbaSYishai Hadas 	if (!async_data) {
1656a124edbaSYishai Hadas 		err = -ENOMEM;
1657a124edbaSYishai Hadas 		goto sub_bytes;
1658a124edbaSYishai Hadas 	}
1659a124edbaSYishai Hadas 
1660a124edbaSYishai Hadas 	err = uverbs_copy_from(&async_data->hdr.wr_id, attrs,
1661a124edbaSYishai Hadas 			       MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_WR_ID);
1662a124edbaSYishai Hadas 	if (err)
1663a124edbaSYishai Hadas 		goto free_async;
1664a124edbaSYishai Hadas 
1665a124edbaSYishai Hadas 	async_data->cmd_out_len = cmd_out_len;
1666a124edbaSYishai Hadas 	async_data->mdev = mdev;
1667a124edbaSYishai Hadas 	async_data->fd_uobj = fd_uobj;
1668a124edbaSYishai Hadas 
1669a124edbaSYishai Hadas 	get_file(fd_uobj->object);
1670a124edbaSYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1671a124edbaSYishai Hadas 	err = mlx5_cmd_exec_cb(&ev_file->async_ctx, cmd_in,
1672a124edbaSYishai Hadas 		    uverbs_attr_get_len(attrs,
1673a124edbaSYishai Hadas 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN),
1674a124edbaSYishai Hadas 		    async_data->hdr.out_data,
1675a124edbaSYishai Hadas 		    async_data->cmd_out_len,
1676a124edbaSYishai Hadas 		    devx_query_callback, &async_data->cb_work);
1677a124edbaSYishai Hadas 
1678a124edbaSYishai Hadas 	if (err)
1679a124edbaSYishai Hadas 		goto cb_err;
1680a124edbaSYishai Hadas 
1681a124edbaSYishai Hadas 	return 0;
1682a124edbaSYishai Hadas 
1683a124edbaSYishai Hadas cb_err:
1684a124edbaSYishai Hadas 	fput(fd_uobj->object);
1685a124edbaSYishai Hadas free_async:
1686a124edbaSYishai Hadas 	kvfree(async_data);
1687a124edbaSYishai Hadas sub_bytes:
1688a124edbaSYishai Hadas 	atomic_sub(cmd_out_len, &ev_file->ev_queue.bytes_in_use);
1689a124edbaSYishai Hadas 	return err;
1690a124edbaSYishai Hadas }
1691a124edbaSYishai Hadas 
1692*75973853SYishai Hadas static void
1693*75973853SYishai Hadas subscribe_event_xa_dealloc(struct mlx5_devx_event_table *devx_event_table,
1694*75973853SYishai Hadas 			   u32 key_level1,
1695*75973853SYishai Hadas 			   bool is_level2,
1696*75973853SYishai Hadas 			   u32 key_level2)
1697*75973853SYishai Hadas {
1698*75973853SYishai Hadas 	struct devx_event *event;
1699*75973853SYishai Hadas 	struct devx_obj_event *xa_val_level2;
1700*75973853SYishai Hadas 
1701*75973853SYishai Hadas 	/* Level 1 is valid for future use, no need to free */
1702*75973853SYishai Hadas 	if (!is_level2)
1703*75973853SYishai Hadas 		return;
1704*75973853SYishai Hadas 
1705*75973853SYishai Hadas 	event = xa_load(&devx_event_table->event_xa, key_level1);
1706*75973853SYishai Hadas 	WARN_ON(!event);
1707*75973853SYishai Hadas 
1708*75973853SYishai Hadas 	xa_val_level2 = xa_load(&event->object_ids,
1709*75973853SYishai Hadas 				key_level2);
1710*75973853SYishai Hadas 	if (list_empty(&xa_val_level2->obj_sub_list)) {
1711*75973853SYishai Hadas 		xa_erase(&event->object_ids,
1712*75973853SYishai Hadas 			 key_level2);
1713*75973853SYishai Hadas 		kfree_rcu(xa_val_level2, rcu);
1714*75973853SYishai Hadas 	}
1715*75973853SYishai Hadas }
1716*75973853SYishai Hadas 
1717*75973853SYishai Hadas static int
1718*75973853SYishai Hadas subscribe_event_xa_alloc(struct mlx5_devx_event_table *devx_event_table,
1719*75973853SYishai Hadas 			 u32 key_level1,
1720*75973853SYishai Hadas 			 bool is_level2,
1721*75973853SYishai Hadas 			 u32 key_level2)
1722*75973853SYishai Hadas {
1723*75973853SYishai Hadas 	struct devx_obj_event *obj_event;
1724*75973853SYishai Hadas 	struct devx_event *event;
1725*75973853SYishai Hadas 	int err;
1726*75973853SYishai Hadas 
1727*75973853SYishai Hadas 	event = xa_load(&devx_event_table->event_xa, key_level1);
1728*75973853SYishai Hadas 	if (!event) {
1729*75973853SYishai Hadas 		event = kzalloc(sizeof(*event), GFP_KERNEL);
1730*75973853SYishai Hadas 		if (!event)
1731*75973853SYishai Hadas 			return -ENOMEM;
1732*75973853SYishai Hadas 
1733*75973853SYishai Hadas 		INIT_LIST_HEAD(&event->unaffiliated_list);
1734*75973853SYishai Hadas 		xa_init(&event->object_ids);
1735*75973853SYishai Hadas 
1736*75973853SYishai Hadas 		err = xa_insert(&devx_event_table->event_xa,
1737*75973853SYishai Hadas 				key_level1,
1738*75973853SYishai Hadas 				event,
1739*75973853SYishai Hadas 				GFP_KERNEL);
1740*75973853SYishai Hadas 		if (err) {
1741*75973853SYishai Hadas 			kfree(event);
1742*75973853SYishai Hadas 			return err;
1743*75973853SYishai Hadas 		}
1744*75973853SYishai Hadas 	}
1745*75973853SYishai Hadas 
1746*75973853SYishai Hadas 	if (!is_level2)
1747*75973853SYishai Hadas 		return 0;
1748*75973853SYishai Hadas 
1749*75973853SYishai Hadas 	obj_event = xa_load(&event->object_ids, key_level2);
1750*75973853SYishai Hadas 	if (!obj_event) {
1751*75973853SYishai Hadas 		obj_event = kzalloc(sizeof(*obj_event), GFP_KERNEL);
1752*75973853SYishai Hadas 		if (!obj_event)
1753*75973853SYishai Hadas 			/* Level1 is valid for future use, no need to free */
1754*75973853SYishai Hadas 			return -ENOMEM;
1755*75973853SYishai Hadas 
1756*75973853SYishai Hadas 		err = xa_insert(&event->object_ids,
1757*75973853SYishai Hadas 				key_level2,
1758*75973853SYishai Hadas 				obj_event,
1759*75973853SYishai Hadas 				GFP_KERNEL);
1760*75973853SYishai Hadas 		if (err)
1761*75973853SYishai Hadas 			return err;
1762*75973853SYishai Hadas 		INIT_LIST_HEAD(&obj_event->obj_sub_list);
1763*75973853SYishai Hadas 	}
1764*75973853SYishai Hadas 
1765*75973853SYishai Hadas 	return 0;
1766*75973853SYishai Hadas }
1767*75973853SYishai Hadas 
1768*75973853SYishai Hadas static bool is_valid_events_legacy(int num_events, u16 *event_type_num_list,
1769*75973853SYishai Hadas 				   struct devx_obj *obj)
1770*75973853SYishai Hadas {
1771*75973853SYishai Hadas 	int i;
1772*75973853SYishai Hadas 
1773*75973853SYishai Hadas 	for (i = 0; i < num_events; i++) {
1774*75973853SYishai Hadas 		if (obj) {
1775*75973853SYishai Hadas 			if (!is_legacy_obj_event_num(event_type_num_list[i]))
1776*75973853SYishai Hadas 				return false;
1777*75973853SYishai Hadas 		} else if (!is_legacy_unaffiliated_event_num(
1778*75973853SYishai Hadas 				event_type_num_list[i])) {
1779*75973853SYishai Hadas 			return false;
1780*75973853SYishai Hadas 		}
1781*75973853SYishai Hadas 	}
1782*75973853SYishai Hadas 
1783*75973853SYishai Hadas 	return true;
1784*75973853SYishai Hadas }
1785*75973853SYishai Hadas 
1786*75973853SYishai Hadas #define MAX_SUPP_EVENT_NUM 255
1787*75973853SYishai Hadas static bool is_valid_events(struct mlx5_core_dev *dev,
1788*75973853SYishai Hadas 			    int num_events, u16 *event_type_num_list,
1789*75973853SYishai Hadas 			    struct devx_obj *obj)
1790*75973853SYishai Hadas {
1791*75973853SYishai Hadas 	__be64 *aff_events;
1792*75973853SYishai Hadas 	__be64 *unaff_events;
1793*75973853SYishai Hadas 	int mask_entry;
1794*75973853SYishai Hadas 	int mask_bit;
1795*75973853SYishai Hadas 	int i;
1796*75973853SYishai Hadas 
1797*75973853SYishai Hadas 	if (MLX5_CAP_GEN(dev, event_cap)) {
1798*75973853SYishai Hadas 		aff_events = MLX5_CAP_DEV_EVENT(dev,
1799*75973853SYishai Hadas 						user_affiliated_events);
1800*75973853SYishai Hadas 		unaff_events = MLX5_CAP_DEV_EVENT(dev,
1801*75973853SYishai Hadas 						  user_unaffiliated_events);
1802*75973853SYishai Hadas 	} else {
1803*75973853SYishai Hadas 		return is_valid_events_legacy(num_events, event_type_num_list,
1804*75973853SYishai Hadas 					      obj);
1805*75973853SYishai Hadas 	}
1806*75973853SYishai Hadas 
1807*75973853SYishai Hadas 	for (i = 0; i < num_events; i++) {
1808*75973853SYishai Hadas 		if (event_type_num_list[i] > MAX_SUPP_EVENT_NUM)
1809*75973853SYishai Hadas 			return false;
1810*75973853SYishai Hadas 
1811*75973853SYishai Hadas 		mask_entry = event_type_num_list[i] / 64;
1812*75973853SYishai Hadas 		mask_bit = event_type_num_list[i] % 64;
1813*75973853SYishai Hadas 
1814*75973853SYishai Hadas 		if (obj) {
1815*75973853SYishai Hadas 			/* CQ completion */
1816*75973853SYishai Hadas 			if (event_type_num_list[i] == 0)
1817*75973853SYishai Hadas 				continue;
1818*75973853SYishai Hadas 
1819*75973853SYishai Hadas 			if (!(be64_to_cpu(aff_events[mask_entry]) &
1820*75973853SYishai Hadas 					(1ull << mask_bit)))
1821*75973853SYishai Hadas 				return false;
1822*75973853SYishai Hadas 
1823*75973853SYishai Hadas 			continue;
1824*75973853SYishai Hadas 		}
1825*75973853SYishai Hadas 
1826*75973853SYishai Hadas 		if (!(be64_to_cpu(unaff_events[mask_entry]) &
1827*75973853SYishai Hadas 				(1ull << mask_bit)))
1828*75973853SYishai Hadas 			return false;
1829*75973853SYishai Hadas 	}
1830*75973853SYishai Hadas 
1831*75973853SYishai Hadas 	return true;
1832*75973853SYishai Hadas }
1833*75973853SYishai Hadas 
1834*75973853SYishai Hadas #define MAX_NUM_EVENTS 16
1835*75973853SYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT)(
1836*75973853SYishai Hadas 	struct uverbs_attr_bundle *attrs)
1837*75973853SYishai Hadas {
1838*75973853SYishai Hadas 	struct ib_uobject *devx_uobj = uverbs_attr_get_uobject(
1839*75973853SYishai Hadas 				attrs,
1840*75973853SYishai Hadas 				MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_OBJ_HANDLE);
1841*75973853SYishai Hadas 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
1842*75973853SYishai Hadas 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1843*75973853SYishai Hadas 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
1844*75973853SYishai Hadas 	struct ib_uobject *fd_uobj;
1845*75973853SYishai Hadas 	struct devx_obj *obj = NULL;
1846*75973853SYishai Hadas 	struct devx_async_event_file *ev_file;
1847*75973853SYishai Hadas 	struct mlx5_devx_event_table *devx_event_table = &dev->devx_event_table;
1848*75973853SYishai Hadas 	u16 *event_type_num_list;
1849*75973853SYishai Hadas 	struct devx_event_subscription *event_sub, *tmp_sub;
1850*75973853SYishai Hadas 	struct list_head sub_list;
1851*75973853SYishai Hadas 	int redirect_fd;
1852*75973853SYishai Hadas 	bool use_eventfd = false;
1853*75973853SYishai Hadas 	int num_events;
1854*75973853SYishai Hadas 	int num_alloc_xa_entries = 0;
1855*75973853SYishai Hadas 	u16 obj_type = 0;
1856*75973853SYishai Hadas 	u64 cookie = 0;
1857*75973853SYishai Hadas 	u32 obj_id = 0;
1858*75973853SYishai Hadas 	int err;
1859*75973853SYishai Hadas 	int i;
1860*75973853SYishai Hadas 
1861*75973853SYishai Hadas 	if (!c->devx_uid)
1862*75973853SYishai Hadas 		return -EINVAL;
1863*75973853SYishai Hadas 
1864*75973853SYishai Hadas 	if (!IS_ERR(devx_uobj)) {
1865*75973853SYishai Hadas 		obj = (struct devx_obj *)devx_uobj->object;
1866*75973853SYishai Hadas 		if (obj)
1867*75973853SYishai Hadas 			obj_id = get_dec_obj_id(obj->obj_id);
1868*75973853SYishai Hadas 	}
1869*75973853SYishai Hadas 
1870*75973853SYishai Hadas 	fd_uobj = uverbs_attr_get_uobject(attrs,
1871*75973853SYishai Hadas 				MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_HANDLE);
1872*75973853SYishai Hadas 	if (IS_ERR(fd_uobj))
1873*75973853SYishai Hadas 		return PTR_ERR(fd_uobj);
1874*75973853SYishai Hadas 
1875*75973853SYishai Hadas 	ev_file = container_of(fd_uobj, struct devx_async_event_file,
1876*75973853SYishai Hadas 			       uobj);
1877*75973853SYishai Hadas 
1878*75973853SYishai Hadas 	if (uverbs_attr_is_valid(attrs,
1879*75973853SYishai Hadas 				 MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM)) {
1880*75973853SYishai Hadas 		err = uverbs_copy_from(&redirect_fd, attrs,
1881*75973853SYishai Hadas 			       MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM);
1882*75973853SYishai Hadas 		if (err)
1883*75973853SYishai Hadas 			return err;
1884*75973853SYishai Hadas 
1885*75973853SYishai Hadas 		use_eventfd = true;
1886*75973853SYishai Hadas 	}
1887*75973853SYishai Hadas 
1888*75973853SYishai Hadas 	if (uverbs_attr_is_valid(attrs,
1889*75973853SYishai Hadas 				 MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE)) {
1890*75973853SYishai Hadas 		if (use_eventfd)
1891*75973853SYishai Hadas 			return -EINVAL;
1892*75973853SYishai Hadas 
1893*75973853SYishai Hadas 		err = uverbs_copy_from(&cookie, attrs,
1894*75973853SYishai Hadas 				MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE);
1895*75973853SYishai Hadas 		if (err)
1896*75973853SYishai Hadas 			return err;
1897*75973853SYishai Hadas 	}
1898*75973853SYishai Hadas 
1899*75973853SYishai Hadas 	num_events = uverbs_attr_ptr_get_array_size(
1900*75973853SYishai Hadas 		attrs, MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST,
1901*75973853SYishai Hadas 		sizeof(u16));
1902*75973853SYishai Hadas 
1903*75973853SYishai Hadas 	if (num_events < 0)
1904*75973853SYishai Hadas 		return num_events;
1905*75973853SYishai Hadas 
1906*75973853SYishai Hadas 	if (num_events > MAX_NUM_EVENTS)
1907*75973853SYishai Hadas 		return -EINVAL;
1908*75973853SYishai Hadas 
1909*75973853SYishai Hadas 	event_type_num_list = uverbs_attr_get_alloced_ptr(attrs,
1910*75973853SYishai Hadas 			MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST);
1911*75973853SYishai Hadas 
1912*75973853SYishai Hadas 	if (!is_valid_events(dev->mdev, num_events, event_type_num_list, obj))
1913*75973853SYishai Hadas 		return -EINVAL;
1914*75973853SYishai Hadas 
1915*75973853SYishai Hadas 	INIT_LIST_HEAD(&sub_list);
1916*75973853SYishai Hadas 
1917*75973853SYishai Hadas 	/* Protect from concurrent subscriptions to same XA entries to allow
1918*75973853SYishai Hadas 	 * both to succeed
1919*75973853SYishai Hadas 	 */
1920*75973853SYishai Hadas 	mutex_lock(&devx_event_table->event_xa_lock);
1921*75973853SYishai Hadas 	for (i = 0; i < num_events; i++) {
1922*75973853SYishai Hadas 		u32 key_level1;
1923*75973853SYishai Hadas 
1924*75973853SYishai Hadas 		if (obj)
1925*75973853SYishai Hadas 			obj_type = get_dec_obj_type(obj,
1926*75973853SYishai Hadas 						    event_type_num_list[i]);
1927*75973853SYishai Hadas 		key_level1 = event_type_num_list[i] | obj_type << 16;
1928*75973853SYishai Hadas 
1929*75973853SYishai Hadas 		err = subscribe_event_xa_alloc(devx_event_table,
1930*75973853SYishai Hadas 					       key_level1,
1931*75973853SYishai Hadas 					       obj,
1932*75973853SYishai Hadas 					       obj_id);
1933*75973853SYishai Hadas 		if (err)
1934*75973853SYishai Hadas 			goto err;
1935*75973853SYishai Hadas 
1936*75973853SYishai Hadas 		num_alloc_xa_entries++;
1937*75973853SYishai Hadas 		event_sub = kzalloc(sizeof(*event_sub), GFP_KERNEL);
1938*75973853SYishai Hadas 		if (!event_sub)
1939*75973853SYishai Hadas 			goto err;
1940*75973853SYishai Hadas 
1941*75973853SYishai Hadas 		list_add_tail(&event_sub->event_list, &sub_list);
1942*75973853SYishai Hadas 		if (use_eventfd) {
1943*75973853SYishai Hadas 			event_sub->eventfd =
1944*75973853SYishai Hadas 				eventfd_ctx_fdget(redirect_fd);
1945*75973853SYishai Hadas 
1946*75973853SYishai Hadas 			if (IS_ERR(event_sub)) {
1947*75973853SYishai Hadas 				err = PTR_ERR(event_sub->eventfd);
1948*75973853SYishai Hadas 				event_sub->eventfd = NULL;
1949*75973853SYishai Hadas 				goto err;
1950*75973853SYishai Hadas 			}
1951*75973853SYishai Hadas 		}
1952*75973853SYishai Hadas 
1953*75973853SYishai Hadas 		event_sub->cookie = cookie;
1954*75973853SYishai Hadas 		event_sub->ev_file = ev_file;
1955*75973853SYishai Hadas 		event_sub->filp = fd_uobj->object;
1956*75973853SYishai Hadas 		/* May be needed upon cleanup the devx object/subscription */
1957*75973853SYishai Hadas 		event_sub->xa_key_level1 = key_level1;
1958*75973853SYishai Hadas 		event_sub->xa_key_level2 = obj_id;
1959*75973853SYishai Hadas 		INIT_LIST_HEAD(&event_sub->obj_list);
1960*75973853SYishai Hadas 	}
1961*75973853SYishai Hadas 
1962*75973853SYishai Hadas 	/* Once all the allocations and the XA data insertions were done we
1963*75973853SYishai Hadas 	 * can go ahead and add all the subscriptions to the relevant lists
1964*75973853SYishai Hadas 	 * without concern of a failure.
1965*75973853SYishai Hadas 	 */
1966*75973853SYishai Hadas 	list_for_each_entry_safe(event_sub, tmp_sub, &sub_list, event_list) {
1967*75973853SYishai Hadas 		struct devx_event *event;
1968*75973853SYishai Hadas 		struct devx_obj_event *obj_event;
1969*75973853SYishai Hadas 
1970*75973853SYishai Hadas 		list_del_init(&event_sub->event_list);
1971*75973853SYishai Hadas 
1972*75973853SYishai Hadas 		spin_lock_irq(&ev_file->lock);
1973*75973853SYishai Hadas 		list_add_tail_rcu(&event_sub->file_list,
1974*75973853SYishai Hadas 				  &ev_file->subscribed_events_list);
1975*75973853SYishai Hadas 		spin_unlock_irq(&ev_file->lock);
1976*75973853SYishai Hadas 
1977*75973853SYishai Hadas 		event = xa_load(&devx_event_table->event_xa,
1978*75973853SYishai Hadas 				event_sub->xa_key_level1);
1979*75973853SYishai Hadas 		WARN_ON(!event);
1980*75973853SYishai Hadas 
1981*75973853SYishai Hadas 		if (!obj) {
1982*75973853SYishai Hadas 			list_add_tail_rcu(&event_sub->xa_list,
1983*75973853SYishai Hadas 					  &event->unaffiliated_list);
1984*75973853SYishai Hadas 			continue;
1985*75973853SYishai Hadas 		}
1986*75973853SYishai Hadas 
1987*75973853SYishai Hadas 		obj_event = xa_load(&event->object_ids, obj_id);
1988*75973853SYishai Hadas 		WARN_ON(!obj_event);
1989*75973853SYishai Hadas 		list_add_tail_rcu(&event_sub->xa_list,
1990*75973853SYishai Hadas 				  &obj_event->obj_sub_list);
1991*75973853SYishai Hadas 		list_add_tail_rcu(&event_sub->obj_list,
1992*75973853SYishai Hadas 				  &obj->event_sub);
1993*75973853SYishai Hadas 	}
1994*75973853SYishai Hadas 
1995*75973853SYishai Hadas 	mutex_unlock(&devx_event_table->event_xa_lock);
1996*75973853SYishai Hadas 	return 0;
1997*75973853SYishai Hadas 
1998*75973853SYishai Hadas err:
1999*75973853SYishai Hadas 	list_for_each_entry_safe(event_sub, tmp_sub, &sub_list, event_list) {
2000*75973853SYishai Hadas 		list_del(&event_sub->event_list);
2001*75973853SYishai Hadas 
2002*75973853SYishai Hadas 		subscribe_event_xa_dealloc(devx_event_table,
2003*75973853SYishai Hadas 					   event_sub->xa_key_level1,
2004*75973853SYishai Hadas 					   obj,
2005*75973853SYishai Hadas 					   obj_id);
2006*75973853SYishai Hadas 
2007*75973853SYishai Hadas 		if (event_sub->eventfd)
2008*75973853SYishai Hadas 			eventfd_ctx_put(event_sub->eventfd);
2009*75973853SYishai Hadas 
2010*75973853SYishai Hadas 		kfree(event_sub);
2011*75973853SYishai Hadas 	}
2012*75973853SYishai Hadas 
2013*75973853SYishai Hadas 	mutex_unlock(&devx_event_table->event_xa_lock);
2014*75973853SYishai Hadas 	return err;
2015*75973853SYishai Hadas }
2016*75973853SYishai Hadas 
2017aeae9457SYishai Hadas static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext,
2018aeae9457SYishai Hadas 			 struct uverbs_attr_bundle *attrs,
2019aeae9457SYishai Hadas 			 struct devx_umem *obj)
2020aeae9457SYishai Hadas {
2021aeae9457SYishai Hadas 	u64 addr;
2022aeae9457SYishai Hadas 	size_t size;
2023bccd0622SJason Gunthorpe 	u32 access;
2024aeae9457SYishai Hadas 	int npages;
2025aeae9457SYishai Hadas 	int err;
2026aeae9457SYishai Hadas 	u32 page_mask;
2027aeae9457SYishai Hadas 
2028aeae9457SYishai Hadas 	if (uverbs_copy_from(&addr, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR) ||
2029bccd0622SJason Gunthorpe 	    uverbs_copy_from(&size, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_LEN))
2030aeae9457SYishai Hadas 		return -EFAULT;
2031aeae9457SYishai Hadas 
2032bccd0622SJason Gunthorpe 	err = uverbs_get_flags32(&access, attrs,
2033bccd0622SJason Gunthorpe 				 MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
203447f07f03SYishai Hadas 				 IB_ACCESS_LOCAL_WRITE |
203547f07f03SYishai Hadas 				 IB_ACCESS_REMOTE_WRITE |
203647f07f03SYishai Hadas 				 IB_ACCESS_REMOTE_READ);
2037bccd0622SJason Gunthorpe 	if (err)
2038bccd0622SJason Gunthorpe 		return err;
2039bccd0622SJason Gunthorpe 
2040aeae9457SYishai Hadas 	err = ib_check_mr_access(access);
2041aeae9457SYishai Hadas 	if (err)
2042aeae9457SYishai Hadas 		return err;
2043aeae9457SYishai Hadas 
2044b0ea0fa5SJason Gunthorpe 	obj->umem = ib_umem_get(&attrs->driver_udata, addr, size, access, 0);
2045aeae9457SYishai Hadas 	if (IS_ERR(obj->umem))
2046aeae9457SYishai Hadas 		return PTR_ERR(obj->umem);
2047aeae9457SYishai Hadas 
2048aeae9457SYishai Hadas 	mlx5_ib_cont_pages(obj->umem, obj->umem->address,
2049aeae9457SYishai Hadas 			   MLX5_MKEY_PAGE_SHIFT_MASK, &npages,
2050aeae9457SYishai Hadas 			   &obj->page_shift, &obj->ncont, NULL);
2051aeae9457SYishai Hadas 
2052aeae9457SYishai Hadas 	if (!npages) {
2053aeae9457SYishai Hadas 		ib_umem_release(obj->umem);
2054aeae9457SYishai Hadas 		return -EINVAL;
2055aeae9457SYishai Hadas 	}
2056aeae9457SYishai Hadas 
2057aeae9457SYishai Hadas 	page_mask = (1 << obj->page_shift) - 1;
2058aeae9457SYishai Hadas 	obj->page_offset = obj->umem->address & page_mask;
2059aeae9457SYishai Hadas 
2060aeae9457SYishai Hadas 	return 0;
2061aeae9457SYishai Hadas }
2062aeae9457SYishai Hadas 
2063b61815e2SJason Gunthorpe static int devx_umem_reg_cmd_alloc(struct uverbs_attr_bundle *attrs,
2064b61815e2SJason Gunthorpe 				   struct devx_umem *obj,
2065aeae9457SYishai Hadas 				   struct devx_umem_reg_cmd *cmd)
2066aeae9457SYishai Hadas {
2067aeae9457SYishai Hadas 	cmd->inlen = MLX5_ST_SZ_BYTES(create_umem_in) +
2068aeae9457SYishai Hadas 		    (MLX5_ST_SZ_BYTES(mtt) * obj->ncont);
2069b61815e2SJason Gunthorpe 	cmd->in = uverbs_zalloc(attrs, cmd->inlen);
2070b61815e2SJason Gunthorpe 	return PTR_ERR_OR_ZERO(cmd->in);
2071aeae9457SYishai Hadas }
2072aeae9457SYishai Hadas 
2073aeae9457SYishai Hadas static void devx_umem_reg_cmd_build(struct mlx5_ib_dev *dev,
2074aeae9457SYishai Hadas 				    struct devx_umem *obj,
2075aeae9457SYishai Hadas 				    struct devx_umem_reg_cmd *cmd)
2076aeae9457SYishai Hadas {
2077aeae9457SYishai Hadas 	void *umem;
2078aeae9457SYishai Hadas 	__be64 *mtt;
2079aeae9457SYishai Hadas 
2080aeae9457SYishai Hadas 	umem = MLX5_ADDR_OF(create_umem_in, cmd->in, umem);
2081aeae9457SYishai Hadas 	mtt = (__be64 *)MLX5_ADDR_OF(umem, umem, mtt);
2082aeae9457SYishai Hadas 
20836e3722baSYishai Hadas 	MLX5_SET(create_umem_in, cmd->in, opcode, MLX5_CMD_OP_CREATE_UMEM);
2084aeae9457SYishai Hadas 	MLX5_SET64(umem, umem, num_of_mtt, obj->ncont);
2085aeae9457SYishai Hadas 	MLX5_SET(umem, umem, log_page_size, obj->page_shift -
2086aeae9457SYishai Hadas 					    MLX5_ADAPTER_PAGE_SHIFT);
2087aeae9457SYishai Hadas 	MLX5_SET(umem, umem, page_offset, obj->page_offset);
2088aeae9457SYishai Hadas 	mlx5_ib_populate_pas(dev, obj->umem, obj->page_shift, mtt,
2089aeae9457SYishai Hadas 			     (obj->umem->writable ? MLX5_IB_MTT_WRITE : 0) |
2090aeae9457SYishai Hadas 			     MLX5_IB_MTT_READ);
2091aeae9457SYishai Hadas }
2092aeae9457SYishai Hadas 
2093e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_REG)(
209415a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
2095aeae9457SYishai Hadas {
2096aeae9457SYishai Hadas 	struct devx_umem_reg_cmd cmd;
2097aeae9457SYishai Hadas 	struct devx_umem *obj;
2098c36ee46dSJason Gunthorpe 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
2099c36ee46dSJason Gunthorpe 		attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE);
2100aeae9457SYishai Hadas 	u32 obj_id;
210189944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
210289944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
2103c36ee46dSJason Gunthorpe 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
2104aeae9457SYishai Hadas 	int err;
2105aeae9457SYishai Hadas 
2106aeae9457SYishai Hadas 	if (!c->devx_uid)
21077e1335a7SYishai Hadas 		return -EINVAL;
21087e1335a7SYishai Hadas 
2109aeae9457SYishai Hadas 	obj = kzalloc(sizeof(struct devx_umem), GFP_KERNEL);
2110aeae9457SYishai Hadas 	if (!obj)
2111aeae9457SYishai Hadas 		return -ENOMEM;
2112aeae9457SYishai Hadas 
2113aeae9457SYishai Hadas 	err = devx_umem_get(dev, &c->ibucontext, attrs, obj);
2114aeae9457SYishai Hadas 	if (err)
2115aeae9457SYishai Hadas 		goto err_obj_free;
2116aeae9457SYishai Hadas 
2117b61815e2SJason Gunthorpe 	err = devx_umem_reg_cmd_alloc(attrs, obj, &cmd);
2118aeae9457SYishai Hadas 	if (err)
2119aeae9457SYishai Hadas 		goto err_umem_release;
2120aeae9457SYishai Hadas 
2121aeae9457SYishai Hadas 	devx_umem_reg_cmd_build(dev, obj, &cmd);
2122aeae9457SYishai Hadas 
21236e3722baSYishai Hadas 	MLX5_SET(create_umem_in, cmd.in, uid, c->devx_uid);
2124aeae9457SYishai Hadas 	err = mlx5_cmd_exec(dev->mdev, cmd.in, cmd.inlen, cmd.out,
2125aeae9457SYishai Hadas 			    sizeof(cmd.out));
2126aeae9457SYishai Hadas 	if (err)
2127b61815e2SJason Gunthorpe 		goto err_umem_release;
2128aeae9457SYishai Hadas 
2129aeae9457SYishai Hadas 	obj->mdev = dev->mdev;
2130aeae9457SYishai Hadas 	uobj->object = obj;
2131aeae9457SYishai Hadas 	devx_obj_build_destroy_cmd(cmd.in, cmd.out, obj->dinbox, &obj->dinlen, &obj_id);
2132aeae9457SYishai Hadas 	err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, &obj_id, sizeof(obj_id));
2133aeae9457SYishai Hadas 	if (err)
2134aeae9457SYishai Hadas 		goto err_umem_destroy;
2135aeae9457SYishai Hadas 
2136aeae9457SYishai Hadas 	return 0;
2137aeae9457SYishai Hadas 
2138aeae9457SYishai Hadas err_umem_destroy:
2139aeae9457SYishai Hadas 	mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, cmd.out, sizeof(cmd.out));
2140aeae9457SYishai Hadas err_umem_release:
2141aeae9457SYishai Hadas 	ib_umem_release(obj->umem);
2142aeae9457SYishai Hadas err_obj_free:
2143aeae9457SYishai Hadas 	kfree(obj);
2144aeae9457SYishai Hadas 	return err;
2145aeae9457SYishai Hadas }
2146aeae9457SYishai Hadas 
2147aeae9457SYishai Hadas static int devx_umem_cleanup(struct ib_uobject *uobject,
2148a6a3797dSShamir Rabinovitch 			     enum rdma_remove_reason why,
2149a6a3797dSShamir Rabinovitch 			     struct uverbs_attr_bundle *attrs)
2150aeae9457SYishai Hadas {
2151aeae9457SYishai Hadas 	struct devx_umem *obj = uobject->object;
2152aeae9457SYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
2153aeae9457SYishai Hadas 	int err;
2154aeae9457SYishai Hadas 
2155aeae9457SYishai Hadas 	err = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out));
21561c77483eSYishai Hadas 	if (ib_is_destroy_retryable(err, why, uobject))
2157aeae9457SYishai Hadas 		return err;
2158aeae9457SYishai Hadas 
2159aeae9457SYishai Hadas 	ib_umem_release(obj->umem);
2160aeae9457SYishai Hadas 	kfree(obj);
2161aeae9457SYishai Hadas 	return 0;
2162aeae9457SYishai Hadas }
2163aeae9457SYishai Hadas 
2164e337dd53SYishai Hadas static int devx_event_notifier(struct notifier_block *nb,
2165e337dd53SYishai Hadas 			       unsigned long event_type, void *data)
2166e337dd53SYishai Hadas {
2167e337dd53SYishai Hadas 	return NOTIFY_DONE;
2168e337dd53SYishai Hadas }
2169e337dd53SYishai Hadas 
2170e337dd53SYishai Hadas void mlx5_ib_devx_init_event_table(struct mlx5_ib_dev *dev)
2171e337dd53SYishai Hadas {
2172e337dd53SYishai Hadas 	struct mlx5_devx_event_table *table = &dev->devx_event_table;
2173e337dd53SYishai Hadas 
2174e337dd53SYishai Hadas 	xa_init(&table->event_xa);
2175e337dd53SYishai Hadas 	mutex_init(&table->event_xa_lock);
2176e337dd53SYishai Hadas 	MLX5_NB_INIT(&table->devx_nb, devx_event_notifier, NOTIFY_ANY);
2177e337dd53SYishai Hadas 	mlx5_eq_notifier_register(dev->mdev, &table->devx_nb);
2178e337dd53SYishai Hadas }
2179e337dd53SYishai Hadas 
2180e337dd53SYishai Hadas void mlx5_ib_devx_cleanup_event_table(struct mlx5_ib_dev *dev)
2181e337dd53SYishai Hadas {
2182e337dd53SYishai Hadas 	struct mlx5_devx_event_table *table = &dev->devx_event_table;
2183*75973853SYishai Hadas 	struct devx_event_subscription *sub, *tmp;
2184*75973853SYishai Hadas 	struct devx_event *event;
2185e337dd53SYishai Hadas 	void *entry;
2186e337dd53SYishai Hadas 	unsigned long id;
2187e337dd53SYishai Hadas 
2188e337dd53SYishai Hadas 	mlx5_eq_notifier_unregister(dev->mdev, &table->devx_nb);
2189*75973853SYishai Hadas 	mutex_lock(&dev->devx_event_table.event_xa_lock);
2190*75973853SYishai Hadas 	xa_for_each(&table->event_xa, id, entry) {
2191*75973853SYishai Hadas 		event = entry;
2192*75973853SYishai Hadas 		list_for_each_entry_safe(sub, tmp, &event->unaffiliated_list,
2193*75973853SYishai Hadas 					 xa_list)
2194*75973853SYishai Hadas 			devx_cleanup_subscription(dev, sub);
2195e337dd53SYishai Hadas 		kfree(entry);
2196*75973853SYishai Hadas 	}
2197*75973853SYishai Hadas 	mutex_unlock(&dev->devx_event_table.event_xa_lock);
2198e337dd53SYishai Hadas 	xa_destroy(&table->event_xa);
2199e337dd53SYishai Hadas }
2200e337dd53SYishai Hadas 
22016bf8f22aSYishai Hadas static ssize_t devx_async_cmd_event_read(struct file *filp, char __user *buf,
22026bf8f22aSYishai Hadas 					 size_t count, loff_t *pos)
22036bf8f22aSYishai Hadas {
22044accbb3fSYishai Hadas 	struct devx_async_cmd_event_file *comp_ev_file = filp->private_data;
22054accbb3fSYishai Hadas 	struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue;
22064accbb3fSYishai Hadas 	struct devx_async_data *event;
22074accbb3fSYishai Hadas 	int ret = 0;
22084accbb3fSYishai Hadas 	size_t eventsz;
22094accbb3fSYishai Hadas 
22104accbb3fSYishai Hadas 	spin_lock_irq(&ev_queue->lock);
22114accbb3fSYishai Hadas 
22124accbb3fSYishai Hadas 	while (list_empty(&ev_queue->event_list)) {
22134accbb3fSYishai Hadas 		spin_unlock_irq(&ev_queue->lock);
22144accbb3fSYishai Hadas 
22154accbb3fSYishai Hadas 		if (filp->f_flags & O_NONBLOCK)
22164accbb3fSYishai Hadas 			return -EAGAIN;
22174accbb3fSYishai Hadas 
22184accbb3fSYishai Hadas 		if (wait_event_interruptible(
22194accbb3fSYishai Hadas 			    ev_queue->poll_wait,
2220eaebaf77SYishai Hadas 			    (!list_empty(&ev_queue->event_list) ||
2221eaebaf77SYishai Hadas 			     ev_queue->is_destroyed))) {
22224accbb3fSYishai Hadas 			return -ERESTARTSYS;
22234accbb3fSYishai Hadas 		}
2224eaebaf77SYishai Hadas 
2225eaebaf77SYishai Hadas 		if (list_empty(&ev_queue->event_list) &&
2226eaebaf77SYishai Hadas 		    ev_queue->is_destroyed)
2227eaebaf77SYishai Hadas 			return -EIO;
2228eaebaf77SYishai Hadas 
22294accbb3fSYishai Hadas 		spin_lock_irq(&ev_queue->lock);
22304accbb3fSYishai Hadas 	}
22314accbb3fSYishai Hadas 
22324accbb3fSYishai Hadas 	event = list_entry(ev_queue->event_list.next,
22334accbb3fSYishai Hadas 			   struct devx_async_data, list);
22344accbb3fSYishai Hadas 	eventsz = event->cmd_out_len +
22354accbb3fSYishai Hadas 			sizeof(struct mlx5_ib_uapi_devx_async_cmd_hdr);
22364accbb3fSYishai Hadas 
22374accbb3fSYishai Hadas 	if (eventsz > count) {
22384accbb3fSYishai Hadas 		spin_unlock_irq(&ev_queue->lock);
22394accbb3fSYishai Hadas 		return -ENOSPC;
22404accbb3fSYishai Hadas 	}
22414accbb3fSYishai Hadas 
22424accbb3fSYishai Hadas 	list_del(ev_queue->event_list.next);
22434accbb3fSYishai Hadas 	spin_unlock_irq(&ev_queue->lock);
22444accbb3fSYishai Hadas 
22454accbb3fSYishai Hadas 	if (copy_to_user(buf, &event->hdr, eventsz))
22464accbb3fSYishai Hadas 		ret = -EFAULT;
22474accbb3fSYishai Hadas 	else
22484accbb3fSYishai Hadas 		ret = eventsz;
22494accbb3fSYishai Hadas 
22504accbb3fSYishai Hadas 	atomic_sub(event->cmd_out_len, &ev_queue->bytes_in_use);
22514accbb3fSYishai Hadas 	kvfree(event);
22524accbb3fSYishai Hadas 	return ret;
22536bf8f22aSYishai Hadas }
22546bf8f22aSYishai Hadas 
22556bf8f22aSYishai Hadas static int devx_async_cmd_event_close(struct inode *inode, struct file *filp)
22566bf8f22aSYishai Hadas {
2257a124edbaSYishai Hadas 	struct ib_uobject *uobj = filp->private_data;
2258a124edbaSYishai Hadas 	struct devx_async_cmd_event_file *comp_ev_file = container_of(
2259a124edbaSYishai Hadas 		uobj, struct devx_async_cmd_event_file, uobj);
2260a124edbaSYishai Hadas 	struct devx_async_data *entry, *tmp;
2261a124edbaSYishai Hadas 
2262a124edbaSYishai Hadas 	spin_lock_irq(&comp_ev_file->ev_queue.lock);
2263a124edbaSYishai Hadas 	list_for_each_entry_safe(entry, tmp,
2264a124edbaSYishai Hadas 				 &comp_ev_file->ev_queue.event_list, list)
2265a124edbaSYishai Hadas 		kvfree(entry);
2266a124edbaSYishai Hadas 	spin_unlock_irq(&comp_ev_file->ev_queue.lock);
2267a124edbaSYishai Hadas 
22686bf8f22aSYishai Hadas 	uverbs_close_fd(filp);
22696bf8f22aSYishai Hadas 	return 0;
22706bf8f22aSYishai Hadas }
22716bf8f22aSYishai Hadas 
22726bf8f22aSYishai Hadas static __poll_t devx_async_cmd_event_poll(struct file *filp,
22736bf8f22aSYishai Hadas 					      struct poll_table_struct *wait)
22746bf8f22aSYishai Hadas {
22754accbb3fSYishai Hadas 	struct devx_async_cmd_event_file *comp_ev_file = filp->private_data;
22764accbb3fSYishai Hadas 	struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue;
22774accbb3fSYishai Hadas 	__poll_t pollflags = 0;
22784accbb3fSYishai Hadas 
22794accbb3fSYishai Hadas 	poll_wait(filp, &ev_queue->poll_wait, wait);
22804accbb3fSYishai Hadas 
22814accbb3fSYishai Hadas 	spin_lock_irq(&ev_queue->lock);
2282eaebaf77SYishai Hadas 	if (ev_queue->is_destroyed)
2283eaebaf77SYishai Hadas 		pollflags = EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
2284eaebaf77SYishai Hadas 	else if (!list_empty(&ev_queue->event_list))
22854accbb3fSYishai Hadas 		pollflags = EPOLLIN | EPOLLRDNORM;
22864accbb3fSYishai Hadas 	spin_unlock_irq(&ev_queue->lock);
22874accbb3fSYishai Hadas 
22884accbb3fSYishai Hadas 	return pollflags;
22896bf8f22aSYishai Hadas }
22906bf8f22aSYishai Hadas 
22911f687edeSBart Van Assche static const struct file_operations devx_async_cmd_event_fops = {
22926bf8f22aSYishai Hadas 	.owner	 = THIS_MODULE,
22936bf8f22aSYishai Hadas 	.read	 = devx_async_cmd_event_read,
22946bf8f22aSYishai Hadas 	.poll    = devx_async_cmd_event_poll,
22956bf8f22aSYishai Hadas 	.release = devx_async_cmd_event_close,
22966bf8f22aSYishai Hadas 	.llseek	 = no_llseek,
22976bf8f22aSYishai Hadas };
22986bf8f22aSYishai Hadas 
22992afc5e1bSYishai Hadas static ssize_t devx_async_event_read(struct file *filp, char __user *buf,
23002afc5e1bSYishai Hadas 				     size_t count, loff_t *pos)
23012afc5e1bSYishai Hadas {
23022afc5e1bSYishai Hadas 	return -EINVAL;
23032afc5e1bSYishai Hadas }
23042afc5e1bSYishai Hadas 
23052afc5e1bSYishai Hadas static __poll_t devx_async_event_poll(struct file *filp,
23062afc5e1bSYishai Hadas 				      struct poll_table_struct *wait)
23072afc5e1bSYishai Hadas {
23082afc5e1bSYishai Hadas 	return 0;
23092afc5e1bSYishai Hadas }
23102afc5e1bSYishai Hadas 
23112afc5e1bSYishai Hadas static int devx_async_event_close(struct inode *inode, struct file *filp)
23122afc5e1bSYishai Hadas {
2313*75973853SYishai Hadas 	struct devx_async_event_file *ev_file = filp->private_data;
2314*75973853SYishai Hadas 	struct devx_event_subscription *event_sub, *event_sub_tmp;
2315*75973853SYishai Hadas 
2316*75973853SYishai Hadas 	mutex_lock(&ev_file->dev->devx_event_table.event_xa_lock);
2317*75973853SYishai Hadas 	/* delete the subscriptions which are related to this FD */
2318*75973853SYishai Hadas 	list_for_each_entry_safe(event_sub, event_sub_tmp,
2319*75973853SYishai Hadas 				 &ev_file->subscribed_events_list, file_list) {
2320*75973853SYishai Hadas 		devx_cleanup_subscription(ev_file->dev, event_sub);
2321*75973853SYishai Hadas 		if (event_sub->eventfd)
2322*75973853SYishai Hadas 			eventfd_ctx_put(event_sub->eventfd);
2323*75973853SYishai Hadas 
2324*75973853SYishai Hadas 		list_del_rcu(&event_sub->file_list);
2325*75973853SYishai Hadas 		/* subscription may not be used by the read API any more */
2326*75973853SYishai Hadas 		kfree_rcu(event_sub, rcu);
2327*75973853SYishai Hadas 	}
2328*75973853SYishai Hadas 
2329*75973853SYishai Hadas 	mutex_unlock(&ev_file->dev->devx_event_table.event_xa_lock);
2330*75973853SYishai Hadas 
23312afc5e1bSYishai Hadas 	uverbs_close_fd(filp);
2332*75973853SYishai Hadas 	put_device(&ev_file->dev->ib_dev.dev);
23332afc5e1bSYishai Hadas 	return 0;
23342afc5e1bSYishai Hadas }
23352afc5e1bSYishai Hadas 
23362afc5e1bSYishai Hadas static const struct file_operations devx_async_event_fops = {
23372afc5e1bSYishai Hadas 	.owner	 = THIS_MODULE,
23382afc5e1bSYishai Hadas 	.read	 = devx_async_event_read,
23392afc5e1bSYishai Hadas 	.poll    = devx_async_event_poll,
23402afc5e1bSYishai Hadas 	.release = devx_async_event_close,
23412afc5e1bSYishai Hadas 	.llseek	 = no_llseek,
23422afc5e1bSYishai Hadas };
23432afc5e1bSYishai Hadas 
23446bf8f22aSYishai Hadas static int devx_hot_unplug_async_cmd_event_file(struct ib_uobject *uobj,
23456bf8f22aSYishai Hadas 						   enum rdma_remove_reason why)
23466bf8f22aSYishai Hadas {
2347a124edbaSYishai Hadas 	struct devx_async_cmd_event_file *comp_ev_file =
2348a124edbaSYishai Hadas 		container_of(uobj, struct devx_async_cmd_event_file,
2349a124edbaSYishai Hadas 			     uobj);
2350eaebaf77SYishai Hadas 	struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue;
2351eaebaf77SYishai Hadas 
2352eaebaf77SYishai Hadas 	spin_lock_irq(&ev_queue->lock);
2353eaebaf77SYishai Hadas 	ev_queue->is_destroyed = 1;
2354eaebaf77SYishai Hadas 	spin_unlock_irq(&ev_queue->lock);
2355eaebaf77SYishai Hadas 
2356eaebaf77SYishai Hadas 	if (why == RDMA_REMOVE_DRIVER_REMOVE)
2357eaebaf77SYishai Hadas 		wake_up_interruptible(&ev_queue->poll_wait);
2358a124edbaSYishai Hadas 
2359a124edbaSYishai Hadas 	mlx5_cmd_cleanup_async_ctx(&comp_ev_file->async_ctx);
23606bf8f22aSYishai Hadas 	return 0;
23616bf8f22aSYishai Hadas };
23626bf8f22aSYishai Hadas 
23632afc5e1bSYishai Hadas static int devx_hot_unplug_async_event_file(struct ib_uobject *uobj,
23642afc5e1bSYishai Hadas 					    enum rdma_remove_reason why)
23652afc5e1bSYishai Hadas {
23662afc5e1bSYishai Hadas 	return 0;
23672afc5e1bSYishai Hadas };
23682afc5e1bSYishai Hadas 
23699a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
23709a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_UMEM_REG,
23719a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE,
2372aeae9457SYishai Hadas 			MLX5_IB_OBJECT_DEVX_UMEM,
2373aeae9457SYishai Hadas 			UVERBS_ACCESS_NEW,
237483bb4442SJason Gunthorpe 			UA_MANDATORY),
23759a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR,
23769a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u64),
237783bb4442SJason Gunthorpe 			   UA_MANDATORY),
23789a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_LEN,
23799a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u64),
238083bb4442SJason Gunthorpe 			   UA_MANDATORY),
2381bccd0622SJason Gunthorpe 	UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
2382bccd0622SJason Gunthorpe 			     enum ib_access_flags),
23839a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID,
23849a119cd5SJason Gunthorpe 			    UVERBS_ATTR_TYPE(u32),
238583bb4442SJason Gunthorpe 			    UA_MANDATORY));
2386aeae9457SYishai Hadas 
2387528922afSYishai Hadas DECLARE_UVERBS_NAMED_METHOD_DESTROY(
23889a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_UMEM_DEREG,
23899a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_DEREG_HANDLE,
2390aeae9457SYishai Hadas 			MLX5_IB_OBJECT_DEVX_UMEM,
2391aeae9457SYishai Hadas 			UVERBS_ACCESS_DESTROY,
239283bb4442SJason Gunthorpe 			UA_MANDATORY));
2393aeae9457SYishai Hadas 
23949a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
23959a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_QUERY_EQN,
23969a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC,
23979a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u32),
239883bb4442SJason Gunthorpe 			   UA_MANDATORY),
23999a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN,
24009a119cd5SJason Gunthorpe 			    UVERBS_ATTR_TYPE(u32),
240183bb4442SJason Gunthorpe 			    UA_MANDATORY));
2402f6fe01b7SYishai Hadas 
24039a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
24049a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_QUERY_UAR,
24059a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX,
24069a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u32),
240783bb4442SJason Gunthorpe 			   UA_MANDATORY),
24089a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX,
24099a119cd5SJason Gunthorpe 			    UVERBS_ATTR_TYPE(u32),
241083bb4442SJason Gunthorpe 			    UA_MANDATORY));
24117c043e90SYishai Hadas 
24129a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
24139a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OTHER,
24149a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
24159a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OTHER_CMD_IN,
24168aa8c95cSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
241783bb4442SJason Gunthorpe 		UA_MANDATORY,
241883bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
24199a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
24209a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT,
24217efce369SYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
2422540cd692SJason Gunthorpe 		UA_MANDATORY));
24237efce369SYishai Hadas 
24249a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
24259a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_CREATE,
24269a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE,
24279a119cd5SJason Gunthorpe 			MLX5_IB_OBJECT_DEVX_OBJ,
24289a119cd5SJason Gunthorpe 			UVERBS_ACCESS_NEW,
242983bb4442SJason Gunthorpe 			UA_MANDATORY),
24309a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
24319a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN,
24329a119cd5SJason Gunthorpe 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
243383bb4442SJason Gunthorpe 		UA_MANDATORY,
243483bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
24359a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
24369a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT,
24379a119cd5SJason Gunthorpe 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
2438540cd692SJason Gunthorpe 		UA_MANDATORY));
24399a119cd5SJason Gunthorpe 
2440528922afSYishai Hadas DECLARE_UVERBS_NAMED_METHOD_DESTROY(
24419a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_DESTROY,
24429a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_DESTROY_HANDLE,
24437efce369SYishai Hadas 			MLX5_IB_OBJECT_DEVX_OBJ,
24447efce369SYishai Hadas 			UVERBS_ACCESS_DESTROY,
244583bb4442SJason Gunthorpe 			UA_MANDATORY));
24467efce369SYishai Hadas 
24479a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
24489a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_MODIFY,
24499a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE,
245034613eb1SYishai Hadas 			UVERBS_IDR_ANY_OBJECT,
2451e662e14dSYishai Hadas 			UVERBS_ACCESS_WRITE,
245283bb4442SJason Gunthorpe 			UA_MANDATORY),
24539a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
24549a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN,
2455e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
245683bb4442SJason Gunthorpe 		UA_MANDATORY,
245783bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
24589a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
24599a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
2460e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
2461540cd692SJason Gunthorpe 		UA_MANDATORY));
2462e662e14dSYishai Hadas 
24639a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
24649a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_QUERY,
24659a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE,
246634613eb1SYishai Hadas 			UVERBS_IDR_ANY_OBJECT,
2467e662e14dSYishai Hadas 			UVERBS_ACCESS_READ,
246883bb4442SJason Gunthorpe 			UA_MANDATORY),
24699a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
24709a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN,
2471e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
247283bb4442SJason Gunthorpe 		UA_MANDATORY,
247383bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
24749a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
24759a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
2476e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
2477540cd692SJason Gunthorpe 		UA_MANDATORY));
2478e662e14dSYishai Hadas 
2479a124edbaSYishai Hadas DECLARE_UVERBS_NAMED_METHOD(
2480a124edbaSYishai Hadas 	MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY,
2481a124edbaSYishai Hadas 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE,
2482a124edbaSYishai Hadas 			UVERBS_IDR_ANY_OBJECT,
2483a124edbaSYishai Hadas 			UVERBS_ACCESS_READ,
2484a124edbaSYishai Hadas 			UA_MANDATORY),
2485a124edbaSYishai Hadas 	UVERBS_ATTR_PTR_IN(
2486a124edbaSYishai Hadas 		MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN,
2487a124edbaSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
2488a124edbaSYishai Hadas 		UA_MANDATORY,
2489a124edbaSYishai Hadas 		UA_ALLOC_AND_COPY),
2490a124edbaSYishai Hadas 	UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_OUT_LEN,
2491a124edbaSYishai Hadas 		u16, UA_MANDATORY),
2492a124edbaSYishai Hadas 	UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_FD,
2493a124edbaSYishai Hadas 		MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
2494a124edbaSYishai Hadas 		UVERBS_ACCESS_READ,
2495a124edbaSYishai Hadas 		UA_MANDATORY),
2496a124edbaSYishai Hadas 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_WR_ID,
2497a124edbaSYishai Hadas 		UVERBS_ATTR_TYPE(u64),
2498a124edbaSYishai Hadas 		UA_MANDATORY));
2499a124edbaSYishai Hadas 
2500*75973853SYishai Hadas DECLARE_UVERBS_NAMED_METHOD(
2501*75973853SYishai Hadas 	MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT,
2502*75973853SYishai Hadas 	UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_HANDLE,
2503*75973853SYishai Hadas 		MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD,
2504*75973853SYishai Hadas 		UVERBS_ACCESS_READ,
2505*75973853SYishai Hadas 		UA_MANDATORY),
2506*75973853SYishai Hadas 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_OBJ_HANDLE,
2507*75973853SYishai Hadas 		MLX5_IB_OBJECT_DEVX_OBJ,
2508*75973853SYishai Hadas 		UVERBS_ACCESS_READ,
2509*75973853SYishai Hadas 		UA_OPTIONAL),
2510*75973853SYishai Hadas 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST,
2511*75973853SYishai Hadas 		UVERBS_ATTR_MIN_SIZE(sizeof(u16)),
2512*75973853SYishai Hadas 		UA_MANDATORY,
2513*75973853SYishai Hadas 		UA_ALLOC_AND_COPY),
2514*75973853SYishai Hadas 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE,
2515*75973853SYishai Hadas 		UVERBS_ATTR_TYPE(u64),
2516*75973853SYishai Hadas 		UA_OPTIONAL),
2517*75973853SYishai Hadas 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM,
2518*75973853SYishai Hadas 		UVERBS_ATTR_TYPE(u32),
2519*75973853SYishai Hadas 		UA_OPTIONAL));
2520*75973853SYishai Hadas 
25216c61d2a5SJason Gunthorpe DECLARE_UVERBS_GLOBAL_METHODS(MLX5_IB_OBJECT_DEVX,
25227c043e90SYishai Hadas 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OTHER),
2523f6fe01b7SYishai Hadas 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR),
2524*75973853SYishai Hadas 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_EQN),
2525*75973853SYishai Hadas 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT));
25268aa8c95cSYishai Hadas 
25276c61d2a5SJason Gunthorpe DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ,
25289a119cd5SJason Gunthorpe 			    UVERBS_TYPE_ALLOC_IDR(devx_obj_cleanup),
25297efce369SYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_CREATE),
2530e662e14dSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY),
2531e662e14dSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_MODIFY),
2532a124edbaSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY),
2533a124edbaSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY));
25347efce369SYishai Hadas 
25356c61d2a5SJason Gunthorpe DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM,
25369a119cd5SJason Gunthorpe 			    UVERBS_TYPE_ALLOC_IDR(devx_umem_cleanup),
2537aeae9457SYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG),
2538aeae9457SYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG));
2539aeae9457SYishai Hadas 
25406bf8f22aSYishai Hadas 
25416bf8f22aSYishai Hadas DECLARE_UVERBS_NAMED_METHOD(
25426bf8f22aSYishai Hadas 	MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC,
25436bf8f22aSYishai Hadas 	UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE,
25446bf8f22aSYishai Hadas 			MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
25456bf8f22aSYishai Hadas 			UVERBS_ACCESS_NEW,
25466bf8f22aSYishai Hadas 			UA_MANDATORY));
25476bf8f22aSYishai Hadas 
25486bf8f22aSYishai Hadas DECLARE_UVERBS_NAMED_OBJECT(
25496bf8f22aSYishai Hadas 	MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
25506bf8f22aSYishai Hadas 	UVERBS_TYPE_ALLOC_FD(sizeof(struct devx_async_cmd_event_file),
25516bf8f22aSYishai Hadas 			     devx_hot_unplug_async_cmd_event_file,
25526bf8f22aSYishai Hadas 			     &devx_async_cmd_event_fops, "[devx_async_cmd]",
25536bf8f22aSYishai Hadas 			     O_RDONLY),
25546bf8f22aSYishai Hadas 	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC));
25556bf8f22aSYishai Hadas 
25562afc5e1bSYishai Hadas DECLARE_UVERBS_NAMED_METHOD(
25572afc5e1bSYishai Hadas 	MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC,
25582afc5e1bSYishai Hadas 	UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_HANDLE,
25592afc5e1bSYishai Hadas 			MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD,
25602afc5e1bSYishai Hadas 			UVERBS_ACCESS_NEW,
25612afc5e1bSYishai Hadas 			UA_MANDATORY),
25622afc5e1bSYishai Hadas 	UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_FLAGS,
25632afc5e1bSYishai Hadas 			enum mlx5_ib_uapi_devx_create_event_channel_flags,
25642afc5e1bSYishai Hadas 			UA_MANDATORY));
25652afc5e1bSYishai Hadas 
25662afc5e1bSYishai Hadas DECLARE_UVERBS_NAMED_OBJECT(
25672afc5e1bSYishai Hadas 	MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD,
25682afc5e1bSYishai Hadas 	UVERBS_TYPE_ALLOC_FD(sizeof(struct devx_async_event_file),
25692afc5e1bSYishai Hadas 			     devx_hot_unplug_async_event_file,
25702afc5e1bSYishai Hadas 			     &devx_async_event_fops, "[devx_async_event]",
25712afc5e1bSYishai Hadas 			     O_RDONLY),
25722afc5e1bSYishai Hadas 	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC));
25732afc5e1bSYishai Hadas 
257436e235c8SJason Gunthorpe static bool devx_is_supported(struct ib_device *device)
2575c59450c4SYishai Hadas {
257636e235c8SJason Gunthorpe 	struct mlx5_ib_dev *dev = to_mdev(device);
257736e235c8SJason Gunthorpe 
25787f575103SMark Bloch 	return MLX5_CAP_GEN(dev->mdev, log_max_uctx);
2579c59450c4SYishai Hadas }
258036e235c8SJason Gunthorpe 
25810cbf432dSJason Gunthorpe const struct uapi_definition mlx5_ib_devx_defs[] = {
258236e235c8SJason Gunthorpe 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
258336e235c8SJason Gunthorpe 		MLX5_IB_OBJECT_DEVX,
258436e235c8SJason Gunthorpe 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
258536e235c8SJason Gunthorpe 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
258636e235c8SJason Gunthorpe 		MLX5_IB_OBJECT_DEVX_OBJ,
258736e235c8SJason Gunthorpe 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
258836e235c8SJason Gunthorpe 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
258936e235c8SJason Gunthorpe 		MLX5_IB_OBJECT_DEVX_UMEM,
259036e235c8SJason Gunthorpe 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
25916bf8f22aSYishai Hadas 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
25926bf8f22aSYishai Hadas 		MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
25936bf8f22aSYishai Hadas 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
25942afc5e1bSYishai Hadas 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
25952afc5e1bSYishai Hadas 		MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD,
25962afc5e1bSYishai Hadas 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
25970cbf432dSJason Gunthorpe 	{},
25980cbf432dSJason Gunthorpe };
2599