xref: /linux/drivers/infiniband/hw/mlx5/devx.c (revision 52c996d3f40b40f87ef9dc80596903309682acc3)
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;
971368ead0SYishai 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;
1031368ead0SYishai 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 {
1141368ead0SYishai Hadas 	u32 in[MLX5_ST_SZ_DW(create_uctx_in)] = {};
1151368ead0SYishai 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 
1411368ead0SYishai 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 {
1471368ead0SYishai Hadas 	u32 in[MLX5_ST_SZ_DW(destroy_uctx_in)] = {};
1481368ead0SYishai 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 
2911368ead0SYishai Hadas static u32 devx_get_created_obj_id(const void *in, const void *out, u16 opcode)
2921368ead0SYishai Hadas {
2931368ead0SYishai Hadas 	switch (opcode) {
2941368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
2951368ead0SYishai Hadas 		return MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
2961368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_UMEM:
2971368ead0SYishai Hadas 		return MLX5_GET(create_umem_out, out, umem_id);
2981368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_MKEY:
2991368ead0SYishai Hadas 		return MLX5_GET(create_mkey_out, out, mkey_index);
3001368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_CQ:
3011368ead0SYishai Hadas 		return MLX5_GET(create_cq_out, out, cqn);
3021368ead0SYishai Hadas 	case MLX5_CMD_OP_ALLOC_PD:
3031368ead0SYishai Hadas 		return MLX5_GET(alloc_pd_out, out, pd);
3041368ead0SYishai Hadas 	case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
3051368ead0SYishai Hadas 		return MLX5_GET(alloc_transport_domain_out, out,
3061368ead0SYishai Hadas 				transport_domain);
3071368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_RMP:
3081368ead0SYishai Hadas 		return MLX5_GET(create_rmp_out, out, rmpn);
3091368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
3101368ead0SYishai Hadas 		return MLX5_GET(create_sq_out, out, sqn);
3111368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
3121368ead0SYishai Hadas 		return MLX5_GET(create_rq_out, out, rqn);
3131368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQT:
3141368ead0SYishai Hadas 		return MLX5_GET(create_rqt_out, out, rqtn);
3151368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIR:
3161368ead0SYishai Hadas 		return MLX5_GET(create_tir_out, out, tirn);
3171368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIS:
3181368ead0SYishai Hadas 		return MLX5_GET(create_tis_out, out, tisn);
3191368ead0SYishai Hadas 	case MLX5_CMD_OP_ALLOC_Q_COUNTER:
3201368ead0SYishai Hadas 		return MLX5_GET(alloc_q_counter_out, out, counter_set_id);
3211368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_TABLE:
3221368ead0SYishai Hadas 		return MLX5_GET(create_flow_table_out, out, table_id);
3231368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_GROUP:
3241368ead0SYishai Hadas 		return MLX5_GET(create_flow_group_out, out, group_id);
3251368ead0SYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
3261368ead0SYishai Hadas 		return MLX5_GET(set_fte_in, in, flow_index);
3271368ead0SYishai Hadas 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
3281368ead0SYishai Hadas 		return MLX5_GET(alloc_flow_counter_out, out, flow_counter_id);
3291368ead0SYishai Hadas 	case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT:
3301368ead0SYishai Hadas 		return MLX5_GET(alloc_packet_reformat_context_out, out,
3311368ead0SYishai Hadas 				packet_reformat_id);
3321368ead0SYishai Hadas 	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
3331368ead0SYishai Hadas 		return MLX5_GET(alloc_modify_header_context_out, out,
3341368ead0SYishai Hadas 				modify_header_id);
3351368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
3361368ead0SYishai Hadas 		return MLX5_GET(create_scheduling_element_out, out,
3371368ead0SYishai Hadas 				scheduling_element_id);
3381368ead0SYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
3391368ead0SYishai Hadas 		return MLX5_GET(add_vxlan_udp_dport_in, in, vxlan_udp_port);
3401368ead0SYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
3411368ead0SYishai Hadas 		return MLX5_GET(set_l2_table_entry_in, in, table_index);
3421368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
3431368ead0SYishai Hadas 		return MLX5_GET(create_qp_out, out, qpn);
3441368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_SRQ:
3451368ead0SYishai Hadas 		return MLX5_GET(create_srq_out, out, srqn);
3461368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
3471368ead0SYishai Hadas 		return MLX5_GET(create_xrc_srq_out, out, xrc_srqn);
3481368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_DCT:
3491368ead0SYishai Hadas 		return MLX5_GET(create_dct_out, out, dctn);
3501368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRQ:
3511368ead0SYishai Hadas 		return MLX5_GET(create_xrq_out, out, xrqn);
3521368ead0SYishai Hadas 	case MLX5_CMD_OP_ATTACH_TO_MCG:
3531368ead0SYishai Hadas 		return MLX5_GET(attach_to_mcg_in, in, qpn);
3541368ead0SYishai Hadas 	case MLX5_CMD_OP_ALLOC_XRCD:
3551368ead0SYishai Hadas 		return MLX5_GET(alloc_xrcd_out, out, xrcd);
3561368ead0SYishai Hadas 	case MLX5_CMD_OP_CREATE_PSV:
3571368ead0SYishai Hadas 		return MLX5_GET(create_psv_out, out, psv0_index);
3581368ead0SYishai Hadas 	default:
3591368ead0SYishai Hadas 		/* The entry must match to one of the devx_is_obj_create_cmd */
3601368ead0SYishai Hadas 		WARN_ON(true);
3611368ead0SYishai Hadas 		return 0;
3621368ead0SYishai Hadas 	}
3631368ead0SYishai Hadas }
3641368ead0SYishai 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,
4761368ead0SYishai Hadas 					MLX5_GET(query_modify_header_context_in,
4771368ead0SYishai 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 
634cfa3b797SMaor Gottlieb 		if (qp->type == IB_QPT_RAW_PACKET ||
6352be08c30SLeon Romanovsky 		    (qp->flags & IB_QP_CREATE_SOURCE_QPN)) {
63634613eb1SYishai Hadas 			struct mlx5_ib_raw_packet_qp *raw_packet_qp =
63734613eb1SYishai Hadas 							 &qp->raw_packet_qp;
63834613eb1SYishai Hadas 			struct mlx5_ib_rq *rq = &raw_packet_qp->rq;
63934613eb1SYishai Hadas 			struct mlx5_ib_sq *sq = &raw_packet_qp->sq;
64034613eb1SYishai Hadas 
64134613eb1SYishai Hadas 			return (get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
64234613eb1SYishai Hadas 					       rq->base.mqp.qpn) == obj_id ||
64334613eb1SYishai Hadas 				get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ,
64434613eb1SYishai Hadas 					       sq->base.mqp.qpn) == obj_id ||
64534613eb1SYishai Hadas 				get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR,
64634613eb1SYishai Hadas 					       rq->tirn) == obj_id ||
64734613eb1SYishai Hadas 				get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS,
64834613eb1SYishai Hadas 					       sq->tisn) == obj_id);
64934613eb1SYishai Hadas 		}
65034613eb1SYishai Hadas 
651cfa3b797SMaor Gottlieb 		if (qp->type == MLX5_IB_QPT_DCT)
65234613eb1SYishai Hadas 			return get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT,
65334613eb1SYishai Hadas 					      qp->dct.mdct.mqp.qpn) == obj_id;
65434613eb1SYishai Hadas 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
65534613eb1SYishai Hadas 				      qp->ibqp.qp_num) == obj_id;
65634613eb1SYishai Hadas 	}
65734613eb1SYishai Hadas 
65834613eb1SYishai Hadas 	case UVERBS_OBJECT_WQ:
65934613eb1SYishai Hadas 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
66034613eb1SYishai Hadas 				      to_mrwq(uobj->object)->core_qp.qpn) ==
66134613eb1SYishai Hadas 				      obj_id;
66234613eb1SYishai Hadas 
66334613eb1SYishai Hadas 	case UVERBS_OBJECT_RWQ_IND_TBL:
66434613eb1SYishai Hadas 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT,
66534613eb1SYishai Hadas 				      to_mrwq_ind_table(uobj->object)->rqtn) ==
66634613eb1SYishai Hadas 				      obj_id;
66734613eb1SYishai Hadas 
66834613eb1SYishai Hadas 	case MLX5_IB_OBJECT_DEVX_OBJ:
6693e358ea8SMark Bloch 	{
6703e358ea8SMark Bloch 		u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
6713e358ea8SMark Bloch 		struct devx_obj *devx_uobj = uobj->object;
6723e358ea8SMark Bloch 
6733e358ea8SMark Bloch 		if (opcode == MLX5_CMD_OP_QUERY_FLOW_COUNTER &&
6743e358ea8SMark Bloch 		    devx_uobj->flow_counter_bulk_size) {
6753e358ea8SMark Bloch 			u64 end;
6763e358ea8SMark Bloch 
6773e358ea8SMark Bloch 			end = devx_uobj->obj_id +
6783e358ea8SMark Bloch 				devx_uobj->flow_counter_bulk_size;
6793e358ea8SMark Bloch 			return devx_uobj->obj_id <= obj_id && end > obj_id;
6803e358ea8SMark Bloch 		}
6813e358ea8SMark Bloch 
6823e358ea8SMark Bloch 		return devx_uobj->obj_id == obj_id;
6833e358ea8SMark Bloch 	}
68434613eb1SYishai Hadas 
685e662e14dSYishai Hadas 	default:
686e662e14dSYishai Hadas 		return false;
687e662e14dSYishai Hadas 	}
688e662e14dSYishai Hadas }
689e662e14dSYishai Hadas 
690ba1a057dSYishai Hadas static void devx_set_umem_valid(const void *in)
691ba1a057dSYishai Hadas {
692ba1a057dSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
693ba1a057dSYishai Hadas 
694ba1a057dSYishai Hadas 	switch (opcode) {
695ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_MKEY:
696ba1a057dSYishai Hadas 		MLX5_SET(create_mkey_in, in, mkey_umem_valid, 1);
697ba1a057dSYishai Hadas 		break;
698ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_CQ:
699ba1a057dSYishai Hadas 	{
700ba1a057dSYishai Hadas 		void *cqc;
701ba1a057dSYishai Hadas 
702ba1a057dSYishai Hadas 		MLX5_SET(create_cq_in, in, cq_umem_valid, 1);
703ba1a057dSYishai Hadas 		cqc = MLX5_ADDR_OF(create_cq_in, in, cq_context);
704ba1a057dSYishai Hadas 		MLX5_SET(cqc, cqc, dbr_umem_valid, 1);
705ba1a057dSYishai Hadas 		break;
706ba1a057dSYishai Hadas 	}
707ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
708ba1a057dSYishai Hadas 	{
709ba1a057dSYishai Hadas 		void *qpc;
710ba1a057dSYishai Hadas 
711ba1a057dSYishai Hadas 		qpc = MLX5_ADDR_OF(create_qp_in, in, qpc);
712ba1a057dSYishai Hadas 		MLX5_SET(qpc, qpc, dbr_umem_valid, 1);
713ba1a057dSYishai Hadas 		MLX5_SET(create_qp_in, in, wq_umem_valid, 1);
714ba1a057dSYishai Hadas 		break;
715ba1a057dSYishai Hadas 	}
716ba1a057dSYishai Hadas 
717ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
718ba1a057dSYishai Hadas 	{
719ba1a057dSYishai Hadas 		void *rqc, *wq;
720ba1a057dSYishai Hadas 
721ba1a057dSYishai Hadas 		rqc = MLX5_ADDR_OF(create_rq_in, in, ctx);
722ba1a057dSYishai Hadas 		wq  = MLX5_ADDR_OF(rqc, rqc, wq);
723ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
724ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, wq_umem_valid, 1);
725ba1a057dSYishai Hadas 		break;
726ba1a057dSYishai Hadas 	}
727ba1a057dSYishai Hadas 
728ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
729ba1a057dSYishai Hadas 	{
730ba1a057dSYishai Hadas 		void *sqc, *wq;
731ba1a057dSYishai Hadas 
732ba1a057dSYishai Hadas 		sqc = MLX5_ADDR_OF(create_sq_in, in, ctx);
733ba1a057dSYishai Hadas 		wq = MLX5_ADDR_OF(sqc, sqc, wq);
734ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
735ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, wq_umem_valid, 1);
736ba1a057dSYishai Hadas 		break;
737ba1a057dSYishai Hadas 	}
738ba1a057dSYishai Hadas 
739ba1a057dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_CQ:
740ba1a057dSYishai Hadas 		MLX5_SET(modify_cq_in, in, cq_umem_valid, 1);
741ba1a057dSYishai Hadas 		break;
742ba1a057dSYishai Hadas 
743ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_RMP:
744ba1a057dSYishai Hadas 	{
745ba1a057dSYishai Hadas 		void *rmpc, *wq;
746ba1a057dSYishai Hadas 
747ba1a057dSYishai Hadas 		rmpc = MLX5_ADDR_OF(create_rmp_in, in, ctx);
748ba1a057dSYishai Hadas 		wq = MLX5_ADDR_OF(rmpc, rmpc, wq);
749ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
750ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, wq_umem_valid, 1);
751ba1a057dSYishai Hadas 		break;
752ba1a057dSYishai Hadas 	}
753ba1a057dSYishai Hadas 
754ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_XRQ:
755ba1a057dSYishai Hadas 	{
756ba1a057dSYishai Hadas 		void *xrqc, *wq;
757ba1a057dSYishai Hadas 
758ba1a057dSYishai Hadas 		xrqc = MLX5_ADDR_OF(create_xrq_in, in, xrq_context);
759ba1a057dSYishai Hadas 		wq = MLX5_ADDR_OF(xrqc, xrqc, wq);
760ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
761ba1a057dSYishai Hadas 		MLX5_SET(wq, wq, wq_umem_valid, 1);
762ba1a057dSYishai Hadas 		break;
763ba1a057dSYishai Hadas 	}
764ba1a057dSYishai Hadas 
765ba1a057dSYishai Hadas 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
766ba1a057dSYishai Hadas 	{
767ba1a057dSYishai Hadas 		void *xrc_srqc;
768ba1a057dSYishai Hadas 
769ba1a057dSYishai Hadas 		MLX5_SET(create_xrc_srq_in, in, xrc_srq_umem_valid, 1);
770ba1a057dSYishai Hadas 		xrc_srqc = MLX5_ADDR_OF(create_xrc_srq_in, in,
771ba1a057dSYishai Hadas 					xrc_srq_context_entry);
772ba1a057dSYishai Hadas 		MLX5_SET(xrc_srqc, xrc_srqc, dbr_umem_valid, 1);
773ba1a057dSYishai Hadas 		break;
774ba1a057dSYishai Hadas 	}
775ba1a057dSYishai Hadas 
776ba1a057dSYishai Hadas 	default:
777ba1a057dSYishai Hadas 		return;
778ba1a057dSYishai Hadas 	}
779ba1a057dSYishai Hadas }
780ba1a057dSYishai Hadas 
7812351776eSYishai Hadas static bool devx_is_obj_create_cmd(const void *in, u16 *opcode)
7827efce369SYishai Hadas {
7832351776eSYishai Hadas 	*opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
7847efce369SYishai Hadas 
7852351776eSYishai Hadas 	switch (*opcode) {
7867efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
7877efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_MKEY:
7887efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_CQ:
7897efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_PD:
7907efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
7917efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RMP:
7927efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
7937efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
7947efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQT:
7957efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIR:
7967efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIS:
7977efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_Q_COUNTER:
7987efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_TABLE:
7997efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_GROUP:
8007efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
80160786f09SMark Bloch 	case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT:
8027efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
8037efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
8047efce369SYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
8057efce369SYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
8067efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
8077efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SRQ:
8087efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
8097efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_DCT:
8107efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRQ:
8117efce369SYishai Hadas 	case MLX5_CMD_OP_ATTACH_TO_MCG:
8127efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_XRCD:
8137efce369SYishai Hadas 		return true;
8147efce369SYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
8157efce369SYishai Hadas 	{
8167efce369SYishai Hadas 		u16 op_mod = MLX5_GET(set_fte_in, in, op_mod);
8177efce369SYishai Hadas 		if (op_mod == 0)
8187efce369SYishai Hadas 			return true;
8197efce369SYishai Hadas 		return false;
8207efce369SYishai Hadas 	}
8218b38c538SMax Gurtovoy 	case MLX5_CMD_OP_CREATE_PSV:
8228b38c538SMax Gurtovoy 	{
8238b38c538SMax Gurtovoy 		u8 num_psv = MLX5_GET(create_psv_in, in, num_psv);
8248b38c538SMax Gurtovoy 
8258b38c538SMax Gurtovoy 		if (num_psv == 1)
8268b38c538SMax Gurtovoy 			return true;
8278b38c538SMax Gurtovoy 		return false;
8288b38c538SMax Gurtovoy 	}
8297efce369SYishai Hadas 	default:
8307efce369SYishai Hadas 		return false;
8317efce369SYishai Hadas 	}
8327efce369SYishai Hadas }
8337efce369SYishai Hadas 
834e662e14dSYishai Hadas static bool devx_is_obj_modify_cmd(const void *in)
835e662e14dSYishai Hadas {
836e662e14dSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
837e662e14dSYishai Hadas 
838e662e14dSYishai Hadas 	switch (opcode) {
839e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
840e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_CQ:
841e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RMP:
842e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_SQ:
843e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RQ:
844e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_RQT:
845e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_TIR:
846e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_TIS:
847e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_FLOW_TABLE:
848e662e14dSYishai Hadas 	case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
849e662e14dSYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
850e662e14dSYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
851e662e14dSYishai Hadas 	case MLX5_CMD_OP_RST2INIT_QP:
852e662e14dSYishai Hadas 	case MLX5_CMD_OP_INIT2RTR_QP:
853819f7427SAharon Landau 	case MLX5_CMD_OP_INIT2INIT_QP:
854e662e14dSYishai Hadas 	case MLX5_CMD_OP_RTR2RTS_QP:
855e662e14dSYishai Hadas 	case MLX5_CMD_OP_RTS2RTS_QP:
856e662e14dSYishai Hadas 	case MLX5_CMD_OP_SQERR2RTS_QP:
857e662e14dSYishai Hadas 	case MLX5_CMD_OP_2ERR_QP:
858e662e14dSYishai Hadas 	case MLX5_CMD_OP_2RST_QP:
859e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_XRC_SRQ:
860e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_RQ:
861e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
862e662e14dSYishai Hadas 	case MLX5_CMD_OP_ARM_XRQ:
863719598c9SYishai Hadas 	case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY:
8648293a598SYishai Hadas 	case MLX5_CMD_OP_RELEASE_XRQ_ERROR:
8658293a598SYishai Hadas 	case MLX5_CMD_OP_MODIFY_XRQ:
866e662e14dSYishai Hadas 		return true;
867e662e14dSYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
868e662e14dSYishai Hadas 	{
869e662e14dSYishai Hadas 		u16 op_mod = MLX5_GET(set_fte_in, in, op_mod);
870e662e14dSYishai Hadas 
871e662e14dSYishai Hadas 		if (op_mod == 1)
872e662e14dSYishai Hadas 			return true;
873e662e14dSYishai Hadas 		return false;
874e662e14dSYishai Hadas 	}
875e662e14dSYishai Hadas 	default:
876e662e14dSYishai Hadas 		return false;
877e662e14dSYishai Hadas 	}
878e662e14dSYishai Hadas }
879e662e14dSYishai Hadas 
880e662e14dSYishai Hadas static bool devx_is_obj_query_cmd(const void *in)
881e662e14dSYishai Hadas {
882e662e14dSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
883e662e14dSYishai Hadas 
884e662e14dSYishai Hadas 	switch (opcode) {
885e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
886e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_MKEY:
887e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_CQ:
888e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RMP:
889e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SQ:
890e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RQ:
891e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_RQT:
892e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_TIR:
893e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_TIS:
894e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_Q_COUNTER:
895e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_TABLE:
896e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_GROUP:
897e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
898e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
899e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT:
900e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
901e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
902e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_QP:
903e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_SRQ:
904e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_XRC_SRQ:
905e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_DCT:
906e662e14dSYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ:
907719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY:
908719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS:
909719598c9SYishai Hadas 	case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT:
910e662e14dSYishai Hadas 		return true;
911e662e14dSYishai Hadas 	default:
912e662e14dSYishai Hadas 		return false;
913e662e14dSYishai Hadas 	}
914e662e14dSYishai Hadas }
915e662e14dSYishai Hadas 
9167e1335a7SYishai Hadas static bool devx_is_whitelist_cmd(void *in)
9177e1335a7SYishai Hadas {
9187e1335a7SYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
9197e1335a7SYishai Hadas 
9207e1335a7SYishai Hadas 	switch (opcode) {
9217e1335a7SYishai Hadas 	case MLX5_CMD_OP_QUERY_HCA_CAP:
9227e1335a7SYishai Hadas 	case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT:
92356e5acd4SMaor Gottlieb 	case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT:
924b021d82eSBodong Wang 	case MLX5_CMD_OP_QUERY_ESW_FUNCTIONS:
9257e1335a7SYishai Hadas 		return true;
9267e1335a7SYishai Hadas 	default:
9277e1335a7SYishai Hadas 		return false;
9287e1335a7SYishai Hadas 	}
9297e1335a7SYishai Hadas }
9307e1335a7SYishai Hadas 
9317e1335a7SYishai Hadas static int devx_get_uid(struct mlx5_ib_ucontext *c, void *cmd_in)
9327e1335a7SYishai Hadas {
9337e1335a7SYishai Hadas 	if (devx_is_whitelist_cmd(cmd_in)) {
9347e1335a7SYishai Hadas 		struct mlx5_ib_dev *dev;
9357e1335a7SYishai Hadas 
9367e1335a7SYishai Hadas 		if (c->devx_uid)
9377e1335a7SYishai Hadas 			return c->devx_uid;
9387e1335a7SYishai Hadas 
9397e1335a7SYishai Hadas 		dev = to_mdev(c->ibucontext.device);
9407e1335a7SYishai Hadas 		if (dev->devx_whitelist_uid)
9417e1335a7SYishai Hadas 			return dev->devx_whitelist_uid;
9427e1335a7SYishai Hadas 
9437e1335a7SYishai Hadas 		return -EOPNOTSUPP;
9447e1335a7SYishai Hadas 	}
9457e1335a7SYishai Hadas 
9467e1335a7SYishai Hadas 	if (!c->devx_uid)
9477e1335a7SYishai Hadas 		return -EINVAL;
9487e1335a7SYishai Hadas 
9497e1335a7SYishai Hadas 	return c->devx_uid;
9507e1335a7SYishai Hadas }
951b6142608SMax Gurtovoy 
952b6142608SMax Gurtovoy static bool devx_is_general_cmd(void *in, struct mlx5_ib_dev *dev)
9538aa8c95cSYishai Hadas {
9548aa8c95cSYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
9558aa8c95cSYishai Hadas 
956b6142608SMax Gurtovoy 	/* Pass all cmds for vhca_tunnel as general, tracking is done in FW */
957b6142608SMax Gurtovoy 	if ((MLX5_CAP_GEN_64(dev->mdev, vhca_tunnel_commands) &&
958b6142608SMax Gurtovoy 	     MLX5_GET(general_obj_in_cmd_hdr, in, vhca_tunnel_id)) ||
959b6142608SMax Gurtovoy 	    (opcode >= MLX5_CMD_OP_GENERAL_START &&
960b6142608SMax Gurtovoy 	     opcode < MLX5_CMD_OP_GENERAL_END))
961719598c9SYishai Hadas 		return true;
962719598c9SYishai Hadas 
9638aa8c95cSYishai Hadas 	switch (opcode) {
9648aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_HCA_CAP:
9657e1335a7SYishai Hadas 	case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT:
96656e5acd4SMaor Gottlieb 	case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT:
9678aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_VPORT_STATE:
9688aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_ADAPTER:
9698aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_ISSI:
9708aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT:
9718aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_ROCE_ADDRESS:
9728aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_VNIC_ENV:
9738aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_VPORT_COUNTER:
9748aa8c95cSYishai Hadas 	case MLX5_CMD_OP_GET_DROPPED_PACKET_LOG:
9758aa8c95cSYishai Hadas 	case MLX5_CMD_OP_NOP:
9768aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_CONG_STATUS:
9778aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_CONG_PARAMS:
9788aa8c95cSYishai Hadas 	case MLX5_CMD_OP_QUERY_CONG_STATISTICS:
9797084ed30SMark Zhang 	case MLX5_CMD_OP_QUERY_LAG:
980b021d82eSBodong Wang 	case MLX5_CMD_OP_QUERY_ESW_FUNCTIONS:
9818aa8c95cSYishai Hadas 		return true;
9828aa8c95cSYishai Hadas 	default:
9838aa8c95cSYishai Hadas 		return false;
9848aa8c95cSYishai Hadas 	}
9858aa8c95cSYishai Hadas }
9868aa8c95cSYishai Hadas 
987e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_EQN)(
98815a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
989f6fe01b7SYishai Hadas {
990e83f0ecdSJason Gunthorpe 	struct mlx5_ib_ucontext *c;
991e83f0ecdSJason Gunthorpe 	struct mlx5_ib_dev *dev;
992f6fe01b7SYishai Hadas 	int user_vector;
993f6fe01b7SYishai Hadas 	int dev_eqn;
994f6fe01b7SYishai Hadas 	int err;
995f6fe01b7SYishai Hadas 
996f6fe01b7SYishai Hadas 	if (uverbs_copy_from(&user_vector, attrs,
997f6fe01b7SYishai Hadas 			     MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC))
998f6fe01b7SYishai Hadas 		return -EFAULT;
999f6fe01b7SYishai Hadas 
100015a1b4beSJason Gunthorpe 	c = devx_ufile2uctx(attrs);
1001e83f0ecdSJason Gunthorpe 	if (IS_ERR(c))
1002e83f0ecdSJason Gunthorpe 		return PTR_ERR(c);
1003e83f0ecdSJason Gunthorpe 	dev = to_mdev(c->ibucontext.device);
1004e83f0ecdSJason Gunthorpe 
1005f14c1a14SMaher Sanalla 	err = mlx5_comp_eqn_get(dev->mdev, user_vector, &dev_eqn);
1006f6fe01b7SYishai Hadas 	if (err < 0)
1007f6fe01b7SYishai Hadas 		return err;
1008f6fe01b7SYishai Hadas 
1009f6fe01b7SYishai Hadas 	if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN,
1010f6fe01b7SYishai Hadas 			   &dev_eqn, sizeof(dev_eqn)))
1011f6fe01b7SYishai Hadas 		return -EFAULT;
1012f6fe01b7SYishai Hadas 
1013f6fe01b7SYishai Hadas 	return 0;
1014f6fe01b7SYishai Hadas }
1015f6fe01b7SYishai Hadas 
10167c043e90SYishai Hadas /*
10177c043e90SYishai Hadas  *Security note:
10187c043e90SYishai Hadas  * The hardware protection mechanism works like this: Each device object that
10197c043e90SYishai Hadas  * is subject to UAR doorbells (QP/SQ/CQ) gets a UAR ID (called uar_page in
10207c043e90SYishai Hadas  * the device specification manual) upon its creation. Then upon doorbell,
10217c043e90SYishai Hadas  * hardware fetches the object context for which the doorbell was rang, and
10227c043e90SYishai Hadas  * validates that the UAR through which the DB was rang matches the UAR ID
10237c043e90SYishai Hadas  * of the object.
10247c043e90SYishai Hadas  * If no match the doorbell is silently ignored by the hardware. Of course,
10257c043e90SYishai Hadas  * the user cannot ring a doorbell on a UAR that was not mapped to it.
10267c043e90SYishai Hadas  * Now in devx, as the devx kernel does not manipulate the QP/SQ/CQ command
10277c043e90SYishai Hadas  * mailboxes (except tagging them with UID), we expose to the user its UAR
10287c043e90SYishai Hadas  * ID, so it can embed it in these objects in the expected specification
10297c043e90SYishai Hadas  * format. So the only thing the user can do is hurt itself by creating a
10307c043e90SYishai Hadas  * QP/SQ/CQ with a UAR ID other than his, and then in this case other users
10317c043e90SYishai Hadas  * may ring a doorbell on its objects.
10327c043e90SYishai Hadas  * The consequence of that will be that another user can schedule a QP/SQ
10337c043e90SYishai Hadas  * of the buggy user for execution (just insert it to the hardware schedule
10347c043e90SYishai Hadas  * queue or arm its CQ for event generation), no further harm is expected.
10357c043e90SYishai Hadas  */
1036e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_UAR)(
103715a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
10387c043e90SYishai Hadas {
103922fa27fbSJason Gunthorpe 	struct mlx5_ib_ucontext *c;
104022fa27fbSJason Gunthorpe 	struct mlx5_ib_dev *dev;
10417c043e90SYishai Hadas 	u32 user_idx;
10427c043e90SYishai Hadas 	s32 dev_idx;
10437c043e90SYishai Hadas 
104415a1b4beSJason Gunthorpe 	c = devx_ufile2uctx(attrs);
104522fa27fbSJason Gunthorpe 	if (IS_ERR(c))
104622fa27fbSJason Gunthorpe 		return PTR_ERR(c);
104722fa27fbSJason Gunthorpe 	dev = to_mdev(c->ibucontext.device);
104822fa27fbSJason Gunthorpe 
10497c043e90SYishai Hadas 	if (uverbs_copy_from(&user_idx, attrs,
10507c043e90SYishai Hadas 			     MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX))
10517c043e90SYishai Hadas 		return -EFAULT;
10527c043e90SYishai Hadas 
105322fa27fbSJason Gunthorpe 	dev_idx = bfregn_to_uar_index(dev, &c->bfregi, user_idx, true);
10547c043e90SYishai Hadas 	if (dev_idx < 0)
10557c043e90SYishai Hadas 		return dev_idx;
10567c043e90SYishai Hadas 
10577c043e90SYishai Hadas 	if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX,
10587c043e90SYishai Hadas 			   &dev_idx, sizeof(dev_idx)))
10597c043e90SYishai Hadas 		return -EFAULT;
10607c043e90SYishai Hadas 
10617c043e90SYishai Hadas 	return 0;
10627c043e90SYishai Hadas }
10637c043e90SYishai Hadas 
1064e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)(
106515a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
10668aa8c95cSYishai Hadas {
106722fa27fbSJason Gunthorpe 	struct mlx5_ib_ucontext *c;
106822fa27fbSJason Gunthorpe 	struct mlx5_ib_dev *dev;
10697efce369SYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(
10707efce369SYishai Hadas 		attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN);
10718aa8c95cSYishai Hadas 	int cmd_out_len = uverbs_attr_get_len(attrs,
10728aa8c95cSYishai Hadas 					MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT);
10738aa8c95cSYishai Hadas 	void *cmd_out;
1074c76a1e90SSaeed Mahameed 	int err, err2;
10757e1335a7SYishai Hadas 	int uid;
10768aa8c95cSYishai Hadas 
107715a1b4beSJason Gunthorpe 	c = devx_ufile2uctx(attrs);
107822fa27fbSJason Gunthorpe 	if (IS_ERR(c))
107922fa27fbSJason Gunthorpe 		return PTR_ERR(c);
108022fa27fbSJason Gunthorpe 	dev = to_mdev(c->ibucontext.device);
108122fa27fbSJason Gunthorpe 
10827e1335a7SYishai Hadas 	uid = devx_get_uid(c, cmd_in);
10837e1335a7SYishai Hadas 	if (uid < 0)
10847e1335a7SYishai Hadas 		return uid;
10858aa8c95cSYishai Hadas 
10868aa8c95cSYishai Hadas 	/* Only white list of some general HCA commands are allowed for this method. */
1087b6142608SMax Gurtovoy 	if (!devx_is_general_cmd(cmd_in, dev))
10888aa8c95cSYishai Hadas 		return -EINVAL;
10898aa8c95cSYishai Hadas 
1090b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
1091b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
1092b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
10938aa8c95cSYishai Hadas 
10947e1335a7SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1095c76a1e90SSaeed Mahameed 	err = mlx5_cmd_do(dev->mdev, cmd_in,
10968aa8c95cSYishai Hadas 			  uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN),
10978aa8c95cSYishai Hadas 			  cmd_out, cmd_out_len);
1098c76a1e90SSaeed Mahameed 	if (err && err != -EREMOTEIO)
10998aa8c95cSYishai Hadas 		return err;
1100b61815e2SJason Gunthorpe 
1101c76a1e90SSaeed Mahameed 	err2 = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, cmd_out,
1102b61815e2SJason Gunthorpe 			      cmd_out_len);
1103c76a1e90SSaeed Mahameed 
1104c76a1e90SSaeed Mahameed 	return err2 ?: err;
11058aa8c95cSYishai Hadas }
11068aa8c95cSYishai Hadas 
11077efce369SYishai Hadas static void devx_obj_build_destroy_cmd(void *in, void *out, void *din,
11087efce369SYishai Hadas 				       u32 *dinlen,
11097efce369SYishai Hadas 				       u32 *obj_id)
11107efce369SYishai Hadas {
11111368ead0SYishai Hadas 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
11127efce369SYishai Hadas 	u16 uid = MLX5_GET(general_obj_in_cmd_hdr, in, uid);
11137efce369SYishai Hadas 
11141368ead0SYishai Hadas 	*obj_id = devx_get_created_obj_id(in, out, opcode);
11157efce369SYishai Hadas 	*dinlen = MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr);
11167efce369SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, din, uid, uid);
11177efce369SYishai Hadas 
11181368ead0SYishai Hadas 	switch (opcode) {
11197efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
11207efce369SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
11211368ead0SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, obj_id, *obj_id);
11221368ead0SYishai Hadas 		MLX5_SET(general_obj_in_cmd_hdr, din, obj_type,
11231368ead0SYishai Hadas 			 MLX5_GET(general_obj_in_cmd_hdr, in, obj_type));
11247efce369SYishai Hadas 		break;
11257efce369SYishai Hadas 
11266e3722baSYishai Hadas 	case MLX5_CMD_OP_CREATE_UMEM:
11271368ead0SYishai Hadas 		MLX5_SET(destroy_umem_in, din, opcode,
11286e3722baSYishai Hadas 			 MLX5_CMD_OP_DESTROY_UMEM);
11291368ead0SYishai Hadas 		MLX5_SET(destroy_umem_in, din, umem_id, *obj_id);
11306e3722baSYishai Hadas 		break;
11317efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_MKEY:
11321368ead0SYishai Hadas 		MLX5_SET(destroy_mkey_in, din, opcode,
11331368ead0SYishai Hadas 			 MLX5_CMD_OP_DESTROY_MKEY);
113422053df0SMark Zhang 		MLX5_SET(destroy_mkey_in, din, mkey_index, *obj_id);
11357efce369SYishai Hadas 		break;
11367efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_CQ:
11371368ead0SYishai Hadas 		MLX5_SET(destroy_cq_in, din, opcode, MLX5_CMD_OP_DESTROY_CQ);
11381368ead0SYishai Hadas 		MLX5_SET(destroy_cq_in, din, cqn, *obj_id);
11397efce369SYishai Hadas 		break;
11407efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_PD:
11411368ead0SYishai Hadas 		MLX5_SET(dealloc_pd_in, din, opcode, MLX5_CMD_OP_DEALLOC_PD);
11421368ead0SYishai Hadas 		MLX5_SET(dealloc_pd_in, din, pd, *obj_id);
11437efce369SYishai Hadas 		break;
11447efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
11451368ead0SYishai Hadas 		MLX5_SET(dealloc_transport_domain_in, din, opcode,
11467efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN);
11471368ead0SYishai Hadas 		MLX5_SET(dealloc_transport_domain_in, din, transport_domain,
11481368ead0SYishai Hadas 			 *obj_id);
11497efce369SYishai Hadas 		break;
11507efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RMP:
11511368ead0SYishai Hadas 		MLX5_SET(destroy_rmp_in, din, opcode, MLX5_CMD_OP_DESTROY_RMP);
11521368ead0SYishai Hadas 		MLX5_SET(destroy_rmp_in, din, rmpn, *obj_id);
11537efce369SYishai Hadas 		break;
11547efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SQ:
11551368ead0SYishai Hadas 		MLX5_SET(destroy_sq_in, din, opcode, MLX5_CMD_OP_DESTROY_SQ);
11561368ead0SYishai Hadas 		MLX5_SET(destroy_sq_in, din, sqn, *obj_id);
11577efce369SYishai Hadas 		break;
11587efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQ:
11591368ead0SYishai Hadas 		MLX5_SET(destroy_rq_in, din, opcode, MLX5_CMD_OP_DESTROY_RQ);
11601368ead0SYishai Hadas 		MLX5_SET(destroy_rq_in, din, rqn, *obj_id);
11617efce369SYishai Hadas 		break;
11627efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_RQT:
11631368ead0SYishai Hadas 		MLX5_SET(destroy_rqt_in, din, opcode, MLX5_CMD_OP_DESTROY_RQT);
11641368ead0SYishai Hadas 		MLX5_SET(destroy_rqt_in, din, rqtn, *obj_id);
11657efce369SYishai Hadas 		break;
11667efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIR:
11678798e4adSYishai Hadas 		MLX5_SET(destroy_tir_in, din, opcode, MLX5_CMD_OP_DESTROY_TIR);
11688798e4adSYishai Hadas 		MLX5_SET(destroy_tir_in, din, tirn, *obj_id);
11697efce369SYishai Hadas 		break;
11707efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_TIS:
11711368ead0SYishai Hadas 		MLX5_SET(destroy_tis_in, din, opcode, MLX5_CMD_OP_DESTROY_TIS);
11721368ead0SYishai Hadas 		MLX5_SET(destroy_tis_in, din, tisn, *obj_id);
11737efce369SYishai Hadas 		break;
11747efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_Q_COUNTER:
11751368ead0SYishai Hadas 		MLX5_SET(dealloc_q_counter_in, din, opcode,
11767efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_Q_COUNTER);
11771368ead0SYishai Hadas 		MLX5_SET(dealloc_q_counter_in, din, counter_set_id, *obj_id);
11787efce369SYishai Hadas 		break;
11797efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_TABLE:
11807efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(destroy_flow_table_in);
11817efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, other_vport,
11827efce369SYishai Hadas 			 MLX5_GET(create_flow_table_in,  in, other_vport));
11837efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, vport_number,
11847efce369SYishai Hadas 			 MLX5_GET(create_flow_table_in,  in, vport_number));
11857efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, table_type,
11867efce369SYishai Hadas 			 MLX5_GET(create_flow_table_in,  in, table_type));
11877efce369SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, table_id, *obj_id);
11881368ead0SYishai Hadas 		MLX5_SET(destroy_flow_table_in, din, opcode,
11897efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_FLOW_TABLE);
11907efce369SYishai Hadas 		break;
11917efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_FLOW_GROUP:
11927efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(destroy_flow_group_in);
11937efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, other_vport,
11947efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, other_vport));
11957efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, vport_number,
11967efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, vport_number));
11977efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, table_type,
11987efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, table_type));
11997efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, table_id,
12007efce369SYishai Hadas 			 MLX5_GET(create_flow_group_in, in, table_id));
12017efce369SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, group_id, *obj_id);
12021368ead0SYishai Hadas 		MLX5_SET(destroy_flow_group_in, din, opcode,
12037efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_FLOW_GROUP);
12047efce369SYishai Hadas 		break;
12057efce369SYishai Hadas 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
12067efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(delete_fte_in);
12077efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, other_vport,
12087efce369SYishai Hadas 			 MLX5_GET(set_fte_in,  in, other_vport));
12097efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, vport_number,
12107efce369SYishai Hadas 			 MLX5_GET(set_fte_in, in, vport_number));
12117efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, table_type,
12127efce369SYishai Hadas 			 MLX5_GET(set_fte_in, in, table_type));
12137efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, table_id,
12147efce369SYishai Hadas 			 MLX5_GET(set_fte_in, in, table_id));
12157efce369SYishai Hadas 		MLX5_SET(delete_fte_in, din, flow_index, *obj_id);
12161368ead0SYishai Hadas 		MLX5_SET(delete_fte_in, din, opcode,
12177efce369SYishai Hadas 			 MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
12187efce369SYishai Hadas 		break;
12197efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
12201368ead0SYishai Hadas 		MLX5_SET(dealloc_flow_counter_in, din, opcode,
12217efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_FLOW_COUNTER);
12221368ead0SYishai Hadas 		MLX5_SET(dealloc_flow_counter_in, din, flow_counter_id,
12231368ead0SYishai Hadas 			 *obj_id);
12247efce369SYishai Hadas 		break;
122560786f09SMark Bloch 	case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT:
12261368ead0SYishai Hadas 		MLX5_SET(dealloc_packet_reformat_context_in, din, opcode,
122760786f09SMark Bloch 			 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
12281368ead0SYishai Hadas 		MLX5_SET(dealloc_packet_reformat_context_in, din,
12291368ead0SYishai Hadas 			 packet_reformat_id, *obj_id);
12307efce369SYishai Hadas 		break;
12317efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
12321368ead0SYishai Hadas 		MLX5_SET(dealloc_modify_header_context_in, din, opcode,
12337efce369SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT);
12341368ead0SYishai Hadas 		MLX5_SET(dealloc_modify_header_context_in, din,
12351368ead0SYishai Hadas 			 modify_header_id, *obj_id);
12367efce369SYishai Hadas 		break;
12377efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
12387efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(destroy_scheduling_element_in);
12397efce369SYishai Hadas 		MLX5_SET(destroy_scheduling_element_in, din,
12407efce369SYishai Hadas 			 scheduling_hierarchy,
12417efce369SYishai Hadas 			 MLX5_GET(create_scheduling_element_in, in,
12427efce369SYishai Hadas 				  scheduling_hierarchy));
12437efce369SYishai Hadas 		MLX5_SET(destroy_scheduling_element_in, din,
12447efce369SYishai Hadas 			 scheduling_element_id, *obj_id);
12451368ead0SYishai Hadas 		MLX5_SET(destroy_scheduling_element_in, din, opcode,
12467efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT);
12477efce369SYishai Hadas 		break;
12487efce369SYishai Hadas 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
12497efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(delete_vxlan_udp_dport_in);
12507efce369SYishai Hadas 		MLX5_SET(delete_vxlan_udp_dport_in, din, vxlan_udp_port, *obj_id);
12511368ead0SYishai Hadas 		MLX5_SET(delete_vxlan_udp_dport_in, din, opcode,
12527efce369SYishai Hadas 			 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
12537efce369SYishai Hadas 		break;
12547efce369SYishai Hadas 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
12557efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(delete_l2_table_entry_in);
12567efce369SYishai Hadas 		MLX5_SET(delete_l2_table_entry_in, din, table_index, *obj_id);
12571368ead0SYishai Hadas 		MLX5_SET(delete_l2_table_entry_in, din, opcode,
12587efce369SYishai Hadas 			 MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY);
12597efce369SYishai Hadas 		break;
12607efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_QP:
12611368ead0SYishai Hadas 		MLX5_SET(destroy_qp_in, din, opcode, MLX5_CMD_OP_DESTROY_QP);
12621368ead0SYishai Hadas 		MLX5_SET(destroy_qp_in, din, qpn, *obj_id);
12637efce369SYishai Hadas 		break;
12647efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_SRQ:
12651368ead0SYishai Hadas 		MLX5_SET(destroy_srq_in, din, opcode, MLX5_CMD_OP_DESTROY_SRQ);
12661368ead0SYishai Hadas 		MLX5_SET(destroy_srq_in, din, srqn, *obj_id);
12677efce369SYishai Hadas 		break;
12687efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
12691368ead0SYishai Hadas 		MLX5_SET(destroy_xrc_srq_in, din, opcode,
12707efce369SYishai Hadas 			 MLX5_CMD_OP_DESTROY_XRC_SRQ);
12711368ead0SYishai Hadas 		MLX5_SET(destroy_xrc_srq_in, din, xrc_srqn, *obj_id);
12727efce369SYishai Hadas 		break;
12737efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_DCT:
12741368ead0SYishai Hadas 		MLX5_SET(destroy_dct_in, din, opcode, MLX5_CMD_OP_DESTROY_DCT);
12751368ead0SYishai Hadas 		MLX5_SET(destroy_dct_in, din, dctn, *obj_id);
12767efce369SYishai Hadas 		break;
12777efce369SYishai Hadas 	case MLX5_CMD_OP_CREATE_XRQ:
12781368ead0SYishai Hadas 		MLX5_SET(destroy_xrq_in, din, opcode, MLX5_CMD_OP_DESTROY_XRQ);
12791368ead0SYishai Hadas 		MLX5_SET(destroy_xrq_in, din, xrqn, *obj_id);
12807efce369SYishai Hadas 		break;
12817efce369SYishai Hadas 	case MLX5_CMD_OP_ATTACH_TO_MCG:
12827efce369SYishai Hadas 		*dinlen = MLX5_ST_SZ_BYTES(detach_from_mcg_in);
12837efce369SYishai Hadas 		MLX5_SET(detach_from_mcg_in, din, qpn,
12847efce369SYishai Hadas 			 MLX5_GET(attach_to_mcg_in, in, qpn));
12857efce369SYishai Hadas 		memcpy(MLX5_ADDR_OF(detach_from_mcg_in, din, multicast_gid),
12867efce369SYishai Hadas 		       MLX5_ADDR_OF(attach_to_mcg_in, in, multicast_gid),
12877efce369SYishai Hadas 		       MLX5_FLD_SZ_BYTES(attach_to_mcg_in, multicast_gid));
12881368ead0SYishai Hadas 		MLX5_SET(detach_from_mcg_in, din, opcode,
12891368ead0SYishai Hadas 			 MLX5_CMD_OP_DETACH_FROM_MCG);
12901368ead0SYishai Hadas 		MLX5_SET(detach_from_mcg_in, din, qpn, *obj_id);
12917efce369SYishai Hadas 		break;
12927efce369SYishai Hadas 	case MLX5_CMD_OP_ALLOC_XRCD:
12931368ead0SYishai Hadas 		MLX5_SET(dealloc_xrcd_in, din, opcode,
12941368ead0SYishai Hadas 			 MLX5_CMD_OP_DEALLOC_XRCD);
12951368ead0SYishai Hadas 		MLX5_SET(dealloc_xrcd_in, din, xrcd, *obj_id);
12967efce369SYishai Hadas 		break;
12978b38c538SMax Gurtovoy 	case MLX5_CMD_OP_CREATE_PSV:
12981368ead0SYishai Hadas 		MLX5_SET(destroy_psv_in, din, opcode,
12998b38c538SMax Gurtovoy 			 MLX5_CMD_OP_DESTROY_PSV);
13001368ead0SYishai Hadas 		MLX5_SET(destroy_psv_in, din, psvn, *obj_id);
13018b38c538SMax Gurtovoy 		break;
13027efce369SYishai Hadas 	default:
13037efce369SYishai Hadas 		/* The entry must match to one of the devx_is_obj_create_cmd */
13047efce369SYishai Hadas 		WARN_ON(true);
13057efce369SYishai Hadas 		break;
13067efce369SYishai Hadas 	}
13077efce369SYishai Hadas }
13087efce369SYishai Hadas 
1309534fd7aaSYishai Hadas static int devx_handle_mkey_indirect(struct devx_obj *obj,
1310534fd7aaSYishai Hadas 				     struct mlx5_ib_dev *dev,
1311534fd7aaSYishai Hadas 				     void *in, void *out)
1312534fd7aaSYishai Hadas {
1313ae0579acSAharon Landau 	struct mlx5_ib_mkey *mkey = &obj->mkey;
1314534fd7aaSYishai Hadas 	void *mkc;
1315534fd7aaSYishai Hadas 	u8 key;
1316534fd7aaSYishai Hadas 
1317534fd7aaSYishai Hadas 	mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
1318534fd7aaSYishai Hadas 	key = MLX5_GET(mkc, mkc, mkey_7_0);
1319534fd7aaSYishai Hadas 	mkey->key = mlx5_idx_to_mkey(
1320534fd7aaSYishai Hadas 			MLX5_GET(create_mkey_out, out, mkey_index)) | key;
1321534fd7aaSYishai Hadas 	mkey->type = MLX5_MKEY_INDIRECT_DEVX;
1322ae0579acSAharon Landau 	mkey->ndescs = MLX5_GET(mkc, mkc, translations_octword_size);
1323db72438cSYishai Hadas 	init_waitqueue_head(&mkey->wait);
1324534fd7aaSYishai Hadas 
1325db72438cSYishai Hadas 	return mlx5r_store_odp_mkey(dev, mkey);
1326534fd7aaSYishai Hadas }
1327534fd7aaSYishai Hadas 
1328fa31f143SYishai Hadas static int devx_handle_mkey_create(struct mlx5_ib_dev *dev,
1329fa31f143SYishai Hadas 				   struct devx_obj *obj,
1330fa31f143SYishai Hadas 				   void *in, int in_len)
1331fa31f143SYishai Hadas {
1332fa31f143SYishai Hadas 	int min_len = MLX5_BYTE_OFF(create_mkey_in, memory_key_mkey_entry) +
1333fa31f143SYishai Hadas 			MLX5_FLD_SZ_BYTES(create_mkey_in,
1334fa31f143SYishai Hadas 			memory_key_mkey_entry);
1335fa31f143SYishai Hadas 	void *mkc;
1336fa31f143SYishai Hadas 	u8 access_mode;
1337fa31f143SYishai Hadas 
1338fa31f143SYishai Hadas 	if (in_len < min_len)
1339fa31f143SYishai Hadas 		return -EINVAL;
1340fa31f143SYishai Hadas 
1341fa31f143SYishai Hadas 	mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
1342fa31f143SYishai Hadas 
1343fa31f143SYishai Hadas 	access_mode = MLX5_GET(mkc, mkc, access_mode_1_0);
1344fa31f143SYishai Hadas 	access_mode |= MLX5_GET(mkc, mkc, access_mode_4_2) << 2;
1345fa31f143SYishai Hadas 
1346fa31f143SYishai Hadas 	if (access_mode == MLX5_MKC_ACCESS_MODE_KLMS ||
1347534fd7aaSYishai Hadas 		access_mode == MLX5_MKC_ACCESS_MODE_KSM) {
1348534fd7aaSYishai Hadas 		if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING))
1349534fd7aaSYishai Hadas 			obj->flags |= DEVX_OBJ_FLAGS_INDIRECT_MKEY;
1350fa31f143SYishai Hadas 		return 0;
1351534fd7aaSYishai Hadas 	}
1352fa31f143SYishai Hadas 
1353fa31f143SYishai Hadas 	MLX5_SET(create_mkey_in, in, mkey_umem_valid, 1);
1354fa31f143SYishai Hadas 	return 0;
1355fa31f143SYishai Hadas }
1356fa31f143SYishai Hadas 
135775973853SYishai Hadas static void devx_cleanup_subscription(struct mlx5_ib_dev *dev,
135875973853SYishai Hadas 				      struct devx_event_subscription *sub)
135975973853SYishai Hadas {
136075973853SYishai Hadas 	struct devx_event *event;
136175973853SYishai Hadas 	struct devx_obj_event *xa_val_level2;
136275973853SYishai Hadas 
136375973853SYishai Hadas 	if (sub->is_cleaned)
136475973853SYishai Hadas 		return;
136575973853SYishai Hadas 
136675973853SYishai Hadas 	sub->is_cleaned = 1;
136775973853SYishai Hadas 	list_del_rcu(&sub->xa_list);
136875973853SYishai Hadas 
136975973853SYishai Hadas 	if (list_empty(&sub->obj_list))
137075973853SYishai Hadas 		return;
137175973853SYishai Hadas 
137275973853SYishai Hadas 	list_del_rcu(&sub->obj_list);
137375973853SYishai Hadas 	/* check whether key level 1 for this obj_sub_list is empty */
137475973853SYishai Hadas 	event = xa_load(&dev->devx_event_table.event_xa,
137575973853SYishai Hadas 			sub->xa_key_level1);
137675973853SYishai Hadas 	WARN_ON(!event);
137775973853SYishai Hadas 
137875973853SYishai Hadas 	xa_val_level2 = xa_load(&event->object_ids, sub->xa_key_level2);
137975973853SYishai Hadas 	if (list_empty(&xa_val_level2->obj_sub_list)) {
138075973853SYishai Hadas 		xa_erase(&event->object_ids,
138175973853SYishai Hadas 			 sub->xa_key_level2);
138275973853SYishai Hadas 		kfree_rcu(xa_val_level2, rcu);
138375973853SYishai Hadas 	}
138475973853SYishai Hadas }
138575973853SYishai Hadas 
13867efce369SYishai Hadas static int devx_obj_cleanup(struct ib_uobject *uobject,
1387a6a3797dSShamir Rabinovitch 			    enum rdma_remove_reason why,
1388a6a3797dSShamir Rabinovitch 			    struct uverbs_attr_bundle *attrs)
13897efce369SYishai Hadas {
13907efce369SYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
139175973853SYishai Hadas 	struct mlx5_devx_event_table *devx_event_table;
13927efce369SYishai Hadas 	struct devx_obj *obj = uobject->object;
139375973853SYishai Hadas 	struct devx_event_subscription *sub_entry, *tmp;
139475973853SYishai Hadas 	struct mlx5_ib_dev *dev;
13957efce369SYishai Hadas 	int ret;
13967efce369SYishai Hadas 
139775973853SYishai Hadas 	dev = mlx5_udata_to_mdev(&attrs->driver_udata);
1398db72438cSYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY &&
1399db72438cSYishai Hadas 	    xa_erase(&obj->ib_dev->odp_mkeys,
1400ae0579acSAharon Landau 		     mlx5_base_mkey(obj->mkey.key)))
140104177915SJason Gunthorpe 		/*
140204177915SJason Gunthorpe 		 * The pagefault_single_data_segment() does commands against
140304177915SJason Gunthorpe 		 * the mmkey, we must wait for that to stop before freeing the
140404177915SJason Gunthorpe 		 * mkey, as another allocation could get the same mkey #.
140504177915SJason Gunthorpe 		 */
1406ae0579acSAharon Landau 		mlx5r_deref_wait_odp_mkey(&obj->mkey);
1407534fd7aaSYishai Hadas 
1408c5ae1954SYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_DCT)
1409333fbaa0SLeon Romanovsky 		ret = mlx5_core_destroy_dct(obj->ib_dev, &obj->core_dct);
1410ef1659adSYishai Hadas 	else if (obj->flags & DEVX_OBJ_FLAGS_CQ)
14115832fdd3SYishai Hadas 		ret = mlx5_core_destroy_cq(obj->ib_dev->mdev, &obj->core_cq);
1412c5ae1954SYishai Hadas 	else
14135832fdd3SYishai Hadas 		ret = mlx5_cmd_exec(obj->ib_dev->mdev, obj->dinbox,
14145832fdd3SYishai Hadas 				    obj->dinlen, out, sizeof(out));
1415efa968eeSLeon Romanovsky 	if (ret)
14167efce369SYishai Hadas 		return ret;
14177efce369SYishai Hadas 
141875973853SYishai Hadas 	devx_event_table = &dev->devx_event_table;
1419534fd7aaSYishai Hadas 
142075973853SYishai Hadas 	mutex_lock(&devx_event_table->event_xa_lock);
142175973853SYishai Hadas 	list_for_each_entry_safe(sub_entry, tmp, &obj->event_sub, obj_list)
142275973853SYishai Hadas 		devx_cleanup_subscription(dev, sub_entry);
142375973853SYishai Hadas 	mutex_unlock(&devx_event_table->event_xa_lock);
142475973853SYishai Hadas 
14257efce369SYishai Hadas 	kfree(obj);
14267efce369SYishai Hadas 	return ret;
14277efce369SYishai Hadas }
14287efce369SYishai Hadas 
1429ef1659adSYishai Hadas static void devx_cq_comp(struct mlx5_core_cq *mcq, struct mlx5_eqe *eqe)
1430ef1659adSYishai Hadas {
1431ef1659adSYishai Hadas 	struct devx_obj *obj = container_of(mcq, struct devx_obj, core_cq);
1432ef1659adSYishai Hadas 	struct mlx5_devx_event_table *table;
1433ef1659adSYishai Hadas 	struct devx_event *event;
1434ef1659adSYishai Hadas 	struct devx_obj_event *obj_event;
1435ef1659adSYishai Hadas 	u32 obj_id = mcq->cqn;
1436ef1659adSYishai Hadas 
1437ef1659adSYishai Hadas 	table = &obj->ib_dev->devx_event_table;
1438ef1659adSYishai Hadas 	rcu_read_lock();
1439ef1659adSYishai Hadas 	event = xa_load(&table->event_xa, MLX5_EVENT_TYPE_COMP);
1440ef1659adSYishai Hadas 	if (!event)
1441ef1659adSYishai Hadas 		goto out;
1442ef1659adSYishai Hadas 
1443ef1659adSYishai Hadas 	obj_event = xa_load(&event->object_ids, obj_id);
1444ef1659adSYishai Hadas 	if (!obj_event)
1445ef1659adSYishai Hadas 		goto out;
1446ef1659adSYishai Hadas 
1447ef1659adSYishai Hadas 	dispatch_event_fd(&obj_event->obj_sub_list, eqe);
1448ef1659adSYishai Hadas out:
1449ef1659adSYishai Hadas 	rcu_read_unlock();
1450ef1659adSYishai Hadas }
1451ef1659adSYishai Hadas 
1452616d5769STal Gilboa static bool is_apu_cq(struct mlx5_ib_dev *dev, const void *in)
14537232c132STal Gilboa {
14547232c132STal Gilboa 	if (!MLX5_CAP_GEN(dev->mdev, apu) ||
1455616d5769STal Gilboa 	    !MLX5_GET(cqc, MLX5_ADDR_OF(create_cq_in, in, cq_context), apu_cq))
14567232c132STal Gilboa 		return false;
14577232c132STal Gilboa 
14587232c132STal Gilboa 	return true;
14597232c132STal Gilboa }
14607232c132STal Gilboa 
1461e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
146215a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
14637efce369SYishai Hadas {
14647efce369SYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN);
14657efce369SYishai Hadas 	int cmd_out_len =  uverbs_attr_get_len(attrs,
14667efce369SYishai Hadas 					MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT);
1467fa31f143SYishai Hadas 	int cmd_in_len = uverbs_attr_get_len(attrs,
1468fa31f143SYishai Hadas 					MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN);
14697efce369SYishai Hadas 	void *cmd_out;
1470c36ee46dSJason Gunthorpe 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
1471c36ee46dSJason Gunthorpe 		attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE);
147289944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
147389944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1474c36ee46dSJason Gunthorpe 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
1475e8ef090aSYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
14767efce369SYishai Hadas 	struct devx_obj *obj;
1477cd5d20f1SYishai Hadas 	u16 obj_type = 0;
1478c76a1e90SSaeed Mahameed 	int err, err2 = 0;
14797e1335a7SYishai Hadas 	int uid;
14802351776eSYishai Hadas 	u32 obj_id;
14812351776eSYishai Hadas 	u16 opcode;
14827efce369SYishai Hadas 
1483b6142608SMax Gurtovoy 	if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id))
1484b6142608SMax Gurtovoy 		return -EINVAL;
1485b6142608SMax Gurtovoy 
14867e1335a7SYishai Hadas 	uid = devx_get_uid(c, cmd_in);
14877e1335a7SYishai Hadas 	if (uid < 0)
14887e1335a7SYishai Hadas 		return uid;
14897efce369SYishai Hadas 
14902351776eSYishai Hadas 	if (!devx_is_obj_create_cmd(cmd_in, &opcode))
14917efce369SYishai Hadas 		return -EINVAL;
14927efce369SYishai Hadas 
1493b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
1494b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
1495b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
1496b61815e2SJason Gunthorpe 
14977efce369SYishai Hadas 	obj = kzalloc(sizeof(struct devx_obj), GFP_KERNEL);
14987efce369SYishai Hadas 	if (!obj)
14997efce369SYishai Hadas 		return -ENOMEM;
15007efce369SYishai Hadas 
15017e1335a7SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1502fa31f143SYishai Hadas 	if (opcode == MLX5_CMD_OP_CREATE_MKEY) {
1503fa31f143SYishai Hadas 		err = devx_handle_mkey_create(dev, obj, cmd_in, cmd_in_len);
1504fa31f143SYishai Hadas 		if (err)
1505fa31f143SYishai Hadas 			goto obj_free;
1506fa31f143SYishai Hadas 	} else {
1507ba1a057dSYishai Hadas 		devx_set_umem_valid(cmd_in);
1508fa31f143SYishai Hadas 	}
1509ba1a057dSYishai Hadas 
1510c5ae1954SYishai Hadas 	if (opcode == MLX5_CMD_OP_CREATE_DCT) {
1511c5ae1954SYishai Hadas 		obj->flags |= DEVX_OBJ_FLAGS_DCT;
1512333fbaa0SLeon Romanovsky 		err = mlx5_core_create_dct(dev, &obj->core_dct, cmd_in,
1513333fbaa0SLeon Romanovsky 					   cmd_in_len, cmd_out, cmd_out_len);
15147232c132STal Gilboa 	} else if (opcode == MLX5_CMD_OP_CREATE_CQ &&
1515616d5769STal Gilboa 		   !is_apu_cq(dev, cmd_in)) {
1516ef1659adSYishai Hadas 		obj->flags |= DEVX_OBJ_FLAGS_CQ;
1517ef1659adSYishai Hadas 		obj->core_cq.comp = devx_cq_comp;
151831803e59SSaeed Mahameed 		err = mlx5_create_cq(dev->mdev, &obj->core_cq,
1519ef1659adSYishai Hadas 				     cmd_in, cmd_in_len, cmd_out,
1520ef1659adSYishai Hadas 				     cmd_out_len);
1521c5ae1954SYishai Hadas 	} else {
1522c76a1e90SSaeed Mahameed 		err = mlx5_cmd_do(dev->mdev, cmd_in, cmd_in_len,
15237efce369SYishai Hadas 				  cmd_out, cmd_out_len);
1524c5ae1954SYishai Hadas 	}
1525c5ae1954SYishai Hadas 
1526c76a1e90SSaeed Mahameed 	if (err == -EREMOTEIO)
1527c76a1e90SSaeed Mahameed 		err2 = uverbs_copy_to(attrs,
1528c76a1e90SSaeed Mahameed 				      MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT,
1529c76a1e90SSaeed Mahameed 				      cmd_out, cmd_out_len);
15307efce369SYishai Hadas 	if (err)
1531b61815e2SJason Gunthorpe 		goto obj_free;
15327efce369SYishai Hadas 
1533208d70f5SYevgeny Kliteynik 	if (opcode == MLX5_CMD_OP_ALLOC_FLOW_COUNTER) {
15343e358ea8SMark Bloch 		u32 bulk = MLX5_GET(alloc_flow_counter_in,
15353e358ea8SMark Bloch 				    cmd_in,
15363e358ea8SMark Bloch 				    flow_counter_bulk_log_size);
15373e358ea8SMark Bloch 
15383e358ea8SMark Bloch 		if (bulk)
15393e358ea8SMark Bloch 			bulk = 1 << bulk;
15403e358ea8SMark Bloch 		else
15413e358ea8SMark Bloch 			bulk = 128UL * MLX5_GET(alloc_flow_counter_in,
1542208d70f5SYevgeny Kliteynik 						cmd_in,
1543208d70f5SYevgeny Kliteynik 						flow_counter_bulk);
15443e358ea8SMark Bloch 		obj->flow_counter_bulk_size = bulk;
1545208d70f5SYevgeny Kliteynik 	}
1546208d70f5SYevgeny Kliteynik 
15477efce369SYishai Hadas 	uobj->object = obj;
154875973853SYishai Hadas 	INIT_LIST_HEAD(&obj->event_sub);
1549ef1659adSYishai Hadas 	obj->ib_dev = dev;
15502351776eSYishai Hadas 	devx_obj_build_destroy_cmd(cmd_in, cmd_out, obj->dinbox, &obj->dinlen,
15512351776eSYishai Hadas 				   &obj_id);
15527efce369SYishai Hadas 	WARN_ON(obj->dinlen > MLX5_MAX_DESTROY_INBOX_SIZE_DW * sizeof(u32));
15537efce369SYishai Hadas 
155404177915SJason Gunthorpe 	err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, cmd_out, cmd_out_len);
155504177915SJason Gunthorpe 	if (err)
155604177915SJason Gunthorpe 		goto obj_destroy;
155704177915SJason Gunthorpe 
155804177915SJason Gunthorpe 	if (opcode == MLX5_CMD_OP_CREATE_GENERAL_OBJECT)
155904177915SJason Gunthorpe 		obj_type = MLX5_GET(general_obj_in_cmd_hdr, cmd_in, obj_type);
156004177915SJason Gunthorpe 	obj->obj_id = get_enc_obj_id(opcode | obj_type << 16, obj_id);
156104177915SJason Gunthorpe 
1562534fd7aaSYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY) {
1563534fd7aaSYishai Hadas 		err = devx_handle_mkey_indirect(obj, dev, cmd_in, cmd_out);
1564534fd7aaSYishai Hadas 		if (err)
1565534fd7aaSYishai Hadas 			goto obj_destroy;
1566534fd7aaSYishai Hadas 	}
15677efce369SYishai Hadas 	return 0;
15687efce369SYishai Hadas 
15690da4d48dSYishai Hadas obj_destroy:
1570c5ae1954SYishai Hadas 	if (obj->flags & DEVX_OBJ_FLAGS_DCT)
1571333fbaa0SLeon Romanovsky 		mlx5_core_destroy_dct(obj->ib_dev, &obj->core_dct);
1572ef1659adSYishai Hadas 	else if (obj->flags & DEVX_OBJ_FLAGS_CQ)
15735832fdd3SYishai Hadas 		mlx5_core_destroy_cq(obj->ib_dev->mdev, &obj->core_cq);
1574c5ae1954SYishai Hadas 	else
15755832fdd3SYishai Hadas 		mlx5_cmd_exec(obj->ib_dev->mdev, obj->dinbox, obj->dinlen, out,
1576c5ae1954SYishai Hadas 			      sizeof(out));
15777efce369SYishai Hadas obj_free:
15787efce369SYishai Hadas 	kfree(obj);
1579c76a1e90SSaeed Mahameed 	return err2 ?: err;
15807efce369SYishai Hadas }
15817efce369SYishai Hadas 
1582e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)(
158315a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
1584e662e14dSYishai Hadas {
1585e662e14dSYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN);
1586e662e14dSYishai Hadas 	int cmd_out_len = uverbs_attr_get_len(attrs,
1587e662e14dSYishai Hadas 					MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT);
1588e662e14dSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
1589e662e14dSYishai Hadas 							  MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE);
159089944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
159189944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
159289944450SShamir Rabinovitch 	struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device);
1593e662e14dSYishai Hadas 	void *cmd_out;
1594c76a1e90SSaeed Mahameed 	int err, err2;
15957e1335a7SYishai Hadas 	int uid;
1596e662e14dSYishai Hadas 
1597b6142608SMax Gurtovoy 	if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id))
1598b6142608SMax Gurtovoy 		return -EINVAL;
1599b6142608SMax Gurtovoy 
16007e1335a7SYishai Hadas 	uid = devx_get_uid(c, cmd_in);
16017e1335a7SYishai Hadas 	if (uid < 0)
16027e1335a7SYishai Hadas 		return uid;
1603e662e14dSYishai Hadas 
1604e662e14dSYishai Hadas 	if (!devx_is_obj_modify_cmd(cmd_in))
1605e662e14dSYishai Hadas 		return -EINVAL;
1606e662e14dSYishai Hadas 
1607e79c9c60SJason Gunthorpe 	if (!devx_is_valid_obj_id(attrs, uobj, cmd_in))
1608e662e14dSYishai Hadas 		return -EINVAL;
1609e662e14dSYishai Hadas 
1610b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
1611b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
1612b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
1613e662e14dSYishai Hadas 
16147e1335a7SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1615ba1a057dSYishai Hadas 	devx_set_umem_valid(cmd_in);
1616ba1a057dSYishai Hadas 
1617c76a1e90SSaeed Mahameed 	err = mlx5_cmd_do(mdev->mdev, cmd_in,
1618e662e14dSYishai Hadas 			  uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN),
1619e662e14dSYishai Hadas 			  cmd_out, cmd_out_len);
1620c76a1e90SSaeed Mahameed 	if (err && err != -EREMOTEIO)
1621e662e14dSYishai Hadas 		return err;
1622b61815e2SJason Gunthorpe 
1623c76a1e90SSaeed Mahameed 	err2 = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
1624b61815e2SJason Gunthorpe 			      cmd_out, cmd_out_len);
1625c76a1e90SSaeed Mahameed 
1626c76a1e90SSaeed Mahameed 	return err2 ?: err;
1627e662e14dSYishai Hadas }
1628e662e14dSYishai Hadas 
1629e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)(
163015a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
1631e662e14dSYishai Hadas {
1632e662e14dSYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN);
1633e662e14dSYishai Hadas 	int cmd_out_len = uverbs_attr_get_len(attrs,
1634e662e14dSYishai Hadas 					      MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT);
1635e662e14dSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
1636e662e14dSYishai Hadas 							  MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE);
163789944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
163889944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1639e662e14dSYishai Hadas 	void *cmd_out;
1640c76a1e90SSaeed Mahameed 	int err, err2;
16417e1335a7SYishai Hadas 	int uid;
164289944450SShamir Rabinovitch 	struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device);
1643e662e14dSYishai Hadas 
1644b6142608SMax Gurtovoy 	if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id))
1645b6142608SMax Gurtovoy 		return -EINVAL;
1646b6142608SMax Gurtovoy 
16477e1335a7SYishai Hadas 	uid = devx_get_uid(c, cmd_in);
16487e1335a7SYishai Hadas 	if (uid < 0)
16497e1335a7SYishai Hadas 		return uid;
1650e662e14dSYishai Hadas 
1651e662e14dSYishai Hadas 	if (!devx_is_obj_query_cmd(cmd_in))
1652e662e14dSYishai Hadas 		return -EINVAL;
1653e662e14dSYishai Hadas 
1654e79c9c60SJason Gunthorpe 	if (!devx_is_valid_obj_id(attrs, uobj, cmd_in))
1655e662e14dSYishai Hadas 		return -EINVAL;
1656e662e14dSYishai Hadas 
1657b61815e2SJason Gunthorpe 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
1658b61815e2SJason Gunthorpe 	if (IS_ERR(cmd_out))
1659b61815e2SJason Gunthorpe 		return PTR_ERR(cmd_out);
1660e662e14dSYishai Hadas 
16617e1335a7SYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1662c76a1e90SSaeed Mahameed 	err = mlx5_cmd_do(mdev->mdev, cmd_in,
1663e662e14dSYishai Hadas 			  uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN),
1664e662e14dSYishai Hadas 			  cmd_out, cmd_out_len);
1665c76a1e90SSaeed Mahameed 	if (err && err != -EREMOTEIO)
1666e662e14dSYishai Hadas 		return err;
1667b61815e2SJason Gunthorpe 
1668c76a1e90SSaeed Mahameed 	err2 = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
1669b61815e2SJason Gunthorpe 			      cmd_out, cmd_out_len);
1670c76a1e90SSaeed Mahameed 
1671c76a1e90SSaeed Mahameed 	return err2 ?: err;
1672e662e14dSYishai Hadas }
1673e662e14dSYishai Hadas 
16746bf8f22aSYishai Hadas struct devx_async_event_queue {
16756bf8f22aSYishai Hadas 	spinlock_t		lock;
16766bf8f22aSYishai Hadas 	wait_queue_head_t	poll_wait;
16776bf8f22aSYishai Hadas 	struct list_head	event_list;
1678a124edbaSYishai Hadas 	atomic_t		bytes_in_use;
1679eaebaf77SYishai Hadas 	u8			is_destroyed:1;
16806bf8f22aSYishai Hadas };
16816bf8f22aSYishai Hadas 
16826bf8f22aSYishai Hadas struct devx_async_cmd_event_file {
16836bf8f22aSYishai Hadas 	struct ib_uobject		uobj;
16846bf8f22aSYishai Hadas 	struct devx_async_event_queue	ev_queue;
1685a124edbaSYishai Hadas 	struct mlx5_async_ctx		async_ctx;
16866bf8f22aSYishai Hadas };
16876bf8f22aSYishai Hadas 
16886bf8f22aSYishai Hadas static void devx_init_event_queue(struct devx_async_event_queue *ev_queue)
16896bf8f22aSYishai Hadas {
16906bf8f22aSYishai Hadas 	spin_lock_init(&ev_queue->lock);
16916bf8f22aSYishai Hadas 	INIT_LIST_HEAD(&ev_queue->event_list);
16926bf8f22aSYishai Hadas 	init_waitqueue_head(&ev_queue->poll_wait);
1693a124edbaSYishai Hadas 	atomic_set(&ev_queue->bytes_in_use, 0);
1694eaebaf77SYishai Hadas 	ev_queue->is_destroyed = 0;
16956bf8f22aSYishai Hadas }
16966bf8f22aSYishai Hadas 
16976bf8f22aSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC)(
16986bf8f22aSYishai Hadas 	struct uverbs_attr_bundle *attrs)
16996bf8f22aSYishai Hadas {
17006bf8f22aSYishai Hadas 	struct devx_async_cmd_event_file *ev_file;
17016bf8f22aSYishai Hadas 
17026bf8f22aSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
17036bf8f22aSYishai Hadas 		attrs, MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE);
1704e79c9c60SJason Gunthorpe 	struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata);
17056bf8f22aSYishai Hadas 
17066bf8f22aSYishai Hadas 	ev_file = container_of(uobj, struct devx_async_cmd_event_file,
17076bf8f22aSYishai Hadas 			       uobj);
17086bf8f22aSYishai Hadas 	devx_init_event_queue(&ev_file->ev_queue);
1709a124edbaSYishai Hadas 	mlx5_cmd_init_async_ctx(mdev->mdev, &ev_file->async_ctx);
17106bf8f22aSYishai Hadas 	return 0;
17116bf8f22aSYishai Hadas }
17126bf8f22aSYishai Hadas 
17132afc5e1bSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC)(
17142afc5e1bSYishai Hadas 	struct uverbs_attr_bundle *attrs)
17152afc5e1bSYishai Hadas {
17162afc5e1bSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
17172afc5e1bSYishai Hadas 		attrs, MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_HANDLE);
17182afc5e1bSYishai Hadas 	struct devx_async_event_file *ev_file;
17192afc5e1bSYishai Hadas 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
17202afc5e1bSYishai Hadas 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
17212afc5e1bSYishai Hadas 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
17222afc5e1bSYishai Hadas 	u32 flags;
17232afc5e1bSYishai Hadas 	int err;
17242afc5e1bSYishai Hadas 
17252afc5e1bSYishai Hadas 	err = uverbs_get_flags32(&flags, attrs,
17262afc5e1bSYishai Hadas 		MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_FLAGS,
17272afc5e1bSYishai Hadas 		MLX5_IB_UAPI_DEVX_CR_EV_CH_FLAGS_OMIT_DATA);
17282afc5e1bSYishai Hadas 
17292afc5e1bSYishai Hadas 	if (err)
17302afc5e1bSYishai Hadas 		return err;
17312afc5e1bSYishai Hadas 
17322afc5e1bSYishai Hadas 	ev_file = container_of(uobj, struct devx_async_event_file,
17332afc5e1bSYishai Hadas 			       uobj);
17342afc5e1bSYishai Hadas 	spin_lock_init(&ev_file->lock);
17352afc5e1bSYishai Hadas 	INIT_LIST_HEAD(&ev_file->event_list);
17362afc5e1bSYishai Hadas 	init_waitqueue_head(&ev_file->poll_wait);
17372afc5e1bSYishai Hadas 	if (flags & MLX5_IB_UAPI_DEVX_CR_EV_CH_FLAGS_OMIT_DATA)
17382afc5e1bSYishai Hadas 		ev_file->omit_data = 1;
17392afc5e1bSYishai Hadas 	INIT_LIST_HEAD(&ev_file->subscribed_events_list);
17402afc5e1bSYishai Hadas 	ev_file->dev = dev;
174175973853SYishai Hadas 	get_device(&dev->ib_dev.dev);
17422afc5e1bSYishai Hadas 	return 0;
17432afc5e1bSYishai Hadas }
17442afc5e1bSYishai Hadas 
1745a124edbaSYishai Hadas static void devx_query_callback(int status, struct mlx5_async_work *context)
1746a124edbaSYishai Hadas {
1747a124edbaSYishai Hadas 	struct devx_async_data *async_data =
1748a124edbaSYishai Hadas 		container_of(context, struct devx_async_data, cb_work);
174993887e66SJason Gunthorpe 	struct devx_async_cmd_event_file *ev_file = async_data->ev_file;
175093887e66SJason Gunthorpe 	struct devx_async_event_queue *ev_queue = &ev_file->ev_queue;
1751a124edbaSYishai Hadas 	unsigned long flags;
1752a124edbaSYishai Hadas 
175393887e66SJason Gunthorpe 	/*
175493887e66SJason Gunthorpe 	 * Note that if the struct devx_async_cmd_event_file uobj begins to be
175593887e66SJason Gunthorpe 	 * destroyed it will block at mlx5_cmd_cleanup_async_ctx() until this
175693887e66SJason Gunthorpe 	 * routine returns, ensuring that it always remains valid here.
175793887e66SJason Gunthorpe 	 */
1758a124edbaSYishai Hadas 	spin_lock_irqsave(&ev_queue->lock, flags);
1759a124edbaSYishai Hadas 	list_add_tail(&async_data->list, &ev_queue->event_list);
1760a124edbaSYishai Hadas 	spin_unlock_irqrestore(&ev_queue->lock, flags);
1761a124edbaSYishai Hadas 
1762a124edbaSYishai Hadas 	wake_up_interruptible(&ev_queue->poll_wait);
1763a124edbaSYishai Hadas }
1764a124edbaSYishai Hadas 
1765a124edbaSYishai Hadas #define MAX_ASYNC_BYTES_IN_USE (1024 * 1024) /* 1MB */
1766a124edbaSYishai Hadas 
1767a124edbaSYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY)(
1768a124edbaSYishai Hadas 	struct uverbs_attr_bundle *attrs)
1769a124edbaSYishai Hadas {
1770a124edbaSYishai Hadas 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs,
1771a124edbaSYishai Hadas 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN);
1772a124edbaSYishai Hadas 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
1773a124edbaSYishai Hadas 				attrs,
1774a124edbaSYishai Hadas 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_HANDLE);
1775a124edbaSYishai Hadas 	u16 cmd_out_len;
177689944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
177789944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1778a124edbaSYishai Hadas 	struct ib_uobject *fd_uobj;
1779a124edbaSYishai Hadas 	int err;
1780a124edbaSYishai Hadas 	int uid;
178189944450SShamir Rabinovitch 	struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device);
1782a124edbaSYishai Hadas 	struct devx_async_cmd_event_file *ev_file;
1783a124edbaSYishai Hadas 	struct devx_async_data *async_data;
1784a124edbaSYishai Hadas 
1785b6142608SMax Gurtovoy 	if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id))
1786b6142608SMax Gurtovoy 		return -EINVAL;
1787b6142608SMax Gurtovoy 
1788a124edbaSYishai Hadas 	uid = devx_get_uid(c, cmd_in);
1789a124edbaSYishai Hadas 	if (uid < 0)
1790a124edbaSYishai Hadas 		return uid;
1791a124edbaSYishai Hadas 
1792a124edbaSYishai Hadas 	if (!devx_is_obj_query_cmd(cmd_in))
1793a124edbaSYishai Hadas 		return -EINVAL;
1794a124edbaSYishai Hadas 
1795a124edbaSYishai Hadas 	err = uverbs_get_const(&cmd_out_len, attrs,
1796a124edbaSYishai Hadas 			       MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_OUT_LEN);
1797a124edbaSYishai Hadas 	if (err)
1798a124edbaSYishai Hadas 		return err;
1799a124edbaSYishai Hadas 
1800e79c9c60SJason Gunthorpe 	if (!devx_is_valid_obj_id(attrs, uobj, cmd_in))
1801a124edbaSYishai Hadas 		return -EINVAL;
1802a124edbaSYishai Hadas 
1803a124edbaSYishai Hadas 	fd_uobj = uverbs_attr_get_uobject(attrs,
1804a124edbaSYishai Hadas 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_FD);
1805a124edbaSYishai Hadas 	if (IS_ERR(fd_uobj))
1806a124edbaSYishai Hadas 		return PTR_ERR(fd_uobj);
1807a124edbaSYishai Hadas 
1808a124edbaSYishai Hadas 	ev_file = container_of(fd_uobj, struct devx_async_cmd_event_file,
1809a124edbaSYishai Hadas 			       uobj);
1810a124edbaSYishai Hadas 
1811a124edbaSYishai Hadas 	if (atomic_add_return(cmd_out_len, &ev_file->ev_queue.bytes_in_use) >
1812a124edbaSYishai Hadas 			MAX_ASYNC_BYTES_IN_USE) {
1813a124edbaSYishai Hadas 		atomic_sub(cmd_out_len, &ev_file->ev_queue.bytes_in_use);
1814a124edbaSYishai Hadas 		return -EAGAIN;
1815a124edbaSYishai Hadas 	}
1816a124edbaSYishai Hadas 
1817a124edbaSYishai Hadas 	async_data = kvzalloc(struct_size(async_data, hdr.out_data,
1818a124edbaSYishai Hadas 					  cmd_out_len), GFP_KERNEL);
1819a124edbaSYishai Hadas 	if (!async_data) {
1820a124edbaSYishai Hadas 		err = -ENOMEM;
1821a124edbaSYishai Hadas 		goto sub_bytes;
1822a124edbaSYishai Hadas 	}
1823a124edbaSYishai Hadas 
1824a124edbaSYishai Hadas 	err = uverbs_copy_from(&async_data->hdr.wr_id, attrs,
1825a124edbaSYishai Hadas 			       MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_WR_ID);
1826a124edbaSYishai Hadas 	if (err)
1827a124edbaSYishai Hadas 		goto free_async;
1828a124edbaSYishai Hadas 
1829a124edbaSYishai Hadas 	async_data->cmd_out_len = cmd_out_len;
1830a124edbaSYishai Hadas 	async_data->mdev = mdev;
183193887e66SJason Gunthorpe 	async_data->ev_file = ev_file;
1832a124edbaSYishai Hadas 
1833a124edbaSYishai Hadas 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1834a124edbaSYishai Hadas 	err = mlx5_cmd_exec_cb(&ev_file->async_ctx, cmd_in,
1835a124edbaSYishai Hadas 		    uverbs_attr_get_len(attrs,
1836a124edbaSYishai Hadas 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN),
1837a124edbaSYishai Hadas 		    async_data->hdr.out_data,
1838a124edbaSYishai Hadas 		    async_data->cmd_out_len,
1839a124edbaSYishai Hadas 		    devx_query_callback, &async_data->cb_work);
1840a124edbaSYishai Hadas 
1841a124edbaSYishai Hadas 	if (err)
184293887e66SJason Gunthorpe 		goto free_async;
1843a124edbaSYishai Hadas 
1844a124edbaSYishai Hadas 	return 0;
1845a124edbaSYishai Hadas 
1846a124edbaSYishai Hadas free_async:
1847a124edbaSYishai Hadas 	kvfree(async_data);
1848a124edbaSYishai Hadas sub_bytes:
1849a124edbaSYishai Hadas 	atomic_sub(cmd_out_len, &ev_file->ev_queue.bytes_in_use);
1850a124edbaSYishai Hadas 	return err;
1851a124edbaSYishai Hadas }
1852a124edbaSYishai Hadas 
185375973853SYishai Hadas static void
185475973853SYishai Hadas subscribe_event_xa_dealloc(struct mlx5_devx_event_table *devx_event_table,
185575973853SYishai Hadas 			   u32 key_level1,
185675973853SYishai Hadas 			   bool is_level2,
185775973853SYishai Hadas 			   u32 key_level2)
185875973853SYishai Hadas {
185975973853SYishai Hadas 	struct devx_event *event;
186075973853SYishai Hadas 	struct devx_obj_event *xa_val_level2;
186175973853SYishai Hadas 
186275973853SYishai Hadas 	/* Level 1 is valid for future use, no need to free */
186375973853SYishai Hadas 	if (!is_level2)
186475973853SYishai Hadas 		return;
186575973853SYishai Hadas 
186675973853SYishai Hadas 	event = xa_load(&devx_event_table->event_xa, key_level1);
186775973853SYishai Hadas 	WARN_ON(!event);
186875973853SYishai Hadas 
186975973853SYishai Hadas 	xa_val_level2 = xa_load(&event->object_ids,
187075973853SYishai Hadas 				key_level2);
187175973853SYishai Hadas 	if (list_empty(&xa_val_level2->obj_sub_list)) {
187275973853SYishai Hadas 		xa_erase(&event->object_ids,
187375973853SYishai Hadas 			 key_level2);
187475973853SYishai Hadas 		kfree_rcu(xa_val_level2, rcu);
187575973853SYishai Hadas 	}
187675973853SYishai Hadas }
187775973853SYishai Hadas 
187875973853SYishai Hadas static int
187975973853SYishai Hadas subscribe_event_xa_alloc(struct mlx5_devx_event_table *devx_event_table,
188075973853SYishai Hadas 			 u32 key_level1,
188175973853SYishai Hadas 			 bool is_level2,
188275973853SYishai Hadas 			 u32 key_level2)
188375973853SYishai Hadas {
188475973853SYishai Hadas 	struct devx_obj_event *obj_event;
188575973853SYishai Hadas 	struct devx_event *event;
188675973853SYishai Hadas 	int err;
188775973853SYishai Hadas 
188875973853SYishai Hadas 	event = xa_load(&devx_event_table->event_xa, key_level1);
188975973853SYishai Hadas 	if (!event) {
189075973853SYishai Hadas 		event = kzalloc(sizeof(*event), GFP_KERNEL);
189175973853SYishai Hadas 		if (!event)
189275973853SYishai Hadas 			return -ENOMEM;
189375973853SYishai Hadas 
189475973853SYishai Hadas 		INIT_LIST_HEAD(&event->unaffiliated_list);
189575973853SYishai Hadas 		xa_init(&event->object_ids);
189675973853SYishai Hadas 
189775973853SYishai Hadas 		err = xa_insert(&devx_event_table->event_xa,
189875973853SYishai Hadas 				key_level1,
189975973853SYishai Hadas 				event,
190075973853SYishai Hadas 				GFP_KERNEL);
190175973853SYishai Hadas 		if (err) {
190275973853SYishai Hadas 			kfree(event);
190375973853SYishai Hadas 			return err;
190475973853SYishai Hadas 		}
190575973853SYishai Hadas 	}
190675973853SYishai Hadas 
190775973853SYishai Hadas 	if (!is_level2)
190875973853SYishai Hadas 		return 0;
190975973853SYishai Hadas 
191075973853SYishai Hadas 	obj_event = xa_load(&event->object_ids, key_level2);
191175973853SYishai Hadas 	if (!obj_event) {
191275973853SYishai Hadas 		obj_event = kzalloc(sizeof(*obj_event), GFP_KERNEL);
191375973853SYishai Hadas 		if (!obj_event)
191475973853SYishai Hadas 			/* Level1 is valid for future use, no need to free */
191575973853SYishai Hadas 			return -ENOMEM;
191675973853SYishai Hadas 
191775973853SYishai Hadas 		err = xa_insert(&event->object_ids,
191875973853SYishai Hadas 				key_level2,
191975973853SYishai Hadas 				obj_event,
192075973853SYishai Hadas 				GFP_KERNEL);
1921087f9c3fSYongzhi Liu 		if (err) {
1922087f9c3fSYongzhi Liu 			kfree(obj_event);
192375973853SYishai Hadas 			return err;
1924087f9c3fSYongzhi Liu 		}
192575973853SYishai Hadas 		INIT_LIST_HEAD(&obj_event->obj_sub_list);
192675973853SYishai Hadas 	}
192775973853SYishai Hadas 
192875973853SYishai Hadas 	return 0;
192975973853SYishai Hadas }
193075973853SYishai Hadas 
193175973853SYishai Hadas static bool is_valid_events_legacy(int num_events, u16 *event_type_num_list,
193275973853SYishai Hadas 				   struct devx_obj *obj)
193375973853SYishai Hadas {
193475973853SYishai Hadas 	int i;
193575973853SYishai Hadas 
193675973853SYishai Hadas 	for (i = 0; i < num_events; i++) {
193775973853SYishai Hadas 		if (obj) {
193875973853SYishai Hadas 			if (!is_legacy_obj_event_num(event_type_num_list[i]))
193975973853SYishai Hadas 				return false;
194075973853SYishai Hadas 		} else if (!is_legacy_unaffiliated_event_num(
194175973853SYishai Hadas 				event_type_num_list[i])) {
194275973853SYishai Hadas 			return false;
194375973853SYishai Hadas 		}
194475973853SYishai Hadas 	}
194575973853SYishai Hadas 
194675973853SYishai Hadas 	return true;
194775973853SYishai Hadas }
194875973853SYishai Hadas 
194975973853SYishai Hadas #define MAX_SUPP_EVENT_NUM 255
195075973853SYishai Hadas static bool is_valid_events(struct mlx5_core_dev *dev,
195175973853SYishai Hadas 			    int num_events, u16 *event_type_num_list,
195275973853SYishai Hadas 			    struct devx_obj *obj)
195375973853SYishai Hadas {
195475973853SYishai Hadas 	__be64 *aff_events;
195575973853SYishai Hadas 	__be64 *unaff_events;
195675973853SYishai Hadas 	int mask_entry;
195775973853SYishai Hadas 	int mask_bit;
195875973853SYishai Hadas 	int i;
195975973853SYishai Hadas 
196075973853SYishai Hadas 	if (MLX5_CAP_GEN(dev, event_cap)) {
196175973853SYishai Hadas 		aff_events = MLX5_CAP_DEV_EVENT(dev,
196275973853SYishai Hadas 						user_affiliated_events);
196375973853SYishai Hadas 		unaff_events = MLX5_CAP_DEV_EVENT(dev,
196475973853SYishai Hadas 						  user_unaffiliated_events);
196575973853SYishai Hadas 	} else {
196675973853SYishai Hadas 		return is_valid_events_legacy(num_events, event_type_num_list,
196775973853SYishai Hadas 					      obj);
196875973853SYishai Hadas 	}
196975973853SYishai Hadas 
197075973853SYishai Hadas 	for (i = 0; i < num_events; i++) {
197175973853SYishai Hadas 		if (event_type_num_list[i] > MAX_SUPP_EVENT_NUM)
197275973853SYishai Hadas 			return false;
197375973853SYishai Hadas 
197475973853SYishai Hadas 		mask_entry = event_type_num_list[i] / 64;
197575973853SYishai Hadas 		mask_bit = event_type_num_list[i] % 64;
197675973853SYishai Hadas 
197775973853SYishai Hadas 		if (obj) {
197875973853SYishai Hadas 			/* CQ completion */
197975973853SYishai Hadas 			if (event_type_num_list[i] == 0)
198075973853SYishai Hadas 				continue;
198175973853SYishai Hadas 
198275973853SYishai Hadas 			if (!(be64_to_cpu(aff_events[mask_entry]) &
198375973853SYishai Hadas 					(1ull << mask_bit)))
198475973853SYishai Hadas 				return false;
198575973853SYishai Hadas 
198675973853SYishai Hadas 			continue;
198775973853SYishai Hadas 		}
198875973853SYishai Hadas 
198975973853SYishai Hadas 		if (!(be64_to_cpu(unaff_events[mask_entry]) &
199075973853SYishai Hadas 				(1ull << mask_bit)))
199175973853SYishai Hadas 			return false;
199275973853SYishai Hadas 	}
199375973853SYishai Hadas 
199475973853SYishai Hadas 	return true;
199575973853SYishai Hadas }
199675973853SYishai Hadas 
199775973853SYishai Hadas #define MAX_NUM_EVENTS 16
199875973853SYishai Hadas static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT)(
199975973853SYishai Hadas 	struct uverbs_attr_bundle *attrs)
200075973853SYishai Hadas {
200175973853SYishai Hadas 	struct ib_uobject *devx_uobj = uverbs_attr_get_uobject(
200275973853SYishai Hadas 				attrs,
200375973853SYishai Hadas 				MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_OBJ_HANDLE);
200475973853SYishai Hadas 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
200575973853SYishai Hadas 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
200675973853SYishai Hadas 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
200775973853SYishai Hadas 	struct ib_uobject *fd_uobj;
200875973853SYishai Hadas 	struct devx_obj *obj = NULL;
200975973853SYishai Hadas 	struct devx_async_event_file *ev_file;
201075973853SYishai Hadas 	struct mlx5_devx_event_table *devx_event_table = &dev->devx_event_table;
201175973853SYishai Hadas 	u16 *event_type_num_list;
201275973853SYishai Hadas 	struct devx_event_subscription *event_sub, *tmp_sub;
201375973853SYishai Hadas 	struct list_head sub_list;
201475973853SYishai Hadas 	int redirect_fd;
201575973853SYishai Hadas 	bool use_eventfd = false;
201675973853SYishai Hadas 	int num_events;
201775973853SYishai Hadas 	u16 obj_type = 0;
201875973853SYishai Hadas 	u64 cookie = 0;
201975973853SYishai Hadas 	u32 obj_id = 0;
202075973853SYishai Hadas 	int err;
202175973853SYishai Hadas 	int i;
202275973853SYishai Hadas 
202375973853SYishai Hadas 	if (!c->devx_uid)
202475973853SYishai Hadas 		return -EINVAL;
202575973853SYishai Hadas 
202675973853SYishai Hadas 	if (!IS_ERR(devx_uobj)) {
202775973853SYishai Hadas 		obj = (struct devx_obj *)devx_uobj->object;
202875973853SYishai Hadas 		if (obj)
202975973853SYishai Hadas 			obj_id = get_dec_obj_id(obj->obj_id);
203075973853SYishai Hadas 	}
203175973853SYishai Hadas 
203275973853SYishai Hadas 	fd_uobj = uverbs_attr_get_uobject(attrs,
203375973853SYishai Hadas 				MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_HANDLE);
203475973853SYishai Hadas 	if (IS_ERR(fd_uobj))
203575973853SYishai Hadas 		return PTR_ERR(fd_uobj);
203675973853SYishai Hadas 
203775973853SYishai Hadas 	ev_file = container_of(fd_uobj, struct devx_async_event_file,
203875973853SYishai Hadas 			       uobj);
203975973853SYishai Hadas 
204075973853SYishai Hadas 	if (uverbs_attr_is_valid(attrs,
204175973853SYishai Hadas 				 MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM)) {
204275973853SYishai Hadas 		err = uverbs_copy_from(&redirect_fd, attrs,
204375973853SYishai Hadas 			       MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM);
204475973853SYishai Hadas 		if (err)
204575973853SYishai Hadas 			return err;
204675973853SYishai Hadas 
204775973853SYishai Hadas 		use_eventfd = true;
204875973853SYishai Hadas 	}
204975973853SYishai Hadas 
205075973853SYishai Hadas 	if (uverbs_attr_is_valid(attrs,
205175973853SYishai Hadas 				 MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE)) {
205275973853SYishai Hadas 		if (use_eventfd)
205375973853SYishai Hadas 			return -EINVAL;
205475973853SYishai Hadas 
205575973853SYishai Hadas 		err = uverbs_copy_from(&cookie, attrs,
205675973853SYishai Hadas 				MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE);
205775973853SYishai Hadas 		if (err)
205875973853SYishai Hadas 			return err;
205975973853SYishai Hadas 	}
206075973853SYishai Hadas 
206175973853SYishai Hadas 	num_events = uverbs_attr_ptr_get_array_size(
206275973853SYishai Hadas 		attrs, MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST,
206375973853SYishai Hadas 		sizeof(u16));
206475973853SYishai Hadas 
206575973853SYishai Hadas 	if (num_events < 0)
206675973853SYishai Hadas 		return num_events;
206775973853SYishai Hadas 
206875973853SYishai Hadas 	if (num_events > MAX_NUM_EVENTS)
206975973853SYishai Hadas 		return -EINVAL;
207075973853SYishai Hadas 
207175973853SYishai Hadas 	event_type_num_list = uverbs_attr_get_alloced_ptr(attrs,
207275973853SYishai Hadas 			MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST);
207375973853SYishai Hadas 
207475973853SYishai Hadas 	if (!is_valid_events(dev->mdev, num_events, event_type_num_list, obj))
207575973853SYishai Hadas 		return -EINVAL;
207675973853SYishai Hadas 
207775973853SYishai Hadas 	INIT_LIST_HEAD(&sub_list);
207875973853SYishai Hadas 
207975973853SYishai Hadas 	/* Protect from concurrent subscriptions to same XA entries to allow
208075973853SYishai Hadas 	 * both to succeed
208175973853SYishai Hadas 	 */
208275973853SYishai Hadas 	mutex_lock(&devx_event_table->event_xa_lock);
208375973853SYishai Hadas 	for (i = 0; i < num_events; i++) {
208475973853SYishai Hadas 		u32 key_level1;
208575973853SYishai Hadas 
208675973853SYishai Hadas 		if (obj)
208775973853SYishai Hadas 			obj_type = get_dec_obj_type(obj,
208875973853SYishai Hadas 						    event_type_num_list[i]);
208975973853SYishai Hadas 		key_level1 = event_type_num_list[i] | obj_type << 16;
209075973853SYishai Hadas 
209175973853SYishai Hadas 		err = subscribe_event_xa_alloc(devx_event_table,
209275973853SYishai Hadas 					       key_level1,
209375973853SYishai Hadas 					       obj,
209475973853SYishai Hadas 					       obj_id);
209575973853SYishai Hadas 		if (err)
209675973853SYishai Hadas 			goto err;
209775973853SYishai Hadas 
209875973853SYishai Hadas 		event_sub = kzalloc(sizeof(*event_sub), GFP_KERNEL);
20993a9b3d45SYueHaibing 		if (!event_sub) {
21003a9b3d45SYueHaibing 			err = -ENOMEM;
210175973853SYishai Hadas 			goto err;
21023a9b3d45SYueHaibing 		}
210375973853SYishai Hadas 
210475973853SYishai Hadas 		list_add_tail(&event_sub->event_list, &sub_list);
21056898d1c6SJason Gunthorpe 		uverbs_uobject_get(&ev_file->uobj);
210675973853SYishai Hadas 		if (use_eventfd) {
210775973853SYishai Hadas 			event_sub->eventfd =
210875973853SYishai Hadas 				eventfd_ctx_fdget(redirect_fd);
210975973853SYishai Hadas 
2110e7e6c632SDan Carpenter 			if (IS_ERR(event_sub->eventfd)) {
211175973853SYishai Hadas 				err = PTR_ERR(event_sub->eventfd);
211275973853SYishai Hadas 				event_sub->eventfd = NULL;
211375973853SYishai Hadas 				goto err;
211475973853SYishai Hadas 			}
211575973853SYishai Hadas 		}
211675973853SYishai Hadas 
211775973853SYishai Hadas 		event_sub->cookie = cookie;
211875973853SYishai Hadas 		event_sub->ev_file = ev_file;
211975973853SYishai Hadas 		/* May be needed upon cleanup the devx object/subscription */
212075973853SYishai Hadas 		event_sub->xa_key_level1 = key_level1;
212175973853SYishai Hadas 		event_sub->xa_key_level2 = obj_id;
212275973853SYishai Hadas 		INIT_LIST_HEAD(&event_sub->obj_list);
212375973853SYishai Hadas 	}
212475973853SYishai Hadas 
212575973853SYishai Hadas 	/* Once all the allocations and the XA data insertions were done we
212675973853SYishai Hadas 	 * can go ahead and add all the subscriptions to the relevant lists
212775973853SYishai Hadas 	 * without concern of a failure.
212875973853SYishai Hadas 	 */
212975973853SYishai Hadas 	list_for_each_entry_safe(event_sub, tmp_sub, &sub_list, event_list) {
213075973853SYishai Hadas 		struct devx_event *event;
213175973853SYishai Hadas 		struct devx_obj_event *obj_event;
213275973853SYishai Hadas 
213375973853SYishai Hadas 		list_del_init(&event_sub->event_list);
213475973853SYishai Hadas 
213575973853SYishai Hadas 		spin_lock_irq(&ev_file->lock);
213675973853SYishai Hadas 		list_add_tail_rcu(&event_sub->file_list,
213775973853SYishai Hadas 				  &ev_file->subscribed_events_list);
213875973853SYishai Hadas 		spin_unlock_irq(&ev_file->lock);
213975973853SYishai Hadas 
214075973853SYishai Hadas 		event = xa_load(&devx_event_table->event_xa,
214175973853SYishai Hadas 				event_sub->xa_key_level1);
214275973853SYishai Hadas 		WARN_ON(!event);
214375973853SYishai Hadas 
214475973853SYishai Hadas 		if (!obj) {
214575973853SYishai Hadas 			list_add_tail_rcu(&event_sub->xa_list,
214675973853SYishai Hadas 					  &event->unaffiliated_list);
214775973853SYishai Hadas 			continue;
214875973853SYishai Hadas 		}
214975973853SYishai Hadas 
215075973853SYishai Hadas 		obj_event = xa_load(&event->object_ids, obj_id);
215175973853SYishai Hadas 		WARN_ON(!obj_event);
215275973853SYishai Hadas 		list_add_tail_rcu(&event_sub->xa_list,
215375973853SYishai Hadas 				  &obj_event->obj_sub_list);
215475973853SYishai Hadas 		list_add_tail_rcu(&event_sub->obj_list,
215575973853SYishai Hadas 				  &obj->event_sub);
215675973853SYishai Hadas 	}
215775973853SYishai Hadas 
215875973853SYishai Hadas 	mutex_unlock(&devx_event_table->event_xa_lock);
215975973853SYishai Hadas 	return 0;
216075973853SYishai Hadas 
216175973853SYishai Hadas err:
216275973853SYishai Hadas 	list_for_each_entry_safe(event_sub, tmp_sub, &sub_list, event_list) {
216375973853SYishai Hadas 		list_del(&event_sub->event_list);
216475973853SYishai Hadas 
216575973853SYishai Hadas 		subscribe_event_xa_dealloc(devx_event_table,
216675973853SYishai Hadas 					   event_sub->xa_key_level1,
216775973853SYishai Hadas 					   obj,
216875973853SYishai Hadas 					   obj_id);
216975973853SYishai Hadas 
217075973853SYishai Hadas 		if (event_sub->eventfd)
217175973853SYishai Hadas 			eventfd_ctx_put(event_sub->eventfd);
21726898d1c6SJason Gunthorpe 		uverbs_uobject_put(&event_sub->ev_file->uobj);
217375973853SYishai Hadas 		kfree(event_sub);
217475973853SYishai Hadas 	}
217575973853SYishai Hadas 
217675973853SYishai Hadas 	mutex_unlock(&devx_event_table->event_xa_lock);
217775973853SYishai Hadas 	return err;
217875973853SYishai Hadas }
217975973853SYishai Hadas 
2180aeae9457SYishai Hadas static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext,
2181aeae9457SYishai Hadas 			 struct uverbs_attr_bundle *attrs,
218272b2f760SJason Gunthorpe 			 struct devx_umem *obj, u32 access_flags)
2183aeae9457SYishai Hadas {
2184aeae9457SYishai Hadas 	u64 addr;
2185aeae9457SYishai Hadas 	size_t size;
2186aeae9457SYishai Hadas 	int err;
2187aeae9457SYishai Hadas 
2188aeae9457SYishai Hadas 	if (uverbs_copy_from(&addr, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR) ||
2189bccd0622SJason Gunthorpe 	    uverbs_copy_from(&size, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_LEN))
2190aeae9457SYishai Hadas 		return -EFAULT;
2191aeae9457SYishai Hadas 
219272b2f760SJason Gunthorpe 	err = ib_check_mr_access(&dev->ib_dev, access_flags);
2193aeae9457SYishai Hadas 	if (err)
2194aeae9457SYishai Hadas 		return err;
2195aeae9457SYishai Hadas 
21969af859c5SJason Gunthorpe 	if (uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_DMABUF_FD)) {
21979af859c5SJason Gunthorpe 		struct ib_umem_dmabuf *umem_dmabuf;
21989af859c5SJason Gunthorpe 		int dmabuf_fd;
21999af859c5SJason Gunthorpe 
22009af859c5SJason Gunthorpe 		err = uverbs_get_raw_fd(&dmabuf_fd, attrs,
22019af859c5SJason Gunthorpe 					MLX5_IB_ATTR_DEVX_UMEM_REG_DMABUF_FD);
22029af859c5SJason Gunthorpe 		if (err)
22039af859c5SJason Gunthorpe 			return -EFAULT;
22049af859c5SJason Gunthorpe 
22059af859c5SJason Gunthorpe 		umem_dmabuf = ib_umem_dmabuf_get_pinned(
220672b2f760SJason Gunthorpe 			&dev->ib_dev, addr, size, dmabuf_fd, access_flags);
22079af859c5SJason Gunthorpe 		if (IS_ERR(umem_dmabuf))
22089af859c5SJason Gunthorpe 			return PTR_ERR(umem_dmabuf);
22099af859c5SJason Gunthorpe 		obj->umem = &umem_dmabuf->umem;
22109af859c5SJason Gunthorpe 	} else {
221172b2f760SJason Gunthorpe 		obj->umem = ib_umem_get(&dev->ib_dev, addr, size, access_flags);
2212aeae9457SYishai Hadas 		if (IS_ERR(obj->umem))
2213aeae9457SYishai Hadas 			return PTR_ERR(obj->umem);
22149af859c5SJason Gunthorpe 	}
2215aeae9457SYishai Hadas 	return 0;
2216aeae9457SYishai Hadas }
2217aeae9457SYishai Hadas 
22187610ab57SJason Gunthorpe static unsigned int devx_umem_find_best_pgsize(struct ib_umem *umem,
22197610ab57SJason Gunthorpe 					       unsigned long pgsz_bitmap)
22207610ab57SJason Gunthorpe {
22217610ab57SJason Gunthorpe 	unsigned long page_size;
22227610ab57SJason Gunthorpe 
22237610ab57SJason Gunthorpe 	/* Don't bother checking larger page sizes as offset must be zero and
22247610ab57SJason Gunthorpe 	 * total DEVX umem length must be equal to total umem length.
22257610ab57SJason Gunthorpe 	 */
22267610ab57SJason Gunthorpe 	pgsz_bitmap &= GENMASK_ULL(max_t(u64, order_base_2(umem->length),
22277610ab57SJason Gunthorpe 					 PAGE_SHIFT),
22287610ab57SJason Gunthorpe 				   MLX5_ADAPTER_PAGE_SHIFT);
22297610ab57SJason Gunthorpe 	if (!pgsz_bitmap)
22307610ab57SJason Gunthorpe 		return 0;
22317610ab57SJason Gunthorpe 
22327610ab57SJason Gunthorpe 	page_size = ib_umem_find_best_pgoff(umem, pgsz_bitmap, U64_MAX);
22337610ab57SJason Gunthorpe 	if (!page_size)
22347610ab57SJason Gunthorpe 		return 0;
22357610ab57SJason Gunthorpe 
22367610ab57SJason Gunthorpe 	/* If the page_size is less than the CPU page size then we can use the
22377610ab57SJason Gunthorpe 	 * offset and create a umem which is a subset of the page list.
22387610ab57SJason Gunthorpe 	 * For larger page sizes we can't be sure the DMA  list reflects the
22397610ab57SJason Gunthorpe 	 * VA so we must ensure that the umem extent is exactly equal to the
22407610ab57SJason Gunthorpe 	 * page list. Reduce the page size until one of these cases is true.
22417610ab57SJason Gunthorpe 	 */
22427610ab57SJason Gunthorpe 	while ((ib_umem_dma_offset(umem, page_size) != 0 ||
22437610ab57SJason Gunthorpe 		(umem->length % page_size) != 0) &&
22447610ab57SJason Gunthorpe 		page_size > PAGE_SIZE)
22457610ab57SJason Gunthorpe 		page_size /= 2;
22467610ab57SJason Gunthorpe 
22477610ab57SJason Gunthorpe 	return page_size;
22487610ab57SJason Gunthorpe }
22497610ab57SJason Gunthorpe 
2250878f7b31SJason Gunthorpe static int devx_umem_reg_cmd_alloc(struct mlx5_ib_dev *dev,
2251878f7b31SJason Gunthorpe 				   struct uverbs_attr_bundle *attrs,
2252b61815e2SJason Gunthorpe 				   struct devx_umem *obj,
225372b2f760SJason Gunthorpe 				   struct devx_umem_reg_cmd *cmd,
225472b2f760SJason Gunthorpe 				   int access)
2255aeae9457SYishai Hadas {
22567610ab57SJason Gunthorpe 	unsigned long pgsz_bitmap;
2257878f7b31SJason Gunthorpe 	unsigned int page_size;
2258aeae9457SYishai Hadas 	__be64 *mtt;
2259878f7b31SJason Gunthorpe 	void *umem;
22607610ab57SJason Gunthorpe 	int ret;
2261878f7b31SJason Gunthorpe 
2262878f7b31SJason Gunthorpe 	/*
22637610ab57SJason Gunthorpe 	 * If the user does not pass in pgsz_bitmap then the user promises not
22647610ab57SJason Gunthorpe 	 * to use umem_offset!=0 in any commands that allocate on top of the
22657610ab57SJason Gunthorpe 	 * umem.
22667610ab57SJason Gunthorpe 	 *
22677610ab57SJason Gunthorpe 	 * If the user wants to use a umem_offset then it must pass in
22687610ab57SJason Gunthorpe 	 * pgsz_bitmap which guides the maximum page size and thus maximum
22697610ab57SJason Gunthorpe 	 * object alignment inside the umem. See the PRM.
22707610ab57SJason Gunthorpe 	 *
22717610ab57SJason Gunthorpe 	 * Users are not allowed to use IOVA here, mkeys are not supported on
22727610ab57SJason Gunthorpe 	 * umem.
2273878f7b31SJason Gunthorpe 	 */
22747610ab57SJason Gunthorpe 	ret = uverbs_get_const_default(&pgsz_bitmap, attrs,
22757610ab57SJason Gunthorpe 			MLX5_IB_ATTR_DEVX_UMEM_REG_PGSZ_BITMAP,
22767610ab57SJason Gunthorpe 			GENMASK_ULL(63,
22777610ab57SJason Gunthorpe 				    min(PAGE_SHIFT, MLX5_ADAPTER_PAGE_SHIFT)));
22787610ab57SJason Gunthorpe 	if (ret)
22797610ab57SJason Gunthorpe 		return ret;
22807610ab57SJason Gunthorpe 
22817610ab57SJason Gunthorpe 	page_size = devx_umem_find_best_pgsize(obj->umem, pgsz_bitmap);
2282878f7b31SJason Gunthorpe 	if (!page_size)
2283878f7b31SJason Gunthorpe 		return -EINVAL;
2284878f7b31SJason Gunthorpe 
2285878f7b31SJason Gunthorpe 	cmd->inlen = MLX5_ST_SZ_BYTES(create_umem_in) +
2286878f7b31SJason Gunthorpe 		     (MLX5_ST_SZ_BYTES(mtt) *
2287878f7b31SJason Gunthorpe 		      ib_umem_num_dma_blocks(obj->umem, page_size));
2288878f7b31SJason Gunthorpe 	cmd->in = uverbs_zalloc(attrs, cmd->inlen);
2289d0b7721cSJason Gunthorpe 	if (IS_ERR(cmd->in))
2290878f7b31SJason Gunthorpe 		return PTR_ERR(cmd->in);
2291aeae9457SYishai Hadas 
2292aeae9457SYishai Hadas 	umem = MLX5_ADDR_OF(create_umem_in, cmd->in, umem);
2293aeae9457SYishai Hadas 	mtt = (__be64 *)MLX5_ADDR_OF(umem, umem, mtt);
2294aeae9457SYishai Hadas 
22956e3722baSYishai Hadas 	MLX5_SET(create_umem_in, cmd->in, opcode, MLX5_CMD_OP_CREATE_UMEM);
22967db0eea9SJason Gunthorpe 	MLX5_SET64(umem, umem, num_of_mtt,
2297878f7b31SJason Gunthorpe 		   ib_umem_num_dma_blocks(obj->umem, page_size));
2298878f7b31SJason Gunthorpe 	MLX5_SET(umem, umem, log_page_size,
2299878f7b31SJason Gunthorpe 		 order_base_2(page_size) - MLX5_ADAPTER_PAGE_SHIFT);
2300878f7b31SJason Gunthorpe 	MLX5_SET(umem, umem, page_offset,
2301878f7b31SJason Gunthorpe 		 ib_umem_dma_offset(obj->umem, page_size));
2302878f7b31SJason Gunthorpe 
230372b2f760SJason Gunthorpe 	if (mlx5_umem_needs_ats(dev, obj->umem, access))
230472b2f760SJason Gunthorpe 		MLX5_SET(umem, umem, ats, 1);
230572b2f760SJason Gunthorpe 
2306878f7b31SJason Gunthorpe 	mlx5_ib_populate_pas(obj->umem, page_size, mtt,
2307aeae9457SYishai Hadas 			     (obj->umem->writable ? MLX5_IB_MTT_WRITE : 0) |
2308aeae9457SYishai Hadas 				     MLX5_IB_MTT_READ);
2309878f7b31SJason Gunthorpe 	return 0;
2310aeae9457SYishai Hadas }
2311aeae9457SYishai Hadas 
2312e83f0ecdSJason Gunthorpe static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_REG)(
231315a1b4beSJason Gunthorpe 	struct uverbs_attr_bundle *attrs)
2314aeae9457SYishai Hadas {
2315aeae9457SYishai Hadas 	struct devx_umem_reg_cmd cmd;
2316aeae9457SYishai Hadas 	struct devx_umem *obj;
2317c36ee46dSJason Gunthorpe 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
2318c36ee46dSJason Gunthorpe 		attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE);
2319aeae9457SYishai Hadas 	u32 obj_id;
232089944450SShamir Rabinovitch 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
232189944450SShamir Rabinovitch 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
2322c36ee46dSJason Gunthorpe 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
232372b2f760SJason Gunthorpe 	int access_flags;
2324aeae9457SYishai Hadas 	int err;
2325aeae9457SYishai Hadas 
2326aeae9457SYishai Hadas 	if (!c->devx_uid)
23277e1335a7SYishai Hadas 		return -EINVAL;
23287e1335a7SYishai Hadas 
232972b2f760SJason Gunthorpe 	err = uverbs_get_flags32(&access_flags, attrs,
233072b2f760SJason Gunthorpe 				 MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
233172b2f760SJason Gunthorpe 				 IB_ACCESS_LOCAL_WRITE |
233272b2f760SJason Gunthorpe 				 IB_ACCESS_REMOTE_WRITE |
233372b2f760SJason Gunthorpe 				 IB_ACCESS_REMOTE_READ |
233472b2f760SJason Gunthorpe 				 IB_ACCESS_RELAXED_ORDERING);
233572b2f760SJason Gunthorpe 	if (err)
233672b2f760SJason Gunthorpe 		return err;
233772b2f760SJason Gunthorpe 
2338aeae9457SYishai Hadas 	obj = kzalloc(sizeof(struct devx_umem), GFP_KERNEL);
2339aeae9457SYishai Hadas 	if (!obj)
2340aeae9457SYishai Hadas 		return -ENOMEM;
2341aeae9457SYishai Hadas 
234272b2f760SJason Gunthorpe 	err = devx_umem_get(dev, &c->ibucontext, attrs, obj, access_flags);
2343aeae9457SYishai Hadas 	if (err)
2344aeae9457SYishai Hadas 		goto err_obj_free;
2345aeae9457SYishai Hadas 
234672b2f760SJason Gunthorpe 	err = devx_umem_reg_cmd_alloc(dev, attrs, obj, &cmd, access_flags);
2347aeae9457SYishai Hadas 	if (err)
2348aeae9457SYishai Hadas 		goto err_umem_release;
2349aeae9457SYishai Hadas 
23506e3722baSYishai Hadas 	MLX5_SET(create_umem_in, cmd.in, uid, c->devx_uid);
2351aeae9457SYishai Hadas 	err = mlx5_cmd_exec(dev->mdev, cmd.in, cmd.inlen, cmd.out,
2352aeae9457SYishai Hadas 			    sizeof(cmd.out));
2353aeae9457SYishai Hadas 	if (err)
2354b61815e2SJason Gunthorpe 		goto err_umem_release;
2355aeae9457SYishai Hadas 
2356aeae9457SYishai Hadas 	obj->mdev = dev->mdev;
2357aeae9457SYishai Hadas 	uobj->object = obj;
2358aeae9457SYishai Hadas 	devx_obj_build_destroy_cmd(cmd.in, cmd.out, obj->dinbox, &obj->dinlen, &obj_id);
23590ac8903cSJason Gunthorpe 	uverbs_finalize_uobj_create(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE);
2360aeae9457SYishai Hadas 
23610ac8903cSJason Gunthorpe 	err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, &obj_id,
23620ac8903cSJason Gunthorpe 			     sizeof(obj_id));
23630ac8903cSJason Gunthorpe 	return err;
2364aeae9457SYishai Hadas 
2365aeae9457SYishai Hadas err_umem_release:
2366aeae9457SYishai Hadas 	ib_umem_release(obj->umem);
2367aeae9457SYishai Hadas err_obj_free:
2368aeae9457SYishai Hadas 	kfree(obj);
2369aeae9457SYishai Hadas 	return err;
2370aeae9457SYishai Hadas }
2371aeae9457SYishai Hadas 
2372aeae9457SYishai Hadas static int devx_umem_cleanup(struct ib_uobject *uobject,
2373a6a3797dSShamir Rabinovitch 			     enum rdma_remove_reason why,
2374a6a3797dSShamir Rabinovitch 			     struct uverbs_attr_bundle *attrs)
2375aeae9457SYishai Hadas {
2376aeae9457SYishai Hadas 	struct devx_umem *obj = uobject->object;
2377aeae9457SYishai Hadas 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
2378aeae9457SYishai Hadas 	int err;
2379aeae9457SYishai Hadas 
2380aeae9457SYishai Hadas 	err = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out));
2381efa968eeSLeon Romanovsky 	if (err)
2382aeae9457SYishai Hadas 		return err;
2383aeae9457SYishai Hadas 
2384aeae9457SYishai Hadas 	ib_umem_release(obj->umem);
2385aeae9457SYishai Hadas 	kfree(obj);
2386aeae9457SYishai Hadas 	return 0;
2387aeae9457SYishai Hadas }
2388aeae9457SYishai Hadas 
23895ec9d8eeSYishai Hadas static bool is_unaffiliated_event(struct mlx5_core_dev *dev,
23905ec9d8eeSYishai Hadas 				  unsigned long event_type)
23915ec9d8eeSYishai Hadas {
23925ec9d8eeSYishai Hadas 	__be64 *unaff_events;
23935ec9d8eeSYishai Hadas 	int mask_entry;
23945ec9d8eeSYishai Hadas 	int mask_bit;
23955ec9d8eeSYishai Hadas 
23965ec9d8eeSYishai Hadas 	if (!MLX5_CAP_GEN(dev, event_cap))
23975ec9d8eeSYishai Hadas 		return is_legacy_unaffiliated_event_num(event_type);
23985ec9d8eeSYishai Hadas 
23995ec9d8eeSYishai Hadas 	unaff_events = MLX5_CAP_DEV_EVENT(dev,
24005ec9d8eeSYishai Hadas 					  user_unaffiliated_events);
24015ec9d8eeSYishai Hadas 	WARN_ON(event_type > MAX_SUPP_EVENT_NUM);
24025ec9d8eeSYishai Hadas 
24035ec9d8eeSYishai Hadas 	mask_entry = event_type / 64;
24045ec9d8eeSYishai Hadas 	mask_bit = event_type % 64;
24055ec9d8eeSYishai Hadas 
24065ec9d8eeSYishai Hadas 	if (!(be64_to_cpu(unaff_events[mask_entry]) & (1ull << mask_bit)))
24075ec9d8eeSYishai Hadas 		return false;
24085ec9d8eeSYishai Hadas 
24095ec9d8eeSYishai Hadas 	return true;
24105ec9d8eeSYishai Hadas }
24115ec9d8eeSYishai Hadas 
24125ec9d8eeSYishai Hadas static u32 devx_get_obj_id_from_event(unsigned long event_type, void *data)
24135ec9d8eeSYishai Hadas {
24145ec9d8eeSYishai Hadas 	struct mlx5_eqe *eqe = data;
24155ec9d8eeSYishai Hadas 	u32 obj_id = 0;
24165ec9d8eeSYishai Hadas 
24175ec9d8eeSYishai Hadas 	switch (event_type) {
24185ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_SRQ_CATAS_ERROR:
24195ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_SRQ_RQ_LIMIT:
24205ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_PATH_MIG:
24215ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_COMM_EST:
24225ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_SQ_DRAINED:
24235ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_SRQ_LAST_WQE:
24245ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_WQ_CATAS_ERROR:
24255ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_PATH_MIG_FAILED:
24265ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR:
24275ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR:
24285ec9d8eeSYishai Hadas 		obj_id = be32_to_cpu(eqe->data.qp_srq.qp_srq_n) & 0xffffff;
24295ec9d8eeSYishai Hadas 		break;
2430972d7560SYishai Hadas 	case MLX5_EVENT_TYPE_XRQ_ERROR:
2431972d7560SYishai Hadas 		obj_id = be32_to_cpu(eqe->data.xrq_err.type_xrqn) & 0xffffff;
2432972d7560SYishai Hadas 		break;
24335ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_DCT_DRAINED:
2434972d7560SYishai Hadas 	case MLX5_EVENT_TYPE_DCT_KEY_VIOLATION:
24355ec9d8eeSYishai Hadas 		obj_id = be32_to_cpu(eqe->data.dct.dctn) & 0xffffff;
24365ec9d8eeSYishai Hadas 		break;
24375ec9d8eeSYishai Hadas 	case MLX5_EVENT_TYPE_CQ_ERROR:
24385ec9d8eeSYishai Hadas 		obj_id = be32_to_cpu(eqe->data.cq_err.cqn) & 0xffffff;
24395ec9d8eeSYishai Hadas 		break;
24405ec9d8eeSYishai Hadas 	default:
24415ec9d8eeSYishai Hadas 		obj_id = MLX5_GET(affiliated_event_header, &eqe->data, obj_id);
24425ec9d8eeSYishai Hadas 		break;
24435ec9d8eeSYishai Hadas 	}
24445ec9d8eeSYishai Hadas 
24455ec9d8eeSYishai Hadas 	return obj_id;
24465ec9d8eeSYishai Hadas }
24475ec9d8eeSYishai Hadas 
24485ec9d8eeSYishai Hadas static int deliver_event(struct devx_event_subscription *event_sub,
24495ec9d8eeSYishai Hadas 			 const void *data)
24505ec9d8eeSYishai Hadas {
24515ec9d8eeSYishai Hadas 	struct devx_async_event_file *ev_file;
24525ec9d8eeSYishai Hadas 	struct devx_async_event_data *event_data;
24535ec9d8eeSYishai Hadas 	unsigned long flags;
24545ec9d8eeSYishai Hadas 
24555ec9d8eeSYishai Hadas 	ev_file = event_sub->ev_file;
24565ec9d8eeSYishai Hadas 
24575ec9d8eeSYishai Hadas 	if (ev_file->omit_data) {
24585ec9d8eeSYishai Hadas 		spin_lock_irqsave(&ev_file->lock, flags);
2459a8af8694SYishai Hadas 		if (!list_empty(&event_sub->event_list) ||
2460a8af8694SYishai Hadas 		    ev_file->is_destroyed) {
24615ec9d8eeSYishai Hadas 			spin_unlock_irqrestore(&ev_file->lock, flags);
24625ec9d8eeSYishai Hadas 			return 0;
24635ec9d8eeSYishai Hadas 		}
24645ec9d8eeSYishai Hadas 
24655ec9d8eeSYishai Hadas 		list_add_tail(&event_sub->event_list, &ev_file->event_list);
24665ec9d8eeSYishai Hadas 		spin_unlock_irqrestore(&ev_file->lock, flags);
24675ec9d8eeSYishai Hadas 		wake_up_interruptible(&ev_file->poll_wait);
24685ec9d8eeSYishai Hadas 		return 0;
24695ec9d8eeSYishai Hadas 	}
24705ec9d8eeSYishai Hadas 
24715ec9d8eeSYishai Hadas 	event_data = kzalloc(sizeof(*event_data) + sizeof(struct mlx5_eqe),
24725ec9d8eeSYishai Hadas 			     GFP_ATOMIC);
24735ec9d8eeSYishai Hadas 	if (!event_data) {
24745ec9d8eeSYishai Hadas 		spin_lock_irqsave(&ev_file->lock, flags);
24755ec9d8eeSYishai Hadas 		ev_file->is_overflow_err = 1;
24765ec9d8eeSYishai Hadas 		spin_unlock_irqrestore(&ev_file->lock, flags);
24775ec9d8eeSYishai Hadas 		return -ENOMEM;
24785ec9d8eeSYishai Hadas 	}
24795ec9d8eeSYishai Hadas 
24805ec9d8eeSYishai Hadas 	event_data->hdr.cookie = event_sub->cookie;
24815ec9d8eeSYishai Hadas 	memcpy(event_data->hdr.out_data, data, sizeof(struct mlx5_eqe));
24825ec9d8eeSYishai Hadas 
24835ec9d8eeSYishai Hadas 	spin_lock_irqsave(&ev_file->lock, flags);
2484f7c8416cSJason Gunthorpe 	if (!ev_file->is_destroyed)
24855ec9d8eeSYishai Hadas 		list_add_tail(&event_data->list, &ev_file->event_list);
2486f7c8416cSJason Gunthorpe 	else
2487f7c8416cSJason Gunthorpe 		kfree(event_data);
24885ec9d8eeSYishai Hadas 	spin_unlock_irqrestore(&ev_file->lock, flags);
24895ec9d8eeSYishai Hadas 	wake_up_interruptible(&ev_file->poll_wait);
24905ec9d8eeSYishai Hadas 
24915ec9d8eeSYishai Hadas 	return 0;
24925ec9d8eeSYishai Hadas }
24935ec9d8eeSYishai Hadas 
24945ec9d8eeSYishai Hadas static void dispatch_event_fd(struct list_head *fd_list,
24955ec9d8eeSYishai Hadas 			      const void *data)
24965ec9d8eeSYishai Hadas {
24975ec9d8eeSYishai Hadas 	struct devx_event_subscription *item;
24985ec9d8eeSYishai Hadas 
24995ec9d8eeSYishai Hadas 	list_for_each_entry_rcu(item, fd_list, xa_list) {
25006898d1c6SJason Gunthorpe 		if (item->eventfd)
25013652117fSChristian Brauner 			eventfd_signal(item->eventfd);
25026898d1c6SJason Gunthorpe 		else
25035ec9d8eeSYishai Hadas 			deliver_event(item, data);
25045ec9d8eeSYishai Hadas 	}
25055ec9d8eeSYishai Hadas }
25065ec9d8eeSYishai Hadas 
2507e337dd53SYishai Hadas static int devx_event_notifier(struct notifier_block *nb,
2508e337dd53SYishai Hadas 			       unsigned long event_type, void *data)
2509e337dd53SYishai Hadas {
25105ec9d8eeSYishai Hadas 	struct mlx5_devx_event_table *table;
25115ec9d8eeSYishai Hadas 	struct mlx5_ib_dev *dev;
25125ec9d8eeSYishai Hadas 	struct devx_event *event;
25135ec9d8eeSYishai Hadas 	struct devx_obj_event *obj_event;
25145ec9d8eeSYishai Hadas 	u16 obj_type = 0;
25155ec9d8eeSYishai Hadas 	bool is_unaffiliated;
25165ec9d8eeSYishai Hadas 	u32 obj_id;
25175ec9d8eeSYishai Hadas 
25185ec9d8eeSYishai Hadas 	/* Explicit filtering to kernel events which may occur frequently */
25195ec9d8eeSYishai Hadas 	if (event_type == MLX5_EVENT_TYPE_CMD ||
25205ec9d8eeSYishai Hadas 	    event_type == MLX5_EVENT_TYPE_PAGE_REQUEST)
25215ec9d8eeSYishai Hadas 		return NOTIFY_OK;
25225ec9d8eeSYishai Hadas 
25235ec9d8eeSYishai Hadas 	table = container_of(nb, struct mlx5_devx_event_table, devx_nb.nb);
25245ec9d8eeSYishai Hadas 	dev = container_of(table, struct mlx5_ib_dev, devx_event_table);
25255ec9d8eeSYishai Hadas 	is_unaffiliated = is_unaffiliated_event(dev->mdev, event_type);
25265ec9d8eeSYishai Hadas 
25275ec9d8eeSYishai Hadas 	if (!is_unaffiliated)
25285ec9d8eeSYishai Hadas 		obj_type = get_event_obj_type(event_type, data);
25295ec9d8eeSYishai Hadas 
25305ec9d8eeSYishai Hadas 	rcu_read_lock();
25315ec9d8eeSYishai Hadas 	event = xa_load(&table->event_xa, event_type | (obj_type << 16));
25325ec9d8eeSYishai Hadas 	if (!event) {
25335ec9d8eeSYishai Hadas 		rcu_read_unlock();
2534e337dd53SYishai Hadas 		return NOTIFY_DONE;
2535e337dd53SYishai Hadas 	}
2536e337dd53SYishai Hadas 
25375ec9d8eeSYishai Hadas 	if (is_unaffiliated) {
25385ec9d8eeSYishai Hadas 		dispatch_event_fd(&event->unaffiliated_list, data);
25395ec9d8eeSYishai Hadas 		rcu_read_unlock();
25405ec9d8eeSYishai Hadas 		return NOTIFY_OK;
25415ec9d8eeSYishai Hadas 	}
25425ec9d8eeSYishai Hadas 
25435ec9d8eeSYishai Hadas 	obj_id = devx_get_obj_id_from_event(event_type, data);
25445ec9d8eeSYishai Hadas 	obj_event = xa_load(&event->object_ids, obj_id);
25455ec9d8eeSYishai Hadas 	if (!obj_event) {
25465ec9d8eeSYishai Hadas 		rcu_read_unlock();
25475ec9d8eeSYishai Hadas 		return NOTIFY_DONE;
25485ec9d8eeSYishai Hadas 	}
25495ec9d8eeSYishai Hadas 
25505ec9d8eeSYishai Hadas 	dispatch_event_fd(&obj_event->obj_sub_list, data);
25515ec9d8eeSYishai Hadas 
25525ec9d8eeSYishai Hadas 	rcu_read_unlock();
25535ec9d8eeSYishai Hadas 	return NOTIFY_OK;
25545ec9d8eeSYishai Hadas }
25555ec9d8eeSYishai Hadas 
2556d8b7515eSLeon Romanovsky int mlx5_ib_devx_init(struct mlx5_ib_dev *dev)
2557e337dd53SYishai Hadas {
2558e337dd53SYishai Hadas 	struct mlx5_devx_event_table *table = &dev->devx_event_table;
2559d8b7515eSLeon Romanovsky 	int uid;
2560e337dd53SYishai Hadas 
2561d8b7515eSLeon Romanovsky 	uid = mlx5_ib_devx_create(dev, false);
2562d8b7515eSLeon Romanovsky 	if (uid > 0) {
2563d8b7515eSLeon Romanovsky 		dev->devx_whitelist_uid = uid;
2564e337dd53SYishai Hadas 		xa_init(&table->event_xa);
2565e337dd53SYishai Hadas 		mutex_init(&table->event_xa_lock);
2566e337dd53SYishai Hadas 		MLX5_NB_INIT(&table->devx_nb, devx_event_notifier, NOTIFY_ANY);
2567e337dd53SYishai Hadas 		mlx5_eq_notifier_register(dev->mdev, &table->devx_nb);
2568e337dd53SYishai Hadas 	}
2569e337dd53SYishai Hadas 
2570d8b7515eSLeon Romanovsky 	return 0;
2571d8b7515eSLeon Romanovsky }
2572d8b7515eSLeon Romanovsky 
2573d8b7515eSLeon Romanovsky void mlx5_ib_devx_cleanup(struct mlx5_ib_dev *dev)
2574e337dd53SYishai Hadas {
2575e337dd53SYishai Hadas 	struct mlx5_devx_event_table *table = &dev->devx_event_table;
257675973853SYishai Hadas 	struct devx_event_subscription *sub, *tmp;
257775973853SYishai Hadas 	struct devx_event *event;
2578e337dd53SYishai Hadas 	void *entry;
2579e337dd53SYishai Hadas 	unsigned long id;
2580e337dd53SYishai Hadas 
2581d8b7515eSLeon Romanovsky 	if (dev->devx_whitelist_uid) {
2582e337dd53SYishai Hadas 		mlx5_eq_notifier_unregister(dev->mdev, &table->devx_nb);
258375973853SYishai Hadas 		mutex_lock(&dev->devx_event_table.event_xa_lock);
258475973853SYishai Hadas 		xa_for_each(&table->event_xa, id, entry) {
258575973853SYishai Hadas 			event = entry;
2586d8b7515eSLeon Romanovsky 			list_for_each_entry_safe(
2587d8b7515eSLeon Romanovsky 				sub, tmp, &event->unaffiliated_list, xa_list)
258875973853SYishai Hadas 				devx_cleanup_subscription(dev, sub);
2589e337dd53SYishai Hadas 			kfree(entry);
259075973853SYishai Hadas 		}
259175973853SYishai Hadas 		mutex_unlock(&dev->devx_event_table.event_xa_lock);
2592e337dd53SYishai Hadas 		xa_destroy(&table->event_xa);
2593d8b7515eSLeon Romanovsky 
2594d8b7515eSLeon Romanovsky 		mlx5_ib_devx_destroy(dev, dev->devx_whitelist_uid);
2595d8b7515eSLeon Romanovsky 	}
2596e337dd53SYishai Hadas }
2597e337dd53SYishai Hadas 
25986bf8f22aSYishai Hadas static ssize_t devx_async_cmd_event_read(struct file *filp, char __user *buf,
25996bf8f22aSYishai Hadas 					 size_t count, loff_t *pos)
26006bf8f22aSYishai Hadas {
26014accbb3fSYishai Hadas 	struct devx_async_cmd_event_file *comp_ev_file = filp->private_data;
26024accbb3fSYishai Hadas 	struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue;
26034accbb3fSYishai Hadas 	struct devx_async_data *event;
26044accbb3fSYishai Hadas 	int ret = 0;
26054accbb3fSYishai Hadas 	size_t eventsz;
26064accbb3fSYishai Hadas 
26074accbb3fSYishai Hadas 	spin_lock_irq(&ev_queue->lock);
26084accbb3fSYishai Hadas 
26094accbb3fSYishai Hadas 	while (list_empty(&ev_queue->event_list)) {
26104accbb3fSYishai Hadas 		spin_unlock_irq(&ev_queue->lock);
26114accbb3fSYishai Hadas 
26124accbb3fSYishai Hadas 		if (filp->f_flags & O_NONBLOCK)
26134accbb3fSYishai Hadas 			return -EAGAIN;
26144accbb3fSYishai Hadas 
26154accbb3fSYishai Hadas 		if (wait_event_interruptible(
26164accbb3fSYishai Hadas 			    ev_queue->poll_wait,
2617eaebaf77SYishai Hadas 			    (!list_empty(&ev_queue->event_list) ||
2618eaebaf77SYishai Hadas 			     ev_queue->is_destroyed))) {
26194accbb3fSYishai Hadas 			return -ERESTARTSYS;
26204accbb3fSYishai Hadas 		}
2621eaebaf77SYishai Hadas 
26224accbb3fSYishai Hadas 		spin_lock_irq(&ev_queue->lock);
2623a8af8694SYishai Hadas 		if (ev_queue->is_destroyed) {
2624a8af8694SYishai Hadas 			spin_unlock_irq(&ev_queue->lock);
2625a8af8694SYishai Hadas 			return -EIO;
2626a8af8694SYishai Hadas 		}
26274accbb3fSYishai Hadas 	}
26284accbb3fSYishai Hadas 
26294accbb3fSYishai Hadas 	event = list_entry(ev_queue->event_list.next,
26304accbb3fSYishai Hadas 			   struct devx_async_data, list);
26314accbb3fSYishai Hadas 	eventsz = event->cmd_out_len +
26324accbb3fSYishai Hadas 			sizeof(struct mlx5_ib_uapi_devx_async_cmd_hdr);
26334accbb3fSYishai Hadas 
26344accbb3fSYishai Hadas 	if (eventsz > count) {
26354accbb3fSYishai Hadas 		spin_unlock_irq(&ev_queue->lock);
26364accbb3fSYishai Hadas 		return -ENOSPC;
26374accbb3fSYishai Hadas 	}
26384accbb3fSYishai Hadas 
26394accbb3fSYishai Hadas 	list_del(ev_queue->event_list.next);
26404accbb3fSYishai Hadas 	spin_unlock_irq(&ev_queue->lock);
26414accbb3fSYishai Hadas 
26424accbb3fSYishai Hadas 	if (copy_to_user(buf, &event->hdr, eventsz))
26434accbb3fSYishai Hadas 		ret = -EFAULT;
26444accbb3fSYishai Hadas 	else
26454accbb3fSYishai Hadas 		ret = eventsz;
26464accbb3fSYishai Hadas 
26474accbb3fSYishai Hadas 	atomic_sub(event->cmd_out_len, &ev_queue->bytes_in_use);
26484accbb3fSYishai Hadas 	kvfree(event);
26494accbb3fSYishai Hadas 	return ret;
26506bf8f22aSYishai Hadas }
26516bf8f22aSYishai Hadas 
26526bf8f22aSYishai Hadas static __poll_t devx_async_cmd_event_poll(struct file *filp,
26536bf8f22aSYishai Hadas 					      struct poll_table_struct *wait)
26546bf8f22aSYishai Hadas {
26554accbb3fSYishai Hadas 	struct devx_async_cmd_event_file *comp_ev_file = filp->private_data;
26564accbb3fSYishai Hadas 	struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue;
26574accbb3fSYishai Hadas 	__poll_t pollflags = 0;
26584accbb3fSYishai Hadas 
26594accbb3fSYishai Hadas 	poll_wait(filp, &ev_queue->poll_wait, wait);
26604accbb3fSYishai Hadas 
26614accbb3fSYishai Hadas 	spin_lock_irq(&ev_queue->lock);
2662eaebaf77SYishai Hadas 	if (ev_queue->is_destroyed)
2663eaebaf77SYishai Hadas 		pollflags = EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
2664eaebaf77SYishai Hadas 	else if (!list_empty(&ev_queue->event_list))
26654accbb3fSYishai Hadas 		pollflags = EPOLLIN | EPOLLRDNORM;
26664accbb3fSYishai Hadas 	spin_unlock_irq(&ev_queue->lock);
26674accbb3fSYishai Hadas 
26684accbb3fSYishai Hadas 	return pollflags;
26696bf8f22aSYishai Hadas }
26706bf8f22aSYishai Hadas 
26711f687edeSBart Van Assche static const struct file_operations devx_async_cmd_event_fops = {
26726bf8f22aSYishai Hadas 	.owner	 = THIS_MODULE,
26736bf8f22aSYishai Hadas 	.read	 = devx_async_cmd_event_read,
26746bf8f22aSYishai Hadas 	.poll    = devx_async_cmd_event_poll,
2675f7c8416cSJason Gunthorpe 	.release = uverbs_uobject_fd_release,
26766bf8f22aSYishai Hadas };
26776bf8f22aSYishai Hadas 
26782afc5e1bSYishai Hadas static ssize_t devx_async_event_read(struct file *filp, char __user *buf,
26792afc5e1bSYishai Hadas 				     size_t count, loff_t *pos)
26802afc5e1bSYishai Hadas {
26815ec9d8eeSYishai Hadas 	struct devx_async_event_file *ev_file = filp->private_data;
26825ec9d8eeSYishai Hadas 	struct devx_event_subscription *event_sub;
26833f649ab7SKees Cook 	struct devx_async_event_data *event;
26845ec9d8eeSYishai Hadas 	int ret = 0;
26855ec9d8eeSYishai Hadas 	size_t eventsz;
26865ec9d8eeSYishai Hadas 	bool omit_data;
26875ec9d8eeSYishai Hadas 	void *event_data;
26885ec9d8eeSYishai Hadas 
26895ec9d8eeSYishai Hadas 	omit_data = ev_file->omit_data;
26905ec9d8eeSYishai Hadas 
26915ec9d8eeSYishai Hadas 	spin_lock_irq(&ev_file->lock);
26925ec9d8eeSYishai Hadas 
26935ec9d8eeSYishai Hadas 	if (ev_file->is_overflow_err) {
26945ec9d8eeSYishai Hadas 		ev_file->is_overflow_err = 0;
26955ec9d8eeSYishai Hadas 		spin_unlock_irq(&ev_file->lock);
26965ec9d8eeSYishai Hadas 		return -EOVERFLOW;
26975ec9d8eeSYishai Hadas 	}
26985ec9d8eeSYishai Hadas 
26995ec9d8eeSYishai Hadas 
27005ec9d8eeSYishai Hadas 	while (list_empty(&ev_file->event_list)) {
27015ec9d8eeSYishai Hadas 		spin_unlock_irq(&ev_file->lock);
27025ec9d8eeSYishai Hadas 
27035ec9d8eeSYishai Hadas 		if (filp->f_flags & O_NONBLOCK)
27045ec9d8eeSYishai Hadas 			return -EAGAIN;
27055ec9d8eeSYishai Hadas 
27065ec9d8eeSYishai Hadas 		if (wait_event_interruptible(ev_file->poll_wait,
27075ec9d8eeSYishai Hadas 			    (!list_empty(&ev_file->event_list) ||
27085ec9d8eeSYishai Hadas 			     ev_file->is_destroyed))) {
27095ec9d8eeSYishai Hadas 			return -ERESTARTSYS;
27105ec9d8eeSYishai Hadas 		}
27115ec9d8eeSYishai Hadas 
27125ec9d8eeSYishai Hadas 		spin_lock_irq(&ev_file->lock);
27135ec9d8eeSYishai Hadas 		if (ev_file->is_destroyed) {
27145ec9d8eeSYishai Hadas 			spin_unlock_irq(&ev_file->lock);
27155ec9d8eeSYishai Hadas 			return -EIO;
27165ec9d8eeSYishai Hadas 		}
27175ec9d8eeSYishai Hadas 	}
27185ec9d8eeSYishai Hadas 
27195ec9d8eeSYishai Hadas 	if (omit_data) {
27205ec9d8eeSYishai Hadas 		event_sub = list_first_entry(&ev_file->event_list,
27215ec9d8eeSYishai Hadas 					struct devx_event_subscription,
27225ec9d8eeSYishai Hadas 					event_list);
27235ec9d8eeSYishai Hadas 		eventsz = sizeof(event_sub->cookie);
27245ec9d8eeSYishai Hadas 		event_data = &event_sub->cookie;
27255ec9d8eeSYishai Hadas 	} else {
27265ec9d8eeSYishai Hadas 		event = list_first_entry(&ev_file->event_list,
27275ec9d8eeSYishai Hadas 				      struct devx_async_event_data, list);
27285ec9d8eeSYishai Hadas 		eventsz = sizeof(struct mlx5_eqe) +
27295ec9d8eeSYishai Hadas 			sizeof(struct mlx5_ib_uapi_devx_async_event_hdr);
27305ec9d8eeSYishai Hadas 		event_data = &event->hdr;
27315ec9d8eeSYishai Hadas 	}
27325ec9d8eeSYishai Hadas 
27335ec9d8eeSYishai Hadas 	if (eventsz > count) {
27345ec9d8eeSYishai Hadas 		spin_unlock_irq(&ev_file->lock);
27352afc5e1bSYishai Hadas 		return -EINVAL;
27362afc5e1bSYishai Hadas 	}
27372afc5e1bSYishai Hadas 
27385ec9d8eeSYishai Hadas 	if (omit_data)
27395ec9d8eeSYishai Hadas 		list_del_init(&event_sub->event_list);
27405ec9d8eeSYishai Hadas 	else
27415ec9d8eeSYishai Hadas 		list_del(&event->list);
27425ec9d8eeSYishai Hadas 
27435ec9d8eeSYishai Hadas 	spin_unlock_irq(&ev_file->lock);
27445ec9d8eeSYishai Hadas 
27455ec9d8eeSYishai Hadas 	if (copy_to_user(buf, event_data, eventsz))
27465ec9d8eeSYishai Hadas 		/* This points to an application issue, not a kernel concern */
27475ec9d8eeSYishai Hadas 		ret = -EFAULT;
27485ec9d8eeSYishai Hadas 	else
27495ec9d8eeSYishai Hadas 		ret = eventsz;
27505ec9d8eeSYishai Hadas 
27515ec9d8eeSYishai Hadas 	if (!omit_data)
27525ec9d8eeSYishai Hadas 		kfree(event);
27535ec9d8eeSYishai Hadas 	return ret;
27545ec9d8eeSYishai Hadas }
27555ec9d8eeSYishai Hadas 
27562afc5e1bSYishai Hadas static __poll_t devx_async_event_poll(struct file *filp,
27572afc5e1bSYishai Hadas 				      struct poll_table_struct *wait)
27582afc5e1bSYishai Hadas {
27595ec9d8eeSYishai Hadas 	struct devx_async_event_file *ev_file = filp->private_data;
27605ec9d8eeSYishai Hadas 	__poll_t pollflags = 0;
27615ec9d8eeSYishai Hadas 
27625ec9d8eeSYishai Hadas 	poll_wait(filp, &ev_file->poll_wait, wait);
27635ec9d8eeSYishai Hadas 
27645ec9d8eeSYishai Hadas 	spin_lock_irq(&ev_file->lock);
27655ec9d8eeSYishai Hadas 	if (ev_file->is_destroyed)
27665ec9d8eeSYishai Hadas 		pollflags = EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
27675ec9d8eeSYishai Hadas 	else if (!list_empty(&ev_file->event_list))
27685ec9d8eeSYishai Hadas 		pollflags = EPOLLIN | EPOLLRDNORM;
27695ec9d8eeSYishai Hadas 	spin_unlock_irq(&ev_file->lock);
27705ec9d8eeSYishai Hadas 
27715ec9d8eeSYishai Hadas 	return pollflags;
27722afc5e1bSYishai Hadas }
27732afc5e1bSYishai Hadas 
27746898d1c6SJason Gunthorpe static void devx_free_subscription(struct rcu_head *rcu)
27756898d1c6SJason Gunthorpe {
27766898d1c6SJason Gunthorpe 	struct devx_event_subscription *event_sub =
27776898d1c6SJason Gunthorpe 		container_of(rcu, struct devx_event_subscription, rcu);
27786898d1c6SJason Gunthorpe 
27796898d1c6SJason Gunthorpe 	if (event_sub->eventfd)
27806898d1c6SJason Gunthorpe 		eventfd_ctx_put(event_sub->eventfd);
27816898d1c6SJason Gunthorpe 	uverbs_uobject_put(&event_sub->ev_file->uobj);
27826898d1c6SJason Gunthorpe 	kfree(event_sub);
27836898d1c6SJason Gunthorpe }
27846898d1c6SJason Gunthorpe 
2785f7c8416cSJason Gunthorpe static const struct file_operations devx_async_event_fops = {
2786f7c8416cSJason Gunthorpe 	.owner	 = THIS_MODULE,
2787f7c8416cSJason Gunthorpe 	.read	 = devx_async_event_read,
2788f7c8416cSJason Gunthorpe 	.poll    = devx_async_event_poll,
2789f7c8416cSJason Gunthorpe 	.release = uverbs_uobject_fd_release,
2790f7c8416cSJason Gunthorpe };
2791f7c8416cSJason Gunthorpe 
2792c5633a72SLeon Romanovsky static void devx_async_cmd_event_destroy_uobj(struct ib_uobject *uobj,
2793f7c8416cSJason Gunthorpe 					      enum rdma_remove_reason why)
27942afc5e1bSYishai Hadas {
2795f7c8416cSJason Gunthorpe 	struct devx_async_cmd_event_file *comp_ev_file =
2796f7c8416cSJason Gunthorpe 		container_of(uobj, struct devx_async_cmd_event_file,
2797f7c8416cSJason Gunthorpe 			     uobj);
2798f7c8416cSJason Gunthorpe 	struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue;
2799f7c8416cSJason Gunthorpe 	struct devx_async_data *entry, *tmp;
2800f7c8416cSJason Gunthorpe 
2801f7c8416cSJason Gunthorpe 	spin_lock_irq(&ev_queue->lock);
2802f7c8416cSJason Gunthorpe 	ev_queue->is_destroyed = 1;
2803f7c8416cSJason Gunthorpe 	spin_unlock_irq(&ev_queue->lock);
2804f7c8416cSJason Gunthorpe 	wake_up_interruptible(&ev_queue->poll_wait);
2805f7c8416cSJason Gunthorpe 
2806f7c8416cSJason Gunthorpe 	mlx5_cmd_cleanup_async_ctx(&comp_ev_file->async_ctx);
2807f7c8416cSJason Gunthorpe 
2808f7c8416cSJason Gunthorpe 	spin_lock_irq(&comp_ev_file->ev_queue.lock);
2809f7c8416cSJason Gunthorpe 	list_for_each_entry_safe(entry, tmp,
2810a8af8694SYishai Hadas 				 &comp_ev_file->ev_queue.event_list, list) {
2811a8af8694SYishai Hadas 		list_del(&entry->list);
2812f7c8416cSJason Gunthorpe 		kvfree(entry);
2813a8af8694SYishai Hadas 	}
2814f7c8416cSJason Gunthorpe 	spin_unlock_irq(&comp_ev_file->ev_queue.lock);
2815f7c8416cSJason Gunthorpe };
2816f7c8416cSJason Gunthorpe 
2817c5633a72SLeon Romanovsky static void devx_async_event_destroy_uobj(struct ib_uobject *uobj,
2818f7c8416cSJason Gunthorpe 					  enum rdma_remove_reason why)
2819f7c8416cSJason Gunthorpe {
2820f7c8416cSJason Gunthorpe 	struct devx_async_event_file *ev_file =
2821f7c8416cSJason Gunthorpe 		container_of(uobj, struct devx_async_event_file,
2822f7c8416cSJason Gunthorpe 			     uobj);
282375973853SYishai Hadas 	struct devx_event_subscription *event_sub, *event_sub_tmp;
2824e9eec6a5SYishai Hadas 	struct mlx5_ib_dev *dev = ev_file->dev;
282575973853SYishai Hadas 
2826f7c8416cSJason Gunthorpe 	spin_lock_irq(&ev_file->lock);
2827f7c8416cSJason Gunthorpe 	ev_file->is_destroyed = 1;
2828a8af8694SYishai Hadas 
2829a8af8694SYishai Hadas 	/* free the pending events allocation */
2830a8af8694SYishai Hadas 	if (ev_file->omit_data) {
2831a8af8694SYishai Hadas 		struct devx_event_subscription *event_sub, *tmp;
2832a8af8694SYishai Hadas 
2833a8af8694SYishai Hadas 		list_for_each_entry_safe(event_sub, tmp, &ev_file->event_list,
2834a8af8694SYishai Hadas 					 event_list)
2835a8af8694SYishai Hadas 			list_del_init(&event_sub->event_list);
2836a8af8694SYishai Hadas 
2837a8af8694SYishai Hadas 	} else {
2838a8af8694SYishai Hadas 		struct devx_async_event_data *entry, *tmp;
2839a8af8694SYishai Hadas 
2840a8af8694SYishai Hadas 		list_for_each_entry_safe(entry, tmp, &ev_file->event_list,
2841a8af8694SYishai Hadas 					 list) {
2842a8af8694SYishai Hadas 			list_del(&entry->list);
2843a8af8694SYishai Hadas 			kfree(entry);
2844a8af8694SYishai Hadas 		}
2845a8af8694SYishai Hadas 	}
2846a8af8694SYishai Hadas 
2847f7c8416cSJason Gunthorpe 	spin_unlock_irq(&ev_file->lock);
2848f7c8416cSJason Gunthorpe 	wake_up_interruptible(&ev_file->poll_wait);
2849f7c8416cSJason Gunthorpe 
2850e9eec6a5SYishai Hadas 	mutex_lock(&dev->devx_event_table.event_xa_lock);
285175973853SYishai Hadas 	/* delete the subscriptions which are related to this FD */
285275973853SYishai Hadas 	list_for_each_entry_safe(event_sub, event_sub_tmp,
285375973853SYishai Hadas 				 &ev_file->subscribed_events_list, file_list) {
2854e9eec6a5SYishai Hadas 		devx_cleanup_subscription(dev, event_sub);
285575973853SYishai Hadas 		list_del_rcu(&event_sub->file_list);
285675973853SYishai Hadas 		/* subscription may not be used by the read API any more */
28576898d1c6SJason Gunthorpe 		call_rcu(&event_sub->rcu, devx_free_subscription);
285875973853SYishai Hadas 	}
2859e9eec6a5SYishai Hadas 	mutex_unlock(&dev->devx_event_table.event_xa_lock);
286075973853SYishai Hadas 
2861e9eec6a5SYishai Hadas 	put_device(&dev->ib_dev.dev);
28622afc5e1bSYishai Hadas };
28632afc5e1bSYishai Hadas 
28649a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
28659a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_UMEM_REG,
28669a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE,
2867aeae9457SYishai Hadas 			MLX5_IB_OBJECT_DEVX_UMEM,
2868aeae9457SYishai Hadas 			UVERBS_ACCESS_NEW,
286983bb4442SJason Gunthorpe 			UA_MANDATORY),
28709a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR,
28719a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u64),
287283bb4442SJason Gunthorpe 			   UA_MANDATORY),
28739a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_LEN,
28749a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u64),
287583bb4442SJason Gunthorpe 			   UA_MANDATORY),
28769af859c5SJason Gunthorpe 	UVERBS_ATTR_RAW_FD(MLX5_IB_ATTR_DEVX_UMEM_REG_DMABUF_FD,
28779af859c5SJason Gunthorpe 			   UA_OPTIONAL),
2878bccd0622SJason Gunthorpe 	UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
2879bccd0622SJason Gunthorpe 			     enum ib_access_flags),
28807610ab57SJason Gunthorpe 	UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_PGSZ_BITMAP,
28817610ab57SJason Gunthorpe 			     u64),
28829a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID,
28839a119cd5SJason Gunthorpe 			    UVERBS_ATTR_TYPE(u32),
288483bb4442SJason Gunthorpe 			    UA_MANDATORY));
2885aeae9457SYishai Hadas 
2886528922afSYishai Hadas DECLARE_UVERBS_NAMED_METHOD_DESTROY(
28879a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_UMEM_DEREG,
28889a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_DEREG_HANDLE,
2889aeae9457SYishai Hadas 			MLX5_IB_OBJECT_DEVX_UMEM,
2890aeae9457SYishai Hadas 			UVERBS_ACCESS_DESTROY,
289183bb4442SJason Gunthorpe 			UA_MANDATORY));
2892aeae9457SYishai Hadas 
28939a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
28949a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_QUERY_EQN,
28959a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC,
28969a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u32),
289783bb4442SJason Gunthorpe 			   UA_MANDATORY),
28989a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN,
28999a119cd5SJason Gunthorpe 			    UVERBS_ATTR_TYPE(u32),
290083bb4442SJason Gunthorpe 			    UA_MANDATORY));
2901f6fe01b7SYishai Hadas 
29029a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
29039a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_QUERY_UAR,
29049a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX,
29059a119cd5SJason Gunthorpe 			   UVERBS_ATTR_TYPE(u32),
290683bb4442SJason Gunthorpe 			   UA_MANDATORY),
29079a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX,
29089a119cd5SJason Gunthorpe 			    UVERBS_ATTR_TYPE(u32),
290983bb4442SJason Gunthorpe 			    UA_MANDATORY));
29107c043e90SYishai Hadas 
29119a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
29129a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OTHER,
29139a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
29149a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OTHER_CMD_IN,
29158aa8c95cSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
291683bb4442SJason Gunthorpe 		UA_MANDATORY,
291783bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
29189a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
29199a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT,
29207efce369SYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
2921540cd692SJason Gunthorpe 		UA_MANDATORY));
29227efce369SYishai Hadas 
29239a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
29249a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_CREATE,
29259a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE,
29269a119cd5SJason Gunthorpe 			MLX5_IB_OBJECT_DEVX_OBJ,
29279a119cd5SJason Gunthorpe 			UVERBS_ACCESS_NEW,
292883bb4442SJason Gunthorpe 			UA_MANDATORY),
29299a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
29309a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN,
29319a119cd5SJason Gunthorpe 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
293283bb4442SJason Gunthorpe 		UA_MANDATORY,
293383bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
29349a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
29359a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT,
29369a119cd5SJason Gunthorpe 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
2937540cd692SJason Gunthorpe 		UA_MANDATORY));
29389a119cd5SJason Gunthorpe 
2939528922afSYishai Hadas DECLARE_UVERBS_NAMED_METHOD_DESTROY(
29409a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_DESTROY,
29419a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_DESTROY_HANDLE,
29427efce369SYishai Hadas 			MLX5_IB_OBJECT_DEVX_OBJ,
29437efce369SYishai Hadas 			UVERBS_ACCESS_DESTROY,
294483bb4442SJason Gunthorpe 			UA_MANDATORY));
29457efce369SYishai Hadas 
29469a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
29479a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_MODIFY,
29489a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE,
294934613eb1SYishai Hadas 			UVERBS_IDR_ANY_OBJECT,
2950*be551ee1SYishai Hadas 			UVERBS_ACCESS_READ,
295183bb4442SJason Gunthorpe 			UA_MANDATORY),
29529a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
29539a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN,
2954e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
295583bb4442SJason Gunthorpe 		UA_MANDATORY,
295683bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
29579a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
29589a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
2959e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
2960540cd692SJason Gunthorpe 		UA_MANDATORY));
2961e662e14dSYishai Hadas 
29629a119cd5SJason Gunthorpe DECLARE_UVERBS_NAMED_METHOD(
29639a119cd5SJason Gunthorpe 	MLX5_IB_METHOD_DEVX_OBJ_QUERY,
29649a119cd5SJason Gunthorpe 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE,
296534613eb1SYishai Hadas 			UVERBS_IDR_ANY_OBJECT,
2966e662e14dSYishai Hadas 			UVERBS_ACCESS_READ,
296783bb4442SJason Gunthorpe 			UA_MANDATORY),
29689a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_IN(
29699a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN,
2970e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
297183bb4442SJason Gunthorpe 		UA_MANDATORY,
297283bb4442SJason Gunthorpe 		UA_ALLOC_AND_COPY),
29739a119cd5SJason Gunthorpe 	UVERBS_ATTR_PTR_OUT(
29749a119cd5SJason Gunthorpe 		MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
2975e662e14dSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
2976540cd692SJason Gunthorpe 		UA_MANDATORY));
2977e662e14dSYishai Hadas 
2978a124edbaSYishai Hadas DECLARE_UVERBS_NAMED_METHOD(
2979a124edbaSYishai Hadas 	MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY,
2980a124edbaSYishai Hadas 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE,
2981a124edbaSYishai Hadas 			UVERBS_IDR_ANY_OBJECT,
2982a124edbaSYishai Hadas 			UVERBS_ACCESS_READ,
2983a124edbaSYishai Hadas 			UA_MANDATORY),
2984a124edbaSYishai Hadas 	UVERBS_ATTR_PTR_IN(
2985a124edbaSYishai Hadas 		MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN,
2986a124edbaSYishai Hadas 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
2987a124edbaSYishai Hadas 		UA_MANDATORY,
2988a124edbaSYishai Hadas 		UA_ALLOC_AND_COPY),
2989a124edbaSYishai Hadas 	UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_OUT_LEN,
2990a124edbaSYishai Hadas 		u16, UA_MANDATORY),
2991a124edbaSYishai Hadas 	UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_FD,
2992a124edbaSYishai Hadas 		MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
2993a124edbaSYishai Hadas 		UVERBS_ACCESS_READ,
2994a124edbaSYishai Hadas 		UA_MANDATORY),
2995a124edbaSYishai Hadas 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_WR_ID,
2996a124edbaSYishai Hadas 		UVERBS_ATTR_TYPE(u64),
2997a124edbaSYishai Hadas 		UA_MANDATORY));
2998a124edbaSYishai Hadas 
299975973853SYishai Hadas DECLARE_UVERBS_NAMED_METHOD(
300075973853SYishai Hadas 	MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT,
300175973853SYishai Hadas 	UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_HANDLE,
300275973853SYishai Hadas 		MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD,
300375973853SYishai Hadas 		UVERBS_ACCESS_READ,
300475973853SYishai Hadas 		UA_MANDATORY),
300575973853SYishai Hadas 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_OBJ_HANDLE,
300675973853SYishai Hadas 		MLX5_IB_OBJECT_DEVX_OBJ,
300775973853SYishai Hadas 		UVERBS_ACCESS_READ,
300875973853SYishai Hadas 		UA_OPTIONAL),
300975973853SYishai Hadas 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST,
301075973853SYishai Hadas 		UVERBS_ATTR_MIN_SIZE(sizeof(u16)),
301175973853SYishai Hadas 		UA_MANDATORY,
301275973853SYishai Hadas 		UA_ALLOC_AND_COPY),
301375973853SYishai Hadas 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE,
301475973853SYishai Hadas 		UVERBS_ATTR_TYPE(u64),
301575973853SYishai Hadas 		UA_OPTIONAL),
301675973853SYishai Hadas 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM,
301775973853SYishai Hadas 		UVERBS_ATTR_TYPE(u32),
301875973853SYishai Hadas 		UA_OPTIONAL));
301975973853SYishai Hadas 
30206c61d2a5SJason Gunthorpe DECLARE_UVERBS_GLOBAL_METHODS(MLX5_IB_OBJECT_DEVX,
30217c043e90SYishai Hadas 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OTHER),
3022f6fe01b7SYishai Hadas 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR),
302375973853SYishai Hadas 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_EQN),
302475973853SYishai Hadas 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT));
30258aa8c95cSYishai Hadas 
30266c61d2a5SJason Gunthorpe DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ,
30279a119cd5SJason Gunthorpe 			    UVERBS_TYPE_ALLOC_IDR(devx_obj_cleanup),
30287efce369SYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_CREATE),
3029e662e14dSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY),
3030e662e14dSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_MODIFY),
3031a124edbaSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY),
3032a124edbaSYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY));
30337efce369SYishai Hadas 
30346c61d2a5SJason Gunthorpe DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM,
30359a119cd5SJason Gunthorpe 			    UVERBS_TYPE_ALLOC_IDR(devx_umem_cleanup),
3036aeae9457SYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG),
3037aeae9457SYishai Hadas 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG));
3038aeae9457SYishai Hadas 
30396bf8f22aSYishai Hadas 
30406bf8f22aSYishai Hadas DECLARE_UVERBS_NAMED_METHOD(
30416bf8f22aSYishai Hadas 	MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC,
30426bf8f22aSYishai Hadas 	UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE,
30436bf8f22aSYishai Hadas 			MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
30446bf8f22aSYishai Hadas 			UVERBS_ACCESS_NEW,
30456bf8f22aSYishai Hadas 			UA_MANDATORY));
30466bf8f22aSYishai Hadas 
30476bf8f22aSYishai Hadas DECLARE_UVERBS_NAMED_OBJECT(
30486bf8f22aSYishai Hadas 	MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
30496bf8f22aSYishai Hadas 	UVERBS_TYPE_ALLOC_FD(sizeof(struct devx_async_cmd_event_file),
3050f7c8416cSJason Gunthorpe 			     devx_async_cmd_event_destroy_uobj,
30516bf8f22aSYishai Hadas 			     &devx_async_cmd_event_fops, "[devx_async_cmd]",
30526bf8f22aSYishai Hadas 			     O_RDONLY),
30536bf8f22aSYishai Hadas 	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC));
30546bf8f22aSYishai Hadas 
30552afc5e1bSYishai Hadas DECLARE_UVERBS_NAMED_METHOD(
30562afc5e1bSYishai Hadas 	MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC,
30572afc5e1bSYishai Hadas 	UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_HANDLE,
30582afc5e1bSYishai Hadas 			MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD,
30592afc5e1bSYishai Hadas 			UVERBS_ACCESS_NEW,
30602afc5e1bSYishai Hadas 			UA_MANDATORY),
30612afc5e1bSYishai Hadas 	UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_FLAGS,
30622afc5e1bSYishai Hadas 			enum mlx5_ib_uapi_devx_create_event_channel_flags,
30632afc5e1bSYishai Hadas 			UA_MANDATORY));
30642afc5e1bSYishai Hadas 
30652afc5e1bSYishai Hadas DECLARE_UVERBS_NAMED_OBJECT(
30662afc5e1bSYishai Hadas 	MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD,
30672afc5e1bSYishai Hadas 	UVERBS_TYPE_ALLOC_FD(sizeof(struct devx_async_event_file),
3068f7c8416cSJason Gunthorpe 			     devx_async_event_destroy_uobj,
30692afc5e1bSYishai Hadas 			     &devx_async_event_fops, "[devx_async_event]",
30702afc5e1bSYishai Hadas 			     O_RDONLY),
30712afc5e1bSYishai Hadas 	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC));
30722afc5e1bSYishai Hadas 
307336e235c8SJason Gunthorpe static bool devx_is_supported(struct ib_device *device)
3074c59450c4SYishai Hadas {
307536e235c8SJason Gunthorpe 	struct mlx5_ib_dev *dev = to_mdev(device);
307636e235c8SJason Gunthorpe 
30777f575103SMark Bloch 	return MLX5_CAP_GEN(dev->mdev, log_max_uctx);
3078c59450c4SYishai Hadas }
307936e235c8SJason Gunthorpe 
30800cbf432dSJason Gunthorpe const struct uapi_definition mlx5_ib_devx_defs[] = {
308136e235c8SJason Gunthorpe 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
308236e235c8SJason Gunthorpe 		MLX5_IB_OBJECT_DEVX,
308336e235c8SJason Gunthorpe 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
308436e235c8SJason Gunthorpe 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
308536e235c8SJason Gunthorpe 		MLX5_IB_OBJECT_DEVX_OBJ,
308636e235c8SJason Gunthorpe 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
308736e235c8SJason Gunthorpe 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
308836e235c8SJason Gunthorpe 		MLX5_IB_OBJECT_DEVX_UMEM,
308936e235c8SJason Gunthorpe 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
30906bf8f22aSYishai Hadas 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
30916bf8f22aSYishai Hadas 		MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
30926bf8f22aSYishai Hadas 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
30932afc5e1bSYishai Hadas 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
30942afc5e1bSYishai Hadas 		MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD,
30952afc5e1bSYishai Hadas 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
30960cbf432dSJason Gunthorpe 	{},
30970cbf432dSJason Gunthorpe };
3098