xref: /linux/drivers/infiniband/hw/mlx5/devx.c (revision 1368ead04c361bb4595ace9122c79dd75e54a650)
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"
17f7c4ffdaSLeon Romanovsky #include "devx.h"
18333fbaa0SLeon Romanovsky #include "qp.h"
1975973853SYishai Hadas #include <linux/xarray.h>
20a8b92ca1SYishai Hadas 
218aa8c95cSYishai Hadas #define UVERBS_MODULE_NAME mlx5_ib
228aa8c95cSYishai Hadas #include <rdma/uverbs_named_ioctl.h>
238aa8c95cSYishai Hadas 
24ef1659adSYishai Hadas static void dispatch_event_fd(struct list_head *fd_list, const void *data);
25ef1659adSYishai Hadas 
26534fd7aaSYishai Hadas enum devx_obj_flags {
27534fd7aaSYishai Hadas 	DEVX_OBJ_FLAGS_INDIRECT_MKEY = 1 << 0,
28c5ae1954SYishai Hadas 	DEVX_OBJ_FLAGS_DCT = 1 << 1,
29ef1659adSYishai Hadas 	DEVX_OBJ_FLAGS_CQ = 1 << 2,
30534fd7aaSYishai Hadas };
31534fd7aaSYishai Hadas 
32a124edbaSYishai Hadas struct devx_async_data {
33a124edbaSYishai Hadas 	struct mlx5_ib_dev *mdev;
34a124edbaSYishai Hadas 	struct list_head list;
3593887e66SJason Gunthorpe 	struct devx_async_cmd_event_file *ev_file;
36a124edbaSYishai Hadas 	struct mlx5_async_work cb_work;
37a124edbaSYishai Hadas 	u16 cmd_out_len;
38a124edbaSYishai Hadas 	/* must be last field in this structure */
39a124edbaSYishai Hadas 	struct mlx5_ib_uapi_devx_async_cmd_hdr hdr;
40a124edbaSYishai Hadas };
41a124edbaSYishai Hadas 
425ec9d8eeSYishai Hadas struct devx_async_event_data {
435ec9d8eeSYishai Hadas 	struct list_head list; /* headed in ev_file->event_list */
445ec9d8eeSYishai Hadas 	struct mlx5_ib_uapi_devx_async_event_hdr hdr;
455ec9d8eeSYishai Hadas };
465ec9d8eeSYishai Hadas 
4775973853SYishai Hadas /* first level XA value data structure */
4875973853SYishai Hadas struct devx_event {
4975973853SYishai Hadas 	struct xarray object_ids; /* second XA level, Key = object id */
5075973853SYishai Hadas 	struct list_head unaffiliated_list;
5175973853SYishai Hadas };
5275973853SYishai Hadas 
5375973853SYishai Hadas /* second level XA value data structure */
5475973853SYishai Hadas struct devx_obj_event {
5575973853SYishai Hadas 	struct rcu_head rcu;
5675973853SYishai Hadas 	struct list_head obj_sub_list;
5775973853SYishai Hadas };
5875973853SYishai Hadas 
5975973853SYishai Hadas struct devx_event_subscription {
6075973853SYishai Hadas 	struct list_head file_list; /* headed in ev_file->
6175973853SYishai Hadas 				     * subscribed_events_list
6275973853SYishai Hadas 				     */
6375973853SYishai Hadas 	struct list_head xa_list; /* headed in devx_event->unaffiliated_list or
6475973853SYishai Hadas 				   * devx_obj_event->obj_sub_list
6575973853SYishai Hadas 				   */
6675973853SYishai Hadas 	struct list_head obj_list; /* headed in devx_object */
6775973853SYishai Hadas 	struct list_head event_list; /* headed in ev_file->event_list or in
6875973853SYishai Hadas 				      * temp list via subscription
6975973853SYishai Hadas 				      */
7075973853SYishai Hadas 
7175973853SYishai Hadas 	u8 is_cleaned:1;
7275973853SYishai Hadas 	u32 xa_key_level1;
7375973853SYishai Hadas 	u32 xa_key_level2;
7475973853SYishai Hadas 	struct rcu_head	rcu;
7575973853SYishai Hadas 	u64 cookie;
7675973853SYishai Hadas 	struct devx_async_event_file *ev_file;
7775973853SYishai Hadas 	struct eventfd_ctx *eventfd;
7875973853SYishai Hadas };
7975973853SYishai Hadas 
802afc5e1bSYishai Hadas struct devx_async_event_file {
812afc5e1bSYishai Hadas 	struct ib_uobject uobj;
822afc5e1bSYishai Hadas 	/* Head of events that are subscribed to this FD */
832afc5e1bSYishai Hadas 	struct list_head subscribed_events_list;
842afc5e1bSYishai Hadas 	spinlock_t lock;
852afc5e1bSYishai Hadas 	wait_queue_head_t poll_wait;
862afc5e1bSYishai Hadas 	struct list_head event_list;
872afc5e1bSYishai Hadas 	struct mlx5_ib_dev *dev;
882afc5e1bSYishai Hadas 	u8 omit_data:1;
895ec9d8eeSYishai Hadas 	u8 is_overflow_err:1;
905ec9d8eeSYishai Hadas 	u8 is_destroyed:1;
912afc5e1bSYishai Hadas };
922afc5e1bSYishai Hadas 
93aeae9457SYishai Hadas struct devx_umem {
94aeae9457SYishai Hadas 	struct mlx5_core_dev		*mdev;
95aeae9457SYishai Hadas 	struct ib_umem			*umem;
96aeae9457SYishai Hadas 	u32				dinlen;
97*1368ead0SYishai Hadas 	u32				dinbox[MLX5_ST_SZ_DW(destroy_umem_in)];
98aeae9457SYishai Hadas };
99aeae9457SYishai Hadas 
100aeae9457SYishai Hadas struct devx_umem_reg_cmd {
101aeae9457SYishai Hadas 	void				*in;
102aeae9457SYishai Hadas 	u32				inlen;
103*1368ead0SYishai Hadas 	u32				out[MLX5_ST_SZ_DW(create_umem_out)];
104aeae9457SYishai Hadas };
105aeae9457SYishai Hadas 
10615a1b4beSJason Gunthorpe static struct mlx5_ib_ucontext *
10715a1b4beSJason Gunthorpe devx_ufile2uctx(const struct uverbs_attr_bundle *attrs)
1088aa8c95cSYishai Hadas {
10915a1b4beSJason Gunthorpe 	return to_mucontext(ib_uverbs_get_ucontext(attrs));
1108aa8c95cSYishai Hadas }
1118aa8c95cSYishai Hadas 
112fb98153bSYishai Hadas int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user)
113a8b92ca1SYishai Hadas {
114*1368ead0SYishai Hadas 	u32 in[MLX5_ST_SZ_DW(create_uctx_in)] = {};
115*1368ead0SYishai Hadas 	u32 out[MLX5_ST_SZ_DW(create_uctx_out)] = {};
1166e3722baSYishai Hadas 	void *uctx;
117a8b92ca1SYishai Hadas 	int err;
11876dc5a84SYishai Hadas 	u16 uid;
119fb98153bSYishai Hadas 	u32 cap = 0;
120a8b92ca1SYishai Hadas 
1216e3722baSYishai Hadas 	/* 0 means not supported */
1226e3722baSYishai Hadas 	if (!MLX5_CAP_GEN(dev->mdev, log_max_uctx))
123a8b92ca1SYishai Hadas 		return -EINVAL;
124a8b92ca1SYishai Hadas 
1256e3722baSYishai Hadas 	uctx = MLX5_ADDR_OF(create_uctx_in, in, uctx);
126fb98153bSYishai Hadas 	if (is_user && capable(CAP_NET_RAW) &&
127fb98153bSYishai Hadas 	    (MLX5_CAP_GEN(dev->mdev, uctx_cap) & MLX5_UCTX_CAP_RAW_TX))
128fb98153bSYishai Hadas 		cap |= MLX5_UCTX_CAP_RAW_TX;
12933cde96fSAriel Levkovich 	if (is_user && capable(CAP_SYS_RAWIO) &&
13033cde96fSAriel Levkovich 	    (MLX5_CAP_GEN(dev->mdev, uctx_cap) &
13133cde96fSAriel Levkovich 	     MLX5_UCTX_CAP_INTERNAL_DEV_RES))
13233cde96fSAriel Levkovich 		cap |= MLX5_UCTX_CAP_INTERNAL_DEV_RES;
133fb98153bSYishai Hadas 
1346e3722baSYishai Hadas 	MLX5_SET(create_uctx_in, in, opcode, MLX5_CMD_OP_CREATE_UCTX);
135fb98153bSYishai Hadas 	MLX5_SET(uctx, uctx, cap, cap);
136a8b92ca1SYishai Hadas 
137a8b92ca1SYishai Hadas 	err = mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
138a8b92ca1SYishai Hadas 	if (err)
139a8b92ca1SYishai Hadas 		return err;
140a8b92ca1SYishai Hadas 
141*1368ead0SYishai Hadas 	uid = MLX5_GET(create_uctx_out, out, uid);
14276dc5a84SYishai Hadas 	return uid;
143a8b92ca1SYishai Hadas }
144a8b92ca1SYishai Hadas 
14576dc5a84SYishai Hadas void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev, u16 uid)
146a8b92ca1SYishai Hadas {
147*1368ead0SYishai Hadas 	u32 in[MLX5_ST_SZ_DW(destroy_uctx_in)] = {};
148*1368ead0SYishai Hadas 	u32 out[MLX5_ST_SZ_DW(destroy_uctx_out)] = {};
149a8b92ca1SYishai Hadas 
1506e3722baSYishai Hadas 	MLX5_SET(destroy_uctx_in, in, opcode, MLX5_CMD_OP_DESTROY_UCTX);
1516e3722baSYishai Hadas 	MLX5_SET(destroy_uctx_in, in, uid, uid);
152a8b92ca1SYishai Hadas 
153a8b92ca1SYishai Hadas 	mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
154a8b92ca1SYishai Hadas }
1558aa8c95cSYishai Hadas 
15675973853SYishai Hadas static bool is_legacy_unaffiliated_event_num(u16 event_num)
15775973853SYishai Hadas {
15875973853SYishai Hadas 	switch (event_num) {
15975973853SYishai Hadas 	case MLX5_EVENT_TYPE_PORT_CHANGE:
16075973853SYishai Hadas 		return true;
16175973853SYishai Hadas 	default:
16275973853SYishai Hadas 		return false;
16375973853SYishai Hadas 	}
16475973853SYishai Hadas }
16575973853SYishai Hadas 
16675973853SYishai Hadas static bool is_legacy_obj_event_num(u16 event_num)
16775973853SYishai Hadas {
16875973853SYishai Hadas 	switch (event_num) {
16975973853SYishai Hadas 	case MLX5_EVENT_TYPE_PATH_MIG:
17075973853SYishai Hadas 	case MLX5_EVENT_TYPE_COMM_EST:
17175973853SYishai Hadas 	case MLX5_EVENT_TYPE_SQ_DRAINED:
17275973853SYishai Hadas 	case MLX5_EVENT_TYPE_SRQ_LAST_WQE:
17375973853SYishai Hadas 	case MLX5_EVENT_TYPE_SRQ_RQ_LIMIT:
17475973853SYishai Hadas 	case MLX5_EVENT_TYPE_CQ_ERROR:
17575973853SYishai Hadas 	case MLX5_EVENT_TYPE_WQ_CATAS_ERROR:
17675973853SYishai Hadas 	case MLX5_EVENT_TYPE_PATH_MIG_FAILED:
17775973853SYishai Hadas 	case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR:
17875973853SYishai Hadas 	case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR:
17975973853SYishai Hadas 	case MLX5_EVENT_TYPE_SRQ_CATAS_ERROR:
18075973853SYishai Hadas 	case MLX5_EVENT_TYPE_DCT_DRAINED:
18175973853SYishai Hadas 	case MLX5_EVENT_TYPE_COMP:
182972d7560SYishai Hadas 	case MLX5_EVENT_TYPE_DCT_KEY_VIOLATION:
183972d7560SYishai Hadas 	case MLX5_EVENT_TYPE_XRQ_ERROR:
18475973853SYishai Hadas 		return true;
18575973853SYishai Hadas 	default:
18675973853SYishai Hadas 		return false;
18775973853SYishai Hadas 	}
18875973853SYishai Hadas }
18975973853SYishai Hadas 
19075973853SYishai Hadas static u16 get_legacy_obj_type(u16 opcode)
19175973853SYishai Hadas {
19275973853SYishai Hadas 	switch (opcode) {
19375973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
19475973853SYishai Hadas 		return MLX5_EVENT_QUEUE_TYPE_RQ;
19575973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
19675973853SYishai Hadas 		return MLX5_EVENT_QUEUE_TYPE_QP;
19775973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
19875973853SYishai Hadas 		return MLX5_EVENT_QUEUE_TYPE_SQ;
19975973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_DCT:
20075973853SYishai Hadas 		return MLX5_EVENT_QUEUE_TYPE_DCT;
20175973853SYishai Hadas 	default:
20275973853SYishai Hadas 		return 0;
20375973853SYishai Hadas 	}
20475973853SYishai Hadas }
20575973853SYishai Hadas 
20675973853SYishai Hadas static u16 get_dec_obj_type(struct devx_obj *obj, u16 event_num)
20775973853SYishai Hadas {
20875973853SYishai Hadas 	u16 opcode;
20975973853SYishai Hadas 
21075973853SYishai Hadas 	opcode = (obj->obj_id >> 32) & 0xffff;
21175973853SYishai Hadas 
21275973853SYishai Hadas 	if (is_legacy_obj_event_num(event_num))
21375973853SYishai Hadas 		return get_legacy_obj_type(opcode);
21475973853SYishai Hadas 
21575973853SYishai Hadas 	switch (opcode) {
21675973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
21775973853SYishai Hadas 		return (obj->obj_id >> 48);
21875973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
21975973853SYishai Hadas 		return MLX5_OBJ_TYPE_RQ;
22075973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
22175973853SYishai Hadas 		return MLX5_OBJ_TYPE_QP;
22275973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
22375973853SYishai Hadas 		return MLX5_OBJ_TYPE_SQ;
22475973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_DCT:
22575973853SYishai Hadas 		return MLX5_OBJ_TYPE_DCT;
22675973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIR:
22775973853SYishai Hadas 		return MLX5_OBJ_TYPE_TIR;
22875973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIS:
22975973853SYishai Hadas 		return MLX5_OBJ_TYPE_TIS;
23075973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_PSV:
23175973853SYishai Hadas 		return MLX5_OBJ_TYPE_PSV;
23275973853SYishai Hadas 	case MLX5_OBJ_TYPE_MKEY:
23375973853SYishai Hadas 		return MLX5_OBJ_TYPE_MKEY;
23475973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_RMP:
23575973853SYishai Hadas 		return MLX5_OBJ_TYPE_RMP;
23675973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
23775973853SYishai Hadas 		return MLX5_OBJ_TYPE_XRC_SRQ;
23875973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRQ:
23975973853SYishai Hadas 		return MLX5_OBJ_TYPE_XRQ;
24075973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQT:
24175973853SYishai Hadas 		return MLX5_OBJ_TYPE_RQT;
24275973853SYishai Hadas 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
24375973853SYishai Hadas 		return MLX5_OBJ_TYPE_FLOW_COUNTER;
24475973853SYishai Hadas 	case MLX5_CMD_OP_CREATE_CQ:
24575973853SYishai Hadas 		return MLX5_OBJ_TYPE_CQ;
24675973853SYishai Hadas 	default:
24775973853SYishai Hadas 		return 0;
24875973853SYishai Hadas 	}
24975973853SYishai Hadas }
25075973853SYishai Hadas 
2515ec9d8eeSYishai Hadas static u16 get_event_obj_type(unsigned long event_type, struct mlx5_eqe *eqe)
2525ec9d8eeSYishai Hadas {
2535ec9d8eeSYishai Hadas 	switch (event_type) {
2545ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_WQ_CATAS_ERROR:
2555ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR:
2565ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR:
2575ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_SRQ_LAST_WQE:
2585ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_PATH_MIG:
2595ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_PATH_MIG_FAILED:
2605ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_COMM_EST:
2615ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_SQ_DRAINED:
2625ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_SRQ_RQ_LIMIT:
2635ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_SRQ_CATAS_ERROR:
2645ec9d8eeSYishai Hadas 		return eqe->data.qp_srq.type;
2655ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_CQ_ERROR:
266972d7560SYishai Hadas 	case MLX5_EVENT_TYPE_XRQ_ERROR:
2675ec9d8eeSYishai Hadas 		return 0;
2685ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_DCT_DRAINED:
269972d7560SYishai Hadas 	case MLX5_EVENT_TYPE_DCT_KEY_VIOLATION:
2705ec9d8eeSYishai Hadas 		return MLX5_EVENT_QUEUE_TYPE_DCT;
2715ec9d8eeSYishai Hadas 	default:
2725ec9d8eeSYishai Hadas 		return MLX5_GET(affiliated_event_header, &eqe->data, obj_type);
2735ec9d8eeSYishai Hadas 	}
2745ec9d8eeSYishai Hadas }
2755ec9d8eeSYishai Hadas 
27675973853SYishai Hadas static u32 get_dec_obj_id(u64 obj_id)
27775973853SYishai Hadas {
27875973853SYishai Hadas 	return (obj_id & 0xffffffff);
27975973853SYishai Hadas }
28075973853SYishai Hadas 
2812351776eSYishai Hadas /*
2822351776eSYishai Hadas  * As the obj_id in the firmware is not globally unique the object type
2832351776eSYishai Hadas  * must be considered upon checking for a valid object id.
2842351776eSYishai Hadas  * For that the opcode of the creator command is encoded as part of the obj_id.
2852351776eSYishai Hadas  */
286cd5d20f1SYishai Hadas static u64 get_enc_obj_id(u32 opcode, u32 obj_id)
2872351776eSYishai Hadas {
2882351776eSYishai Hadas 	return ((u64)opcode << 32) | obj_id;
2892351776eSYishai Hadas }
2902351776eSYishai Hadas 
291*1368ead0SYishai Hadas static u32 devx_get_created_obj_id(const void *in, const void *out, u16 opcode)
292*1368ead0SYishai Hadas {
293*1368ead0SYishai Hadas 	switch (opcode) {
294*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
295*1368ead0SYishai Hadas 		return MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
296*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_UMEM:
297*1368ead0SYishai Hadas 		return MLX5_GET(create_umem_out, out, umem_id);
298*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_MKEY:
299*1368ead0SYishai Hadas 		return MLX5_GET(create_mkey_out, out, mkey_index);
300*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_CQ:
301*1368ead0SYishai Hadas 		return MLX5_GET(create_cq_out, out, cqn);
302*1368ead0SYishai Hadas 	case MLX5_CMD_OP_ALLOC_PD:
303*1368ead0SYishai Hadas 		return MLX5_GET(alloc_pd_out, out, pd);
304*1368ead0SYishai Hadas 	case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
305*1368ead0SYishai Hadas 		return MLX5_GET(alloc_transport_domain_out, out,
306*1368ead0SYishai Hadas 				transport_domain);
307*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_RMP:
308*1368ead0SYishai Hadas 		return MLX5_GET(create_rmp_out, out, rmpn);
309*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
310*1368ead0SYishai Hadas 		return MLX5_GET(create_sq_out, out, sqn);
311*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
312*1368ead0SYishai Hadas 		return MLX5_GET(create_rq_out, out, rqn);
313*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQT:
314*1368ead0SYishai Hadas 		return MLX5_GET(create_rqt_out, out, rqtn);
315*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIR:
316*1368ead0SYishai Hadas 		return MLX5_GET(create_tir_out, out, tirn);
317*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIS:
318*1368ead0SYishai Hadas 		return MLX5_GET(create_tis_out, out, tisn);
319*1368ead0SYishai Hadas 	case MLX5_CMD_OP_ALLOC_Q_COUNTER:
320*1368ead0SYishai Hadas 		return MLX5_GET(alloc_q_counter_out, out, counter_set_id);
321*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_TABLE:
322*1368ead0SYishai Hadas 		return MLX5_GET(create_flow_table_out, out, table_id);
323*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_GROUP:
324*1368ead0SYishai Hadas 		return MLX5_GET(create_flow_group_out, out, group_id);
325*1368ead0SYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
326*1368ead0SYishai Hadas 		return MLX5_GET(set_fte_in, in, flow_index);
327*1368ead0SYishai Hadas 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
328*1368ead0SYishai Hadas 		return MLX5_GET(alloc_flow_counter_out, out, flow_counter_id);
329*1368ead0SYishai Hadas 	case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT:
330*1368ead0SYishai Hadas 		return MLX5_GET(alloc_packet_reformat_context_out, out,
331*1368ead0SYishai Hadas 				packet_reformat_id);
332*1368ead0SYishai Hadas 	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
333*1368ead0SYishai Hadas 		return MLX5_GET(alloc_modify_header_context_out, out,
334*1368ead0SYishai Hadas 				modify_header_id);
335*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
336*1368ead0SYishai Hadas 		return MLX5_GET(create_scheduling_element_out, out,
337*1368ead0SYishai Hadas 				scheduling_element_id);
338*1368ead0SYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
339*1368ead0SYishai Hadas 		return MLX5_GET(add_vxlan_udp_dport_in, in, vxlan_udp_port);
340*1368ead0SYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
341*1368ead0SYishai Hadas 		return MLX5_GET(set_l2_table_entry_in, in, table_index);
342*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
343*1368ead0SYishai Hadas 		return MLX5_GET(create_qp_out, out, qpn);
344*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_SRQ:
345*1368ead0SYishai Hadas 		return MLX5_GET(create_srq_out, out, srqn);
346*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
347*1368ead0SYishai Hadas 		return MLX5_GET(create_xrc_srq_out, out, xrc_srqn);
348*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_DCT:
349*1368ead0SYishai Hadas 		return MLX5_GET(create_dct_out, out, dctn);
350*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRQ:
351*1368ead0SYishai Hadas 		return MLX5_GET(create_xrq_out, out, xrqn);
352*1368ead0SYishai Hadas 	case MLX5_CMD_OP_ATTACH_TO_MCG:
353*1368ead0SYishai Hadas 		return MLX5_GET(attach_to_mcg_in, in, qpn);
354*1368ead0SYishai Hadas 	case MLX5_CMD_OP_ALLOC_XRCD:
355*1368ead0SYishai Hadas 		return MLX5_GET(alloc_xrcd_out, out, xrcd);
356*1368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_PSV:
357*1368ead0SYishai Hadas 		return MLX5_GET(create_psv_out, out, psv0_index);
358*1368ead0SYishai Hadas 	default:
359*1368ead0SYishai Hadas 		/* The entry must match to one of the devx_is_obj_create_cmd */
360*1368ead0SYishai Hadas 		WARN_ON(true);
361*1368ead0SYishai Hadas 		return 0;
362*1368ead0SYishai Hadas 	}
363*1368ead0SYishai Hadas }
364*1368ead0SYishai Hadas 
36534613eb1SYishai Hadas static u64 devx_get_obj_id(const void *in)
366e662e14dSYishai Hadas {
367e662e14dSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
3682351776eSYishai Hadas 	u64 obj_id;
369e662e14dSYishai Hadas 
370e662e14dSYishai Hadas 	switch (opcode) {
371e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
372e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
373cd5d20f1SYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_GENERAL_OBJECT |
374cd5d20f1SYishai Hadas 					MLX5_GET(general_obj_in_cmd_hdr, in,
375cd5d20f1SYishai Hadas 						 obj_type) << 16,
3762351776eSYishai Hadas 					MLX5_GET(general_obj_in_cmd_hdr, in,
3772351776eSYishai Hadas 						 obj_id));
378e662e14dSYishai Hadas 		break;
379e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_MKEY:
3802351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_MKEY,
3812351776eSYishai Hadas 					MLX5_GET(query_mkey_in, in,
3822351776eSYishai Hadas 						 mkey_index));
383e662e14dSYishai Hadas 		break;
384e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_CQ:
3852351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ,
3862351776eSYishai Hadas 					MLX5_GET(query_cq_in, in, cqn));
387e662e14dSYishai Hadas 		break;
388e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_CQ:
3892351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ,
3902351776eSYishai Hadas 					MLX5_GET(modify_cq_in, in, cqn));
391e662e14dSYishai Hadas 		break;
392e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SQ:
3932351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ,
3942351776eSYishai Hadas 					MLX5_GET(query_sq_in, in, sqn));
395e662e14dSYishai Hadas 		break;
396e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_SQ:
3972351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ,
3982351776eSYishai Hadas 					MLX5_GET(modify_sq_in, in, sqn));
399e662e14dSYishai Hadas 		break;
400e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RQ:
4012351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
4022351776eSYishai Hadas 					MLX5_GET(query_rq_in, in, rqn));
403e662e14dSYishai Hadas 		break;
404e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RQ:
4052351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
4062351776eSYishai Hadas 					MLX5_GET(modify_rq_in, in, rqn));
407e662e14dSYishai Hadas 		break;
408e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RMP:
4092351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RMP,
4102351776eSYishai Hadas 					MLX5_GET(query_rmp_in, in, rmpn));
411e662e14dSYishai Hadas 		break;
412e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RMP:
4132351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RMP,
4142351776eSYishai Hadas 					MLX5_GET(modify_rmp_in, in, rmpn));
415e662e14dSYishai Hadas 		break;
416e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RQT:
4172351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT,
4182351776eSYishai Hadas 					MLX5_GET(query_rqt_in, in, rqtn));
419e662e14dSYishai Hadas 		break;
420e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RQT:
4212351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT,
4222351776eSYishai Hadas 					MLX5_GET(modify_rqt_in, in, rqtn));
423e662e14dSYishai Hadas 		break;
424e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_TIR:
4252351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR,
4262351776eSYishai Hadas 					MLX5_GET(query_tir_in, in, tirn));
427e662e14dSYishai Hadas 		break;
428e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_TIR:
4292351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR,
4302351776eSYishai Hadas 					MLX5_GET(modify_tir_in, in, tirn));
431e662e14dSYishai Hadas 		break;
432e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_TIS:
4332351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS,
4342351776eSYishai Hadas 					MLX5_GET(query_tis_in, in, tisn));
435e662e14dSYishai Hadas 		break;
436e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_TIS:
4372351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS,
4382351776eSYishai Hadas 					MLX5_GET(modify_tis_in, in, tisn));
439e662e14dSYishai Hadas 		break;
440e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_TABLE:
4412351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_TABLE,
4422351776eSYishai Hadas 					MLX5_GET(query_flow_table_in, in,
4432351776eSYishai Hadas 						 table_id));
444e662e14dSYishai Hadas 		break;
445e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_FLOW_TABLE:
4462351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_TABLE,
4472351776eSYishai Hadas 					MLX5_GET(modify_flow_table_in, in,
4482351776eSYishai Hadas 						 table_id));
449e662e14dSYishai Hadas 		break;
450e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_GROUP:
4512351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_GROUP,
4522351776eSYishai Hadas 					MLX5_GET(query_flow_group_in, in,
4532351776eSYishai Hadas 						 group_id));
454e662e14dSYishai Hadas 		break;
455e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
4562351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY,
4572351776eSYishai Hadas 					MLX5_GET(query_fte_in, in,
4582351776eSYishai Hadas 						 flow_index));
459e662e14dSYishai Hadas 		break;
460e662e14dSYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
4612351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY,
4622351776eSYishai Hadas 					MLX5_GET(set_fte_in, in, flow_index));
463e662e14dSYishai Hadas 		break;
464e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_Q_COUNTER:
4652351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_Q_COUNTER,
4662351776eSYishai Hadas 					MLX5_GET(query_q_counter_in, in,
4672351776eSYishai Hadas 						 counter_set_id));
468e662e14dSYishai Hadas 		break;
469e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
4702351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_FLOW_COUNTER,
4712351776eSYishai Hadas 					MLX5_GET(query_flow_counter_in, in,
4722351776eSYishai Hadas 						 flow_counter_id));
473e662e14dSYishai Hadas 		break;
474e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT:
4752351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT,
476*1368ead0SYishai Hadas 					MLX5_GET(query_modify_header_context_in,
477*1368ead0SYishai Hadas 						 in, modify_header_id));
478e662e14dSYishai Hadas 		break;
479e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
4802351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT,
4812351776eSYishai Hadas 					MLX5_GET(query_scheduling_element_in,
4822351776eSYishai Hadas 						 in, scheduling_element_id));
483e662e14dSYishai Hadas 		break;
484e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
4852351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT,
4862351776eSYishai Hadas 					MLX5_GET(modify_scheduling_element_in,
4872351776eSYishai Hadas 						 in, scheduling_element_id));
488e662e14dSYishai Hadas 		break;
489e662e14dSYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
4902351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT,
4912351776eSYishai Hadas 					MLX5_GET(add_vxlan_udp_dport_in, in,
4922351776eSYishai Hadas 						 vxlan_udp_port));
493e662e14dSYishai Hadas 		break;
494e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
4952351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_L2_TABLE_ENTRY,
4962351776eSYishai Hadas 					MLX5_GET(query_l2_table_entry_in, in,
4972351776eSYishai Hadas 						 table_index));
498e662e14dSYishai Hadas 		break;
499e662e14dSYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
5002351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_L2_TABLE_ENTRY,
5012351776eSYishai Hadas 					MLX5_GET(set_l2_table_entry_in, in,
5022351776eSYishai Hadas 						 table_index));
503e662e14dSYishai Hadas 		break;
504e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_QP:
5052351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
5062351776eSYishai Hadas 					MLX5_GET(query_qp_in, in, qpn));
507e662e14dSYishai Hadas 		break;
508e662e14dSYishai Hadas 	case MLX5_CMD_OP_RST2INIT_QP:
5092351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
5102351776eSYishai Hadas 					MLX5_GET(rst2init_qp_in, in, qpn));
511e662e14dSYishai Hadas 		break;
512d246a306SMark Zhang 	case MLX5_CMD_OP_INIT2INIT_QP:
513d246a306SMark Zhang 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
514d246a306SMark Zhang 					MLX5_GET(init2init_qp_in, in, qpn));
515d246a306SMark Zhang 		break;
516e662e14dSYishai Hadas 	case MLX5_CMD_OP_INIT2RTR_QP:
5172351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
5182351776eSYishai Hadas 					MLX5_GET(init2rtr_qp_in, in, qpn));
519e662e14dSYishai Hadas 		break;
520e662e14dSYishai Hadas 	case MLX5_CMD_OP_RTR2RTS_QP:
5212351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
5222351776eSYishai Hadas 					MLX5_GET(rtr2rts_qp_in, in, qpn));
523e662e14dSYishai Hadas 		break;
524e662e14dSYishai Hadas 	case MLX5_CMD_OP_RTS2RTS_QP:
5252351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
5262351776eSYishai Hadas 					MLX5_GET(rts2rts_qp_in, in, qpn));
527e662e14dSYishai Hadas 		break;
528e662e14dSYishai Hadas 	case MLX5_CMD_OP_SQERR2RTS_QP:
5292351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
5302351776eSYishai Hadas 					MLX5_GET(sqerr2rts_qp_in, in, qpn));
531e662e14dSYishai Hadas 		break;
532e662e14dSYishai Hadas 	case MLX5_CMD_OP_2ERR_QP:
5332351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
5342351776eSYishai Hadas 					MLX5_GET(qp_2err_in, in, qpn));
535e662e14dSYishai Hadas 		break;
536e662e14dSYishai Hadas 	case MLX5_CMD_OP_2RST_QP:
5372351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
5382351776eSYishai Hadas 					MLX5_GET(qp_2rst_in, in, qpn));
539e662e14dSYishai Hadas 		break;
540e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_DCT:
5412351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT,
5422351776eSYishai Hadas 					MLX5_GET(query_dct_in, in, dctn));
543e662e14dSYishai Hadas 		break;
544e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ:
545719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY:
546719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS:
5472351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRQ,
5482351776eSYishai Hadas 					MLX5_GET(query_xrq_in, in, xrqn));
549e662e14dSYishai Hadas 		break;
550e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_XRC_SRQ:
5512351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRC_SRQ,
5522351776eSYishai Hadas 					MLX5_GET(query_xrc_srq_in, in,
5532351776eSYishai Hadas 						 xrc_srqn));
554e662e14dSYishai Hadas 		break;
555e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_XRC_SRQ:
5562351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRC_SRQ,
5572351776eSYishai Hadas 					MLX5_GET(arm_xrc_srq_in, in, xrc_srqn));
558e662e14dSYishai Hadas 		break;
559e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SRQ:
5602351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SRQ,
5612351776eSYishai Hadas 					MLX5_GET(query_srq_in, in, srqn));
562e662e14dSYishai Hadas 		break;
563e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_RQ:
5642351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
5652351776eSYishai Hadas 					MLX5_GET(arm_rq_in, in, srq_number));
566e662e14dSYishai Hadas 		break;
567e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
5682351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT,
5692351776eSYishai Hadas 					MLX5_GET(drain_dct_in, in, dctn));
570e662e14dSYishai Hadas 		break;
571e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_XRQ:
572719598c9SYishai Hadas 	case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY:
5738293a598SYishai Hadas 	case MLX5_CMD_OP_RELEASE_XRQ_ERROR:
5748293a598SYishai Hadas 	case MLX5_CMD_OP_MODIFY_XRQ:
5752351776eSYishai Hadas 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRQ,
5762351776eSYishai Hadas 					MLX5_GET(arm_xrq_in, in, xrqn));
577e662e14dSYishai Hadas 		break;
578719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT:
579719598c9SYishai Hadas 		obj_id = get_enc_obj_id
580719598c9SYishai Hadas 				(MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT,
581719598c9SYishai Hadas 				 MLX5_GET(query_packet_reformat_context_in,
582719598c9SYishai Hadas 					  in, packet_reformat_id));
583719598c9SYishai Hadas 		break;
584e662e14dSYishai Hadas 	default:
58534613eb1SYishai Hadas 		obj_id = 0;
586e662e14dSYishai Hadas 	}
587e662e14dSYishai Hadas 
58834613eb1SYishai Hadas 	return obj_id;
58934613eb1SYishai Hadas }
590e662e14dSYishai Hadas 
591e79c9c60SJason Gunthorpe static bool devx_is_valid_obj_id(struct uverbs_attr_bundle *attrs,
592e79c9c60SJason Gunthorpe 				 struct ib_uobject *uobj, const void *in)
59334613eb1SYishai Hadas {
594e79c9c60SJason Gunthorpe 	struct mlx5_ib_dev *dev = mlx5_udata_to_mdev(&attrs->driver_udata);
59534613eb1SYishai Hadas 	u64 obj_id = devx_get_obj_id(in);
59634613eb1SYishai Hadas 
59734613eb1SYishai Hadas 	if (!obj_id)
598e662e14dSYishai Hadas 		return false;
59934613eb1SYishai Hadas 
60034613eb1SYishai Hadas 	switch (uobj_get_object_id(uobj)) {
60134613eb1SYishai Hadas 	case UVERBS_OBJECT_CQ:
60234613eb1SYishai Hadas 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ,
60334613eb1SYishai Hadas 				      to_mcq(uobj->object)->mcq.cqn) ==
60434613eb1SYishai Hadas 				      obj_id;
60534613eb1SYishai Hadas 
60634613eb1SYishai Hadas 	case UVERBS_OBJECT_SRQ:
60734613eb1SYishai Hadas 	{
60834613eb1SYishai Hadas 		struct mlx5_core_srq *srq = &(to_msrq(uobj->object)->msrq);
60934613eb1SYishai Hadas 		u16 opcode;
61034613eb1SYishai Hadas 
61134613eb1SYishai Hadas 		switch (srq->common.res) {
61234613eb1SYishai Hadas 		case MLX5_RES_XSRQ:
61334613eb1SYishai Hadas 			opcode = MLX5_CMD_OP_CREATE_XRC_SRQ;
61434613eb1SYishai Hadas 			break;
61534613eb1SYishai Hadas 		case MLX5_RES_XRQ:
61634613eb1SYishai Hadas 			opcode = MLX5_CMD_OP_CREATE_XRQ;
61734613eb1SYishai Hadas 			break;
61834613eb1SYishai Hadas 		default:
61934613eb1SYishai Hadas 			if (!dev->mdev->issi)
62034613eb1SYishai Hadas 				opcode = MLX5_CMD_OP_CREATE_SRQ;
62134613eb1SYishai Hadas 			else
62234613eb1SYishai Hadas 				opcode = MLX5_CMD_OP_CREATE_RMP;
62334613eb1SYishai Hadas 		}
62434613eb1SYishai Hadas 
62534613eb1SYishai Hadas 		return get_enc_obj_id(opcode,
62634613eb1SYishai Hadas 				      to_msrq(uobj->object)->msrq.srqn) ==
62734613eb1SYishai Hadas 				      obj_id;
62834613eb1SYishai Hadas 	}
62934613eb1SYishai Hadas 
63034613eb1SYishai Hadas 	case UVERBS_OBJECT_QP:
63134613eb1SYishai Hadas 	{
63234613eb1SYishai Hadas 		struct mlx5_ib_qp *qp = to_mqp(uobj->object);
63334613eb1SYishai Hadas 		enum ib_qp_type	qp_type = qp->ibqp.qp_type;
63434613eb1SYishai Hadas 
63534613eb1SYishai Hadas 		if (qp_type == IB_QPT_RAW_PACKET ||
6362be08c30SLeon Romanovsky 		    (qp->flags & IB_QP_CREATE_SOURCE_QPN)) {
63734613eb1SYishai Hadas 			struct mlx5_ib_raw_packet_qp *raw_packet_qp =
63834613eb1SYishai Hadas 							 &qp->raw_packet_qp;
63934613eb1SYishai Hadas 			struct mlx5_ib_rq *rq = &raw_packet_qp->rq;
64034613eb1SYishai Hadas 			struct mlx5_ib_sq *sq = &raw_packet_qp->sq;
64134613eb1SYishai Hadas 
64234613eb1SYishai Hadas 			return (get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
64334613eb1SYishai Hadas 					       rq->base.mqp.qpn) == obj_id ||
64434613eb1SYishai Hadas 				get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ,
64534613eb1SYishai Hadas 					       sq->base.mqp.qpn) == obj_id ||
64634613eb1SYishai Hadas 				get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR,
64734613eb1SYishai Hadas 					       rq->tirn) == obj_id ||
64834613eb1SYishai Hadas 				get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS,
64934613eb1SYishai Hadas 					       sq->tisn) == obj_id);
65034613eb1SYishai Hadas 		}
65134613eb1SYishai Hadas 
65234613eb1SYishai Hadas 		if (qp_type == MLX5_IB_QPT_DCT)
65334613eb1SYishai Hadas 			return get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT,
65434613eb1SYishai Hadas 					      qp->dct.mdct.mqp.qpn) == obj_id;
65534613eb1SYishai Hadas 
65634613eb1SYishai Hadas 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
65734613eb1SYishai Hadas 				      qp->ibqp.qp_num) == obj_id;
65834613eb1SYishai Hadas 	}
65934613eb1SYishai Hadas 
66034613eb1SYishai Hadas 	case UVERBS_OBJECT_WQ:
66134613eb1SYishai Hadas 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
66234613eb1SYishai Hadas 				      to_mrwq(uobj->object)->core_qp.qpn) ==
66334613eb1SYishai Hadas 				      obj_id;
66434613eb1SYishai Hadas 
66534613eb1SYishai Hadas 	case UVERBS_OBJECT_RWQ_IND_TBL:
66634613eb1SYishai Hadas 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT,
66734613eb1SYishai Hadas 				      to_mrwq_ind_table(uobj->object)->rqtn) ==
66834613eb1SYishai Hadas 				      obj_id;
66934613eb1SYishai Hadas 
67034613eb1SYishai Hadas 	case MLX5_IB_OBJECT_DEVX_OBJ:
67134613eb1SYishai Hadas 		return ((struct devx_obj *)uobj->object)->obj_id == obj_id;
67234613eb1SYishai Hadas 
673e662e14dSYishai Hadas 	default:
674e662e14dSYishai Hadas 		return false;
675e662e14dSYishai Hadas 	}
676e662e14dSYishai Hadas }
677e662e14dSYishai Hadas 
678ba1a057dSYishai Hadas static void devx_set_umem_valid(const void *in)
679ba1a057dSYishai Hadas {
680ba1a057dSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
681ba1a057dSYishai Hadas 
682ba1a057dSYishai Hadas 	switch (opcode) {
683ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_MKEY:
684ba1a057dSYishai Hadas 		MLX5_SET(create_mkey_in, in, mkey_umem_valid, 1);
685ba1a057dSYishai Hadas 		break;
686ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_CQ:
687ba1a057dSYishai Hadas 	{
688ba1a057dSYishai Hadas 		void *cqc;
689ba1a057dSYishai Hadas 
690ba1a057dSYishai Hadas 		MLX5_SET(create_cq_in, in, cq_umem_valid, 1);
691ba1a057dSYishai Hadas 		cqc = MLX5_ADDR_OF(create_cq_in, in, cq_context);
692ba1a057dSYishai Hadas 		MLX5_SET(cqc, cqc, dbr_umem_valid, 1);
693ba1a057dSYishai Hadas 		break;
694ba1a057dSYishai Hadas 	}
695ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
696ba1a057dSYishai Hadas 	{
697ba1a057dSYishai Hadas 		void *qpc;
698ba1a057dSYishai Hadas 
699ba1a057dSYishai Hadas 		qpc = MLX5_ADDR_OF(create_qp_in, in, qpc);
700ba1a057dSYishai Hadas 		MLX5_SET(qpc, qpc, dbr_umem_valid, 1);
701ba1a057dSYishai Hadas 		MLX5_SET(create_qp_in, in, wq_umem_valid, 1);
702ba1a057dSYishai Hadas 		break;
703ba1a057dSYishai Hadas 	}
704ba1a057dSYishai Hadas 
705ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
706ba1a057dSYishai Hadas 	{
707ba1a057dSYishai Hadas 		void *rqc, *wq;
708ba1a057dSYishai Hadas 
709ba1a057dSYishai Hadas 		rqc = MLX5_ADDR_OF(create_rq_in, in, ctx);
710ba1a057dSYishai Hadas 		wq  = MLX5_ADDR_OF(rqc, rqc, wq);
711ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
712ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, wq_umem_valid, 1);
713ba1a057dSYishai Hadas 		break;
714ba1a057dSYishai Hadas 	}
715ba1a057dSYishai Hadas 
716ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
717ba1a057dSYishai Hadas 	{
718ba1a057dSYishai Hadas 		void *sqc, *wq;
719ba1a057dSYishai Hadas 
720ba1a057dSYishai Hadas 		sqc = MLX5_ADDR_OF(create_sq_in, in, ctx);
721ba1a057dSYishai Hadas 		wq = MLX5_ADDR_OF(sqc, sqc, wq);
722ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
723ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, wq_umem_valid, 1);
724ba1a057dSYishai Hadas 		break;
725ba1a057dSYishai Hadas 	}
726ba1a057dSYishai Hadas 
727ba1a057dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_CQ:
728ba1a057dSYishai Hadas 		MLX5_SET(modify_cq_in, in, cq_umem_valid, 1);
729ba1a057dSYishai Hadas 		break;
730ba1a057dSYishai Hadas 
731ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_RMP:
732ba1a057dSYishai Hadas 	{
733ba1a057dSYishai Hadas 		void *rmpc, *wq;
734ba1a057dSYishai Hadas 
735ba1a057dSYishai Hadas 		rmpc = MLX5_ADDR_OF(create_rmp_in, in, ctx);
736ba1a057dSYishai Hadas 		wq = MLX5_ADDR_OF(rmpc, rmpc, wq);
737ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
738ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, wq_umem_valid, 1);
739ba1a057dSYishai Hadas 		break;
740ba1a057dSYishai Hadas 	}
741ba1a057dSYishai Hadas 
742ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_XRQ:
743ba1a057dSYishai Hadas 	{
744ba1a057dSYishai Hadas 		void *xrqc, *wq;
745ba1a057dSYishai Hadas 
746ba1a057dSYishai Hadas 		xrqc = MLX5_ADDR_OF(create_xrq_in, in, xrq_context);
747ba1a057dSYishai Hadas 		wq = MLX5_ADDR_OF(xrqc, xrqc, wq);
748ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
749ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, wq_umem_valid, 1);
750ba1a057dSYishai Hadas 		break;
751ba1a057dSYishai Hadas 	}
752ba1a057dSYishai Hadas 
753ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
754ba1a057dSYishai Hadas 	{
755ba1a057dSYishai Hadas 		void *xrc_srqc;
756ba1a057dSYishai Hadas 
757ba1a057dSYishai Hadas 		MLX5_SET(create_xrc_srq_in, in, xrc_srq_umem_valid, 1);
758ba1a057dSYishai Hadas 		xrc_srqc = MLX5_ADDR_OF(create_xrc_srq_in, in,
759ba1a057dSYishai Hadas 					xrc_srq_context_entry);
760ba1a057dSYishai Hadas 		MLX5_SET(xrc_srqc, xrc_srqc, dbr_umem_valid, 1);
761ba1a057dSYishai Hadas 		break;
762ba1a057dSYishai Hadas 	}
763ba1a057dSYishai Hadas 
764ba1a057dSYishai Hadas 	default:
765ba1a057dSYishai Hadas 		return;
766ba1a057dSYishai Hadas 	}
767ba1a057dSYishai Hadas }
768ba1a057dSYishai Hadas 
7692351776eSYishai Hadas static bool devx_is_obj_create_cmd(const void *in, u16 *opcode)
7707efce369SYishai Hadas {
7712351776eSYishai Hadas 	*opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
7727efce369SYishai Hadas 
7732351776eSYishai Hadas 	switch (*opcode) {
7747efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
7757efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_MKEY:
7767efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_CQ:
7777efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_PD:
7787efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
7797efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RMP:
7807efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
7817efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
7827efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQT:
7837efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIR:
7847efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIS:
7857efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_Q_COUNTER:
7867efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_TABLE:
7877efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_GROUP:
7887efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
78960786f09SMark Bloch 	case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT:
7907efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
7917efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
7927efce369SYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
7937efce369SYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
7947efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
7957efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SRQ:
7967efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
7977efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_DCT:
7987efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRQ:
7997efce369SYishai Hadas 	case MLX5_CMD_OP_ATTACH_TO_MCG:
8007efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_XRCD:
8017efce369SYishai Hadas 		return true;
8027efce369SYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
8037efce369SYishai Hadas 	{
8047efce369SYishai Hadas 		u16 op_mod = MLX5_GET(set_fte_in, in, op_mod);
8057efce369SYishai Hadas 		if (op_mod == 0)
8067efce369SYishai Hadas 			return true;
8077efce369SYishai Hadas 		return false;
8087efce369SYishai Hadas 	}
8098b38c538SMax Gurtovoy 	case MLX5_CMD_OP_CREATE_PSV:
8108b38c538SMax Gurtovoy 	{
8118b38c538SMax Gurtovoy 		u8 num_psv = MLX5_GET(create_psv_in, in, num_psv);
8128b38c538SMax Gurtovoy 
8138b38c538SMax Gurtovoy 		if (num_psv == 1)
8148b38c538SMax Gurtovoy 			return true;
8158b38c538SMax Gurtovoy 		return false;
8168b38c538SMax Gurtovoy 	}
8177efce369SYishai Hadas 	default:
8187efce369SYishai Hadas 		return false;
8197efce369SYishai Hadas 	}
8207efce369SYishai Hadas }
8217efce369SYishai Hadas 
822e662e14dSYishai Hadas static bool devx_is_obj_modify_cmd(const void *in)
823e662e14dSYishai Hadas {
824e662e14dSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
825e662e14dSYishai Hadas 
826e662e14dSYishai Hadas 	switch (opcode) {
827e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
828e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_CQ:
829e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RMP:
830e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_SQ:
831e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RQ:
832e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RQT:
833e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_TIR:
834e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_TIS:
835e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_FLOW_TABLE:
836e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
837e662e14dSYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
838e662e14dSYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
839e662e14dSYishai Hadas 	case MLX5_CMD_OP_RST2INIT_QP:
840e662e14dSYishai Hadas 	case MLX5_CMD_OP_INIT2RTR_QP:
841819f7427SAharon Landau 	case MLX5_CMD_OP_INIT2INIT_QP:
842e662e14dSYishai Hadas 	case MLX5_CMD_OP_RTR2RTS_QP:
843e662e14dSYishai Hadas 	case MLX5_CMD_OP_RTS2RTS_QP:
844e662e14dSYishai Hadas 	case MLX5_CMD_OP_SQERR2RTS_QP:
845e662e14dSYishai Hadas 	case MLX5_CMD_OP_2ERR_QP:
846e662e14dSYishai Hadas 	case MLX5_CMD_OP_2RST_QP:
847e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_XRC_SRQ:
848e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_RQ:
849e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
850e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_XRQ:
851719598c9SYishai Hadas 	case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY:
8528293a598SYishai Hadas 	case MLX5_CMD_OP_RELEASE_XRQ_ERROR:
8538293a598SYishai Hadas 	case MLX5_CMD_OP_MODIFY_XRQ:
854e662e14dSYishai Hadas 		return true;
855e662e14dSYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
856e662e14dSYishai Hadas 	{
857e662e14dSYishai Hadas 		u16 op_mod = MLX5_GET(set_fte_in, in, op_mod);
858e662e14dSYishai Hadas 
859e662e14dSYishai Hadas 		if (op_mod == 1)
860e662e14dSYishai Hadas 			return true;
861e662e14dSYishai Hadas 		return false;
862e662e14dSYishai Hadas 	}
863e662e14dSYishai Hadas 	default:
864e662e14dSYishai Hadas 		return false;
865e662e14dSYishai Hadas 	}
866e662e14dSYishai Hadas }
867e662e14dSYishai Hadas 
868e662e14dSYishai Hadas static bool devx_is_obj_query_cmd(const void *in)
869e662e14dSYishai Hadas {
870e662e14dSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
871e662e14dSYishai Hadas 
872e662e14dSYishai Hadas 	switch (opcode) {
873e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
874e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_MKEY:
875e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_CQ:
876e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RMP:
877e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SQ:
878e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RQ:
879e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RQT:
880e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_TIR:
881e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_TIS:
882e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_Q_COUNTER:
883e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_TABLE:
884e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_GROUP:
885e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
886e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
887e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT:
888e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
889e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
890e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_QP:
891e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SRQ:
892e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_XRC_SRQ:
893e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_DCT:
894e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ:
895719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY:
896719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS:
897719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT:
898e662e14dSYishai Hadas 		return true;
899e662e14dSYishai Hadas 	default:
900e662e14dSYishai Hadas 		return false;
901e662e14dSYishai Hadas 	}
902e662e14dSYishai Hadas }
903e662e14dSYishai Hadas 
9047e1335a7SYishai Hadas static bool devx_is_whitelist_cmd(void *in)
9057e1335a7SYishai Hadas {
9067e1335a7SYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
9077e1335a7SYishai Hadas 
9087e1335a7SYishai Hadas 	switch (opcode) {
9097e1335a7SYishai Hadas 	case MLX5_CMD_OP_QUERY_HCA_CAP:
9107e1335a7SYishai Hadas 	case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT:
91156e5acd4SMaor Gottlieb 	case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT:
9127e1335a7SYishai Hadas 		return true;
9137e1335a7SYishai Hadas 	default:
9147e1335a7SYishai Hadas 		return false;
9157e1335a7SYishai Hadas 	}
9167e1335a7SYishai Hadas }
9177e1335a7SYishai Hadas 
9187e1335a7SYishai Hadas static int devx_get_uid(struct mlx5_ib_ucontext *c, void *cmd_in)
9197e1335a7SYishai Hadas {
9207e1335a7SYishai Hadas 	if (devx_is_whitelist_cmd(cmd_in)) {
9217e1335a7SYishai Hadas 		struct mlx5_ib_dev *dev;
9227e1335a7SYishai Hadas 
9237e1335a7SYishai Hadas 		if (c->devx_uid)
9247e1335a7SYishai Hadas 			return c->devx_uid;
9257e1335a7SYishai Hadas 
9267e1335a7SYishai Hadas 		dev = to_mdev(c->ibucontext.device);
9277e1335a7SYishai Hadas 		if (dev->devx_whitelist_uid)
9287e1335a7SYishai Hadas 			return dev->devx_whitelist_uid;
9297e1335a7SYishai Hadas 
9307e1335a7SYishai Hadas 		return -EOPNOTSUPP;
9317e1335a7SYishai Hadas 	}
9327e1335a7SYishai Hadas 
9337e1335a7SYishai Hadas 	if (!c->devx_uid)
9347e1335a7SYishai Hadas 		return -EINVAL;
9357e1335a7SYishai Hadas 
9367e1335a7SYishai Hadas 	return c->devx_uid;
9377e1335a7SYishai Hadas }
938b6142608SMax Gurtovoy 
939b6142608SMax Gurtovoy static bool devx_is_general_cmd(void *in, struct mlx5_ib_dev *dev)
9408aa8c95cSYishai Hadas {
9418aa8c95cSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
9428aa8c95cSYishai Hadas 
943b6142608SMax Gurtovoy 	/* Pass all cmds for vhca_tunnel as general, tracking is done in FW */
944b6142608SMax Gurtovoy 	if ((MLX5_CAP_GEN_64(dev->mdev, vhca_tunnel_commands) &&
945b6142608SMax Gurtovoy 	     MLX5_GET(general_obj_in_cmd_hdr, in, vhca_tunnel_id)) ||
946b6142608SMax Gurtovoy 	    (opcode >= MLX5_CMD_OP_GENERAL_START &&
947b6142608SMax Gurtovoy 	     opcode < MLX5_CMD_OP_GENERAL_END))
948719598c9SYishai Hadas 		return true;
949719598c9SYishai Hadas 
9508aa8c95cSYishai Hadas 	switch (opcode) {
9518aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_HCA_CAP:
9527e1335a7SYishai Hadas 	case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT:
95356e5acd4SMaor Gottlieb 	case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT:
9548aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_VPORT_STATE:
9558aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_ADAPTER:
9568aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_ISSI:
9578aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT:
9588aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_ROCE_ADDRESS:
9598aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_VNIC_ENV:
9608aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_VPORT_COUNTER:
9618aa8c95cSYishai Hadas 	case MLX5_CMD_OP_GET_DROPPED_PACKET_LOG:
9628aa8c95cSYishai Hadas 	case MLX5_CMD_OP_NOP:
9638aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_CONG_STATUS:
9648aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_CONG_PARAMS:
9658aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_CONG_STATISTICS:
9667084ed30SMark Zhang 	case MLX5_CMD_OP_QUERY_LAG:
9678aa8c95cSYishai Hadas 		return true;
9688aa8c95cSYishai Hadas 	default:
9698aa8c95cSYishai Hadas 		return false;
9708aa8c95cSYishai Hadas 	}
9718aa8c95cSYishai Hadas }
9728aa8c95cSYishai Hadas 
973e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_EQN)(
97415a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
975f6fe01b7SYishai Hadas {
976e83f0ecdSJason Gunthorpe 	struct mlx5_ib_ucontext *c;
977e83f0ecdSJason Gunthorpe 	struct mlx5_ib_dev *dev;
978f6fe01b7SYishai Hadas 	int user_vector;
979f6fe01b7SYishai Hadas 	int dev_eqn;
980f6fe01b7SYishai Hadas 	unsigned int irqn;
981f6fe01b7SYishai Hadas 	int err;
982f6fe01b7SYishai Hadas 
983f6fe01b7SYishai Hadas 	if (uverbs_copy_from(&user_vector, attrs,
984f6fe01b7SYishai Hadas 			     MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC))
985f6fe01b7SYishai Hadas 		return -EFAULT;
986f6fe01b7SYishai Hadas 
98715a1b4beSJason Gunthorpe 	c = devx_ufile2uctx(attrs);
988e83f0ecdSJason Gunthorpe 	if (IS_ERR(c))
989e83f0ecdSJason Gunthorpe 		return PTR_ERR(c);
990e83f0ecdSJason Gunthorpe 	dev = to_mdev(c->ibucontext.device);
991e83f0ecdSJason Gunthorpe 
992f6fe01b7SYishai Hadas 	err = mlx5_vector2eqn(dev->mdev, user_vector, &dev_eqn, &irqn);
993f6fe01b7SYishai Hadas 	if (err < 0)
994f6fe01b7SYishai Hadas 		return err;
995f6fe01b7SYishai Hadas 
996f6fe01b7SYishai Hadas 	if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN,
997f6fe01b7SYishai Hadas 			   &dev_eqn, sizeof(dev_eqn)))
998f6fe01b7SYishai Hadas 		return -EFAULT;
999f6fe01b7SYishai Hadas 
1000f6fe01b7SYishai Hadas 	return 0;
1001f6fe01b7SYishai Hadas }
1002f6fe01b7SYishai Hadas 
10037c043e90SYishai Hadas /*
10047c043e90SYishai Hadas  *Security note:
10057c043e90SYishai Hadas  * The hardware protection mechanism works like this: Each device object that
10067c043e90SYishai Hadas  * is subject to UAR doorbells (QP/SQ/CQ) gets a UAR ID (called uar_page in
10077c043e90SYishai Hadas  * the device specification manual) upon its creation. Then upon doorbell,
10087c043e90SYishai Hadas  * hardware fetches the object context for which the doorbell was rang, and
10097c043e90SYishai Hadas  * validates that the UAR through which the DB was rang matches the UAR ID
10107c043e90SYishai Hadas  * of the object.
10117c043e90SYishai Hadas  * If no match the doorbell is silently ignored by the hardware. Of course,
10127c043e90SYishai Hadas  * the user cannot ring a doorbell on a UAR that was not mapped to it.
10137c043e90SYishai Hadas  * Now in devx, as the devx kernel does not manipulate the QP/SQ/CQ command
10147c043e90SYishai Hadas  * mailboxes (except tagging them with UID), we expose to the user its UAR
10157c043e90SYishai Hadas  * ID, so it can embed it in these objects in the expected specification
10167c043e90SYishai Hadas  * format. So the only thing the user can do is hurt itself by creating a
10177c043e90SYishai Hadas  * QP/SQ/CQ with a UAR ID other than his, and then in this case other users
10187c043e90SYishai Hadas  * may ring a doorbell on its objects.
10197c043e90SYishai Hadas  * The consequence of that will be that another user can schedule a QP/SQ
10207c043e90SYishai Hadas  * of the buggy user for execution (just insert it to the hardware schedule
10217c043e90SYishai Hadas  * queue or arm its CQ for event generation), no further harm is expected.
10227c043e90SYishai Hadas  */
1023e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_UAR)(
102415a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
10257c043e90SYishai Hadas {
102622fa27fbSJason Gunthorpe 	struct mlx5_ib_ucontext *c;
102722fa27fbSJason Gunthorpe 	struct mlx5_ib_dev *dev;
10287c043e90SYishai Hadas 	u32 user_idx;
10297c043e90SYishai Hadas 	s32 dev_idx;
10307c043e90SYishai Hadas 
103115a1b4beSJason Gunthorpe 	c = devx_ufile2uctx(attrs);
103222fa27fbSJason Gunthorpe 	if (IS_ERR(c))
103322fa27fbSJason Gunthorpe 		return PTR_ERR(c);
103422fa27fbSJason Gunthorpe 	dev = to_mdev(c->ibucontext.device);
103522fa27fbSJason Gunthorpe 
10367c043e90SYishai Hadas 	if (uverbs_copy_from(&user_idx, attrs,
10377c043e90SYishai Hadas 			     MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX))
10387c043e90SYishai Hadas 		return -EFAULT;
10397c043e90SYishai Hadas 
104022fa27fbSJason Gunthorpe 	dev_idx = bfregn_to_uar_index(dev, &c->bfregi, user_idx, true);
10417c043e90SYishai Hadas 	if (dev_idx < 0)
10427c043e90SYishai Hadas 		return dev_idx;
10437c043e90SYishai Hadas 
10447c043e90SYishai Hadas 	if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX,
10457c043e90SYishai Hadas 			   &dev_idx, sizeof(dev_idx)))
10467c043e90SYishai Hadas 		return -EFAULT;
10477c043e90SYishai Hadas 
10487c043e90SYishai Hadas 	return 0;
10497c043e90SYishai Hadas }
10507c043e90SYishai Hadas 
1051e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)(
105215a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
10538aa8c95cSYishai Hadas {
105422fa27fbSJason Gunthorpe 	struct mlx5_ib_ucontext *c;
105522fa27fbSJason Gunthorpe 	struct mlx5_ib_dev *dev;
10567efce369SYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(
10577efce369SYishai Hadas 		attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN);
10588aa8c95cSYishai Hadas 	int cmd_out_len = uverbs_attr_get_len(attrs,
10598aa8c95cSYishai Hadas 					MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT);
10608aa8c95cSYishai Hadas 	void *cmd_out;
10618aa8c95cSYishai Hadas 	int err;
10627e1335a7SYishai Hadas 	int uid;
10638aa8c95cSYishai Hadas 
106415a1b4beSJason Gunthorpe 	c = devx_ufile2uctx(attrs);
106522fa27fbSJason Gunthorpe 	if (IS_ERR(c))
106622fa27fbSJason Gunthorpe 		return PTR_ERR(c);
106722fa27fbSJason Gunthorpe 	dev = to_mdev(c->ibucontext.device);
106822fa27fbSJason Gunthorpe 
10697e1335a7SYishai Hadas 	uid = devx_get_uid(c, cmd_in);
10707e1335a7SYishai Hadas 	if (uid < 0)
10717e1335a7SYishai Hadas 		return uid;
10728aa8c95cSYishai Hadas 
10738aa8c95cSYishai Hadas 	/* Only white list of some general HCA commands are allowed for this method. */
1074b6142608SMax Gurtovoy 	if (!devx_is_general_cmd(cmd_in, dev))
10758aa8c95cSYishai Hadas 		return -EINVAL;
10768aa8c95cSYishai Hadas 
1077b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
1078b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
1079b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
10808aa8c95cSYishai Hadas 
10817e1335a7SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
10828aa8c95cSYishai Hadas 	err = mlx5_cmd_exec(dev->mdev, cmd_in,
10838aa8c95cSYishai Hadas 			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN),
10848aa8c95cSYishai Hadas 			    cmd_out, cmd_out_len);
10858aa8c95cSYishai Hadas 	if (err)
10868aa8c95cSYishai Hadas 		return err;
1087b61815e2SJason Gunthorpe 
1088b61815e2SJason Gunthorpe 	return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, cmd_out,
1089b61815e2SJason Gunthorpe 			      cmd_out_len);
10908aa8c95cSYishai Hadas }
10918aa8c95cSYishai Hadas 
10927efce369SYishai Hadas static void devx_obj_build_destroy_cmd(void *in, void *out, void *din,
10937efce369SYishai Hadas 				       u32 *dinlen,
10947efce369SYishai Hadas 				       u32 *obj_id)
10957efce369SYishai Hadas {
1096*1368ead0SYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
10977efce369SYishai Hadas 	u16 uid = MLX5_GET(general_obj_in_cmd_hdr, in, uid);
10987efce369SYishai Hadas 
1099*1368ead0SYishai Hadas 	*obj_id = devx_get_created_obj_id(in, out, opcode);
11007efce369SYishai Hadas 	*dinlen = MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr);
11017efce369SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, din, uid, uid);
11027efce369SYishai Hadas 
1103*1368ead0SYishai Hadas 	switch (opcode) {
11047efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
11057efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
1106*1368ead0SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, obj_id, *obj_id);
1107*1368ead0SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, obj_type,
1108*1368ead0SYishai Hadas 			 MLX5_GET(general_obj_in_cmd_hdr, in, obj_type));
11097efce369SYishai Hadas 		break;
11107efce369SYishai Hadas 
11116e3722baSYishai Hadas 	case MLX5_CMD_OP_CREATE_UMEM:
1112*1368ead0SYishai Hadas 		MLX5_SET(destroy_umem_in, din, opcode,
11136e3722baSYishai Hadas 			 MLX5_CMD_OP_DESTROY_UMEM);
1114*1368ead0SYishai Hadas 		MLX5_SET(destroy_umem_in, din, umem_id, *obj_id);
11156e3722baSYishai Hadas 		break;
11167efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_MKEY:
1117*1368ead0SYishai Hadas 		MLX5_SET(destroy_mkey_in, din, opcode,
1118*1368ead0SYishai Hadas 			 MLX5_CMD_OP_DESTROY_MKEY);
1119*1368ead0SYishai Hadas 		MLX5_SET(destroy_mkey_in, in, mkey_index, *obj_id);
11207efce369SYishai Hadas 		break;
11217efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_CQ:
1122*1368ead0SYishai Hadas 		MLX5_SET(destroy_cq_in, din, opcode, MLX5_CMD_OP_DESTROY_CQ);
1123*1368ead0SYishai Hadas 		MLX5_SET(destroy_cq_in, din, cqn, *obj_id);
11247efce369SYishai Hadas 		break;
11257efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_PD:
1126*1368ead0SYishai Hadas 		MLX5_SET(dealloc_pd_in, din, opcode, MLX5_CMD_OP_DEALLOC_PD);
1127*1368ead0SYishai Hadas 		MLX5_SET(dealloc_pd_in, din, pd, *obj_id);
11287efce369SYishai Hadas 		break;
11297efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
1130*1368ead0SYishai Hadas 		MLX5_SET(dealloc_transport_domain_in, din, opcode,
11317efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN);
1132*1368ead0SYishai Hadas 		MLX5_SET(dealloc_transport_domain_in, din, transport_domain,
1133*1368ead0SYishai Hadas 			 *obj_id);
11347efce369SYishai Hadas 		break;
11357efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RMP:
1136*1368ead0SYishai Hadas 		MLX5_SET(destroy_rmp_in, din, opcode, MLX5_CMD_OP_DESTROY_RMP);
1137*1368ead0SYishai Hadas 		MLX5_SET(destroy_rmp_in, din, rmpn, *obj_id);
11387efce369SYishai Hadas 		break;
11397efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
1140*1368ead0SYishai Hadas 		MLX5_SET(destroy_sq_in, din, opcode, MLX5_CMD_OP_DESTROY_SQ);
1141*1368ead0SYishai Hadas 		MLX5_SET(destroy_sq_in, din, sqn, *obj_id);
11427efce369SYishai Hadas 		break;
11437efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
1144*1368ead0SYishai Hadas 		MLX5_SET(destroy_rq_in, din, opcode, MLX5_CMD_OP_DESTROY_RQ);
1145*1368ead0SYishai Hadas 		MLX5_SET(destroy_rq_in, din, rqn, *obj_id);
11467efce369SYishai Hadas 		break;
11477efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQT:
1148*1368ead0SYishai Hadas 		MLX5_SET(destroy_rqt_in, din, opcode, MLX5_CMD_OP_DESTROY_RQT);
1149*1368ead0SYishai Hadas 		MLX5_SET(destroy_rqt_in, din, rqtn, *obj_id);
11507efce369SYishai Hadas 		break;
11517efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIR:
11528798e4adSYishai Hadas 		MLX5_SET(destroy_tir_in, din, opcode, MLX5_CMD_OP_DESTROY_TIR);
11538798e4adSYishai Hadas 		MLX5_SET(destroy_tir_in, din, tirn, *obj_id);
11547efce369SYishai Hadas 		break;
11557efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIS:
1156*1368ead0SYishai Hadas 		MLX5_SET(destroy_tis_in, din, opcode, MLX5_CMD_OP_DESTROY_TIS);
1157*1368ead0SYishai Hadas 		MLX5_SET(destroy_tis_in, din, tisn, *obj_id);
11587efce369SYishai Hadas 		break;
11597efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_Q_COUNTER:
1160*1368ead0SYishai Hadas 		MLX5_SET(dealloc_q_counter_in, din, opcode,
11617efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_Q_COUNTER);
1162*1368ead0SYishai Hadas 		MLX5_SET(dealloc_q_counter_in, din, counter_set_id, *obj_id);
11637efce369SYishai Hadas 		break;
11647efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_TABLE:
11657efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(destroy_flow_table_in);
11667efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, other_vport,
11677efce369SYishai Hadas 			 MLX5_GET(create_flow_table_in,  in, other_vport));
11687efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, vport_number,
11697efce369SYishai Hadas 			 MLX5_GET(create_flow_table_in,  in, vport_number));
11707efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, table_type,
11717efce369SYishai Hadas 			 MLX5_GET(create_flow_table_in,  in, table_type));
11727efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, table_id, *obj_id);
1173*1368ead0SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, opcode,
11747efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_FLOW_TABLE);
11757efce369SYishai Hadas 		break;
11767efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_GROUP:
11777efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(destroy_flow_group_in);
11787efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, other_vport,
11797efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, other_vport));
11807efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, vport_number,
11817efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, vport_number));
11827efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, table_type,
11837efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, table_type));
11847efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, table_id,
11857efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, table_id));
11867efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, group_id, *obj_id);
1187*1368ead0SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, opcode,
11887efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_FLOW_GROUP);
11897efce369SYishai Hadas 		break;
11907efce369SYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
11917efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(delete_fte_in);
11927efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, other_vport,
11937efce369SYishai Hadas 			 MLX5_GET(set_fte_in,  in, other_vport));
11947efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, vport_number,
11957efce369SYishai Hadas 			 MLX5_GET(set_fte_in, in, vport_number));
11967efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, table_type,
11977efce369SYishai Hadas 			 MLX5_GET(set_fte_in, in, table_type));
11987efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, table_id,
11997efce369SYishai Hadas 			 MLX5_GET(set_fte_in, in, table_id));
12007efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, flow_index, *obj_id);
1201*1368ead0SYishai Hadas 		MLX5_SET(delete_fte_in, din, opcode,
12027efce369SYishai Hadas 			 MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
12037efce369SYishai Hadas 		break;
12047efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
1205*1368ead0SYishai Hadas 		MLX5_SET(dealloc_flow_counter_in, din, opcode,
12067efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_FLOW_COUNTER);
1207*1368ead0SYishai Hadas 		MLX5_SET(dealloc_flow_counter_in, din, flow_counter_id,
1208*1368ead0SYishai Hadas 			 *obj_id);
12097efce369SYishai Hadas 		break;
121060786f09SMark Bloch 	case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT:
1211*1368ead0SYishai Hadas 		MLX5_SET(dealloc_packet_reformat_context_in, din, opcode,
121260786f09SMark Bloch 			 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
1213*1368ead0SYishai Hadas 		MLX5_SET(dealloc_packet_reformat_context_in, din,
1214*1368ead0SYishai Hadas 			 packet_reformat_id, *obj_id);
12157efce369SYishai Hadas 		break;
12167efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
1217*1368ead0SYishai Hadas 		MLX5_SET(dealloc_modify_header_context_in, din, opcode,
12187efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT);
1219*1368ead0SYishai Hadas 		MLX5_SET(dealloc_modify_header_context_in, din,
1220*1368ead0SYishai Hadas 			 modify_header_id, *obj_id);
12217efce369SYishai Hadas 		break;
12227efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
12237efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(destroy_scheduling_element_in);
12247efce369SYishai Hadas 		MLX5_SET(destroy_scheduling_element_in, din,
12257efce369SYishai Hadas 			 scheduling_hierarchy,
12267efce369SYishai Hadas 			 MLX5_GET(create_scheduling_element_in, in,
12277efce369SYishai Hadas 				  scheduling_hierarchy));
12287efce369SYishai Hadas 		MLX5_SET(destroy_scheduling_element_in, din,
12297efce369SYishai Hadas 			 scheduling_element_id, *obj_id);
1230*1368ead0SYishai Hadas 		MLX5_SET(destroy_scheduling_element_in, din, opcode,
12317efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT);
12327efce369SYishai Hadas 		break;
12337efce369SYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
12347efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(delete_vxlan_udp_dport_in);
12357efce369SYishai Hadas 		MLX5_SET(delete_vxlan_udp_dport_in, din, vxlan_udp_port, *obj_id);
1236*1368ead0SYishai Hadas 		MLX5_SET(delete_vxlan_udp_dport_in, din, opcode,
12377efce369SYishai Hadas 			 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
12387efce369SYishai Hadas 		break;
12397efce369SYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
12407efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(delete_l2_table_entry_in);
12417efce369SYishai Hadas 		MLX5_SET(delete_l2_table_entry_in, din, table_index, *obj_id);
1242*1368ead0SYishai Hadas 		MLX5_SET(delete_l2_table_entry_in, din, opcode,
12437efce369SYishai Hadas 			 MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY);
12447efce369SYishai Hadas 		break;
12457efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
1246*1368ead0SYishai Hadas 		MLX5_SET(destroy_qp_in, din, opcode, MLX5_CMD_OP_DESTROY_QP);
1247*1368ead0SYishai Hadas 		MLX5_SET(destroy_qp_in, din, qpn, *obj_id);
12487efce369SYishai Hadas 		break;
12497efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SRQ:
1250*1368ead0SYishai Hadas 		MLX5_SET(destroy_srq_in, din, opcode, MLX5_CMD_OP_DESTROY_SRQ);
1251*1368ead0SYishai Hadas 		MLX5_SET(destroy_srq_in, din, srqn, *obj_id);
12527efce369SYishai Hadas 		break;
12537efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
1254*1368ead0SYishai Hadas 		MLX5_SET(destroy_xrc_srq_in, din, opcode,
12557efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_XRC_SRQ);
1256*1368ead0SYishai Hadas 		MLX5_SET(destroy_xrc_srq_in, din, xrc_srqn, *obj_id);
12577efce369SYishai Hadas 		break;
12587efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_DCT:
1259*1368ead0SYishai Hadas 		MLX5_SET(destroy_dct_in, din, opcode, MLX5_CMD_OP_DESTROY_DCT);
1260*1368ead0SYishai Hadas 		MLX5_SET(destroy_dct_in, din, dctn, *obj_id);
12617efce369SYishai Hadas 		break;
12627efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRQ:
1263*1368ead0SYishai Hadas 		MLX5_SET(destroy_xrq_in, din, opcode, MLX5_CMD_OP_DESTROY_XRQ);
1264*1368ead0SYishai Hadas 		MLX5_SET(destroy_xrq_in, din, xrqn, *obj_id);
12657efce369SYishai Hadas 		break;
12667efce369SYishai Hadas 	case MLX5_CMD_OP_ATTACH_TO_MCG:
12677efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(detach_from_mcg_in);
12687efce369SYishai Hadas 		MLX5_SET(detach_from_mcg_in, din, qpn,
12697efce369SYishai Hadas 			 MLX5_GET(attach_to_mcg_in, in, qpn));
12707efce369SYishai Hadas 		memcpy(MLX5_ADDR_OF(detach_from_mcg_in, din, multicast_gid),
12717efce369SYishai Hadas 		       MLX5_ADDR_OF(attach_to_mcg_in, in, multicast_gid),
12727efce369SYishai Hadas 		       MLX5_FLD_SZ_BYTES(attach_to_mcg_in, multicast_gid));
1273*1368ead0SYishai Hadas 		MLX5_SET(detach_from_mcg_in, din, opcode,
1274*1368ead0SYishai Hadas 			 MLX5_CMD_OP_DETACH_FROM_MCG);
1275*1368ead0SYishai Hadas 		MLX5_SET(detach_from_mcg_in, din, qpn, *obj_id);
12767efce369SYishai Hadas 		break;
12777efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_XRCD:
1278*1368ead0SYishai Hadas 		MLX5_SET(dealloc_xrcd_in, din, opcode,
1279*1368ead0SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_XRCD);
1280*1368ead0SYishai Hadas 		MLX5_SET(dealloc_xrcd_in, din, xrcd, *obj_id);
12817efce369SYishai Hadas 		break;
12828b38c538SMax Gurtovoy 	case MLX5_CMD_OP_CREATE_PSV:
1283*1368ead0SYishai Hadas 		MLX5_SET(destroy_psv_in, din, opcode,
12848b38c538SMax Gurtovoy 			 MLX5_CMD_OP_DESTROY_PSV);
1285*1368ead0SYishai Hadas 		MLX5_SET(destroy_psv_in, din, psvn, *obj_id);
12868b38c538SMax Gurtovoy 		break;
12877efce369SYishai Hadas 	default:
12887efce369SYishai Hadas 		/* The entry must match to one of the devx_is_obj_create_cmd */
12897efce369SYishai Hadas 		WARN_ON(true);
12907efce369SYishai Hadas 		break;
12917efce369SYishai Hadas 	}
12927efce369SYishai Hadas }
12937efce369SYishai Hadas 
1294534fd7aaSYishai Hadas static int devx_handle_mkey_indirect(struct devx_obj *obj,
1295534fd7aaSYishai Hadas 				     struct mlx5_ib_dev *dev,
1296534fd7aaSYishai Hadas 				     void *in, void *out)
1297534fd7aaSYishai Hadas {
1298534fd7aaSYishai Hadas 	struct mlx5_ib_devx_mr *devx_mr = &obj->devx_mr;
1299534fd7aaSYishai Hadas 	struct mlx5_core_mkey *mkey;
1300534fd7aaSYishai Hadas 	void *mkc;
1301534fd7aaSYishai Hadas 	u8 key;
1302534fd7aaSYishai Hadas 
1303534fd7aaSYishai Hadas 	mkey = &devx_mr->mmkey;
1304534fd7aaSYishai Hadas 	mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
1305534fd7aaSYishai Hadas 	key = MLX5_GET(mkc, mkc, mkey_7_0);
1306534fd7aaSYishai Hadas 	mkey->key = mlx5_idx_to_mkey(
1307534fd7aaSYishai Hadas 			MLX5_GET(create_mkey_out, out, mkey_index)) | key;
1308534fd7aaSYishai Hadas 	mkey->type = MLX5_MKEY_INDIRECT_DEVX;
1309534fd7aaSYishai Hadas 	mkey->iova = MLX5_GET64(mkc, mkc, start_addr);
1310534fd7aaSYishai Hadas 	mkey->size = MLX5_GET64(mkc, mkc, len);
1311534fd7aaSYishai Hadas 	mkey->pd = MLX5_GET(mkc, mkc, pd);
1312534fd7aaSYishai Hadas 	devx_mr->ndescs = MLX5_GET(mkc, mkc, translations_octword_size);
1313534fd7aaSYishai Hadas 
1314806b101bSJason Gunthorpe 	return xa_err(xa_store(&dev->odp_mkeys, mlx5_base_mkey(mkey->key), mkey,
1315806b101bSJason Gunthorpe 			       GFP_KERNEL));
1316534fd7aaSYishai Hadas }
1317534fd7aaSYishai Hadas 
1318fa31f143SYishai Hadas static int devx_handle_mkey_create(struct mlx5_ib_dev *dev,
1319fa31f143SYishai Hadas 				   struct devx_obj *obj,
1320fa31f143SYishai Hadas 				   void *in, int in_len)
1321fa31f143SYishai Hadas {
1322fa31f143SYishai Hadas 	int min_len = MLX5_BYTE_OFF(create_mkey_in, memory_key_mkey_entry) +
1323fa31f143SYishai Hadas 			MLX5_FLD_SZ_BYTES(create_mkey_in,
1324fa31f143SYishai Hadas 			memory_key_mkey_entry);
1325fa31f143SYishai Hadas 	void *mkc;
1326fa31f143SYishai Hadas 	u8 access_mode;
1327fa31f143SYishai Hadas 
1328fa31f143SYishai Hadas 	if (in_len < min_len)
1329fa31f143SYishai Hadas 		return -EINVAL;
1330fa31f143SYishai Hadas 
1331fa31f143SYishai Hadas 	mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
1332fa31f143SYishai Hadas 
1333fa31f143SYishai Hadas 	access_mode = MLX5_GET(mkc, mkc, access_mode_1_0);
1334fa31f143SYishai Hadas 	access_mode |= MLX5_GET(mkc, mkc, access_mode_4_2) << 2;
1335fa31f143SYishai Hadas 
1336fa31f143SYishai Hadas 	if (access_mode == MLX5_MKC_ACCESS_MODE_KLMS ||
1337534fd7aaSYishai Hadas 		access_mode == MLX5_MKC_ACCESS_MODE_KSM) {
1338534fd7aaSYishai Hadas 		if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING))
1339534fd7aaSYishai Hadas 			obj->flags |= DEVX_OBJ_FLAGS_INDIRECT_MKEY;
1340fa31f143SYishai Hadas 		return 0;
1341534fd7aaSYishai Hadas 	}
1342fa31f143SYishai Hadas 
1343fa31f143SYishai Hadas 	MLX5_SET(create_mkey_in, in, mkey_umem_valid, 1);
1344fa31f143SYishai Hadas 	return 0;
1345fa31f143SYishai Hadas }
1346fa31f143SYishai Hadas 
134775973853SYishai Hadas static void devx_cleanup_subscription(struct mlx5_ib_dev *dev,
134875973853SYishai Hadas 				      struct devx_event_subscription *sub)
134975973853SYishai Hadas {
135075973853SYishai Hadas 	struct devx_event *event;
135175973853SYishai Hadas 	struct devx_obj_event *xa_val_level2;
135275973853SYishai Hadas 
135375973853SYishai Hadas 	if (sub->is_cleaned)
135475973853SYishai Hadas 		return;
135575973853SYishai Hadas 
135675973853SYishai Hadas 	sub->is_cleaned = 1;
135775973853SYishai Hadas 	list_del_rcu(&sub->xa_list);
135875973853SYishai Hadas 
135975973853SYishai Hadas 	if (list_empty(&sub->obj_list))
136075973853SYishai Hadas 		return;
136175973853SYishai Hadas 
136275973853SYishai Hadas 	list_del_rcu(&sub->obj_list);
136375973853SYishai Hadas 	/* check whether key level 1 for this obj_sub_list is empty */
136475973853SYishai Hadas 	event = xa_load(&dev->devx_event_table.event_xa,
136575973853SYishai Hadas 			sub->xa_key_level1);
136675973853SYishai Hadas 	WARN_ON(!event);
136775973853SYishai Hadas 
136875973853SYishai Hadas 	xa_val_level2 = xa_load(&event->object_ids, sub->xa_key_level2);
136975973853SYishai Hadas 	if (list_empty(&xa_val_level2->obj_sub_list)) {
137075973853SYishai Hadas 		xa_erase(&event->object_ids,
137175973853SYishai Hadas 			 sub->xa_key_level2);
137275973853SYishai Hadas 		kfree_rcu(xa_val_level2, rcu);
137375973853SYishai Hadas 	}
137475973853SYishai Hadas }
137575973853SYishai Hadas 
13767efce369SYishai Hadas static int devx_obj_cleanup(struct ib_uobject *uobject,
1377a6a3797dSShamir Rabinovitch 			    enum rdma_remove_reason why,
1378a6a3797dSShamir Rabinovitch 			    struct uverbs_attr_bundle *attrs)
13797efce369SYishai Hadas {
13807efce369SYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
138175973853SYishai Hadas 	struct mlx5_devx_event_table *devx_event_table;
13827efce369SYishai Hadas 	struct devx_obj *obj = uobject->object;
138375973853SYishai Hadas 	struct devx_event_subscription *sub_entry, *tmp;
138475973853SYishai Hadas 	struct mlx5_ib_dev *dev;
13857efce369SYishai Hadas 	int ret;
13867efce369SYishai Hadas 
138775973853SYishai Hadas 	dev = mlx5_udata_to_mdev(&attrs->driver_udata);
138804177915SJason Gunthorpe 	if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY) {
138904177915SJason Gunthorpe 		/*
139004177915SJason Gunthorpe 		 * The pagefault_single_data_segment() does commands against
139104177915SJason Gunthorpe 		 * the mmkey, we must wait for that to stop before freeing the
139204177915SJason Gunthorpe 		 * mkey, as another allocation could get the same mkey #.
139304177915SJason Gunthorpe 		 */
1394806b101bSJason Gunthorpe 		xa_erase(&obj->ib_dev->odp_mkeys,
139504177915SJason Gunthorpe 			 mlx5_base_mkey(obj->devx_mr.mmkey.key));
1396806b101bSJason Gunthorpe 		synchronize_srcu(&dev->odp_srcu);
139704177915SJason Gunthorpe 	}
1398534fd7aaSYishai Hadas 
1399c5ae1954SYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_DCT)
1400333fbaa0SLeon Romanovsky 		ret = mlx5_core_destroy_dct(obj->ib_dev, &obj->core_dct);
1401ef1659adSYishai Hadas 	else if (obj->flags & DEVX_OBJ_FLAGS_CQ)
14025832fdd3SYishai Hadas 		ret = mlx5_core_destroy_cq(obj->ib_dev->mdev, &obj->core_cq);
1403c5ae1954SYishai Hadas 	else
14045832fdd3SYishai Hadas 		ret = mlx5_cmd_exec(obj->ib_dev->mdev, obj->dinbox,
14055832fdd3SYishai Hadas 				    obj->dinlen, out, sizeof(out));
1406efa968eeSLeon Romanovsky 	if (ret)
14077efce369SYishai Hadas 		return ret;
14087efce369SYishai Hadas 
140975973853SYishai Hadas 	devx_event_table = &dev->devx_event_table;
1410534fd7aaSYishai Hadas 
141175973853SYishai Hadas 	mutex_lock(&devx_event_table->event_xa_lock);
141275973853SYishai Hadas 	list_for_each_entry_safe(sub_entry, tmp, &obj->event_sub, obj_list)
141375973853SYishai Hadas 		devx_cleanup_subscription(dev, sub_entry);
141475973853SYishai Hadas 	mutex_unlock(&devx_event_table->event_xa_lock);
141575973853SYishai Hadas 
14167efce369SYishai Hadas 	kfree(obj);
14177efce369SYishai Hadas 	return ret;
14187efce369SYishai Hadas }
14197efce369SYishai Hadas 
1420ef1659adSYishai Hadas static void devx_cq_comp(struct mlx5_core_cq *mcq, struct mlx5_eqe *eqe)
1421ef1659adSYishai Hadas {
1422ef1659adSYishai Hadas 	struct devx_obj *obj = container_of(mcq, struct devx_obj, core_cq);
1423ef1659adSYishai Hadas 	struct mlx5_devx_event_table *table;
1424ef1659adSYishai Hadas 	struct devx_event *event;
1425ef1659adSYishai Hadas 	struct devx_obj_event *obj_event;
1426ef1659adSYishai Hadas 	u32 obj_id = mcq->cqn;
1427ef1659adSYishai Hadas 
1428ef1659adSYishai Hadas 	table = &obj->ib_dev->devx_event_table;
1429ef1659adSYishai Hadas 	rcu_read_lock();
1430ef1659adSYishai Hadas 	event = xa_load(&table->event_xa, MLX5_EVENT_TYPE_COMP);
1431ef1659adSYishai Hadas 	if (!event)
1432ef1659adSYishai Hadas 		goto out;
1433ef1659adSYishai Hadas 
1434ef1659adSYishai Hadas 	obj_event = xa_load(&event->object_ids, obj_id);
1435ef1659adSYishai Hadas 	if (!obj_event)
1436ef1659adSYishai Hadas 		goto out;
1437ef1659adSYishai Hadas 
1438ef1659adSYishai Hadas 	dispatch_event_fd(&obj_event->obj_sub_list, eqe);
1439ef1659adSYishai Hadas out:
1440ef1659adSYishai Hadas 	rcu_read_unlock();
1441ef1659adSYishai Hadas }
1442ef1659adSYishai Hadas 
1443e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
144415a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
14457efce369SYishai Hadas {
14467efce369SYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN);
14477efce369SYishai Hadas 	int cmd_out_len =  uverbs_attr_get_len(attrs,
14487efce369SYishai Hadas 					MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT);
1449fa31f143SYishai Hadas 	int cmd_in_len = uverbs_attr_get_len(attrs,
1450fa31f143SYishai Hadas 					MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN);
14517efce369SYishai Hadas 	void *cmd_out;
1452c36ee46dSJason Gunthorpe 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
1453c36ee46dSJason Gunthorpe 		attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE);
145489944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
145589944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1456c36ee46dSJason Gunthorpe 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
1457e8ef090aSYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
14587efce369SYishai Hadas 	struct devx_obj *obj;
1459cd5d20f1SYishai Hadas 	u16 obj_type = 0;
14607efce369SYishai Hadas 	int err;
14617e1335a7SYishai Hadas 	int uid;
14622351776eSYishai Hadas 	u32 obj_id;
14632351776eSYishai Hadas 	u16 opcode;
14647efce369SYishai Hadas 
1465b6142608SMax Gurtovoy 	if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id))
1466b6142608SMax Gurtovoy 		return -EINVAL;
1467b6142608SMax Gurtovoy 
14687e1335a7SYishai Hadas 	uid = devx_get_uid(c, cmd_in);
14697e1335a7SYishai Hadas 	if (uid < 0)
14707e1335a7SYishai Hadas 		return uid;
14717efce369SYishai Hadas 
14722351776eSYishai Hadas 	if (!devx_is_obj_create_cmd(cmd_in, &opcode))
14737efce369SYishai Hadas 		return -EINVAL;
14747efce369SYishai Hadas 
1475b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
1476b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
1477b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
1478b61815e2SJason Gunthorpe 
14797efce369SYishai Hadas 	obj = kzalloc(sizeof(struct devx_obj), GFP_KERNEL);
14807efce369SYishai Hadas 	if (!obj)
14817efce369SYishai Hadas 		return -ENOMEM;
14827efce369SYishai Hadas 
14837e1335a7SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1484fa31f143SYishai Hadas 	if (opcode == MLX5_CMD_OP_CREATE_MKEY) {
1485fa31f143SYishai Hadas 		err = devx_handle_mkey_create(dev, obj, cmd_in, cmd_in_len);
1486fa31f143SYishai Hadas 		if (err)
1487fa31f143SYishai Hadas 			goto obj_free;
1488fa31f143SYishai Hadas 	} else {
1489ba1a057dSYishai Hadas 		devx_set_umem_valid(cmd_in);
1490fa31f143SYishai Hadas 	}
1491ba1a057dSYishai Hadas 
1492c5ae1954SYishai Hadas 	if (opcode == MLX5_CMD_OP_CREATE_DCT) {
1493c5ae1954SYishai Hadas 		obj->flags |= DEVX_OBJ_FLAGS_DCT;
1494333fbaa0SLeon Romanovsky 		err = mlx5_core_create_dct(dev, &obj->core_dct, cmd_in,
1495333fbaa0SLeon Romanovsky 					   cmd_in_len, cmd_out, cmd_out_len);
1496ef1659adSYishai Hadas 	} else if (opcode == MLX5_CMD_OP_CREATE_CQ) {
1497ef1659adSYishai Hadas 		obj->flags |= DEVX_OBJ_FLAGS_CQ;
1498ef1659adSYishai Hadas 		obj->core_cq.comp = devx_cq_comp;
1499ef1659adSYishai Hadas 		err = mlx5_core_create_cq(dev->mdev, &obj->core_cq,
1500ef1659adSYishai Hadas 					  cmd_in, cmd_in_len, cmd_out,
1501ef1659adSYishai Hadas 					  cmd_out_len);
1502c5ae1954SYishai Hadas 	} else {
15037efce369SYishai Hadas 		err = mlx5_cmd_exec(dev->mdev, cmd_in,
1504fa31f143SYishai Hadas 				    cmd_in_len,
15057efce369SYishai Hadas 				    cmd_out, cmd_out_len);
1506c5ae1954SYishai Hadas 	}
1507c5ae1954SYishai Hadas 
15087efce369SYishai Hadas 	if (err)
1509b61815e2SJason Gunthorpe 		goto obj_free;
15107efce369SYishai Hadas 
1511208d70f5SYevgeny Kliteynik 	if (opcode == MLX5_CMD_OP_ALLOC_FLOW_COUNTER) {
1512208d70f5SYevgeny Kliteynik 		u8 bulk = MLX5_GET(alloc_flow_counter_in,
1513208d70f5SYevgeny Kliteynik 				   cmd_in,
1514208d70f5SYevgeny Kliteynik 				   flow_counter_bulk);
1515208d70f5SYevgeny Kliteynik 		obj->flow_counter_bulk_size = 128UL * bulk;
1516208d70f5SYevgeny Kliteynik 	}
1517208d70f5SYevgeny Kliteynik 
15187efce369SYishai Hadas 	uobj->object = obj;
151975973853SYishai Hadas 	INIT_LIST_HEAD(&obj->event_sub);
1520ef1659adSYishai Hadas 	obj->ib_dev = dev;
15212351776eSYishai Hadas 	devx_obj_build_destroy_cmd(cmd_in, cmd_out, obj->dinbox, &obj->dinlen,
15222351776eSYishai Hadas 				   &obj_id);
15237efce369SYishai Hadas 	WARN_ON(obj->dinlen > MLX5_MAX_DESTROY_INBOX_SIZE_DW * sizeof(u32));
15247efce369SYishai Hadas 
152504177915SJason Gunthorpe 	err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, cmd_out, cmd_out_len);
152604177915SJason Gunthorpe 	if (err)
152704177915SJason Gunthorpe 		goto obj_destroy;
152804177915SJason Gunthorpe 
152904177915SJason Gunthorpe 	if (opcode == MLX5_CMD_OP_CREATE_GENERAL_OBJECT)
153004177915SJason Gunthorpe 		obj_type = MLX5_GET(general_obj_in_cmd_hdr, cmd_in, obj_type);
153104177915SJason Gunthorpe 	obj->obj_id = get_enc_obj_id(opcode | obj_type << 16, obj_id);
153204177915SJason Gunthorpe 
1533534fd7aaSYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY) {
1534534fd7aaSYishai Hadas 		err = devx_handle_mkey_indirect(obj, dev, cmd_in, cmd_out);
1535534fd7aaSYishai Hadas 		if (err)
1536534fd7aaSYishai Hadas 			goto obj_destroy;
1537534fd7aaSYishai Hadas 	}
15387efce369SYishai Hadas 	return 0;
15397efce369SYishai Hadas 
15400da4d48dSYishai Hadas obj_destroy:
1541c5ae1954SYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_DCT)
1542333fbaa0SLeon Romanovsky 		mlx5_core_destroy_dct(obj->ib_dev, &obj->core_dct);
1543ef1659adSYishai Hadas 	else if (obj->flags & DEVX_OBJ_FLAGS_CQ)
15445832fdd3SYishai Hadas 		mlx5_core_destroy_cq(obj->ib_dev->mdev, &obj->core_cq);
1545c5ae1954SYishai Hadas 	else
15465832fdd3SYishai Hadas 		mlx5_cmd_exec(obj->ib_dev->mdev, obj->dinbox, obj->dinlen, out,
1547c5ae1954SYishai Hadas 			      sizeof(out));
15487efce369SYishai Hadas obj_free:
15497efce369SYishai Hadas 	kfree(obj);
15507efce369SYishai Hadas 	return err;
15517efce369SYishai Hadas }
15527efce369SYishai Hadas 
1553e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)(
155415a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
1555e662e14dSYishai Hadas {
1556e662e14dSYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN);
1557e662e14dSYishai Hadas 	int cmd_out_len = uverbs_attr_get_len(attrs,
1558e662e14dSYishai Hadas 					MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT);
1559e662e14dSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
1560e662e14dSYishai Hadas 							  MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE);
156189944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
156289944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
156389944450SShamir Rabinovitch 	struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device);
1564e662e14dSYishai Hadas 	void *cmd_out;
1565e662e14dSYishai Hadas 	int err;
15667e1335a7SYishai Hadas 	int uid;
1567e662e14dSYishai Hadas 
1568b6142608SMax Gurtovoy 	if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id))
1569b6142608SMax Gurtovoy 		return -EINVAL;
1570b6142608SMax Gurtovoy 
15717e1335a7SYishai Hadas 	uid = devx_get_uid(c, cmd_in);
15727e1335a7SYishai Hadas 	if (uid < 0)
15737e1335a7SYishai Hadas 		return uid;
1574e662e14dSYishai Hadas 
1575e662e14dSYishai Hadas 	if (!devx_is_obj_modify_cmd(cmd_in))
1576e662e14dSYishai Hadas 		return -EINVAL;
1577e662e14dSYishai Hadas 
1578e79c9c60SJason Gunthorpe 	if (!devx_is_valid_obj_id(attrs, uobj, cmd_in))
1579e662e14dSYishai Hadas 		return -EINVAL;
1580e662e14dSYishai Hadas 
1581b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
1582b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
1583b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
1584e662e14dSYishai Hadas 
15857e1335a7SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1586ba1a057dSYishai Hadas 	devx_set_umem_valid(cmd_in);
1587ba1a057dSYishai Hadas 
158834613eb1SYishai Hadas 	err = mlx5_cmd_exec(mdev->mdev, cmd_in,
1589e662e14dSYishai Hadas 			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN),
1590e662e14dSYishai Hadas 			    cmd_out, cmd_out_len);
1591e662e14dSYishai Hadas 	if (err)
1592e662e14dSYishai Hadas 		return err;
1593b61815e2SJason Gunthorpe 
1594b61815e2SJason Gunthorpe 	return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
1595b61815e2SJason Gunthorpe 			      cmd_out, cmd_out_len);
1596e662e14dSYishai Hadas }
1597e662e14dSYishai Hadas 
1598e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)(
159915a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
1600e662e14dSYishai Hadas {
1601e662e14dSYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN);
1602e662e14dSYishai Hadas 	int cmd_out_len = uverbs_attr_get_len(attrs,
1603e662e14dSYishai Hadas 					      MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT);
1604e662e14dSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
1605e662e14dSYishai Hadas 							  MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE);
160689944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
160789944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1608e662e14dSYishai Hadas 	void *cmd_out;
1609e662e14dSYishai Hadas 	int err;
16107e1335a7SYishai Hadas 	int uid;
161189944450SShamir Rabinovitch 	struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device);
1612e662e14dSYishai Hadas 
1613b6142608SMax Gurtovoy 	if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id))
1614b6142608SMax Gurtovoy 		return -EINVAL;
1615b6142608SMax Gurtovoy 
16167e1335a7SYishai Hadas 	uid = devx_get_uid(c, cmd_in);
16177e1335a7SYishai Hadas 	if (uid < 0)
16187e1335a7SYishai Hadas 		return uid;
1619e662e14dSYishai Hadas 
1620e662e14dSYishai Hadas 	if (!devx_is_obj_query_cmd(cmd_in))
1621e662e14dSYishai Hadas 		return -EINVAL;
1622e662e14dSYishai Hadas 
1623e79c9c60SJason Gunthorpe 	if (!devx_is_valid_obj_id(attrs, uobj, cmd_in))
1624e662e14dSYishai Hadas 		return -EINVAL;
1625e662e14dSYishai Hadas 
1626b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
1627b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
1628b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
1629e662e14dSYishai Hadas 
16307e1335a7SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
163134613eb1SYishai Hadas 	err = mlx5_cmd_exec(mdev->mdev, cmd_in,
1632e662e14dSYishai Hadas 			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN),
1633e662e14dSYishai Hadas 			    cmd_out, cmd_out_len);
1634e662e14dSYishai Hadas 	if (err)
1635e662e14dSYishai Hadas 		return err;
1636b61815e2SJason Gunthorpe 
1637b61815e2SJason Gunthorpe 	return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
1638b61815e2SJason Gunthorpe 			      cmd_out, cmd_out_len);
1639e662e14dSYishai Hadas }
1640e662e14dSYishai Hadas 
16416bf8f22aSYishai Hadas struct devx_async_event_queue {
16426bf8f22aSYishai Hadas 	spinlock_t		lock;
16436bf8f22aSYishai Hadas 	wait_queue_head_t	poll_wait;
16446bf8f22aSYishai Hadas 	struct list_head	event_list;
1645a124edbaSYishai Hadas 	atomic_t		bytes_in_use;
1646eaebaf77SYishai Hadas 	u8			is_destroyed:1;
16476bf8f22aSYishai Hadas };
16486bf8f22aSYishai Hadas 
16496bf8f22aSYishai Hadas struct devx_async_cmd_event_file {
16506bf8f22aSYishai Hadas 	struct ib_uobject		uobj;
16516bf8f22aSYishai Hadas 	struct devx_async_event_queue	ev_queue;
1652a124edbaSYishai Hadas 	struct mlx5_async_ctx		async_ctx;
16536bf8f22aSYishai Hadas };
16546bf8f22aSYishai Hadas 
16556bf8f22aSYishai Hadas static void devx_init_event_queue(struct devx_async_event_queue *ev_queue)
16566bf8f22aSYishai Hadas {
16576bf8f22aSYishai Hadas 	spin_lock_init(&ev_queue->lock);
16586bf8f22aSYishai Hadas 	INIT_LIST_HEAD(&ev_queue->event_list);
16596bf8f22aSYishai Hadas 	init_waitqueue_head(&ev_queue->poll_wait);
1660a124edbaSYishai Hadas 	atomic_set(&ev_queue->bytes_in_use, 0);
1661eaebaf77SYishai Hadas 	ev_queue->is_destroyed = 0;
16626bf8f22aSYishai Hadas }
16636bf8f22aSYishai Hadas 
16646bf8f22aSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC)(
16656bf8f22aSYishai Hadas 	struct uverbs_attr_bundle *attrs)
16666bf8f22aSYishai Hadas {
16676bf8f22aSYishai Hadas 	struct devx_async_cmd_event_file *ev_file;
16686bf8f22aSYishai Hadas 
16696bf8f22aSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
16706bf8f22aSYishai Hadas 		attrs, MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE);
1671e79c9c60SJason Gunthorpe 	struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata);
16726bf8f22aSYishai Hadas 
16736bf8f22aSYishai Hadas 	ev_file = container_of(uobj, struct devx_async_cmd_event_file,
16746bf8f22aSYishai Hadas 			       uobj);
16756bf8f22aSYishai Hadas 	devx_init_event_queue(&ev_file->ev_queue);
1676a124edbaSYishai Hadas 	mlx5_cmd_init_async_ctx(mdev->mdev, &ev_file->async_ctx);
16776bf8f22aSYishai Hadas 	return 0;
16786bf8f22aSYishai Hadas }
16796bf8f22aSYishai Hadas 
16802afc5e1bSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC)(
16812afc5e1bSYishai Hadas 	struct uverbs_attr_bundle *attrs)
16822afc5e1bSYishai Hadas {
16832afc5e1bSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
16842afc5e1bSYishai Hadas 		attrs, MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_HANDLE);
16852afc5e1bSYishai Hadas 	struct devx_async_event_file *ev_file;
16862afc5e1bSYishai Hadas 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
16872afc5e1bSYishai Hadas 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
16882afc5e1bSYishai Hadas 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
16892afc5e1bSYishai Hadas 	u32 flags;
16902afc5e1bSYishai Hadas 	int err;
16912afc5e1bSYishai Hadas 
16922afc5e1bSYishai Hadas 	err = uverbs_get_flags32(&flags, attrs,
16932afc5e1bSYishai Hadas 		MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_FLAGS,
16942afc5e1bSYishai Hadas 		MLX5_IB_UAPI_DEVX_CR_EV_CH_FLAGS_OMIT_DATA);
16952afc5e1bSYishai Hadas 
16962afc5e1bSYishai Hadas 	if (err)
16972afc5e1bSYishai Hadas 		return err;
16982afc5e1bSYishai Hadas 
16992afc5e1bSYishai Hadas 	ev_file = container_of(uobj, struct devx_async_event_file,
17002afc5e1bSYishai Hadas 			       uobj);
17012afc5e1bSYishai Hadas 	spin_lock_init(&ev_file->lock);
17022afc5e1bSYishai Hadas 	INIT_LIST_HEAD(&ev_file->event_list);
17032afc5e1bSYishai Hadas 	init_waitqueue_head(&ev_file->poll_wait);
17042afc5e1bSYishai Hadas 	if (flags & MLX5_IB_UAPI_DEVX_CR_EV_CH_FLAGS_OMIT_DATA)
17052afc5e1bSYishai Hadas 		ev_file->omit_data = 1;
17062afc5e1bSYishai Hadas 	INIT_LIST_HEAD(&ev_file->subscribed_events_list);
17072afc5e1bSYishai Hadas 	ev_file->dev = dev;
170875973853SYishai Hadas 	get_device(&dev->ib_dev.dev);
17092afc5e1bSYishai Hadas 	return 0;
17102afc5e1bSYishai Hadas }
17112afc5e1bSYishai Hadas 
1712a124edbaSYishai Hadas static void devx_query_callback(int status, struct mlx5_async_work *context)
1713a124edbaSYishai Hadas {
1714a124edbaSYishai Hadas 	struct devx_async_data *async_data =
1715a124edbaSYishai Hadas 		container_of(context, struct devx_async_data, cb_work);
171693887e66SJason Gunthorpe 	struct devx_async_cmd_event_file *ev_file = async_data->ev_file;
171793887e66SJason Gunthorpe 	struct devx_async_event_queue *ev_queue = &ev_file->ev_queue;
1718a124edbaSYishai Hadas 	unsigned long flags;
1719a124edbaSYishai Hadas 
172093887e66SJason Gunthorpe 	/*
172193887e66SJason Gunthorpe 	 * Note that if the struct devx_async_cmd_event_file uobj begins to be
172293887e66SJason Gunthorpe 	 * destroyed it will block at mlx5_cmd_cleanup_async_ctx() until this
172393887e66SJason Gunthorpe 	 * routine returns, ensuring that it always remains valid here.
172493887e66SJason Gunthorpe 	 */
1725a124edbaSYishai Hadas 	spin_lock_irqsave(&ev_queue->lock, flags);
1726a124edbaSYishai Hadas 	list_add_tail(&async_data->list, &ev_queue->event_list);
1727a124edbaSYishai Hadas 	spin_unlock_irqrestore(&ev_queue->lock, flags);
1728a124edbaSYishai Hadas 
1729a124edbaSYishai Hadas 	wake_up_interruptible(&ev_queue->poll_wait);
1730a124edbaSYishai Hadas }
1731a124edbaSYishai Hadas 
1732a124edbaSYishai Hadas #define MAX_ASYNC_BYTES_IN_USE (1024 * 1024) /* 1MB */
1733a124edbaSYishai Hadas 
1734a124edbaSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY)(
1735a124edbaSYishai Hadas 	struct uverbs_attr_bundle *attrs)
1736a124edbaSYishai Hadas {
1737a124edbaSYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs,
1738a124edbaSYishai Hadas 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN);
1739a124edbaSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
1740a124edbaSYishai Hadas 				attrs,
1741a124edbaSYishai Hadas 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_HANDLE);
1742a124edbaSYishai Hadas 	u16 cmd_out_len;
174389944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
174489944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1745a124edbaSYishai Hadas 	struct ib_uobject *fd_uobj;
1746a124edbaSYishai Hadas 	int err;
1747a124edbaSYishai Hadas 	int uid;
174889944450SShamir Rabinovitch 	struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device);
1749a124edbaSYishai Hadas 	struct devx_async_cmd_event_file *ev_file;
1750a124edbaSYishai Hadas 	struct devx_async_data *async_data;
1751a124edbaSYishai Hadas 
1752b6142608SMax Gurtovoy 	if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id))
1753b6142608SMax Gurtovoy 		return -EINVAL;
1754b6142608SMax Gurtovoy 
1755a124edbaSYishai Hadas 	uid = devx_get_uid(c, cmd_in);
1756a124edbaSYishai Hadas 	if (uid < 0)
1757a124edbaSYishai Hadas 		return uid;
1758a124edbaSYishai Hadas 
1759a124edbaSYishai Hadas 	if (!devx_is_obj_query_cmd(cmd_in))
1760a124edbaSYishai Hadas 		return -EINVAL;
1761a124edbaSYishai Hadas 
1762a124edbaSYishai Hadas 	err = uverbs_get_const(&cmd_out_len, attrs,
1763a124edbaSYishai Hadas 			       MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_OUT_LEN);
1764a124edbaSYishai Hadas 	if (err)
1765a124edbaSYishai Hadas 		return err;
1766a124edbaSYishai Hadas 
1767e79c9c60SJason Gunthorpe 	if (!devx_is_valid_obj_id(attrs, uobj, cmd_in))
1768a124edbaSYishai Hadas 		return -EINVAL;
1769a124edbaSYishai Hadas 
1770a124edbaSYishai Hadas 	fd_uobj = uverbs_attr_get_uobject(attrs,
1771a124edbaSYishai Hadas 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_FD);
1772a124edbaSYishai Hadas 	if (IS_ERR(fd_uobj))
1773a124edbaSYishai Hadas 		return PTR_ERR(fd_uobj);
1774a124edbaSYishai Hadas 
1775a124edbaSYishai Hadas 	ev_file = container_of(fd_uobj, struct devx_async_cmd_event_file,
1776a124edbaSYishai Hadas 			       uobj);
1777a124edbaSYishai Hadas 
1778a124edbaSYishai Hadas 	if (atomic_add_return(cmd_out_len, &ev_file->ev_queue.bytes_in_use) >
1779a124edbaSYishai Hadas 			MAX_ASYNC_BYTES_IN_USE) {
1780a124edbaSYishai Hadas 		atomic_sub(cmd_out_len, &ev_file->ev_queue.bytes_in_use);
1781a124edbaSYishai Hadas 		return -EAGAIN;
1782a124edbaSYishai Hadas 	}
1783a124edbaSYishai Hadas 
1784a124edbaSYishai Hadas 	async_data = kvzalloc(struct_size(async_data, hdr.out_data,
1785a124edbaSYishai Hadas 					  cmd_out_len), GFP_KERNEL);
1786a124edbaSYishai Hadas 	if (!async_data) {
1787a124edbaSYishai Hadas 		err = -ENOMEM;
1788a124edbaSYishai Hadas 		goto sub_bytes;
1789a124edbaSYishai Hadas 	}
1790a124edbaSYishai Hadas 
1791a124edbaSYishai Hadas 	err = uverbs_copy_from(&async_data->hdr.wr_id, attrs,
1792a124edbaSYishai Hadas 			       MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_WR_ID);
1793a124edbaSYishai Hadas 	if (err)
1794a124edbaSYishai Hadas 		goto free_async;
1795a124edbaSYishai Hadas 
1796a124edbaSYishai Hadas 	async_data->cmd_out_len = cmd_out_len;
1797a124edbaSYishai Hadas 	async_data->mdev = mdev;
179893887e66SJason Gunthorpe 	async_data->ev_file = ev_file;
1799a124edbaSYishai Hadas 
1800a124edbaSYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1801a124edbaSYishai Hadas 	err = mlx5_cmd_exec_cb(&ev_file->async_ctx, cmd_in,
1802a124edbaSYishai Hadas 		    uverbs_attr_get_len(attrs,
1803a124edbaSYishai Hadas 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN),
1804a124edbaSYishai Hadas 		    async_data->hdr.out_data,
1805a124edbaSYishai Hadas 		    async_data->cmd_out_len,
1806a124edbaSYishai Hadas 		    devx_query_callback, &async_data->cb_work);
1807a124edbaSYishai Hadas 
1808a124edbaSYishai Hadas 	if (err)
180993887e66SJason Gunthorpe 		goto free_async;
1810a124edbaSYishai Hadas 
1811a124edbaSYishai Hadas 	return 0;
1812a124edbaSYishai Hadas 
1813a124edbaSYishai Hadas free_async:
1814a124edbaSYishai Hadas 	kvfree(async_data);
1815a124edbaSYishai Hadas sub_bytes:
1816a124edbaSYishai Hadas 	atomic_sub(cmd_out_len, &ev_file->ev_queue.bytes_in_use);
1817a124edbaSYishai Hadas 	return err;
1818a124edbaSYishai Hadas }
1819a124edbaSYishai Hadas 
182075973853SYishai Hadas static void
182175973853SYishai Hadas subscribe_event_xa_dealloc(struct mlx5_devx_event_table *devx_event_table,
182275973853SYishai Hadas 			   u32 key_level1,
182375973853SYishai Hadas 			   bool is_level2,
182475973853SYishai Hadas 			   u32 key_level2)
182575973853SYishai Hadas {
182675973853SYishai Hadas 	struct devx_event *event;
182775973853SYishai Hadas 	struct devx_obj_event *xa_val_level2;
182875973853SYishai Hadas 
182975973853SYishai Hadas 	/* Level 1 is valid for future use, no need to free */
183075973853SYishai Hadas 	if (!is_level2)
183175973853SYishai Hadas 		return;
183275973853SYishai Hadas 
183375973853SYishai Hadas 	event = xa_load(&devx_event_table->event_xa, key_level1);
183475973853SYishai Hadas 	WARN_ON(!event);
183575973853SYishai Hadas 
183675973853SYishai Hadas 	xa_val_level2 = xa_load(&event->object_ids,
183775973853SYishai Hadas 				key_level2);
183875973853SYishai Hadas 	if (list_empty(&xa_val_level2->obj_sub_list)) {
183975973853SYishai Hadas 		xa_erase(&event->object_ids,
184075973853SYishai Hadas 			 key_level2);
184175973853SYishai Hadas 		kfree_rcu(xa_val_level2, rcu);
184275973853SYishai Hadas 	}
184375973853SYishai Hadas }
184475973853SYishai Hadas 
184575973853SYishai Hadas static int
184675973853SYishai Hadas subscribe_event_xa_alloc(struct mlx5_devx_event_table *devx_event_table,
184775973853SYishai Hadas 			 u32 key_level1,
184875973853SYishai Hadas 			 bool is_level2,
184975973853SYishai Hadas 			 u32 key_level2)
185075973853SYishai Hadas {
185175973853SYishai Hadas 	struct devx_obj_event *obj_event;
185275973853SYishai Hadas 	struct devx_event *event;
185375973853SYishai Hadas 	int err;
185475973853SYishai Hadas 
185575973853SYishai Hadas 	event = xa_load(&devx_event_table->event_xa, key_level1);
185675973853SYishai Hadas 	if (!event) {
185775973853SYishai Hadas 		event = kzalloc(sizeof(*event), GFP_KERNEL);
185875973853SYishai Hadas 		if (!event)
185975973853SYishai Hadas 			return -ENOMEM;
186075973853SYishai Hadas 
186175973853SYishai Hadas 		INIT_LIST_HEAD(&event->unaffiliated_list);
186275973853SYishai Hadas 		xa_init(&event->object_ids);
186375973853SYishai Hadas 
186475973853SYishai Hadas 		err = xa_insert(&devx_event_table->event_xa,
186575973853SYishai Hadas 				key_level1,
186675973853SYishai Hadas 				event,
186775973853SYishai Hadas 				GFP_KERNEL);
186875973853SYishai Hadas 		if (err) {
186975973853SYishai Hadas 			kfree(event);
187075973853SYishai Hadas 			return err;
187175973853SYishai Hadas 		}
187275973853SYishai Hadas 	}
187375973853SYishai Hadas 
187475973853SYishai Hadas 	if (!is_level2)
187575973853SYishai Hadas 		return 0;
187675973853SYishai Hadas 
187775973853SYishai Hadas 	obj_event = xa_load(&event->object_ids, key_level2);
187875973853SYishai Hadas 	if (!obj_event) {
187975973853SYishai Hadas 		obj_event = kzalloc(sizeof(*obj_event), GFP_KERNEL);
188075973853SYishai Hadas 		if (!obj_event)
188175973853SYishai Hadas 			/* Level1 is valid for future use, no need to free */
188275973853SYishai Hadas 			return -ENOMEM;
188375973853SYishai Hadas 
188475973853SYishai Hadas 		err = xa_insert(&event->object_ids,
188575973853SYishai Hadas 				key_level2,
188675973853SYishai Hadas 				obj_event,
188775973853SYishai Hadas 				GFP_KERNEL);
188875973853SYishai Hadas 		if (err)
188975973853SYishai Hadas 			return err;
189075973853SYishai Hadas 		INIT_LIST_HEAD(&obj_event->obj_sub_list);
189175973853SYishai Hadas 	}
189275973853SYishai Hadas 
189375973853SYishai Hadas 	return 0;
189475973853SYishai Hadas }
189575973853SYishai Hadas 
189675973853SYishai Hadas static bool is_valid_events_legacy(int num_events, u16 *event_type_num_list,
189775973853SYishai Hadas 				   struct devx_obj *obj)
189875973853SYishai Hadas {
189975973853SYishai Hadas 	int i;
190075973853SYishai Hadas 
190175973853SYishai Hadas 	for (i = 0; i < num_events; i++) {
190275973853SYishai Hadas 		if (obj) {
190375973853SYishai Hadas 			if (!is_legacy_obj_event_num(event_type_num_list[i]))
190475973853SYishai Hadas 				return false;
190575973853SYishai Hadas 		} else if (!is_legacy_unaffiliated_event_num(
190675973853SYishai Hadas 				event_type_num_list[i])) {
190775973853SYishai Hadas 			return false;
190875973853SYishai Hadas 		}
190975973853SYishai Hadas 	}
191075973853SYishai Hadas 
191175973853SYishai Hadas 	return true;
191275973853SYishai Hadas }
191375973853SYishai Hadas 
191475973853SYishai Hadas #define MAX_SUPP_EVENT_NUM 255
191575973853SYishai Hadas static bool is_valid_events(struct mlx5_core_dev *dev,
191675973853SYishai Hadas 			    int num_events, u16 *event_type_num_list,
191775973853SYishai Hadas 			    struct devx_obj *obj)
191875973853SYishai Hadas {
191975973853SYishai Hadas 	__be64 *aff_events;
192075973853SYishai Hadas 	__be64 *unaff_events;
192175973853SYishai Hadas 	int mask_entry;
192275973853SYishai Hadas 	int mask_bit;
192375973853SYishai Hadas 	int i;
192475973853SYishai Hadas 
192575973853SYishai Hadas 	if (MLX5_CAP_GEN(dev, event_cap)) {
192675973853SYishai Hadas 		aff_events = MLX5_CAP_DEV_EVENT(dev,
192775973853SYishai Hadas 						user_affiliated_events);
192875973853SYishai Hadas 		unaff_events = MLX5_CAP_DEV_EVENT(dev,
192975973853SYishai Hadas 						  user_unaffiliated_events);
193075973853SYishai Hadas 	} else {
193175973853SYishai Hadas 		return is_valid_events_legacy(num_events, event_type_num_list,
193275973853SYishai Hadas 					      obj);
193375973853SYishai Hadas 	}
193475973853SYishai Hadas 
193575973853SYishai Hadas 	for (i = 0; i < num_events; i++) {
193675973853SYishai Hadas 		if (event_type_num_list[i] > MAX_SUPP_EVENT_NUM)
193775973853SYishai Hadas 			return false;
193875973853SYishai Hadas 
193975973853SYishai Hadas 		mask_entry = event_type_num_list[i] / 64;
194075973853SYishai Hadas 		mask_bit = event_type_num_list[i] % 64;
194175973853SYishai Hadas 
194275973853SYishai Hadas 		if (obj) {
194375973853SYishai Hadas 			/* CQ completion */
194475973853SYishai Hadas 			if (event_type_num_list[i] == 0)
194575973853SYishai Hadas 				continue;
194675973853SYishai Hadas 
194775973853SYishai Hadas 			if (!(be64_to_cpu(aff_events[mask_entry]) &
194875973853SYishai Hadas 					(1ull << mask_bit)))
194975973853SYishai Hadas 				return false;
195075973853SYishai Hadas 
195175973853SYishai Hadas 			continue;
195275973853SYishai Hadas 		}
195375973853SYishai Hadas 
195475973853SYishai Hadas 		if (!(be64_to_cpu(unaff_events[mask_entry]) &
195575973853SYishai Hadas 				(1ull << mask_bit)))
195675973853SYishai Hadas 			return false;
195775973853SYishai Hadas 	}
195875973853SYishai Hadas 
195975973853SYishai Hadas 	return true;
196075973853SYishai Hadas }
196175973853SYishai Hadas 
196275973853SYishai Hadas #define MAX_NUM_EVENTS 16
196375973853SYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT)(
196475973853SYishai Hadas 	struct uverbs_attr_bundle *attrs)
196575973853SYishai Hadas {
196675973853SYishai Hadas 	struct ib_uobject *devx_uobj = uverbs_attr_get_uobject(
196775973853SYishai Hadas 				attrs,
196875973853SYishai Hadas 				MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_OBJ_HANDLE);
196975973853SYishai Hadas 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
197075973853SYishai Hadas 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
197175973853SYishai Hadas 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
197275973853SYishai Hadas 	struct ib_uobject *fd_uobj;
197375973853SYishai Hadas 	struct devx_obj *obj = NULL;
197475973853SYishai Hadas 	struct devx_async_event_file *ev_file;
197575973853SYishai Hadas 	struct mlx5_devx_event_table *devx_event_table = &dev->devx_event_table;
197675973853SYishai Hadas 	u16 *event_type_num_list;
197775973853SYishai Hadas 	struct devx_event_subscription *event_sub, *tmp_sub;
197875973853SYishai Hadas 	struct list_head sub_list;
197975973853SYishai Hadas 	int redirect_fd;
198075973853SYishai Hadas 	bool use_eventfd = false;
198175973853SYishai Hadas 	int num_events;
198275973853SYishai Hadas 	int num_alloc_xa_entries = 0;
198375973853SYishai Hadas 	u16 obj_type = 0;
198475973853SYishai Hadas 	u64 cookie = 0;
198575973853SYishai Hadas 	u32 obj_id = 0;
198675973853SYishai Hadas 	int err;
198775973853SYishai Hadas 	int i;
198875973853SYishai Hadas 
198975973853SYishai Hadas 	if (!c->devx_uid)
199075973853SYishai Hadas 		return -EINVAL;
199175973853SYishai Hadas 
199275973853SYishai Hadas 	if (!IS_ERR(devx_uobj)) {
199375973853SYishai Hadas 		obj = (struct devx_obj *)devx_uobj->object;
199475973853SYishai Hadas 		if (obj)
199575973853SYishai Hadas 			obj_id = get_dec_obj_id(obj->obj_id);
199675973853SYishai Hadas 	}
199775973853SYishai Hadas 
199875973853SYishai Hadas 	fd_uobj = uverbs_attr_get_uobject(attrs,
199975973853SYishai Hadas 				MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_HANDLE);
200075973853SYishai Hadas 	if (IS_ERR(fd_uobj))
200175973853SYishai Hadas 		return PTR_ERR(fd_uobj);
200275973853SYishai Hadas 
200375973853SYishai Hadas 	ev_file = container_of(fd_uobj, struct devx_async_event_file,
200475973853SYishai Hadas 			       uobj);
200575973853SYishai Hadas 
200675973853SYishai Hadas 	if (uverbs_attr_is_valid(attrs,
200775973853SYishai Hadas 				 MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM)) {
200875973853SYishai Hadas 		err = uverbs_copy_from(&redirect_fd, attrs,
200975973853SYishai Hadas 			       MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM);
201075973853SYishai Hadas 		if (err)
201175973853SYishai Hadas 			return err;
201275973853SYishai Hadas 
201375973853SYishai Hadas 		use_eventfd = true;
201475973853SYishai Hadas 	}
201575973853SYishai Hadas 
201675973853SYishai Hadas 	if (uverbs_attr_is_valid(attrs,
201775973853SYishai Hadas 				 MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE)) {
201875973853SYishai Hadas 		if (use_eventfd)
201975973853SYishai Hadas 			return -EINVAL;
202075973853SYishai Hadas 
202175973853SYishai Hadas 		err = uverbs_copy_from(&cookie, attrs,
202275973853SYishai Hadas 				MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE);
202375973853SYishai Hadas 		if (err)
202475973853SYishai Hadas 			return err;
202575973853SYishai Hadas 	}
202675973853SYishai Hadas 
202775973853SYishai Hadas 	num_events = uverbs_attr_ptr_get_array_size(
202875973853SYishai Hadas 		attrs, MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST,
202975973853SYishai Hadas 		sizeof(u16));
203075973853SYishai Hadas 
203175973853SYishai Hadas 	if (num_events < 0)
203275973853SYishai Hadas 		return num_events;
203375973853SYishai Hadas 
203475973853SYishai Hadas 	if (num_events > MAX_NUM_EVENTS)
203575973853SYishai Hadas 		return -EINVAL;
203675973853SYishai Hadas 
203775973853SYishai Hadas 	event_type_num_list = uverbs_attr_get_alloced_ptr(attrs,
203875973853SYishai Hadas 			MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST);
203975973853SYishai Hadas 
204075973853SYishai Hadas 	if (!is_valid_events(dev->mdev, num_events, event_type_num_list, obj))
204175973853SYishai Hadas 		return -EINVAL;
204275973853SYishai Hadas 
204375973853SYishai Hadas 	INIT_LIST_HEAD(&sub_list);
204475973853SYishai Hadas 
204575973853SYishai Hadas 	/* Protect from concurrent subscriptions to same XA entries to allow
204675973853SYishai Hadas 	 * both to succeed
204775973853SYishai Hadas 	 */
204875973853SYishai Hadas 	mutex_lock(&devx_event_table->event_xa_lock);
204975973853SYishai Hadas 	for (i = 0; i < num_events; i++) {
205075973853SYishai Hadas 		u32 key_level1;
205175973853SYishai Hadas 
205275973853SYishai Hadas 		if (obj)
205375973853SYishai Hadas 			obj_type = get_dec_obj_type(obj,
205475973853SYishai Hadas 						    event_type_num_list[i]);
205575973853SYishai Hadas 		key_level1 = event_type_num_list[i] | obj_type << 16;
205675973853SYishai Hadas 
205775973853SYishai Hadas 		err = subscribe_event_xa_alloc(devx_event_table,
205875973853SYishai Hadas 					       key_level1,
205975973853SYishai Hadas 					       obj,
206075973853SYishai Hadas 					       obj_id);
206175973853SYishai Hadas 		if (err)
206275973853SYishai Hadas 			goto err;
206375973853SYishai Hadas 
206475973853SYishai Hadas 		num_alloc_xa_entries++;
206575973853SYishai Hadas 		event_sub = kzalloc(sizeof(*event_sub), GFP_KERNEL);
206675973853SYishai Hadas 		if (!event_sub)
206775973853SYishai Hadas 			goto err;
206875973853SYishai Hadas 
206975973853SYishai Hadas 		list_add_tail(&event_sub->event_list, &sub_list);
20706898d1c6SJason Gunthorpe 		uverbs_uobject_get(&ev_file->uobj);
207175973853SYishai Hadas 		if (use_eventfd) {
207275973853SYishai Hadas 			event_sub->eventfd =
207375973853SYishai Hadas 				eventfd_ctx_fdget(redirect_fd);
207475973853SYishai Hadas 
2075e7e6c632SDan Carpenter 			if (IS_ERR(event_sub->eventfd)) {
207675973853SYishai Hadas 				err = PTR_ERR(event_sub->eventfd);
207775973853SYishai Hadas 				event_sub->eventfd = NULL;
207875973853SYishai Hadas 				goto err;
207975973853SYishai Hadas 			}
208075973853SYishai Hadas 		}
208175973853SYishai Hadas 
208275973853SYishai Hadas 		event_sub->cookie = cookie;
208375973853SYishai Hadas 		event_sub->ev_file = ev_file;
208475973853SYishai Hadas 		/* May be needed upon cleanup the devx object/subscription */
208575973853SYishai Hadas 		event_sub->xa_key_level1 = key_level1;
208675973853SYishai Hadas 		event_sub->xa_key_level2 = obj_id;
208775973853SYishai Hadas 		INIT_LIST_HEAD(&event_sub->obj_list);
208875973853SYishai Hadas 	}
208975973853SYishai Hadas 
209075973853SYishai Hadas 	/* Once all the allocations and the XA data insertions were done we
209175973853SYishai Hadas 	 * can go ahead and add all the subscriptions to the relevant lists
209275973853SYishai Hadas 	 * without concern of a failure.
209375973853SYishai Hadas 	 */
209475973853SYishai Hadas 	list_for_each_entry_safe(event_sub, tmp_sub, &sub_list, event_list) {
209575973853SYishai Hadas 		struct devx_event *event;
209675973853SYishai Hadas 		struct devx_obj_event *obj_event;
209775973853SYishai Hadas 
209875973853SYishai Hadas 		list_del_init(&event_sub->event_list);
209975973853SYishai Hadas 
210075973853SYishai Hadas 		spin_lock_irq(&ev_file->lock);
210175973853SYishai Hadas 		list_add_tail_rcu(&event_sub->file_list,
210275973853SYishai Hadas 				  &ev_file->subscribed_events_list);
210375973853SYishai Hadas 		spin_unlock_irq(&ev_file->lock);
210475973853SYishai Hadas 
210575973853SYishai Hadas 		event = xa_load(&devx_event_table->event_xa,
210675973853SYishai Hadas 				event_sub->xa_key_level1);
210775973853SYishai Hadas 		WARN_ON(!event);
210875973853SYishai Hadas 
210975973853SYishai Hadas 		if (!obj) {
211075973853SYishai Hadas 			list_add_tail_rcu(&event_sub->xa_list,
211175973853SYishai Hadas 					  &event->unaffiliated_list);
211275973853SYishai Hadas 			continue;
211375973853SYishai Hadas 		}
211475973853SYishai Hadas 
211575973853SYishai Hadas 		obj_event = xa_load(&event->object_ids, obj_id);
211675973853SYishai Hadas 		WARN_ON(!obj_event);
211775973853SYishai Hadas 		list_add_tail_rcu(&event_sub->xa_list,
211875973853SYishai Hadas 				  &obj_event->obj_sub_list);
211975973853SYishai Hadas 		list_add_tail_rcu(&event_sub->obj_list,
212075973853SYishai Hadas 				  &obj->event_sub);
212175973853SYishai Hadas 	}
212275973853SYishai Hadas 
212375973853SYishai Hadas 	mutex_unlock(&devx_event_table->event_xa_lock);
212475973853SYishai Hadas 	return 0;
212575973853SYishai Hadas 
212675973853SYishai Hadas err:
212775973853SYishai Hadas 	list_for_each_entry_safe(event_sub, tmp_sub, &sub_list, event_list) {
212875973853SYishai Hadas 		list_del(&event_sub->event_list);
212975973853SYishai Hadas 
213075973853SYishai Hadas 		subscribe_event_xa_dealloc(devx_event_table,
213175973853SYishai Hadas 					   event_sub->xa_key_level1,
213275973853SYishai Hadas 					   obj,
213375973853SYishai Hadas 					   obj_id);
213475973853SYishai Hadas 
213575973853SYishai Hadas 		if (event_sub->eventfd)
213675973853SYishai Hadas 			eventfd_ctx_put(event_sub->eventfd);
21376898d1c6SJason Gunthorpe 		uverbs_uobject_put(&event_sub->ev_file->uobj);
213875973853SYishai Hadas 		kfree(event_sub);
213975973853SYishai Hadas 	}
214075973853SYishai Hadas 
214175973853SYishai Hadas 	mutex_unlock(&devx_event_table->event_xa_lock);
214275973853SYishai Hadas 	return err;
214375973853SYishai Hadas }
214475973853SYishai Hadas 
2145aeae9457SYishai Hadas static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext,
2146aeae9457SYishai Hadas 			 struct uverbs_attr_bundle *attrs,
2147aeae9457SYishai Hadas 			 struct devx_umem *obj)
2148aeae9457SYishai Hadas {
2149aeae9457SYishai Hadas 	u64 addr;
2150aeae9457SYishai Hadas 	size_t size;
2151bccd0622SJason Gunthorpe 	u32 access;
2152aeae9457SYishai Hadas 	int err;
2153aeae9457SYishai Hadas 
2154aeae9457SYishai Hadas 	if (uverbs_copy_from(&addr, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR) ||
2155bccd0622SJason Gunthorpe 	    uverbs_copy_from(&size, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_LEN))
2156aeae9457SYishai Hadas 		return -EFAULT;
2157aeae9457SYishai Hadas 
2158bccd0622SJason Gunthorpe 	err = uverbs_get_flags32(&access, attrs,
2159bccd0622SJason Gunthorpe 				 MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
216047f07f03SYishai Hadas 				 IB_ACCESS_LOCAL_WRITE |
216147f07f03SYishai Hadas 				 IB_ACCESS_REMOTE_WRITE |
216247f07f03SYishai Hadas 				 IB_ACCESS_REMOTE_READ);
2163bccd0622SJason Gunthorpe 	if (err)
2164bccd0622SJason Gunthorpe 		return err;
2165bccd0622SJason Gunthorpe 
2166adac4cb3SJason Gunthorpe 	err = ib_check_mr_access(&dev->ib_dev, access);
2167aeae9457SYishai Hadas 	if (err)
2168aeae9457SYishai Hadas 		return err;
2169aeae9457SYishai Hadas 
2170c320e527SMoni Shoua 	obj->umem = ib_umem_get(&dev->ib_dev, addr, size, access);
2171aeae9457SYishai Hadas 	if (IS_ERR(obj->umem))
2172aeae9457SYishai Hadas 		return PTR_ERR(obj->umem);
2173aeae9457SYishai Hadas 	return 0;
2174aeae9457SYishai Hadas }
2175aeae9457SYishai Hadas 
2176878f7b31SJason Gunthorpe static int devx_umem_reg_cmd_alloc(struct mlx5_ib_dev *dev,
2177878f7b31SJason Gunthorpe 				   struct uverbs_attr_bundle *attrs,
2178b61815e2SJason Gunthorpe 				   struct devx_umem *obj,
2179aeae9457SYishai Hadas 				   struct devx_umem_reg_cmd *cmd)
2180aeae9457SYishai Hadas {
2181878f7b31SJason Gunthorpe 	unsigned int page_size;
2182aeae9457SYishai Hadas 	__be64 *mtt;
2183878f7b31SJason Gunthorpe 	void *umem;
2184878f7b31SJason Gunthorpe 
2185878f7b31SJason Gunthorpe 	/*
2186878f7b31SJason Gunthorpe 	 * We don't know what the user intends to use this umem for, but the HW
2187878f7b31SJason Gunthorpe 	 * restrictions must be met. MR, doorbell records, QP, WQ and CQ all
2188878f7b31SJason Gunthorpe 	 * have different requirements. Since we have no idea how to sort this
2189878f7b31SJason Gunthorpe 	 * out, only support PAGE_SIZE with the expectation that userspace will
2190878f7b31SJason Gunthorpe 	 * provide the necessary alignments inside the known PAGE_SIZE and that
2191878f7b31SJason Gunthorpe 	 * FW will check everything.
2192878f7b31SJason Gunthorpe 	 */
2193878f7b31SJason Gunthorpe 	page_size = ib_umem_find_best_pgoff(
2194878f7b31SJason Gunthorpe 		obj->umem, PAGE_SIZE,
2195878f7b31SJason Gunthorpe 		__mlx5_page_offset_to_bitmask(__mlx5_bit_sz(umem, page_offset),
2196878f7b31SJason Gunthorpe 					      0));
2197878f7b31SJason Gunthorpe 	if (!page_size)
2198878f7b31SJason Gunthorpe 		return -EINVAL;
2199878f7b31SJason Gunthorpe 
2200878f7b31SJason Gunthorpe 	cmd->inlen = MLX5_ST_SZ_BYTES(create_umem_in) +
2201878f7b31SJason Gunthorpe 		     (MLX5_ST_SZ_BYTES(mtt) *
2202878f7b31SJason Gunthorpe 		      ib_umem_num_dma_blocks(obj->umem, page_size));
2203878f7b31SJason Gunthorpe 	cmd->in = uverbs_zalloc(attrs, cmd->inlen);
2204d0b7721cSJason Gunthorpe 	if (IS_ERR(cmd->in))
2205878f7b31SJason Gunthorpe 		return PTR_ERR(cmd->in);
2206aeae9457SYishai Hadas 
2207aeae9457SYishai Hadas 	umem = MLX5_ADDR_OF(create_umem_in, cmd->in, umem);
2208aeae9457SYishai Hadas 	mtt = (__be64 *)MLX5_ADDR_OF(umem, umem, mtt);
2209aeae9457SYishai Hadas 
22106e3722baSYishai Hadas 	MLX5_SET(create_umem_in, cmd->in, opcode, MLX5_CMD_OP_CREATE_UMEM);
22117db0eea9SJason Gunthorpe 	MLX5_SET64(umem, umem, num_of_mtt,
2212878f7b31SJason Gunthorpe 		   ib_umem_num_dma_blocks(obj->umem, page_size));
2213878f7b31SJason Gunthorpe 	MLX5_SET(umem, umem, log_page_size,
2214878f7b31SJason Gunthorpe 		 order_base_2(page_size) - MLX5_ADAPTER_PAGE_SHIFT);
2215878f7b31SJason Gunthorpe 	MLX5_SET(umem, umem, page_offset,
2216878f7b31SJason Gunthorpe 		 ib_umem_dma_offset(obj->umem, page_size));
2217878f7b31SJason Gunthorpe 
2218878f7b31SJason Gunthorpe 	mlx5_ib_populate_pas(obj->umem, page_size, mtt,
2219aeae9457SYishai Hadas 			     (obj->umem->writable ? MLX5_IB_MTT_WRITE : 0) |
2220aeae9457SYishai Hadas 				     MLX5_IB_MTT_READ);
2221878f7b31SJason Gunthorpe 	return 0;
2222aeae9457SYishai Hadas }
2223aeae9457SYishai Hadas 
2224e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_REG)(
222515a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
2226aeae9457SYishai Hadas {
2227aeae9457SYishai Hadas 	struct devx_umem_reg_cmd cmd;
2228aeae9457SYishai Hadas 	struct devx_umem *obj;
2229c36ee46dSJason Gunthorpe 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
2230c36ee46dSJason Gunthorpe 		attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE);
2231aeae9457SYishai Hadas 	u32 obj_id;
223289944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
223389944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
2234c36ee46dSJason Gunthorpe 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
2235aeae9457SYishai Hadas 	int err;
2236aeae9457SYishai Hadas 
2237aeae9457SYishai Hadas 	if (!c->devx_uid)
22387e1335a7SYishai Hadas 		return -EINVAL;
22397e1335a7SYishai Hadas 
2240aeae9457SYishai Hadas 	obj = kzalloc(sizeof(struct devx_umem), GFP_KERNEL);
2241aeae9457SYishai Hadas 	if (!obj)
2242aeae9457SYishai Hadas 		return -ENOMEM;
2243aeae9457SYishai Hadas 
2244aeae9457SYishai Hadas 	err = devx_umem_get(dev, &c->ibucontext, attrs, obj);
2245aeae9457SYishai Hadas 	if (err)
2246aeae9457SYishai Hadas 		goto err_obj_free;
2247aeae9457SYishai Hadas 
2248878f7b31SJason Gunthorpe 	err = devx_umem_reg_cmd_alloc(dev, attrs, obj, &cmd);
2249aeae9457SYishai Hadas 	if (err)
2250aeae9457SYishai Hadas 		goto err_umem_release;
2251aeae9457SYishai Hadas 
22526e3722baSYishai Hadas 	MLX5_SET(create_umem_in, cmd.in, uid, c->devx_uid);
2253aeae9457SYishai Hadas 	err = mlx5_cmd_exec(dev->mdev, cmd.in, cmd.inlen, cmd.out,
2254aeae9457SYishai Hadas 			    sizeof(cmd.out));
2255aeae9457SYishai Hadas 	if (err)
2256b61815e2SJason Gunthorpe 		goto err_umem_release;
2257aeae9457SYishai Hadas 
2258aeae9457SYishai Hadas 	obj->mdev = dev->mdev;
2259aeae9457SYishai Hadas 	uobj->object = obj;
2260aeae9457SYishai Hadas 	devx_obj_build_destroy_cmd(cmd.in, cmd.out, obj->dinbox, &obj->dinlen, &obj_id);
22610ac8903cSJason Gunthorpe 	uverbs_finalize_uobj_create(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE);
2262aeae9457SYishai Hadas 
22630ac8903cSJason Gunthorpe 	err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, &obj_id,
22640ac8903cSJason Gunthorpe 			     sizeof(obj_id));
22650ac8903cSJason Gunthorpe 	return err;
2266aeae9457SYishai Hadas 
2267aeae9457SYishai Hadas err_umem_release:
2268aeae9457SYishai Hadas 	ib_umem_release(obj->umem);
2269aeae9457SYishai Hadas err_obj_free:
2270aeae9457SYishai Hadas 	kfree(obj);
2271aeae9457SYishai Hadas 	return err;
2272aeae9457SYishai Hadas }
2273aeae9457SYishai Hadas 
2274aeae9457SYishai Hadas static int devx_umem_cleanup(struct ib_uobject *uobject,
2275a6a3797dSShamir Rabinovitch 			     enum rdma_remove_reason why,
2276a6a3797dSShamir Rabinovitch 			     struct uverbs_attr_bundle *attrs)
2277aeae9457SYishai Hadas {
2278aeae9457SYishai Hadas 	struct devx_umem *obj = uobject->object;
2279aeae9457SYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
2280aeae9457SYishai Hadas 	int err;
2281aeae9457SYishai Hadas 
2282aeae9457SYishai Hadas 	err = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out));
2283efa968eeSLeon Romanovsky 	if (err)
2284aeae9457SYishai Hadas 		return err;
2285aeae9457SYishai Hadas 
2286aeae9457SYishai Hadas 	ib_umem_release(obj->umem);
2287aeae9457SYishai Hadas 	kfree(obj);
2288aeae9457SYishai Hadas 	return 0;
2289aeae9457SYishai Hadas }
2290aeae9457SYishai Hadas 
22915ec9d8eeSYishai Hadas static bool is_unaffiliated_event(struct mlx5_core_dev *dev,
22925ec9d8eeSYishai Hadas 				  unsigned long event_type)
22935ec9d8eeSYishai Hadas {
22945ec9d8eeSYishai Hadas 	__be64 *unaff_events;
22955ec9d8eeSYishai Hadas 	int mask_entry;
22965ec9d8eeSYishai Hadas 	int mask_bit;
22975ec9d8eeSYishai Hadas 
22985ec9d8eeSYishai Hadas 	if (!MLX5_CAP_GEN(dev, event_cap))
22995ec9d8eeSYishai Hadas 		return is_legacy_unaffiliated_event_num(event_type);
23005ec9d8eeSYishai Hadas 
23015ec9d8eeSYishai Hadas 	unaff_events = MLX5_CAP_DEV_EVENT(dev,
23025ec9d8eeSYishai Hadas 					  user_unaffiliated_events);
23035ec9d8eeSYishai Hadas 	WARN_ON(event_type > MAX_SUPP_EVENT_NUM);
23045ec9d8eeSYishai Hadas 
23055ec9d8eeSYishai Hadas 	mask_entry = event_type / 64;
23065ec9d8eeSYishai Hadas 	mask_bit = event_type % 64;
23075ec9d8eeSYishai Hadas 
23085ec9d8eeSYishai Hadas 	if (!(be64_to_cpu(unaff_events[mask_entry]) & (1ull << mask_bit)))
23095ec9d8eeSYishai Hadas 		return false;
23105ec9d8eeSYishai Hadas 
23115ec9d8eeSYishai Hadas 	return true;
23125ec9d8eeSYishai Hadas }
23135ec9d8eeSYishai Hadas 
23145ec9d8eeSYishai Hadas static u32 devx_get_obj_id_from_event(unsigned long event_type, void *data)
23155ec9d8eeSYishai Hadas {
23165ec9d8eeSYishai Hadas 	struct mlx5_eqe *eqe = data;
23175ec9d8eeSYishai Hadas 	u32 obj_id = 0;
23185ec9d8eeSYishai Hadas 
23195ec9d8eeSYishai Hadas 	switch (event_type) {
23205ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_SRQ_CATAS_ERROR:
23215ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_SRQ_RQ_LIMIT:
23225ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_PATH_MIG:
23235ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_COMM_EST:
23245ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_SQ_DRAINED:
23255ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_SRQ_LAST_WQE:
23265ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_WQ_CATAS_ERROR:
23275ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_PATH_MIG_FAILED:
23285ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR:
23295ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR:
23305ec9d8eeSYishai Hadas 		obj_id = be32_to_cpu(eqe->data.qp_srq.qp_srq_n) & 0xffffff;
23315ec9d8eeSYishai Hadas 		break;
2332972d7560SYishai Hadas 	case MLX5_EVENT_TYPE_XRQ_ERROR:
2333972d7560SYishai Hadas 		obj_id = be32_to_cpu(eqe->data.xrq_err.type_xrqn) & 0xffffff;
2334972d7560SYishai Hadas 		break;
23355ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_DCT_DRAINED:
2336972d7560SYishai Hadas 	case MLX5_EVENT_TYPE_DCT_KEY_VIOLATION:
23375ec9d8eeSYishai Hadas 		obj_id = be32_to_cpu(eqe->data.dct.dctn) & 0xffffff;
23385ec9d8eeSYishai Hadas 		break;
23395ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_CQ_ERROR:
23405ec9d8eeSYishai Hadas 		obj_id = be32_to_cpu(eqe->data.cq_err.cqn) & 0xffffff;
23415ec9d8eeSYishai Hadas 		break;
23425ec9d8eeSYishai Hadas 	default:
23435ec9d8eeSYishai Hadas 		obj_id = MLX5_GET(affiliated_event_header, &eqe->data, obj_id);
23445ec9d8eeSYishai Hadas 		break;
23455ec9d8eeSYishai Hadas 	}
23465ec9d8eeSYishai Hadas 
23475ec9d8eeSYishai Hadas 	return obj_id;
23485ec9d8eeSYishai Hadas }
23495ec9d8eeSYishai Hadas 
23505ec9d8eeSYishai Hadas static int deliver_event(struct devx_event_subscription *event_sub,
23515ec9d8eeSYishai Hadas 			 const void *data)
23525ec9d8eeSYishai Hadas {
23535ec9d8eeSYishai Hadas 	struct devx_async_event_file *ev_file;
23545ec9d8eeSYishai Hadas 	struct devx_async_event_data *event_data;
23555ec9d8eeSYishai Hadas 	unsigned long flags;
23565ec9d8eeSYishai Hadas 
23575ec9d8eeSYishai Hadas 	ev_file = event_sub->ev_file;
23585ec9d8eeSYishai Hadas 
23595ec9d8eeSYishai Hadas 	if (ev_file->omit_data) {
23605ec9d8eeSYishai Hadas 		spin_lock_irqsave(&ev_file->lock, flags);
2361a8af8694SYishai Hadas 		if (!list_empty(&event_sub->event_list) ||
2362a8af8694SYishai Hadas 		    ev_file->is_destroyed) {
23635ec9d8eeSYishai Hadas 			spin_unlock_irqrestore(&ev_file->lock, flags);
23645ec9d8eeSYishai Hadas 			return 0;
23655ec9d8eeSYishai Hadas 		}
23665ec9d8eeSYishai Hadas 
23675ec9d8eeSYishai Hadas 		list_add_tail(&event_sub->event_list, &ev_file->event_list);
23685ec9d8eeSYishai Hadas 		spin_unlock_irqrestore(&ev_file->lock, flags);
23695ec9d8eeSYishai Hadas 		wake_up_interruptible(&ev_file->poll_wait);
23705ec9d8eeSYishai Hadas 		return 0;
23715ec9d8eeSYishai Hadas 	}
23725ec9d8eeSYishai Hadas 
23735ec9d8eeSYishai Hadas 	event_data = kzalloc(sizeof(*event_data) + sizeof(struct mlx5_eqe),
23745ec9d8eeSYishai Hadas 			     GFP_ATOMIC);
23755ec9d8eeSYishai Hadas 	if (!event_data) {
23765ec9d8eeSYishai Hadas 		spin_lock_irqsave(&ev_file->lock, flags);
23775ec9d8eeSYishai Hadas 		ev_file->is_overflow_err = 1;
23785ec9d8eeSYishai Hadas 		spin_unlock_irqrestore(&ev_file->lock, flags);
23795ec9d8eeSYishai Hadas 		return -ENOMEM;
23805ec9d8eeSYishai Hadas 	}
23815ec9d8eeSYishai Hadas 
23825ec9d8eeSYishai Hadas 	event_data->hdr.cookie = event_sub->cookie;
23835ec9d8eeSYishai Hadas 	memcpy(event_data->hdr.out_data, data, sizeof(struct mlx5_eqe));
23845ec9d8eeSYishai Hadas 
23855ec9d8eeSYishai Hadas 	spin_lock_irqsave(&ev_file->lock, flags);
2386f7c8416cSJason Gunthorpe 	if (!ev_file->is_destroyed)
23875ec9d8eeSYishai Hadas 		list_add_tail(&event_data->list, &ev_file->event_list);
2388f7c8416cSJason Gunthorpe 	else
2389f7c8416cSJason Gunthorpe 		kfree(event_data);
23905ec9d8eeSYishai Hadas 	spin_unlock_irqrestore(&ev_file->lock, flags);
23915ec9d8eeSYishai Hadas 	wake_up_interruptible(&ev_file->poll_wait);
23925ec9d8eeSYishai Hadas 
23935ec9d8eeSYishai Hadas 	return 0;
23945ec9d8eeSYishai Hadas }
23955ec9d8eeSYishai Hadas 
23965ec9d8eeSYishai Hadas static void dispatch_event_fd(struct list_head *fd_list,
23975ec9d8eeSYishai Hadas 			      const void *data)
23985ec9d8eeSYishai Hadas {
23995ec9d8eeSYishai Hadas 	struct devx_event_subscription *item;
24005ec9d8eeSYishai Hadas 
24015ec9d8eeSYishai Hadas 	list_for_each_entry_rcu(item, fd_list, xa_list) {
24026898d1c6SJason Gunthorpe 		if (item->eventfd)
24035ec9d8eeSYishai Hadas 			eventfd_signal(item->eventfd, 1);
24046898d1c6SJason Gunthorpe 		else
24055ec9d8eeSYishai Hadas 			deliver_event(item, data);
24065ec9d8eeSYishai Hadas 	}
24075ec9d8eeSYishai Hadas }
24085ec9d8eeSYishai Hadas 
2409e337dd53SYishai Hadas static int devx_event_notifier(struct notifier_block *nb,
2410e337dd53SYishai Hadas 			       unsigned long event_type, void *data)
2411e337dd53SYishai Hadas {
24125ec9d8eeSYishai Hadas 	struct mlx5_devx_event_table *table;
24135ec9d8eeSYishai Hadas 	struct mlx5_ib_dev *dev;
24145ec9d8eeSYishai Hadas 	struct devx_event *event;
24155ec9d8eeSYishai Hadas 	struct devx_obj_event *obj_event;
24165ec9d8eeSYishai Hadas 	u16 obj_type = 0;
24175ec9d8eeSYishai Hadas 	bool is_unaffiliated;
24185ec9d8eeSYishai Hadas 	u32 obj_id;
24195ec9d8eeSYishai Hadas 
24205ec9d8eeSYishai Hadas 	/* Explicit filtering to kernel events which may occur frequently */
24215ec9d8eeSYishai Hadas 	if (event_type == MLX5_EVENT_TYPE_CMD ||
24225ec9d8eeSYishai Hadas 	    event_type == MLX5_EVENT_TYPE_PAGE_REQUEST)
24235ec9d8eeSYishai Hadas 		return NOTIFY_OK;
24245ec9d8eeSYishai Hadas 
24255ec9d8eeSYishai Hadas 	table = container_of(nb, struct mlx5_devx_event_table, devx_nb.nb);
24265ec9d8eeSYishai Hadas 	dev = container_of(table, struct mlx5_ib_dev, devx_event_table);
24275ec9d8eeSYishai Hadas 	is_unaffiliated = is_unaffiliated_event(dev->mdev, event_type);
24285ec9d8eeSYishai Hadas 
24295ec9d8eeSYishai Hadas 	if (!is_unaffiliated)
24305ec9d8eeSYishai Hadas 		obj_type = get_event_obj_type(event_type, data);
24315ec9d8eeSYishai Hadas 
24325ec9d8eeSYishai Hadas 	rcu_read_lock();
24335ec9d8eeSYishai Hadas 	event = xa_load(&table->event_xa, event_type | (obj_type << 16));
24345ec9d8eeSYishai Hadas 	if (!event) {
24355ec9d8eeSYishai Hadas 		rcu_read_unlock();
2436e337dd53SYishai Hadas 		return NOTIFY_DONE;
2437e337dd53SYishai Hadas 	}
2438e337dd53SYishai Hadas 
24395ec9d8eeSYishai Hadas 	if (is_unaffiliated) {
24405ec9d8eeSYishai Hadas 		dispatch_event_fd(&event->unaffiliated_list, data);
24415ec9d8eeSYishai Hadas 		rcu_read_unlock();
24425ec9d8eeSYishai Hadas 		return NOTIFY_OK;
24435ec9d8eeSYishai Hadas 	}
24445ec9d8eeSYishai Hadas 
24455ec9d8eeSYishai Hadas 	obj_id = devx_get_obj_id_from_event(event_type, data);
24465ec9d8eeSYishai Hadas 	obj_event = xa_load(&event->object_ids, obj_id);
24475ec9d8eeSYishai Hadas 	if (!obj_event) {
24485ec9d8eeSYishai Hadas 		rcu_read_unlock();
24495ec9d8eeSYishai Hadas 		return NOTIFY_DONE;
24505ec9d8eeSYishai Hadas 	}
24515ec9d8eeSYishai Hadas 
24525ec9d8eeSYishai Hadas 	dispatch_event_fd(&obj_event->obj_sub_list, data);
24535ec9d8eeSYishai Hadas 
24545ec9d8eeSYishai Hadas 	rcu_read_unlock();
24555ec9d8eeSYishai Hadas 	return NOTIFY_OK;
24565ec9d8eeSYishai Hadas }
24575ec9d8eeSYishai Hadas 
2458d8b7515eSLeon Romanovsky int mlx5_ib_devx_init(struct mlx5_ib_dev *dev)
2459e337dd53SYishai Hadas {
2460e337dd53SYishai Hadas 	struct mlx5_devx_event_table *table = &dev->devx_event_table;
2461d8b7515eSLeon Romanovsky 	int uid;
2462e337dd53SYishai Hadas 
2463d8b7515eSLeon Romanovsky 	uid = mlx5_ib_devx_create(dev, false);
2464d8b7515eSLeon Romanovsky 	if (uid > 0) {
2465d8b7515eSLeon Romanovsky 		dev->devx_whitelist_uid = uid;
2466e337dd53SYishai Hadas 		xa_init(&table->event_xa);
2467e337dd53SYishai Hadas 		mutex_init(&table->event_xa_lock);
2468e337dd53SYishai Hadas 		MLX5_NB_INIT(&table->devx_nb, devx_event_notifier, NOTIFY_ANY);
2469e337dd53SYishai Hadas 		mlx5_eq_notifier_register(dev->mdev, &table->devx_nb);
2470e337dd53SYishai Hadas 	}
2471e337dd53SYishai Hadas 
2472d8b7515eSLeon Romanovsky 	return 0;
2473d8b7515eSLeon Romanovsky }
2474d8b7515eSLeon Romanovsky 
2475d8b7515eSLeon Romanovsky void mlx5_ib_devx_cleanup(struct mlx5_ib_dev *dev)
2476e337dd53SYishai Hadas {
2477e337dd53SYishai Hadas 	struct mlx5_devx_event_table *table = &dev->devx_event_table;
247875973853SYishai Hadas 	struct devx_event_subscription *sub, *tmp;
247975973853SYishai Hadas 	struct devx_event *event;
2480e337dd53SYishai Hadas 	void *entry;
2481e337dd53SYishai Hadas 	unsigned long id;
2482e337dd53SYishai Hadas 
2483d8b7515eSLeon Romanovsky 	if (dev->devx_whitelist_uid) {
2484e337dd53SYishai Hadas 		mlx5_eq_notifier_unregister(dev->mdev, &table->devx_nb);
248575973853SYishai Hadas 		mutex_lock(&dev->devx_event_table.event_xa_lock);
248675973853SYishai Hadas 		xa_for_each(&table->event_xa, id, entry) {
248775973853SYishai Hadas 			event = entry;
2488d8b7515eSLeon Romanovsky 			list_for_each_entry_safe(
2489d8b7515eSLeon Romanovsky 				sub, tmp, &event->unaffiliated_list, xa_list)
249075973853SYishai Hadas 				devx_cleanup_subscription(dev, sub);
2491e337dd53SYishai Hadas 			kfree(entry);
249275973853SYishai Hadas 		}
249375973853SYishai Hadas 		mutex_unlock(&dev->devx_event_table.event_xa_lock);
2494e337dd53SYishai Hadas 		xa_destroy(&table->event_xa);
2495d8b7515eSLeon Romanovsky 
2496d8b7515eSLeon Romanovsky 		mlx5_ib_devx_destroy(dev, dev->devx_whitelist_uid);
2497d8b7515eSLeon Romanovsky 	}
2498e337dd53SYishai Hadas }
2499e337dd53SYishai Hadas 
25006bf8f22aSYishai Hadas static ssize_t devx_async_cmd_event_read(struct file *filp, char __user *buf,
25016bf8f22aSYishai Hadas 					 size_t count, loff_t *pos)
25026bf8f22aSYishai Hadas {
25034accbb3fSYishai Hadas 	struct devx_async_cmd_event_file *comp_ev_file = filp->private_data;
25044accbb3fSYishai Hadas 	struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue;
25054accbb3fSYishai Hadas 	struct devx_async_data *event;
25064accbb3fSYishai Hadas 	int ret = 0;
25074accbb3fSYishai Hadas 	size_t eventsz;
25084accbb3fSYishai Hadas 
25094accbb3fSYishai Hadas 	spin_lock_irq(&ev_queue->lock);
25104accbb3fSYishai Hadas 
25114accbb3fSYishai Hadas 	while (list_empty(&ev_queue->event_list)) {
25124accbb3fSYishai Hadas 		spin_unlock_irq(&ev_queue->lock);
25134accbb3fSYishai Hadas 
25144accbb3fSYishai Hadas 		if (filp->f_flags & O_NONBLOCK)
25154accbb3fSYishai Hadas 			return -EAGAIN;
25164accbb3fSYishai Hadas 
25174accbb3fSYishai Hadas 		if (wait_event_interruptible(
25184accbb3fSYishai Hadas 			    ev_queue->poll_wait,
2519eaebaf77SYishai Hadas 			    (!list_empty(&ev_queue->event_list) ||
2520eaebaf77SYishai Hadas 			     ev_queue->is_destroyed))) {
25214accbb3fSYishai Hadas 			return -ERESTARTSYS;
25224accbb3fSYishai Hadas 		}
2523eaebaf77SYishai Hadas 
25244accbb3fSYishai Hadas 		spin_lock_irq(&ev_queue->lock);
2525a8af8694SYishai Hadas 		if (ev_queue->is_destroyed) {
2526a8af8694SYishai Hadas 			spin_unlock_irq(&ev_queue->lock);
2527a8af8694SYishai Hadas 			return -EIO;
2528a8af8694SYishai Hadas 		}
25294accbb3fSYishai Hadas 	}
25304accbb3fSYishai Hadas 
25314accbb3fSYishai Hadas 	event = list_entry(ev_queue->event_list.next,
25324accbb3fSYishai Hadas 			   struct devx_async_data, list);
25334accbb3fSYishai Hadas 	eventsz = event->cmd_out_len +
25344accbb3fSYishai Hadas 			sizeof(struct mlx5_ib_uapi_devx_async_cmd_hdr);
25354accbb3fSYishai Hadas 
25364accbb3fSYishai Hadas 	if (eventsz > count) {
25374accbb3fSYishai Hadas 		spin_unlock_irq(&ev_queue->lock);
25384accbb3fSYishai Hadas 		return -ENOSPC;
25394accbb3fSYishai Hadas 	}
25404accbb3fSYishai Hadas 
25414accbb3fSYishai Hadas 	list_del(ev_queue->event_list.next);
25424accbb3fSYishai Hadas 	spin_unlock_irq(&ev_queue->lock);
25434accbb3fSYishai Hadas 
25444accbb3fSYishai Hadas 	if (copy_to_user(buf, &event->hdr, eventsz))
25454accbb3fSYishai Hadas 		ret = -EFAULT;
25464accbb3fSYishai Hadas 	else
25474accbb3fSYishai Hadas 		ret = eventsz;
25484accbb3fSYishai Hadas 
25494accbb3fSYishai Hadas 	atomic_sub(event->cmd_out_len, &ev_queue->bytes_in_use);
25504accbb3fSYishai Hadas 	kvfree(event);
25514accbb3fSYishai Hadas 	return ret;
25526bf8f22aSYishai Hadas }
25536bf8f22aSYishai Hadas 
25546bf8f22aSYishai Hadas static __poll_t devx_async_cmd_event_poll(struct file *filp,
25556bf8f22aSYishai Hadas 					      struct poll_table_struct *wait)
25566bf8f22aSYishai Hadas {
25574accbb3fSYishai Hadas 	struct devx_async_cmd_event_file *comp_ev_file = filp->private_data;
25584accbb3fSYishai Hadas 	struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue;
25594accbb3fSYishai Hadas 	__poll_t pollflags = 0;
25604accbb3fSYishai Hadas 
25614accbb3fSYishai Hadas 	poll_wait(filp, &ev_queue->poll_wait, wait);
25624accbb3fSYishai Hadas 
25634accbb3fSYishai Hadas 	spin_lock_irq(&ev_queue->lock);
2564eaebaf77SYishai Hadas 	if (ev_queue->is_destroyed)
2565eaebaf77SYishai Hadas 		pollflags = EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
2566eaebaf77SYishai Hadas 	else if (!list_empty(&ev_queue->event_list))
25674accbb3fSYishai Hadas 		pollflags = EPOLLIN | EPOLLRDNORM;
25684accbb3fSYishai Hadas 	spin_unlock_irq(&ev_queue->lock);
25694accbb3fSYishai Hadas 
25704accbb3fSYishai Hadas 	return pollflags;
25716bf8f22aSYishai Hadas }
25726bf8f22aSYishai Hadas 
25731f687edeSBart Van Assche static const struct file_operations devx_async_cmd_event_fops = {
25746bf8f22aSYishai Hadas 	.owner	 = THIS_MODULE,
25756bf8f22aSYishai Hadas 	.read	 = devx_async_cmd_event_read,
25766bf8f22aSYishai Hadas 	.poll    = devx_async_cmd_event_poll,
2577f7c8416cSJason Gunthorpe 	.release = uverbs_uobject_fd_release,
25786bf8f22aSYishai Hadas 	.llseek	 = no_llseek,
25796bf8f22aSYishai Hadas };
25806bf8f22aSYishai Hadas 
25812afc5e1bSYishai Hadas static ssize_t devx_async_event_read(struct file *filp, char __user *buf,
25822afc5e1bSYishai Hadas 				     size_t count, loff_t *pos)
25832afc5e1bSYishai Hadas {
25845ec9d8eeSYishai Hadas 	struct devx_async_event_file *ev_file = filp->private_data;
25855ec9d8eeSYishai Hadas 	struct devx_event_subscription *event_sub;
25863f649ab7SKees Cook 	struct devx_async_event_data *event;
25875ec9d8eeSYishai Hadas 	int ret = 0;
25885ec9d8eeSYishai Hadas 	size_t eventsz;
25895ec9d8eeSYishai Hadas 	bool omit_data;
25905ec9d8eeSYishai Hadas 	void *event_data;
25915ec9d8eeSYishai Hadas 
25925ec9d8eeSYishai Hadas 	omit_data = ev_file->omit_data;
25935ec9d8eeSYishai Hadas 
25945ec9d8eeSYishai Hadas 	spin_lock_irq(&ev_file->lock);
25955ec9d8eeSYishai Hadas 
25965ec9d8eeSYishai Hadas 	if (ev_file->is_overflow_err) {
25975ec9d8eeSYishai Hadas 		ev_file->is_overflow_err = 0;
25985ec9d8eeSYishai Hadas 		spin_unlock_irq(&ev_file->lock);
25995ec9d8eeSYishai Hadas 		return -EOVERFLOW;
26005ec9d8eeSYishai Hadas 	}
26015ec9d8eeSYishai Hadas 
26025ec9d8eeSYishai Hadas 
26035ec9d8eeSYishai Hadas 	while (list_empty(&ev_file->event_list)) {
26045ec9d8eeSYishai Hadas 		spin_unlock_irq(&ev_file->lock);
26055ec9d8eeSYishai Hadas 
26065ec9d8eeSYishai Hadas 		if (filp->f_flags & O_NONBLOCK)
26075ec9d8eeSYishai Hadas 			return -EAGAIN;
26085ec9d8eeSYishai Hadas 
26095ec9d8eeSYishai Hadas 		if (wait_event_interruptible(ev_file->poll_wait,
26105ec9d8eeSYishai Hadas 			    (!list_empty(&ev_file->event_list) ||
26115ec9d8eeSYishai Hadas 			     ev_file->is_destroyed))) {
26125ec9d8eeSYishai Hadas 			return -ERESTARTSYS;
26135ec9d8eeSYishai Hadas 		}
26145ec9d8eeSYishai Hadas 
26155ec9d8eeSYishai Hadas 		spin_lock_irq(&ev_file->lock);
26165ec9d8eeSYishai Hadas 		if (ev_file->is_destroyed) {
26175ec9d8eeSYishai Hadas 			spin_unlock_irq(&ev_file->lock);
26185ec9d8eeSYishai Hadas 			return -EIO;
26195ec9d8eeSYishai Hadas 		}
26205ec9d8eeSYishai Hadas 	}
26215ec9d8eeSYishai Hadas 
26225ec9d8eeSYishai Hadas 	if (omit_data) {
26235ec9d8eeSYishai Hadas 		event_sub = list_first_entry(&ev_file->event_list,
26245ec9d8eeSYishai Hadas 					struct devx_event_subscription,
26255ec9d8eeSYishai Hadas 					event_list);
26265ec9d8eeSYishai Hadas 		eventsz = sizeof(event_sub->cookie);
26275ec9d8eeSYishai Hadas 		event_data = &event_sub->cookie;
26285ec9d8eeSYishai Hadas 	} else {
26295ec9d8eeSYishai Hadas 		event = list_first_entry(&ev_file->event_list,
26305ec9d8eeSYishai Hadas 				      struct devx_async_event_data, list);
26315ec9d8eeSYishai Hadas 		eventsz = sizeof(struct mlx5_eqe) +
26325ec9d8eeSYishai Hadas 			sizeof(struct mlx5_ib_uapi_devx_async_event_hdr);
26335ec9d8eeSYishai Hadas 		event_data = &event->hdr;
26345ec9d8eeSYishai Hadas 	}
26355ec9d8eeSYishai Hadas 
26365ec9d8eeSYishai Hadas 	if (eventsz > count) {
26375ec9d8eeSYishai Hadas 		spin_unlock_irq(&ev_file->lock);
26382afc5e1bSYishai Hadas 		return -EINVAL;
26392afc5e1bSYishai Hadas 	}
26402afc5e1bSYishai Hadas 
26415ec9d8eeSYishai Hadas 	if (omit_data)
26425ec9d8eeSYishai Hadas 		list_del_init(&event_sub->event_list);
26435ec9d8eeSYishai Hadas 	else
26445ec9d8eeSYishai Hadas 		list_del(&event->list);
26455ec9d8eeSYishai Hadas 
26465ec9d8eeSYishai Hadas 	spin_unlock_irq(&ev_file->lock);
26475ec9d8eeSYishai Hadas 
26485ec9d8eeSYishai Hadas 	if (copy_to_user(buf, event_data, eventsz))
26495ec9d8eeSYishai Hadas 		/* This points to an application issue, not a kernel concern */
26505ec9d8eeSYishai Hadas 		ret = -EFAULT;
26515ec9d8eeSYishai Hadas 	else
26525ec9d8eeSYishai Hadas 		ret = eventsz;
26535ec9d8eeSYishai Hadas 
26545ec9d8eeSYishai Hadas 	if (!omit_data)
26555ec9d8eeSYishai Hadas 		kfree(event);
26565ec9d8eeSYishai Hadas 	return ret;
26575ec9d8eeSYishai Hadas }
26585ec9d8eeSYishai Hadas 
26592afc5e1bSYishai Hadas static __poll_t devx_async_event_poll(struct file *filp,
26602afc5e1bSYishai Hadas 				      struct poll_table_struct *wait)
26612afc5e1bSYishai Hadas {
26625ec9d8eeSYishai Hadas 	struct devx_async_event_file *ev_file = filp->private_data;
26635ec9d8eeSYishai Hadas 	__poll_t pollflags = 0;
26645ec9d8eeSYishai Hadas 
26655ec9d8eeSYishai Hadas 	poll_wait(filp, &ev_file->poll_wait, wait);
26665ec9d8eeSYishai Hadas 
26675ec9d8eeSYishai Hadas 	spin_lock_irq(&ev_file->lock);
26685ec9d8eeSYishai Hadas 	if (ev_file->is_destroyed)
26695ec9d8eeSYishai Hadas 		pollflags = EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
26705ec9d8eeSYishai Hadas 	else if (!list_empty(&ev_file->event_list))
26715ec9d8eeSYishai Hadas 		pollflags = EPOLLIN | EPOLLRDNORM;
26725ec9d8eeSYishai Hadas 	spin_unlock_irq(&ev_file->lock);
26735ec9d8eeSYishai Hadas 
26745ec9d8eeSYishai Hadas 	return pollflags;
26752afc5e1bSYishai Hadas }
26762afc5e1bSYishai Hadas 
26776898d1c6SJason Gunthorpe static void devx_free_subscription(struct rcu_head *rcu)
26786898d1c6SJason Gunthorpe {
26796898d1c6SJason Gunthorpe 	struct devx_event_subscription *event_sub =
26806898d1c6SJason Gunthorpe 		container_of(rcu, struct devx_event_subscription, rcu);
26816898d1c6SJason Gunthorpe 
26826898d1c6SJason Gunthorpe 	if (event_sub->eventfd)
26836898d1c6SJason Gunthorpe 		eventfd_ctx_put(event_sub->eventfd);
26846898d1c6SJason Gunthorpe 	uverbs_uobject_put(&event_sub->ev_file->uobj);
26856898d1c6SJason Gunthorpe 	kfree(event_sub);
26866898d1c6SJason Gunthorpe }
26876898d1c6SJason Gunthorpe 
2688f7c8416cSJason Gunthorpe static const struct file_operations devx_async_event_fops = {
2689f7c8416cSJason Gunthorpe 	.owner	 = THIS_MODULE,
2690f7c8416cSJason Gunthorpe 	.read	 = devx_async_event_read,
2691f7c8416cSJason Gunthorpe 	.poll    = devx_async_event_poll,
2692f7c8416cSJason Gunthorpe 	.release = uverbs_uobject_fd_release,
2693f7c8416cSJason Gunthorpe 	.llseek	 = no_llseek,
2694f7c8416cSJason Gunthorpe };
2695f7c8416cSJason Gunthorpe 
2696c5633a72SLeon Romanovsky static void devx_async_cmd_event_destroy_uobj(struct ib_uobject *uobj,
2697f7c8416cSJason Gunthorpe 					      enum rdma_remove_reason why)
26982afc5e1bSYishai Hadas {
2699f7c8416cSJason Gunthorpe 	struct devx_async_cmd_event_file *comp_ev_file =
2700f7c8416cSJason Gunthorpe 		container_of(uobj, struct devx_async_cmd_event_file,
2701f7c8416cSJason Gunthorpe 			     uobj);
2702f7c8416cSJason Gunthorpe 	struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue;
2703f7c8416cSJason Gunthorpe 	struct devx_async_data *entry, *tmp;
2704f7c8416cSJason Gunthorpe 
2705f7c8416cSJason Gunthorpe 	spin_lock_irq(&ev_queue->lock);
2706f7c8416cSJason Gunthorpe 	ev_queue->is_destroyed = 1;
2707f7c8416cSJason Gunthorpe 	spin_unlock_irq(&ev_queue->lock);
2708f7c8416cSJason Gunthorpe 	wake_up_interruptible(&ev_queue->poll_wait);
2709f7c8416cSJason Gunthorpe 
2710f7c8416cSJason Gunthorpe 	mlx5_cmd_cleanup_async_ctx(&comp_ev_file->async_ctx);
2711f7c8416cSJason Gunthorpe 
2712f7c8416cSJason Gunthorpe 	spin_lock_irq(&comp_ev_file->ev_queue.lock);
2713f7c8416cSJason Gunthorpe 	list_for_each_entry_safe(entry, tmp,
2714a8af8694SYishai Hadas 				 &comp_ev_file->ev_queue.event_list, list) {
2715a8af8694SYishai Hadas 		list_del(&entry->list);
2716f7c8416cSJason Gunthorpe 		kvfree(entry);
2717a8af8694SYishai Hadas 	}
2718f7c8416cSJason Gunthorpe 	spin_unlock_irq(&comp_ev_file->ev_queue.lock);
2719f7c8416cSJason Gunthorpe };
2720f7c8416cSJason Gunthorpe 
2721c5633a72SLeon Romanovsky static void devx_async_event_destroy_uobj(struct ib_uobject *uobj,
2722f7c8416cSJason Gunthorpe 					  enum rdma_remove_reason why)
2723f7c8416cSJason Gunthorpe {
2724f7c8416cSJason Gunthorpe 	struct devx_async_event_file *ev_file =
2725f7c8416cSJason Gunthorpe 		container_of(uobj, struct devx_async_event_file,
2726f7c8416cSJason Gunthorpe 			     uobj);
272775973853SYishai Hadas 	struct devx_event_subscription *event_sub, *event_sub_tmp;
2728e9eec6a5SYishai Hadas 	struct mlx5_ib_dev *dev = ev_file->dev;
272975973853SYishai Hadas 
2730f7c8416cSJason Gunthorpe 	spin_lock_irq(&ev_file->lock);
2731f7c8416cSJason Gunthorpe 	ev_file->is_destroyed = 1;
2732a8af8694SYishai Hadas 
2733a8af8694SYishai Hadas 	/* free the pending events allocation */
2734a8af8694SYishai Hadas 	if (ev_file->omit_data) {
2735a8af8694SYishai Hadas 		struct devx_event_subscription *event_sub, *tmp;
2736a8af8694SYishai Hadas 
2737a8af8694SYishai Hadas 		list_for_each_entry_safe(event_sub, tmp, &ev_file->event_list,
2738a8af8694SYishai Hadas 					 event_list)
2739a8af8694SYishai Hadas 			list_del_init(&event_sub->event_list);
2740a8af8694SYishai Hadas 
2741a8af8694SYishai Hadas 	} else {
2742a8af8694SYishai Hadas 		struct devx_async_event_data *entry, *tmp;
2743a8af8694SYishai Hadas 
2744a8af8694SYishai Hadas 		list_for_each_entry_safe(entry, tmp, &ev_file->event_list,
2745a8af8694SYishai Hadas 					 list) {
2746a8af8694SYishai Hadas 			list_del(&entry->list);
2747a8af8694SYishai Hadas 			kfree(entry);
2748a8af8694SYishai Hadas 		}
2749a8af8694SYishai Hadas 	}
2750a8af8694SYishai Hadas 
2751f7c8416cSJason Gunthorpe 	spin_unlock_irq(&ev_file->lock);
2752f7c8416cSJason Gunthorpe 	wake_up_interruptible(&ev_file->poll_wait);
2753f7c8416cSJason Gunthorpe 
2754e9eec6a5SYishai Hadas 	mutex_lock(&dev->devx_event_table.event_xa_lock);
275575973853SYishai Hadas 	/* delete the subscriptions which are related to this FD */
275675973853SYishai Hadas 	list_for_each_entry_safe(event_sub, event_sub_tmp,
275775973853SYishai Hadas 				 &ev_file->subscribed_events_list, file_list) {
2758e9eec6a5SYishai Hadas 		devx_cleanup_subscription(dev, event_sub);
275975973853SYishai Hadas 		list_del_rcu(&event_sub->file_list);
276075973853SYishai Hadas 		/* subscription may not be used by the read API any more */
27616898d1c6SJason Gunthorpe 		call_rcu(&event_sub->rcu, devx_free_subscription);
276275973853SYishai Hadas 	}
2763e9eec6a5SYishai Hadas 	mutex_unlock(&dev->devx_event_table.event_xa_lock);
276475973853SYishai Hadas 
2765e9eec6a5SYishai Hadas 	put_device(&dev->ib_dev.dev);
27662afc5e1bSYishai Hadas };
27672afc5e1bSYishai Hadas 
27689a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
27699a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_UMEM_REG,
27709a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE,
2771aeae9457SYishai Hadas 			MLX5_IB_OBJECT_DEVX_UMEM,
2772aeae9457SYishai Hadas 			UVERBS_ACCESS_NEW,
277383bb4442SJason Gunthorpe 			UA_MANDATORY),
27749a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR,
27759a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u64),
277683bb4442SJason Gunthorpe 			   UA_MANDATORY),
27779a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_LEN,
27789a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u64),
277983bb4442SJason Gunthorpe 			   UA_MANDATORY),
2780bccd0622SJason Gunthorpe 	UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
2781bccd0622SJason Gunthorpe 			     enum ib_access_flags),
27829a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID,
27839a119cd5SJason Gunthorpe 			    UVERBS_ATTR_TYPE(u32),
278483bb4442SJason Gunthorpe 			    UA_MANDATORY));
2785aeae9457SYishai Hadas 
2786528922afSYishai Hadas DECLARE_UVERBS_NAMED_METHOD_DESTROY(
27879a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_UMEM_DEREG,
27889a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_DEREG_HANDLE,
2789aeae9457SYishai Hadas 			MLX5_IB_OBJECT_DEVX_UMEM,
2790aeae9457SYishai Hadas 			UVERBS_ACCESS_DESTROY,
279183bb4442SJason Gunthorpe 			UA_MANDATORY));
2792aeae9457SYishai Hadas 
27939a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
27949a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_QUERY_EQN,
27959a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC,
27969a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u32),
279783bb4442SJason Gunthorpe 			   UA_MANDATORY),
27989a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN,
27999a119cd5SJason Gunthorpe 			    UVERBS_ATTR_TYPE(u32),
280083bb4442SJason Gunthorpe 			    UA_MANDATORY));
2801f6fe01b7SYishai Hadas 
28029a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
28039a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_QUERY_UAR,
28049a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX,
28059a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u32),
280683bb4442SJason Gunthorpe 			   UA_MANDATORY),
28079a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX,
28089a119cd5SJason Gunthorpe 			    UVERBS_ATTR_TYPE(u32),
280983bb4442SJason Gunthorpe 			    UA_MANDATORY));
28107c043e90SYishai Hadas 
28119a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
28129a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OTHER,
28139a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
28149a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OTHER_CMD_IN,
28158aa8c95cSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
281683bb4442SJason Gunthorpe 		UA_MANDATORY,
281783bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
28189a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
28199a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT,
28207efce369SYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
2821540cd692SJason Gunthorpe 		UA_MANDATORY));
28227efce369SYishai Hadas 
28239a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
28249a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_CREATE,
28259a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE,
28269a119cd5SJason Gunthorpe 			MLX5_IB_OBJECT_DEVX_OBJ,
28279a119cd5SJason Gunthorpe 			UVERBS_ACCESS_NEW,
282883bb4442SJason Gunthorpe 			UA_MANDATORY),
28299a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
28309a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN,
28319a119cd5SJason Gunthorpe 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
283283bb4442SJason Gunthorpe 		UA_MANDATORY,
283383bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
28349a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
28359a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT,
28369a119cd5SJason Gunthorpe 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
2837540cd692SJason Gunthorpe 		UA_MANDATORY));
28389a119cd5SJason Gunthorpe 
2839528922afSYishai Hadas DECLARE_UVERBS_NAMED_METHOD_DESTROY(
28409a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_DESTROY,
28419a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_DESTROY_HANDLE,
28427efce369SYishai Hadas 			MLX5_IB_OBJECT_DEVX_OBJ,
28437efce369SYishai Hadas 			UVERBS_ACCESS_DESTROY,
284483bb4442SJason Gunthorpe 			UA_MANDATORY));
28457efce369SYishai Hadas 
28469a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
28479a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_MODIFY,
28489a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE,
284934613eb1SYishai Hadas 			UVERBS_IDR_ANY_OBJECT,
2850e662e14dSYishai Hadas 			UVERBS_ACCESS_WRITE,
285183bb4442SJason Gunthorpe 			UA_MANDATORY),
28529a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
28539a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN,
2854e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
285583bb4442SJason Gunthorpe 		UA_MANDATORY,
285683bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
28579a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
28589a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
2859e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
2860540cd692SJason Gunthorpe 		UA_MANDATORY));
2861e662e14dSYishai Hadas 
28629a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
28639a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_QUERY,
28649a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE,
286534613eb1SYishai Hadas 			UVERBS_IDR_ANY_OBJECT,
2866e662e14dSYishai Hadas 			UVERBS_ACCESS_READ,
286783bb4442SJason Gunthorpe 			UA_MANDATORY),
28689a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
28699a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN,
2870e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
287183bb4442SJason Gunthorpe 		UA_MANDATORY,
287283bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
28739a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
28749a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
2875e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
2876540cd692SJason Gunthorpe 		UA_MANDATORY));
2877e662e14dSYishai Hadas 
2878a124edbaSYishai Hadas DECLARE_UVERBS_NAMED_METHOD(
2879a124edbaSYishai Hadas 	MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY,
2880a124edbaSYishai Hadas 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE,
2881a124edbaSYishai Hadas 			UVERBS_IDR_ANY_OBJECT,
2882a124edbaSYishai Hadas 			UVERBS_ACCESS_READ,
2883a124edbaSYishai Hadas 			UA_MANDATORY),
2884a124edbaSYishai Hadas 	UVERBS_ATTR_PTR_IN(
2885a124edbaSYishai Hadas 		MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN,
2886a124edbaSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
2887a124edbaSYishai Hadas 		UA_MANDATORY,
2888a124edbaSYishai Hadas 		UA_ALLOC_AND_COPY),
2889a124edbaSYishai Hadas 	UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_OUT_LEN,
2890a124edbaSYishai Hadas 		u16, UA_MANDATORY),
2891a124edbaSYishai Hadas 	UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_FD,
2892a124edbaSYishai Hadas 		MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
2893a124edbaSYishai Hadas 		UVERBS_ACCESS_READ,
2894a124edbaSYishai Hadas 		UA_MANDATORY),
2895a124edbaSYishai Hadas 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_WR_ID,
2896a124edbaSYishai Hadas 		UVERBS_ATTR_TYPE(u64),
2897a124edbaSYishai Hadas 		UA_MANDATORY));
2898a124edbaSYishai Hadas 
289975973853SYishai Hadas DECLARE_UVERBS_NAMED_METHOD(
290075973853SYishai Hadas 	MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT,
290175973853SYishai Hadas 	UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_HANDLE,
290275973853SYishai Hadas 		MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD,
290375973853SYishai Hadas 		UVERBS_ACCESS_READ,
290475973853SYishai Hadas 		UA_MANDATORY),
290575973853SYishai Hadas 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_OBJ_HANDLE,
290675973853SYishai Hadas 		MLX5_IB_OBJECT_DEVX_OBJ,
290775973853SYishai Hadas 		UVERBS_ACCESS_READ,
290875973853SYishai Hadas 		UA_OPTIONAL),
290975973853SYishai Hadas 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST,
291075973853SYishai Hadas 		UVERBS_ATTR_MIN_SIZE(sizeof(u16)),
291175973853SYishai Hadas 		UA_MANDATORY,
291275973853SYishai Hadas 		UA_ALLOC_AND_COPY),
291375973853SYishai Hadas 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE,
291475973853SYishai Hadas 		UVERBS_ATTR_TYPE(u64),
291575973853SYishai Hadas 		UA_OPTIONAL),
291675973853SYishai Hadas 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM,
291775973853SYishai Hadas 		UVERBS_ATTR_TYPE(u32),
291875973853SYishai Hadas 		UA_OPTIONAL));
291975973853SYishai Hadas 
29206c61d2a5SJason Gunthorpe DECLARE_UVERBS_GLOBAL_METHODS(MLX5_IB_OBJECT_DEVX,
29217c043e90SYishai Hadas 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OTHER),
2922f6fe01b7SYishai Hadas 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR),
292375973853SYishai Hadas 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_EQN),
292475973853SYishai Hadas 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT));
29258aa8c95cSYishai Hadas 
29266c61d2a5SJason Gunthorpe DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ,
29279a119cd5SJason Gunthorpe 			    UVERBS_TYPE_ALLOC_IDR(devx_obj_cleanup),
29287efce369SYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_CREATE),
2929e662e14dSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY),
2930e662e14dSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_MODIFY),
2931a124edbaSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY),
2932a124edbaSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY));
29337efce369SYishai Hadas 
29346c61d2a5SJason Gunthorpe DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM,
29359a119cd5SJason Gunthorpe 			    UVERBS_TYPE_ALLOC_IDR(devx_umem_cleanup),
2936aeae9457SYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG),
2937aeae9457SYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG));
2938aeae9457SYishai Hadas 
29396bf8f22aSYishai Hadas 
29406bf8f22aSYishai Hadas DECLARE_UVERBS_NAMED_METHOD(
29416bf8f22aSYishai Hadas 	MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC,
29426bf8f22aSYishai Hadas 	UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE,
29436bf8f22aSYishai Hadas 			MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
29446bf8f22aSYishai Hadas 			UVERBS_ACCESS_NEW,
29456bf8f22aSYishai Hadas 			UA_MANDATORY));
29466bf8f22aSYishai Hadas 
29476bf8f22aSYishai Hadas DECLARE_UVERBS_NAMED_OBJECT(
29486bf8f22aSYishai Hadas 	MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
29496bf8f22aSYishai Hadas 	UVERBS_TYPE_ALLOC_FD(sizeof(struct devx_async_cmd_event_file),
2950f7c8416cSJason Gunthorpe 			     devx_async_cmd_event_destroy_uobj,
29516bf8f22aSYishai Hadas 			     &devx_async_cmd_event_fops, "[devx_async_cmd]",
29526bf8f22aSYishai Hadas 			     O_RDONLY),
29536bf8f22aSYishai Hadas 	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC));
29546bf8f22aSYishai Hadas 
29552afc5e1bSYishai Hadas DECLARE_UVERBS_NAMED_METHOD(
29562afc5e1bSYishai Hadas 	MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC,
29572afc5e1bSYishai Hadas 	UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_HANDLE,
29582afc5e1bSYishai Hadas 			MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD,
29592afc5e1bSYishai Hadas 			UVERBS_ACCESS_NEW,
29602afc5e1bSYishai Hadas 			UA_MANDATORY),
29612afc5e1bSYishai Hadas 	UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_FLAGS,
29622afc5e1bSYishai Hadas 			enum mlx5_ib_uapi_devx_create_event_channel_flags,
29632afc5e1bSYishai Hadas 			UA_MANDATORY));
29642afc5e1bSYishai Hadas 
29652afc5e1bSYishai Hadas DECLARE_UVERBS_NAMED_OBJECT(
29662afc5e1bSYishai Hadas 	MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD,
29672afc5e1bSYishai Hadas 	UVERBS_TYPE_ALLOC_FD(sizeof(struct devx_async_event_file),
2968f7c8416cSJason Gunthorpe 			     devx_async_event_destroy_uobj,
29692afc5e1bSYishai Hadas 			     &devx_async_event_fops, "[devx_async_event]",
29702afc5e1bSYishai Hadas 			     O_RDONLY),
29712afc5e1bSYishai Hadas 	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC));
29722afc5e1bSYishai Hadas 
297336e235c8SJason Gunthorpe static bool devx_is_supported(struct ib_device *device)
2974c59450c4SYishai Hadas {
297536e235c8SJason Gunthorpe 	struct mlx5_ib_dev *dev = to_mdev(device);
297636e235c8SJason Gunthorpe 
29777f575103SMark Bloch 	return MLX5_CAP_GEN(dev->mdev, log_max_uctx);
2978c59450c4SYishai Hadas }
297936e235c8SJason Gunthorpe 
29800cbf432dSJason Gunthorpe const struct uapi_definition mlx5_ib_devx_defs[] = {
298136e235c8SJason Gunthorpe 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
298236e235c8SJason Gunthorpe 		MLX5_IB_OBJECT_DEVX,
298336e235c8SJason Gunthorpe 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
298436e235c8SJason Gunthorpe 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
298536e235c8SJason Gunthorpe 		MLX5_IB_OBJECT_DEVX_OBJ,
298636e235c8SJason Gunthorpe 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
298736e235c8SJason Gunthorpe 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
298836e235c8SJason Gunthorpe 		MLX5_IB_OBJECT_DEVX_UMEM,
298936e235c8SJason Gunthorpe 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
29906bf8f22aSYishai Hadas 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
29916bf8f22aSYishai Hadas 		MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
29926bf8f22aSYishai Hadas 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
29932afc5e1bSYishai Hadas 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
29942afc5e1bSYishai Hadas 		MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD,
29952afc5e1bSYishai Hadas 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
29960cbf432dSJason Gunthorpe 	{},
29970cbf432dSJason Gunthorpe };
2998