xref: /freebsd-src/sys/dev/mlx5/mlx5_ib/mlx5_ib_devx.c (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
1b633e08cSHans Petter Selasky /*-
2b633e08cSHans Petter Selasky  * Copyright (c) 2018-2020, Mellanox Technologies. All rights reserved.
3b633e08cSHans Petter Selasky  *
4b633e08cSHans Petter Selasky  * Redistribution and use in source and binary forms, with or without
5b633e08cSHans Petter Selasky  * modification, are permitted provided that the following conditions
6b633e08cSHans Petter Selasky  * are met:
7b633e08cSHans Petter Selasky  * 1. Redistributions of source code must retain the above copyright
8b633e08cSHans Petter Selasky  *    notice, this list of conditions and the following disclaimer.
9b633e08cSHans Petter Selasky  * 2. Redistributions in binary form must reproduce the above copyright
10b633e08cSHans Petter Selasky  *    notice, this list of conditions and the following disclaimer in the
11b633e08cSHans Petter Selasky  *    documentation and/or other materials provided with the distribution.
12b633e08cSHans Petter Selasky  *
13b633e08cSHans Petter Selasky  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14b633e08cSHans Petter Selasky  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15b633e08cSHans Petter Selasky  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16b633e08cSHans Petter Selasky  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17b633e08cSHans Petter Selasky  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18b633e08cSHans Petter Selasky  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19b633e08cSHans Petter Selasky  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20b633e08cSHans Petter Selasky  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21b633e08cSHans Petter Selasky  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22b633e08cSHans Petter Selasky  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23b633e08cSHans Petter Selasky  * SUCH DAMAGE.
24b633e08cSHans Petter Selasky  */
25b633e08cSHans Petter Selasky 
2670600979SKonstantin Belousov #include "opt_rss.h"
2770600979SKonstantin Belousov #include "opt_ratelimit.h"
2870600979SKonstantin Belousov 
29b633e08cSHans Petter Selasky #include <rdma/ib_user_verbs.h>
30b633e08cSHans Petter Selasky #include <rdma/ib_verbs.h>
31b633e08cSHans Petter Selasky #include <rdma/uverbs_types.h>
32b633e08cSHans Petter Selasky #include <rdma/uverbs_ioctl.h>
33b633e08cSHans Petter Selasky #include <rdma/mlx5_user_ioctl_cmds.h>
34b633e08cSHans Petter Selasky #include <rdma/mlx5_user_ioctl_verbs.h>
35b633e08cSHans Petter Selasky #include <rdma/ib_umem.h>
36b633e08cSHans Petter Selasky #include <rdma/uverbs_std_types.h>
37b633e08cSHans Petter Selasky #include <dev/mlx5/driver.h>
38b633e08cSHans Petter Selasky #include <dev/mlx5/fs.h>
39*028130b8SKonstantin Belousov #include <dev/mlx5/mlx5_ib/mlx5_ib.h>
40b633e08cSHans Petter Selasky 
41b633e08cSHans Petter Selasky #include <sys/priv.h>
42b633e08cSHans Petter Selasky 
43b633e08cSHans Petter Selasky #include <linux/xarray.h>
44b633e08cSHans Petter Selasky #include <linux/rculist.h>
45b633e08cSHans Petter Selasky #include <linux/srcu.h>
46b633e08cSHans Petter Selasky #include <linux/file.h>
47b633e08cSHans Petter Selasky #include <linux/poll.h>
48b633e08cSHans Petter Selasky #include <linux/wait.h>
49b633e08cSHans Petter Selasky 
50b633e08cSHans Petter Selasky #define UVERBS_MODULE_NAME mlx5_ib
51b633e08cSHans Petter Selasky #include <rdma/uverbs_named_ioctl.h>
52b633e08cSHans Petter Selasky 
53b633e08cSHans Petter Selasky static void dispatch_event_fd(struct list_head *fd_list, const void *data);
54b633e08cSHans Petter Selasky 
55b633e08cSHans Petter Selasky enum devx_obj_flags {
56b633e08cSHans Petter Selasky 	DEVX_OBJ_FLAGS_DCT = 1 << 1,
57b633e08cSHans Petter Selasky 	DEVX_OBJ_FLAGS_CQ = 1 << 2,
58b633e08cSHans Petter Selasky };
59b633e08cSHans Petter Selasky 
60b633e08cSHans Petter Selasky struct devx_async_data {
61b633e08cSHans Petter Selasky 	struct mlx5_ib_dev *mdev;
62b633e08cSHans Petter Selasky 	struct list_head list;
63b633e08cSHans Petter Selasky 	struct devx_async_cmd_event_file *ev_file;
64b633e08cSHans Petter Selasky 	struct mlx5_async_work cb_work;
65b633e08cSHans Petter Selasky 	u16 cmd_out_len;
66b633e08cSHans Petter Selasky 	/* must be last field in this structure */
67b633e08cSHans Petter Selasky 	struct mlx5_ib_uapi_devx_async_cmd_hdr hdr;
68b633e08cSHans Petter Selasky };
69b633e08cSHans Petter Selasky 
70b633e08cSHans Petter Selasky struct devx_async_event_data {
71b633e08cSHans Petter Selasky 	struct list_head list; /* headed in ev_file->event_list */
72b633e08cSHans Petter Selasky 	struct mlx5_ib_uapi_devx_async_event_hdr hdr;
73b633e08cSHans Petter Selasky };
74b633e08cSHans Petter Selasky 
75b633e08cSHans Petter Selasky /* first level XA value data structure */
76b633e08cSHans Petter Selasky struct devx_event {
77b633e08cSHans Petter Selasky 	struct xarray object_ids; /* second XA level, Key = object id */
78b633e08cSHans Petter Selasky 	struct list_head unaffiliated_list;
79b633e08cSHans Petter Selasky };
80b633e08cSHans Petter Selasky 
81b633e08cSHans Petter Selasky /* second level XA value data structure */
82b633e08cSHans Petter Selasky struct devx_obj_event {
83b633e08cSHans Petter Selasky 	struct rcu_head rcu;
84b633e08cSHans Petter Selasky 	struct list_head obj_sub_list;
85b633e08cSHans Petter Selasky };
86b633e08cSHans Petter Selasky 
87b633e08cSHans Petter Selasky struct devx_event_subscription {
88b633e08cSHans Petter Selasky 	struct list_head file_list; /* headed in ev_file->
89b633e08cSHans Petter Selasky 				     * subscribed_events_list
90b633e08cSHans Petter Selasky 				     */
91b633e08cSHans Petter Selasky 	struct list_head xa_list; /* headed in devx_event->unaffiliated_list or
92b633e08cSHans Petter Selasky 				   * devx_obj_event->obj_sub_list
93b633e08cSHans Petter Selasky 				   */
94b633e08cSHans Petter Selasky 	struct list_head obj_list; /* headed in devx_object */
95b633e08cSHans Petter Selasky 	struct list_head event_list; /* headed in ev_file->event_list or in
96b633e08cSHans Petter Selasky 				      * temp list via subscription
97b633e08cSHans Petter Selasky 				      */
98b633e08cSHans Petter Selasky 
99b633e08cSHans Petter Selasky 	u8 is_cleaned:1;
100b633e08cSHans Petter Selasky 	u32 xa_key_level1;
101b633e08cSHans Petter Selasky 	u32 xa_key_level2;
102b633e08cSHans Petter Selasky 	struct rcu_head	rcu;
103b633e08cSHans Petter Selasky 	u64 cookie;
104b633e08cSHans Petter Selasky 	struct devx_async_event_file *ev_file;
105b633e08cSHans Petter Selasky 	struct fd eventfd;
106b633e08cSHans Petter Selasky };
107b633e08cSHans Petter Selasky 
108b633e08cSHans Petter Selasky struct devx_async_event_file {
109b633e08cSHans Petter Selasky 	struct ib_uobject uobj;
110b633e08cSHans Petter Selasky 	/* Head of events that are subscribed to this FD */
111b633e08cSHans Petter Selasky 	struct list_head subscribed_events_list;
112b633e08cSHans Petter Selasky 	spinlock_t lock;
113b633e08cSHans Petter Selasky 	wait_queue_head_t poll_wait;
114b633e08cSHans Petter Selasky 	struct list_head event_list;
115b633e08cSHans Petter Selasky 	struct mlx5_ib_dev *dev;
116b633e08cSHans Petter Selasky 	u8 omit_data:1;
117b633e08cSHans Petter Selasky 	u8 is_overflow_err:1;
118b633e08cSHans Petter Selasky 	u8 is_destroyed:1;
119b633e08cSHans Petter Selasky };
120b633e08cSHans Petter Selasky 
121b633e08cSHans Petter Selasky #define MLX5_MAX_DESTROY_INBOX_SIZE_DW MLX5_ST_SZ_DW(delete_fte_in)
122b633e08cSHans Petter Selasky struct devx_obj {
123b633e08cSHans Petter Selasky 	struct mlx5_ib_dev	*ib_dev;
124b633e08cSHans Petter Selasky 	u64			obj_id;
125b633e08cSHans Petter Selasky 	u32			dinlen; /* destroy inbox length */
126b633e08cSHans Petter Selasky 	u32			dinbox[MLX5_MAX_DESTROY_INBOX_SIZE_DW];
127b633e08cSHans Petter Selasky 	u32			flags;
128b633e08cSHans Petter Selasky 	union {
129b633e08cSHans Petter Selasky 		struct mlx5_ib_devx_mr	devx_mr;
130b633e08cSHans Petter Selasky 		struct mlx5_core_dct	core_dct;
131b633e08cSHans Petter Selasky 		struct mlx5_core_cq	core_cq;
132b633e08cSHans Petter Selasky 		u32			flow_counter_bulk_size;
133b633e08cSHans Petter Selasky 	};
134b633e08cSHans Petter Selasky 	struct list_head event_sub; /* holds devx_event_subscription entries */
135b633e08cSHans Petter Selasky };
136b633e08cSHans Petter Selasky 
137b633e08cSHans Petter Selasky struct devx_umem {
138b633e08cSHans Petter Selasky 	struct mlx5_core_dev		*mdev;
139b633e08cSHans Petter Selasky 	struct ib_umem			*umem;
140b633e08cSHans Petter Selasky 	u32				page_offset;
141b633e08cSHans Petter Selasky 	int				page_shift;
142b633e08cSHans Petter Selasky 	int				ncont;
143b633e08cSHans Petter Selasky 	u32				dinlen;
144b633e08cSHans Petter Selasky 	u32				dinbox[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)];
145b633e08cSHans Petter Selasky };
146b633e08cSHans Petter Selasky 
147b633e08cSHans Petter Selasky struct devx_umem_reg_cmd {
148b633e08cSHans Petter Selasky 	void				*in;
149b633e08cSHans Petter Selasky 	u32				inlen;
150b633e08cSHans Petter Selasky 	u32				out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
151b633e08cSHans Petter Selasky };
152b633e08cSHans Petter Selasky 
153b633e08cSHans Petter Selasky static struct mlx5_ib_ucontext *
devx_ufile2uctx(const struct uverbs_attr_bundle * attrs)154b633e08cSHans Petter Selasky devx_ufile2uctx(const struct uverbs_attr_bundle *attrs)
155b633e08cSHans Petter Selasky {
156b633e08cSHans Petter Selasky 	return to_mucontext(ib_uverbs_get_ucontext(attrs));
157b633e08cSHans Petter Selasky }
158b633e08cSHans Petter Selasky 
mlx5_ib_devx_create(struct mlx5_ib_dev * dev,bool is_user)159b633e08cSHans Petter Selasky int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user)
160b633e08cSHans Petter Selasky {
161b633e08cSHans Petter Selasky 	u32 in[MLX5_ST_SZ_DW(create_uctx_in)] = {0};
162b633e08cSHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
163b633e08cSHans Petter Selasky 	void *uctx;
164b633e08cSHans Petter Selasky 	int err;
165b633e08cSHans Petter Selasky 	u16 uid;
166b633e08cSHans Petter Selasky 	u32 cap = 0;
167b633e08cSHans Petter Selasky 
168b633e08cSHans Petter Selasky 	/* 0 means not supported */
169b633e08cSHans Petter Selasky 	if (!MLX5_CAP_GEN(dev->mdev, log_max_uctx))
170b633e08cSHans Petter Selasky 		return -EINVAL;
171b633e08cSHans Petter Selasky 
172b633e08cSHans Petter Selasky 	uctx = MLX5_ADDR_OF(create_uctx_in, in, uctx);
173b633e08cSHans Petter Selasky 	if (is_user && priv_check(curthread, PRIV_NET_RAW) == 0 &&
174b633e08cSHans Petter Selasky 	    (MLX5_CAP_GEN(dev->mdev, uctx_cap) & MLX5_UCTX_CAP_RAW_TX))
175b633e08cSHans Petter Selasky 		cap |= MLX5_UCTX_CAP_RAW_TX;
176b633e08cSHans Petter Selasky 	if (is_user && priv_check(curthread, PRIV_DRIVER) == 0 &&
177b633e08cSHans Petter Selasky 	    (MLX5_CAP_GEN(dev->mdev, uctx_cap) &
178b633e08cSHans Petter Selasky 	     MLX5_UCTX_CAP_INTERNAL_DEV_RES))
179b633e08cSHans Petter Selasky 		cap |= MLX5_UCTX_CAP_INTERNAL_DEV_RES;
180b633e08cSHans Petter Selasky 
181b633e08cSHans Petter Selasky 	MLX5_SET(create_uctx_in, in, opcode, MLX5_CMD_OP_CREATE_UCTX);
182b633e08cSHans Petter Selasky 	MLX5_SET(uctx, uctx, cap, cap);
183b633e08cSHans Petter Selasky 
184b633e08cSHans Petter Selasky 	err = mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
185b633e08cSHans Petter Selasky 	if (err)
186b633e08cSHans Petter Selasky 		return err;
187b633e08cSHans Petter Selasky 
188b633e08cSHans Petter Selasky 	uid = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
189b633e08cSHans Petter Selasky 	return uid;
190b633e08cSHans Petter Selasky }
191b633e08cSHans Petter Selasky 
mlx5_ib_devx_destroy(struct mlx5_ib_dev * dev,u16 uid)192b633e08cSHans Petter Selasky void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev, u16 uid)
193b633e08cSHans Petter Selasky {
194b633e08cSHans Petter Selasky 	u32 in[MLX5_ST_SZ_DW(destroy_uctx_in)] = {0};
195b633e08cSHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
196b633e08cSHans Petter Selasky 
197b633e08cSHans Petter Selasky 	MLX5_SET(destroy_uctx_in, in, opcode, MLX5_CMD_OP_DESTROY_UCTX);
198b633e08cSHans Petter Selasky 	MLX5_SET(destroy_uctx_in, in, uid, uid);
199b633e08cSHans Petter Selasky 
200b633e08cSHans Petter Selasky 	mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
201b633e08cSHans Petter Selasky }
202b633e08cSHans Petter Selasky 
mlx5_ib_devx_is_flow_dest(void * obj,int * dest_id,int * dest_type)203b633e08cSHans Petter Selasky bool mlx5_ib_devx_is_flow_dest(void *obj, int *dest_id, int *dest_type)
204b633e08cSHans Petter Selasky {
205b633e08cSHans Petter Selasky 	struct devx_obj *devx_obj = obj;
206b633e08cSHans Petter Selasky 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode);
207b633e08cSHans Petter Selasky 
208b633e08cSHans Petter Selasky 	switch (opcode) {
209b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_DESTROY_TIR:
210b633e08cSHans Petter Selasky 		*dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR;
211b633e08cSHans Petter Selasky 		*dest_id = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox,
212b633e08cSHans Petter Selasky 				    obj_id);
213b633e08cSHans Petter Selasky 		return true;
214b633e08cSHans Petter Selasky 
215b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_DESTROY_FLOW_TABLE:
216b633e08cSHans Petter Selasky 		*dest_type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
217b633e08cSHans Petter Selasky 		*dest_id = MLX5_GET(destroy_flow_table_in, devx_obj->dinbox,
218b633e08cSHans Petter Selasky 				    table_id);
219b633e08cSHans Petter Selasky 		return true;
220b633e08cSHans Petter Selasky 	default:
221b633e08cSHans Petter Selasky 		return false;
222b633e08cSHans Petter Selasky 	}
223b633e08cSHans Petter Selasky }
224b633e08cSHans Petter Selasky 
mlx5_ib_devx_is_flow_counter(void * obj,u32 offset,u32 * counter_id)225b633e08cSHans Petter Selasky bool mlx5_ib_devx_is_flow_counter(void *obj, u32 offset, u32 *counter_id)
226b633e08cSHans Petter Selasky {
227b633e08cSHans Petter Selasky 	struct devx_obj *devx_obj = obj;
228b633e08cSHans Petter Selasky 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode);
229b633e08cSHans Petter Selasky 
230b633e08cSHans Petter Selasky 	if (opcode == MLX5_CMD_OP_DEALLOC_FLOW_COUNTER) {
231b633e08cSHans Petter Selasky 
232b633e08cSHans Petter Selasky 		if (offset && offset >= devx_obj->flow_counter_bulk_size)
233b633e08cSHans Petter Selasky 			return false;
234b633e08cSHans Petter Selasky 
235b633e08cSHans Petter Selasky 		*counter_id = MLX5_GET(dealloc_flow_counter_in,
236b633e08cSHans Petter Selasky 				       devx_obj->dinbox,
237b633e08cSHans Petter Selasky 				       flow_counter_id);
238b633e08cSHans Petter Selasky 		*counter_id += offset;
239b633e08cSHans Petter Selasky 		return true;
240b633e08cSHans Petter Selasky 	}
241b633e08cSHans Petter Selasky 
242b633e08cSHans Petter Selasky 	return false;
243b633e08cSHans Petter Selasky }
244b633e08cSHans Petter Selasky 
is_legacy_unaffiliated_event_num(u16 event_num)245b633e08cSHans Petter Selasky static bool is_legacy_unaffiliated_event_num(u16 event_num)
246b633e08cSHans Petter Selasky {
247b633e08cSHans Petter Selasky 	switch (event_num) {
248b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_PORT_CHANGE:
249b633e08cSHans Petter Selasky 		return true;
250b633e08cSHans Petter Selasky 	default:
251b633e08cSHans Petter Selasky 		return false;
252b633e08cSHans Petter Selasky 	}
253b633e08cSHans Petter Selasky }
254b633e08cSHans Petter Selasky 
is_legacy_obj_event_num(u16 event_num)255b633e08cSHans Petter Selasky static bool is_legacy_obj_event_num(u16 event_num)
256b633e08cSHans Petter Selasky {
257b633e08cSHans Petter Selasky 	switch (event_num) {
258b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_PATH_MIG:
259b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_COMM_EST:
260b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_SQ_DRAINED:
261b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_SRQ_LAST_WQE:
262b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_SRQ_RQ_LIMIT:
263b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_CQ_ERROR:
264b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_WQ_CATAS_ERROR:
265b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_PATH_MIG_FAILED:
266b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR:
267b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR:
268b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_SRQ_CATAS_ERROR:
269b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_DCT_DRAINED:
270b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_COMP:
271b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_DCT_KEY_VIOLATION:
272b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_XRQ_ERROR:
273b633e08cSHans Petter Selasky 		return true;
274b633e08cSHans Petter Selasky 	default:
275b633e08cSHans Petter Selasky 		return false;
276b633e08cSHans Petter Selasky 	}
277b633e08cSHans Petter Selasky }
278b633e08cSHans Petter Selasky 
get_legacy_obj_type(u16 opcode)279b633e08cSHans Petter Selasky static u16 get_legacy_obj_type(u16 opcode)
280b633e08cSHans Petter Selasky {
281b633e08cSHans Petter Selasky 	switch (opcode) {
282b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_RQ:
283b633e08cSHans Petter Selasky 		return MLX5_EVENT_QUEUE_TYPE_RQ;
284b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_QP:
285b633e08cSHans Petter Selasky 		return MLX5_EVENT_QUEUE_TYPE_QP;
286b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_SQ:
287b633e08cSHans Petter Selasky 		return MLX5_EVENT_QUEUE_TYPE_SQ;
288b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_DCT:
289b633e08cSHans Petter Selasky 		return MLX5_EVENT_QUEUE_TYPE_DCT;
290b633e08cSHans Petter Selasky 	default:
291b633e08cSHans Petter Selasky 		return 0;
292b633e08cSHans Petter Selasky 	}
293b633e08cSHans Petter Selasky }
294b633e08cSHans Petter Selasky 
get_dec_obj_type(struct devx_obj * obj,u16 event_num)295b633e08cSHans Petter Selasky static u16 get_dec_obj_type(struct devx_obj *obj, u16 event_num)
296b633e08cSHans Petter Selasky {
297b633e08cSHans Petter Selasky 	u16 opcode;
298b633e08cSHans Petter Selasky 
299b633e08cSHans Petter Selasky 	opcode = (obj->obj_id >> 32) & 0xffff;
300b633e08cSHans Petter Selasky 
301b633e08cSHans Petter Selasky 	if (is_legacy_obj_event_num(event_num))
302b633e08cSHans Petter Selasky 		return get_legacy_obj_type(opcode);
303b633e08cSHans Petter Selasky 
304b633e08cSHans Petter Selasky 	switch (opcode) {
305b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_GENERAL_OBJ:
306b633e08cSHans Petter Selasky 		return (obj->obj_id >> 48);
307b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_RQ:
308b633e08cSHans Petter Selasky 		return MLX5_OBJ_TYPE_RQ;
309b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_QP:
310b633e08cSHans Petter Selasky 		return MLX5_OBJ_TYPE_QP;
311b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_SQ:
312b633e08cSHans Petter Selasky 		return MLX5_OBJ_TYPE_SQ;
313b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_DCT:
314b633e08cSHans Petter Selasky 		return MLX5_OBJ_TYPE_DCT;
315b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_TIR:
316b633e08cSHans Petter Selasky 		return MLX5_OBJ_TYPE_TIR;
317b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_TIS:
318b633e08cSHans Petter Selasky 		return MLX5_OBJ_TYPE_TIS;
319b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_PSV:
320b633e08cSHans Petter Selasky 		return MLX5_OBJ_TYPE_PSV;
321b633e08cSHans Petter Selasky 	case MLX5_OBJ_TYPE_MKEY:
322b633e08cSHans Petter Selasky 		return MLX5_OBJ_TYPE_MKEY;
323b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_RMP:
324b633e08cSHans Petter Selasky 		return MLX5_OBJ_TYPE_RMP;
325b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
326b633e08cSHans Petter Selasky 		return MLX5_OBJ_TYPE_XRC_SRQ;
327b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_XRQ:
328b633e08cSHans Petter Selasky 		return MLX5_OBJ_TYPE_XRQ;
329b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_RQT:
330b633e08cSHans Petter Selasky 		return MLX5_OBJ_TYPE_RQT;
331b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
332b633e08cSHans Petter Selasky 		return MLX5_OBJ_TYPE_FLOW_COUNTER;
333b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_CQ:
334b633e08cSHans Petter Selasky 		return MLX5_OBJ_TYPE_CQ;
335b633e08cSHans Petter Selasky 	default:
336b633e08cSHans Petter Selasky 		return 0;
337b633e08cSHans Petter Selasky 	}
338b633e08cSHans Petter Selasky }
339b633e08cSHans Petter Selasky 
get_event_obj_type(unsigned long event_type,struct mlx5_eqe * eqe)340b633e08cSHans Petter Selasky static u16 get_event_obj_type(unsigned long event_type, struct mlx5_eqe *eqe)
341b633e08cSHans Petter Selasky {
342b633e08cSHans Petter Selasky 	switch (event_type) {
343b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_WQ_CATAS_ERROR:
344b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR:
345b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR:
346b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_SRQ_LAST_WQE:
347b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_PATH_MIG:
348b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_PATH_MIG_FAILED:
349b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_COMM_EST:
350b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_SQ_DRAINED:
351b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_SRQ_RQ_LIMIT:
352b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_SRQ_CATAS_ERROR:
353b633e08cSHans Petter Selasky 		return eqe->data.qp_srq.type;
354b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_CQ_ERROR:
355b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_XRQ_ERROR:
356b633e08cSHans Petter Selasky 		return 0;
357b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_DCT_DRAINED:
358b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_DCT_KEY_VIOLATION:
359b633e08cSHans Petter Selasky 		return MLX5_EVENT_QUEUE_TYPE_DCT;
360b633e08cSHans Petter Selasky 	default:
361b633e08cSHans Petter Selasky 		return MLX5_GET(affiliated_event_header, &eqe->data, obj_type);
362b633e08cSHans Petter Selasky 	}
363b633e08cSHans Petter Selasky }
364b633e08cSHans Petter Selasky 
get_dec_obj_id(u64 obj_id)365b633e08cSHans Petter Selasky static u32 get_dec_obj_id(u64 obj_id)
366b633e08cSHans Petter Selasky {
367b633e08cSHans Petter Selasky 	return (obj_id & 0xffffffff);
368b633e08cSHans Petter Selasky }
369b633e08cSHans Petter Selasky 
370b633e08cSHans Petter Selasky /*
371b633e08cSHans Petter Selasky  * As the obj_id in the firmware is not globally unique the object type
372b633e08cSHans Petter Selasky  * must be considered upon checking for a valid object id.
373b633e08cSHans Petter Selasky  * For that the opcode of the creator command is encoded as part of the obj_id.
374b633e08cSHans Petter Selasky  */
get_enc_obj_id(u32 opcode,u32 obj_id)375b633e08cSHans Petter Selasky static u64 get_enc_obj_id(u32 opcode, u32 obj_id)
376b633e08cSHans Petter Selasky {
377b633e08cSHans Petter Selasky 	return ((u64)opcode << 32) | obj_id;
378b633e08cSHans Petter Selasky }
379b633e08cSHans Petter Selasky 
devx_get_obj_id(const void * in)380b633e08cSHans Petter Selasky static u64 devx_get_obj_id(const void *in)
381b633e08cSHans Petter Selasky {
382b633e08cSHans Petter Selasky 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
383b633e08cSHans Petter Selasky 	u64 obj_id;
384b633e08cSHans Petter Selasky 
385b633e08cSHans Petter Selasky 	switch (opcode) {
386b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_GENERAL_OBJ:
387b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_GENERAL_OBJ:
388b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_GENERAL_OBJ |
389b633e08cSHans Petter Selasky 					MLX5_GET(general_obj_in_cmd_hdr, in,
390b633e08cSHans Petter Selasky 						 obj_type) << 16,
391b633e08cSHans Petter Selasky 					MLX5_GET(general_obj_in_cmd_hdr, in,
392b633e08cSHans Petter Selasky 						 obj_id));
393b633e08cSHans Petter Selasky 		break;
394b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_MKEY:
395b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_MKEY,
396b633e08cSHans Petter Selasky 					MLX5_GET(query_mkey_in, in,
397b633e08cSHans Petter Selasky 						 mkey_index));
398b633e08cSHans Petter Selasky 		break;
399b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_CQ:
400b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ,
401b633e08cSHans Petter Selasky 					MLX5_GET(query_cq_in, in, cqn));
402b633e08cSHans Petter Selasky 		break;
403b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_CQ:
404b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ,
405b633e08cSHans Petter Selasky 					MLX5_GET(modify_cq_in, in, cqn));
406b633e08cSHans Petter Selasky 		break;
407b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_SQ:
408b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ,
409b633e08cSHans Petter Selasky 					MLX5_GET(query_sq_in, in, sqn));
410b633e08cSHans Petter Selasky 		break;
411b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_SQ:
412b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ,
413b633e08cSHans Petter Selasky 					MLX5_GET(modify_sq_in, in, sqn));
414b633e08cSHans Petter Selasky 		break;
415b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_RQ:
416b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
417b633e08cSHans Petter Selasky 					MLX5_GET(query_rq_in, in, rqn));
418b633e08cSHans Petter Selasky 		break;
419b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_RQ:
420b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
421b633e08cSHans Petter Selasky 					MLX5_GET(modify_rq_in, in, rqn));
422b633e08cSHans Petter Selasky 		break;
423b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_RMP:
424b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RMP,
425b633e08cSHans Petter Selasky 					MLX5_GET(query_rmp_in, in, rmpn));
426b633e08cSHans Petter Selasky 		break;
427b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_RMP:
428b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RMP,
429b633e08cSHans Petter Selasky 					MLX5_GET(modify_rmp_in, in, rmpn));
430b633e08cSHans Petter Selasky 		break;
431b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_RQT:
432b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT,
433b633e08cSHans Petter Selasky 					MLX5_GET(query_rqt_in, in, rqtn));
434b633e08cSHans Petter Selasky 		break;
435b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_RQT:
436b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT,
437b633e08cSHans Petter Selasky 					MLX5_GET(modify_rqt_in, in, rqtn));
438b633e08cSHans Petter Selasky 		break;
439b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_TIR:
440b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR,
441b633e08cSHans Petter Selasky 					MLX5_GET(query_tir_in, in, tirn));
442b633e08cSHans Petter Selasky 		break;
443b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_TIR:
444b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR,
445b633e08cSHans Petter Selasky 					MLX5_GET(modify_tir_in, in, tirn));
446b633e08cSHans Petter Selasky 		break;
447b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_TIS:
448b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS,
449b633e08cSHans Petter Selasky 					MLX5_GET(query_tis_in, in, tisn));
450b633e08cSHans Petter Selasky 		break;
451b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_TIS:
452b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS,
453b633e08cSHans Petter Selasky 					MLX5_GET(modify_tis_in, in, tisn));
454b633e08cSHans Petter Selasky 		break;
455b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_FLOW_TABLE:
456b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_TABLE,
457b633e08cSHans Petter Selasky 					MLX5_GET(query_flow_table_in, in,
458b633e08cSHans Petter Selasky 						 table_id));
459b633e08cSHans Petter Selasky 		break;
460b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_FLOW_TABLE:
461b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_TABLE,
462b633e08cSHans Petter Selasky 					MLX5_GET(modify_flow_table_in, in,
463b633e08cSHans Petter Selasky 						 table_id));
464b633e08cSHans Petter Selasky 		break;
465b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_FLOW_GROUP:
466b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_FLOW_GROUP,
467b633e08cSHans Petter Selasky 					MLX5_GET(query_flow_group_in, in,
468b633e08cSHans Petter Selasky 						 group_id));
469b633e08cSHans Petter Selasky 		break;
470b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
471b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY,
472b633e08cSHans Petter Selasky 					MLX5_GET(query_fte_in, in,
473b633e08cSHans Petter Selasky 						 flow_index));
474b633e08cSHans Petter Selasky 		break;
475b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
476b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY,
477b633e08cSHans Petter Selasky 					MLX5_GET(set_fte_in, in, flow_index));
478b633e08cSHans Petter Selasky 		break;
479b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_Q_COUNTER:
480b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_Q_COUNTER,
481b633e08cSHans Petter Selasky 					MLX5_GET(query_q_counter_in, in,
482b633e08cSHans Petter Selasky 						 counter_set_id));
483b633e08cSHans Petter Selasky 		break;
484b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
485b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_FLOW_COUNTER,
486b633e08cSHans Petter Selasky 					MLX5_GET(query_flow_counter_in, in,
487b633e08cSHans Petter Selasky 						 flow_counter_id));
488b633e08cSHans Petter Selasky 		break;
489b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT:
490b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT,
491b633e08cSHans Petter Selasky 					MLX5_GET(general_obj_in_cmd_hdr, in,
492b633e08cSHans Petter Selasky 						 obj_id));
493b633e08cSHans Petter Selasky 		break;
494b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
495b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT,
496b633e08cSHans Petter Selasky 					MLX5_GET(query_scheduling_element_in,
497b633e08cSHans Petter Selasky 						 in, scheduling_element_id));
498b633e08cSHans Petter Selasky 		break;
499b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
500b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT,
501b633e08cSHans Petter Selasky 					MLX5_GET(modify_scheduling_element_in,
502b633e08cSHans Petter Selasky 						 in, scheduling_element_id));
503b633e08cSHans Petter Selasky 		break;
504b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
505b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT,
506b633e08cSHans Petter Selasky 					MLX5_GET(add_vxlan_udp_dport_in, in,
507b633e08cSHans Petter Selasky 						 vxlan_udp_port));
508b633e08cSHans Petter Selasky 		break;
509b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
510b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_L2_TABLE_ENTRY,
511b633e08cSHans Petter Selasky 					MLX5_GET(query_l2_table_entry_in, in,
512b633e08cSHans Petter Selasky 						 table_index));
513b633e08cSHans Petter Selasky 		break;
514b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
515b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_SET_L2_TABLE_ENTRY,
516b633e08cSHans Petter Selasky 					MLX5_GET(set_l2_table_entry_in, in,
517b633e08cSHans Petter Selasky 						 table_index));
518b633e08cSHans Petter Selasky 		break;
519b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_QP:
520b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
521b633e08cSHans Petter Selasky 					MLX5_GET(query_qp_in, in, qpn));
522b633e08cSHans Petter Selasky 		break;
523b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_RST2INIT_QP:
524b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
525b633e08cSHans Petter Selasky 					MLX5_GET(rst2init_qp_in, in, qpn));
526b633e08cSHans Petter Selasky 		break;
527b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_INIT2RTR_QP:
528b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
529b633e08cSHans Petter Selasky 					MLX5_GET(init2rtr_qp_in, in, qpn));
530b633e08cSHans Petter Selasky 		break;
531b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_RTR2RTS_QP:
532b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
533b633e08cSHans Petter Selasky 					MLX5_GET(rtr2rts_qp_in, in, qpn));
534b633e08cSHans Petter Selasky 		break;
535b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_RTS2RTS_QP:
536b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
537b633e08cSHans Petter Selasky 					MLX5_GET(rts2rts_qp_in, in, qpn));
538b633e08cSHans Petter Selasky 		break;
539b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_SQERR2RTS_QP:
540b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
541b633e08cSHans Petter Selasky 					MLX5_GET(sqerr2rts_qp_in, in, qpn));
542b633e08cSHans Petter Selasky 		break;
543b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_2ERR_QP:
544b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
545b633e08cSHans Petter Selasky 					MLX5_GET(qp_2err_in, in, qpn));
546b633e08cSHans Petter Selasky 		break;
547b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_2RST_QP:
548b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
549b633e08cSHans Petter Selasky 					MLX5_GET(qp_2rst_in, in, qpn));
550b633e08cSHans Petter Selasky 		break;
551b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_DCT:
552b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT,
553b633e08cSHans Petter Selasky 					MLX5_GET(query_dct_in, in, dctn));
554b633e08cSHans Petter Selasky 		break;
555b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_XRQ:
556b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY:
557b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS:
558b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRQ,
559b633e08cSHans Petter Selasky 					MLX5_GET(query_xrq_in, in, xrqn));
560b633e08cSHans Petter Selasky 		break;
561b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_XRC_SRQ:
562b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRC_SRQ,
563b633e08cSHans Petter Selasky 					MLX5_GET(query_xrc_srq_in, in,
564b633e08cSHans Petter Selasky 						 xrc_srqn));
565b633e08cSHans Petter Selasky 		break;
566b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ARM_XRC_SRQ:
567b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRC_SRQ,
568b633e08cSHans Petter Selasky 					MLX5_GET(arm_xrc_srq_in, in, xrc_srqn));
569b633e08cSHans Petter Selasky 		break;
570b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_SRQ:
571b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_SRQ,
572b633e08cSHans Petter Selasky 					MLX5_GET(query_srq_in, in, srqn));
573b633e08cSHans Petter Selasky 		break;
574b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ARM_RQ:
575b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
576b633e08cSHans Petter Selasky 					MLX5_GET(arm_rq_in, in, srq_number));
577b633e08cSHans Petter Selasky 		break;
578b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
579b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT,
580b633e08cSHans Petter Selasky 					MLX5_GET(drain_dct_in, in, dctn));
581b633e08cSHans Petter Selasky 		break;
582b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ARM_XRQ:
583b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY:
584b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_RELEASE_XRQ_ERROR:
585b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_XRQ:
586b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_XRQ,
587b633e08cSHans Petter Selasky 					MLX5_GET(arm_xrq_in, in, xrqn));
588b633e08cSHans Petter Selasky 		break;
589b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT:
590b633e08cSHans Petter Selasky 		obj_id = get_enc_obj_id
591b633e08cSHans Petter Selasky 				(MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT,
592b633e08cSHans Petter Selasky 				 MLX5_GET(query_packet_reformat_context_in,
593b633e08cSHans Petter Selasky 					  in, packet_reformat_id));
594b633e08cSHans Petter Selasky 		break;
595b633e08cSHans Petter Selasky 	default:
596b633e08cSHans Petter Selasky 		obj_id = 0;
597b633e08cSHans Petter Selasky 	}
598b633e08cSHans Petter Selasky 
599b633e08cSHans Petter Selasky 	return obj_id;
600b633e08cSHans Petter Selasky }
601b633e08cSHans Petter Selasky 
devx_is_valid_obj_id(struct uverbs_attr_bundle * attrs,struct ib_uobject * uobj,const void * in)602b633e08cSHans Petter Selasky static bool devx_is_valid_obj_id(struct uverbs_attr_bundle *attrs,
603b633e08cSHans Petter Selasky 				 struct ib_uobject *uobj, const void *in)
604b633e08cSHans Petter Selasky {
605b633e08cSHans Petter Selasky 	struct mlx5_ib_dev *dev = mlx5_udata_to_mdev(&attrs->driver_udata);
606b633e08cSHans Petter Selasky 	u64 obj_id = devx_get_obj_id(in);
607b633e08cSHans Petter Selasky 
608b633e08cSHans Petter Selasky 	if (!obj_id)
609b633e08cSHans Petter Selasky 		return false;
610b633e08cSHans Petter Selasky 
611b633e08cSHans Petter Selasky 	switch (uobj_get_object_id(uobj)) {
612b633e08cSHans Petter Selasky 	case UVERBS_OBJECT_CQ:
613b633e08cSHans Petter Selasky 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_CQ,
614b633e08cSHans Petter Selasky 				      to_mcq(uobj->object)->mcq.cqn) ==
615b633e08cSHans Petter Selasky 				      obj_id;
616b633e08cSHans Petter Selasky 
617b633e08cSHans Petter Selasky 	case UVERBS_OBJECT_SRQ:
618b633e08cSHans Petter Selasky 	{
619b633e08cSHans Petter Selasky 		struct mlx5_core_srq *srq = &(to_msrq(uobj->object)->msrq);
620b633e08cSHans Petter Selasky 		u16 opcode;
621b633e08cSHans Petter Selasky 
622b633e08cSHans Petter Selasky 		switch (srq->common.res) {
623b633e08cSHans Petter Selasky 		case MLX5_RES_XSRQ:
624b633e08cSHans Petter Selasky 			opcode = MLX5_CMD_OP_CREATE_XRC_SRQ;
625b633e08cSHans Petter Selasky 			break;
626b633e08cSHans Petter Selasky 		case MLX5_RES_XRQ:
627b633e08cSHans Petter Selasky 			opcode = MLX5_CMD_OP_CREATE_XRQ;
628b633e08cSHans Petter Selasky 			break;
629b633e08cSHans Petter Selasky 		default:
630b633e08cSHans Petter Selasky 			if (!dev->mdev->issi)
631b633e08cSHans Petter Selasky 				opcode = MLX5_CMD_OP_CREATE_SRQ;
632b633e08cSHans Petter Selasky 			else
633b633e08cSHans Petter Selasky 				opcode = MLX5_CMD_OP_CREATE_RMP;
634b633e08cSHans Petter Selasky 		}
635b633e08cSHans Petter Selasky 
636b633e08cSHans Petter Selasky 		return get_enc_obj_id(opcode,
637b633e08cSHans Petter Selasky 				      to_msrq(uobj->object)->msrq.srqn) ==
638b633e08cSHans Petter Selasky 				      obj_id;
639b633e08cSHans Petter Selasky 	}
640b633e08cSHans Petter Selasky 
641b633e08cSHans Petter Selasky 	case UVERBS_OBJECT_QP:
642b633e08cSHans Petter Selasky 	{
643b633e08cSHans Petter Selasky 		struct mlx5_ib_qp *qp = to_mqp(uobj->object);
644b633e08cSHans Petter Selasky 		enum ib_qp_type	qp_type = qp->ibqp.qp_type;
645b633e08cSHans Petter Selasky 
646b633e08cSHans Petter Selasky 		if (qp_type == IB_QPT_RAW_PACKET ||
647b633e08cSHans Petter Selasky 		    (qp->flags & MLX5_IB_QP_UNDERLAY)) {
648b633e08cSHans Petter Selasky 			struct mlx5_ib_raw_packet_qp *raw_packet_qp =
649b633e08cSHans Petter Selasky 							 &qp->raw_packet_qp;
650b633e08cSHans Petter Selasky 			struct mlx5_ib_rq *rq = &raw_packet_qp->rq;
651b633e08cSHans Petter Selasky 			struct mlx5_ib_sq *sq = &raw_packet_qp->sq;
652b633e08cSHans Petter Selasky 
653b633e08cSHans Petter Selasky 			return (get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
654b633e08cSHans Petter Selasky 					       rq->base.mqp.qpn) == obj_id ||
655b633e08cSHans Petter Selasky 				get_enc_obj_id(MLX5_CMD_OP_CREATE_SQ,
656b633e08cSHans Petter Selasky 					       sq->base.mqp.qpn) == obj_id ||
657b633e08cSHans Petter Selasky 				get_enc_obj_id(MLX5_CMD_OP_CREATE_TIR,
658b633e08cSHans Petter Selasky 					       rq->tirn) == obj_id ||
659b633e08cSHans Petter Selasky 				get_enc_obj_id(MLX5_CMD_OP_CREATE_TIS,
660b633e08cSHans Petter Selasky 					       sq->tisn) == obj_id);
661b633e08cSHans Petter Selasky 		}
662b633e08cSHans Petter Selasky 
663b633e08cSHans Petter Selasky 		if (qp_type == MLX5_IB_QPT_DCT)
664b633e08cSHans Petter Selasky 			return get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT,
665b633e08cSHans Petter Selasky 					      qp->dct.mdct.dctn) == obj_id;
666b633e08cSHans Petter Selasky 
667b633e08cSHans Petter Selasky 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
668b633e08cSHans Petter Selasky 				      qp->ibqp.qp_num) == obj_id;
669b633e08cSHans Petter Selasky 	}
670b633e08cSHans Petter Selasky 
671b633e08cSHans Petter Selasky 	case UVERBS_OBJECT_WQ:
672b633e08cSHans Petter Selasky 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_RQ,
673b633e08cSHans Petter Selasky 				      to_mrwq(uobj->object)->core_qp.qpn) ==
674b633e08cSHans Petter Selasky 				      obj_id;
675b633e08cSHans Petter Selasky 
676b633e08cSHans Petter Selasky 	case UVERBS_OBJECT_RWQ_IND_TBL:
677b633e08cSHans Petter Selasky 		return get_enc_obj_id(MLX5_CMD_OP_CREATE_RQT,
678b633e08cSHans Petter Selasky 				      to_mrwq_ind_table(uobj->object)->rqtn) ==
679b633e08cSHans Petter Selasky 				      obj_id;
680b633e08cSHans Petter Selasky 
681b633e08cSHans Petter Selasky 	case MLX5_IB_OBJECT_DEVX_OBJ:
682b633e08cSHans Petter Selasky 		return ((struct devx_obj *)uobj->object)->obj_id == obj_id;
683b633e08cSHans Petter Selasky 
684b633e08cSHans Petter Selasky 	default:
685b633e08cSHans Petter Selasky 		return false;
686b633e08cSHans Petter Selasky 	}
687b633e08cSHans Petter Selasky }
688b633e08cSHans Petter Selasky 
devx_set_umem_valid(const void * in)689b633e08cSHans Petter Selasky static void devx_set_umem_valid(const void *in)
690b633e08cSHans Petter Selasky {
691b633e08cSHans Petter Selasky 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
692b633e08cSHans Petter Selasky 
693b633e08cSHans Petter Selasky 	switch (opcode) {
694b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_MKEY:
695b633e08cSHans Petter Selasky 		MLX5_SET(create_mkey_in, in, mkey_umem_valid, 1);
696b633e08cSHans Petter Selasky 		break;
697b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_CQ:
698b633e08cSHans Petter Selasky 	{
699b633e08cSHans Petter Selasky 		void *cqc;
700b633e08cSHans Petter Selasky 
701b633e08cSHans Petter Selasky 		MLX5_SET(create_cq_in, in, cq_umem_valid, 1);
702b633e08cSHans Petter Selasky 		cqc = MLX5_ADDR_OF(create_cq_in, in, cq_context);
703b633e08cSHans Petter Selasky 		MLX5_SET(cqc, cqc, dbr_umem_valid, 1);
704b633e08cSHans Petter Selasky 		break;
705b633e08cSHans Petter Selasky 	}
706b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_QP:
707b633e08cSHans Petter Selasky 	{
708b633e08cSHans Petter Selasky 		void *qpc;
709b633e08cSHans Petter Selasky 
710b633e08cSHans Petter Selasky 		qpc = MLX5_ADDR_OF(create_qp_in, in, qpc);
711b633e08cSHans Petter Selasky 		MLX5_SET(qpc, qpc, dbr_umem_valid, 1);
712b633e08cSHans Petter Selasky 		MLX5_SET(create_qp_in, in, wq_umem_valid, 1);
713b633e08cSHans Petter Selasky 		break;
714b633e08cSHans Petter Selasky 	}
715b633e08cSHans Petter Selasky 
716b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_RQ:
717b633e08cSHans Petter Selasky 	{
718b633e08cSHans Petter Selasky 		void *rqc, *wq;
719b633e08cSHans Petter Selasky 
720b633e08cSHans Petter Selasky 		rqc = MLX5_ADDR_OF(create_rq_in, in, ctx);
721b633e08cSHans Petter Selasky 		wq  = MLX5_ADDR_OF(rqc, rqc, wq);
722b633e08cSHans Petter Selasky 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
723b633e08cSHans Petter Selasky 		MLX5_SET(wq, wq, wq_umem_valid, 1);
724b633e08cSHans Petter Selasky 		break;
725b633e08cSHans Petter Selasky 	}
726b633e08cSHans Petter Selasky 
727b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_SQ:
728b633e08cSHans Petter Selasky 	{
729b633e08cSHans Petter Selasky 		void *sqc, *wq;
730b633e08cSHans Petter Selasky 
731b633e08cSHans Petter Selasky 		sqc = MLX5_ADDR_OF(create_sq_in, in, ctx);
732b633e08cSHans Petter Selasky 		wq = MLX5_ADDR_OF(sqc, sqc, wq);
733b633e08cSHans Petter Selasky 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
734b633e08cSHans Petter Selasky 		MLX5_SET(wq, wq, wq_umem_valid, 1);
735b633e08cSHans Petter Selasky 		break;
736b633e08cSHans Petter Selasky 	}
737b633e08cSHans Petter Selasky 
738b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_CQ:
739b633e08cSHans Petter Selasky 		MLX5_SET(modify_cq_in, in, cq_umem_valid, 1);
740b633e08cSHans Petter Selasky 		break;
741b633e08cSHans Petter Selasky 
742b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_RMP:
743b633e08cSHans Petter Selasky 	{
744b633e08cSHans Petter Selasky 		void *rmpc, *wq;
745b633e08cSHans Petter Selasky 
746b633e08cSHans Petter Selasky 		rmpc = MLX5_ADDR_OF(create_rmp_in, in, ctx);
747b633e08cSHans Petter Selasky 		wq = MLX5_ADDR_OF(rmpc, rmpc, wq);
748b633e08cSHans Petter Selasky 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
749b633e08cSHans Petter Selasky 		MLX5_SET(wq, wq, wq_umem_valid, 1);
750b633e08cSHans Petter Selasky 		break;
751b633e08cSHans Petter Selasky 	}
752b633e08cSHans Petter Selasky 
753b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_XRQ:
754b633e08cSHans Petter Selasky 	{
755b633e08cSHans Petter Selasky 		void *xrqc, *wq;
756b633e08cSHans Petter Selasky 
757b633e08cSHans Petter Selasky 		xrqc = MLX5_ADDR_OF(create_xrq_in, in, xrq_context);
758b633e08cSHans Petter Selasky 		wq = MLX5_ADDR_OF(xrqc, xrqc, wq);
759b633e08cSHans Petter Selasky 		MLX5_SET(wq, wq, dbr_umem_valid, 1);
760b633e08cSHans Petter Selasky 		MLX5_SET(wq, wq, wq_umem_valid, 1);
761b633e08cSHans Petter Selasky 		break;
762b633e08cSHans Petter Selasky 	}
763b633e08cSHans Petter Selasky 
764b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
765b633e08cSHans Petter Selasky 	{
766b633e08cSHans Petter Selasky 		void *xrc_srqc;
767b633e08cSHans Petter Selasky 
768b633e08cSHans Petter Selasky 		MLX5_SET(create_xrc_srq_in, in, xrc_srq_umem_valid, 1);
769b633e08cSHans Petter Selasky 		xrc_srqc = MLX5_ADDR_OF(create_xrc_srq_in, in,
770b633e08cSHans Petter Selasky 					xrc_srq_context_entry);
771b633e08cSHans Petter Selasky 		MLX5_SET(xrc_srqc, xrc_srqc, dbr_umem_valid, 1);
772b633e08cSHans Petter Selasky 		break;
773b633e08cSHans Petter Selasky 	}
774b633e08cSHans Petter Selasky 
775b633e08cSHans Petter Selasky 	default:
776b633e08cSHans Petter Selasky 		return;
777b633e08cSHans Petter Selasky 	}
778b633e08cSHans Petter Selasky }
779b633e08cSHans Petter Selasky 
devx_is_obj_create_cmd(const void * in,u16 * opcode)780b633e08cSHans Petter Selasky static bool devx_is_obj_create_cmd(const void *in, u16 *opcode)
781b633e08cSHans Petter Selasky {
782b633e08cSHans Petter Selasky 	*opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
783b633e08cSHans Petter Selasky 
784b633e08cSHans Petter Selasky 	switch (*opcode) {
785b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_GENERAL_OBJ:
786b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_MKEY:
787b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_CQ:
788b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ALLOC_PD:
789b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
790b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_RMP:
791b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_SQ:
792b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_RQ:
793b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_RQT:
794b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_TIR:
795b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_TIS:
796b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ALLOC_Q_COUNTER:
797b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_FLOW_TABLE:
798b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_FLOW_GROUP:
799b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
800b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT:
801b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
802b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
803b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
804b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
805b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_QP:
806b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_SRQ:
807b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
808b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_DCT:
809b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_XRQ:
810b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ATTACH_TO_MCG:
811b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ALLOC_XRCD:
812b633e08cSHans Petter Selasky 		return true;
813b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
814b633e08cSHans Petter Selasky 	{
815b633e08cSHans Petter Selasky 		u16 op_mod = MLX5_GET(set_fte_in, in, op_mod);
816b633e08cSHans Petter Selasky 		if (op_mod == 0)
817b633e08cSHans Petter Selasky 			return true;
818b633e08cSHans Petter Selasky 		return false;
819b633e08cSHans Petter Selasky 	}
820b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_PSV:
821b633e08cSHans Petter Selasky 	{
822b633e08cSHans Petter Selasky 		u8 num_psv = MLX5_GET(create_psv_in, in, num_psv);
823b633e08cSHans Petter Selasky 
824b633e08cSHans Petter Selasky 		if (num_psv == 1)
825b633e08cSHans Petter Selasky 			return true;
826b633e08cSHans Petter Selasky 		return false;
827b633e08cSHans Petter Selasky 	}
828b633e08cSHans Petter Selasky 	default:
829b633e08cSHans Petter Selasky 		return false;
830b633e08cSHans Petter Selasky 	}
831b633e08cSHans Petter Selasky }
832b633e08cSHans Petter Selasky 
devx_is_obj_modify_cmd(const void * in)833b633e08cSHans Petter Selasky static bool devx_is_obj_modify_cmd(const void *in)
834b633e08cSHans Petter Selasky {
835b633e08cSHans Petter Selasky 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
836b633e08cSHans Petter Selasky 
837b633e08cSHans Petter Selasky 	switch (opcode) {
838b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_GENERAL_OBJ:
839b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_CQ:
840b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_RMP:
841b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_SQ:
842b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_RQ:
843b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_RQT:
844b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_TIR:
845b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_TIS:
846b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_FLOW_TABLE:
847b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
848b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
849b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
850b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_RST2INIT_QP:
851b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_INIT2RTR_QP:
852b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_RTR2RTS_QP:
853b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_RTS2RTS_QP:
854b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_SQERR2RTS_QP:
855b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_2ERR_QP:
856b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_2RST_QP:
857b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ARM_XRC_SRQ:
858b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ARM_RQ:
859b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
860b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ARM_XRQ:
861b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY:
862b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_RELEASE_XRQ_ERROR:
863b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_MODIFY_XRQ:
864b633e08cSHans Petter Selasky 		return true;
865b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
866b633e08cSHans Petter Selasky 	{
867b633e08cSHans Petter Selasky 		u16 op_mod = MLX5_GET(set_fte_in, in, op_mod);
868b633e08cSHans Petter Selasky 
869b633e08cSHans Petter Selasky 		if (op_mod == 1)
870b633e08cSHans Petter Selasky 			return true;
871b633e08cSHans Petter Selasky 		return false;
872b633e08cSHans Petter Selasky 	}
873b633e08cSHans Petter Selasky 	default:
874b633e08cSHans Petter Selasky 		return false;
875b633e08cSHans Petter Selasky 	}
876b633e08cSHans Petter Selasky }
877b633e08cSHans Petter Selasky 
devx_is_obj_query_cmd(const void * in)878b633e08cSHans Petter Selasky static bool devx_is_obj_query_cmd(const void *in)
879b633e08cSHans Petter Selasky {
880b633e08cSHans Petter Selasky 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
881b633e08cSHans Petter Selasky 
882b633e08cSHans Petter Selasky 	switch (opcode) {
883b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_GENERAL_OBJ:
884b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_MKEY:
885b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_CQ:
886b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_RMP:
887b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_SQ:
888b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_RQ:
889b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_RQT:
890b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_TIR:
891b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_TIS:
892b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_Q_COUNTER:
893b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_FLOW_TABLE:
894b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_FLOW_GROUP:
895b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
896b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
897b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT:
898b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
899b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
900b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_QP:
901b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_SRQ:
902b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_XRC_SRQ:
903b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_DCT:
904b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_XRQ:
905b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY:
906b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS:
907b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT:
908b633e08cSHans Petter Selasky 		return true;
909b633e08cSHans Petter Selasky 	default:
910b633e08cSHans Petter Selasky 		return false;
911b633e08cSHans Petter Selasky 	}
912b633e08cSHans Petter Selasky }
913b633e08cSHans Petter Selasky 
devx_is_whitelist_cmd(void * in)914b633e08cSHans Petter Selasky static bool devx_is_whitelist_cmd(void *in)
915b633e08cSHans Petter Selasky {
916b633e08cSHans Petter Selasky 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
917b633e08cSHans Petter Selasky 
918b633e08cSHans Petter Selasky 	switch (opcode) {
919b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_HCA_CAP:
920b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT:
921b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT:
922b633e08cSHans Petter Selasky 		return true;
923b633e08cSHans Petter Selasky 	default:
924b633e08cSHans Petter Selasky 		return false;
925b633e08cSHans Petter Selasky 	}
926b633e08cSHans Petter Selasky }
927b633e08cSHans Petter Selasky 
devx_get_uid(struct mlx5_ib_ucontext * c,void * cmd_in)928b633e08cSHans Petter Selasky static int devx_get_uid(struct mlx5_ib_ucontext *c, void *cmd_in)
929b633e08cSHans Petter Selasky {
930b633e08cSHans Petter Selasky 	if (devx_is_whitelist_cmd(cmd_in)) {
931b633e08cSHans Petter Selasky 		if (c->devx_uid)
932b633e08cSHans Petter Selasky 			return c->devx_uid;
933b633e08cSHans Petter Selasky 
934b633e08cSHans Petter Selasky 		return -EOPNOTSUPP;
935b633e08cSHans Petter Selasky 	}
936b633e08cSHans Petter Selasky 
937b633e08cSHans Petter Selasky 	if (!c->devx_uid)
938b633e08cSHans Petter Selasky 		return -EINVAL;
939b633e08cSHans Petter Selasky 
940b633e08cSHans Petter Selasky 	return c->devx_uid;
941b633e08cSHans Petter Selasky }
942b633e08cSHans Petter Selasky 
devx_is_general_cmd(void * in,struct mlx5_ib_dev * dev)943b633e08cSHans Petter Selasky static bool devx_is_general_cmd(void *in, struct mlx5_ib_dev *dev)
944b633e08cSHans Petter Selasky {
945b633e08cSHans Petter Selasky 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
946b633e08cSHans Petter Selasky 
947b633e08cSHans Petter Selasky 	/* Pass all cmds for vhca_tunnel as general, tracking is done in FW */
948b633e08cSHans Petter Selasky 	if ((MLX5_CAP_GEN_64(dev->mdev, vhca_tunnel_commands) &&
949b633e08cSHans Petter Selasky 	     MLX5_GET(general_obj_in_cmd_hdr, in, vhca_tunnel_id)) ||
950b633e08cSHans Petter Selasky 	    (opcode >= MLX5_CMD_OP_GENERAL_START &&
951b633e08cSHans Petter Selasky 	     opcode < MLX5_CMD_OP_GENERAL_END))
952b633e08cSHans Petter Selasky 		return true;
953b633e08cSHans Petter Selasky 
954b633e08cSHans Petter Selasky 	switch (opcode) {
955b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_HCA_CAP:
956b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT:
957b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT:
958b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_VPORT_STATE:
959b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_ADAPTER:
960b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_ISSI:
961b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT:
962b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_ROCE_ADDRESS:
963b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_VNIC_ENV:
964b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_VPORT_COUNTER:
965b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_GET_DROPPED_PACKET_LOG:
966b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_NOP:
967b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_CONG_STATUS:
968b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_CONG_PARAMS:
969b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_CONG_STATISTICS:
970b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_QUERY_LAG:
971b633e08cSHans Petter Selasky 		return true;
972b633e08cSHans Petter Selasky 	default:
973b633e08cSHans Petter Selasky 		return false;
974b633e08cSHans Petter Selasky 	}
975b633e08cSHans Petter Selasky }
976b633e08cSHans Petter Selasky 
UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_EQN)977b633e08cSHans Petter Selasky static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_EQN)(
978b633e08cSHans Petter Selasky 	struct uverbs_attr_bundle *attrs)
979b633e08cSHans Petter Selasky {
980b633e08cSHans Petter Selasky 	struct mlx5_ib_ucontext *c;
981b633e08cSHans Petter Selasky 	struct mlx5_ib_dev *dev;
982b633e08cSHans Petter Selasky 	int user_vector;
983b633e08cSHans Petter Selasky 	int dev_eqn;
984b633e08cSHans Petter Selasky 	unsigned int irqn;
985b633e08cSHans Petter Selasky 	int err;
986b633e08cSHans Petter Selasky 
987b633e08cSHans Petter Selasky 	if (uverbs_copy_from(&user_vector, attrs,
988b633e08cSHans Petter Selasky 			     MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC))
989b633e08cSHans Petter Selasky 		return -EFAULT;
990b633e08cSHans Petter Selasky 
991b633e08cSHans Petter Selasky 	c = devx_ufile2uctx(attrs);
992b633e08cSHans Petter Selasky 	if (IS_ERR(c))
993b633e08cSHans Petter Selasky 		return PTR_ERR(c);
994b633e08cSHans Petter Selasky 	dev = to_mdev(c->ibucontext.device);
995b633e08cSHans Petter Selasky 
996b633e08cSHans Petter Selasky 	err = mlx5_vector2eqn(dev->mdev, user_vector, &dev_eqn, &irqn);
997b633e08cSHans Petter Selasky 	if (err < 0)
998b633e08cSHans Petter Selasky 		return err;
999b633e08cSHans Petter Selasky 
1000b633e08cSHans Petter Selasky 	if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN,
1001b633e08cSHans Petter Selasky 			   &dev_eqn, sizeof(dev_eqn)))
1002b633e08cSHans Petter Selasky 		return -EFAULT;
1003b633e08cSHans Petter Selasky 
1004b633e08cSHans Petter Selasky 	return 0;
1005b633e08cSHans Petter Selasky }
1006b633e08cSHans Petter Selasky 
1007b633e08cSHans Petter Selasky /*
1008b633e08cSHans Petter Selasky  *Security note:
1009b633e08cSHans Petter Selasky  * The hardware protection mechanism works like this: Each device object that
1010b633e08cSHans Petter Selasky  * is subject to UAR doorbells (QP/SQ/CQ) gets a UAR ID (called uar_page in
1011b633e08cSHans Petter Selasky  * the device specification manual) upon its creation. Then upon doorbell,
1012b633e08cSHans Petter Selasky  * hardware fetches the object context for which the doorbell was rang, and
1013b633e08cSHans Petter Selasky  * validates that the UAR through which the DB was rang matches the UAR ID
1014b633e08cSHans Petter Selasky  * of the object.
1015b633e08cSHans Petter Selasky  * If no match the doorbell is silently ignored by the hardware. Of course,
1016b633e08cSHans Petter Selasky  * the user cannot ring a doorbell on a UAR that was not mapped to it.
1017b633e08cSHans Petter Selasky  * Now in devx, as the devx kernel does not manipulate the QP/SQ/CQ command
1018b633e08cSHans Petter Selasky  * mailboxes (except tagging them with UID), we expose to the user its UAR
1019b633e08cSHans Petter Selasky  * ID, so it can embed it in these objects in the expected specification
1020b633e08cSHans Petter Selasky  * format. So the only thing the user can do is hurt itself by creating a
1021b633e08cSHans Petter Selasky  * QP/SQ/CQ with a UAR ID other than his, and then in this case other users
1022b633e08cSHans Petter Selasky  * may ring a doorbell on its objects.
1023b633e08cSHans Petter Selasky  * The consequence of that will be that another user can schedule a QP/SQ
1024b633e08cSHans Petter Selasky  * of the buggy user for execution (just insert it to the hardware schedule
1025b633e08cSHans Petter Selasky  * queue or arm its CQ for event generation), no further harm is expected.
1026b633e08cSHans Petter Selasky  */
UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_UAR)1027b633e08cSHans Petter Selasky static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_UAR)(
1028b633e08cSHans Petter Selasky 	struct uverbs_attr_bundle *attrs)
1029b633e08cSHans Petter Selasky {
1030b633e08cSHans Petter Selasky 	struct mlx5_ib_ucontext *c;
1031b633e08cSHans Petter Selasky 	struct mlx5_ib_dev *dev;
1032b633e08cSHans Petter Selasky 	u32 user_idx;
1033b633e08cSHans Petter Selasky 	s32 dev_idx;
1034b633e08cSHans Petter Selasky 
1035b633e08cSHans Petter Selasky 	c = devx_ufile2uctx(attrs);
1036b633e08cSHans Petter Selasky 	if (IS_ERR(c))
1037b633e08cSHans Petter Selasky 		return PTR_ERR(c);
1038b633e08cSHans Petter Selasky 	dev = to_mdev(c->ibucontext.device);
1039b633e08cSHans Petter Selasky 
1040b633e08cSHans Petter Selasky 	if (uverbs_copy_from(&user_idx, attrs,
1041b633e08cSHans Petter Selasky 			     MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX))
1042b633e08cSHans Petter Selasky 		return -EFAULT;
1043b633e08cSHans Petter Selasky 
1044b633e08cSHans Petter Selasky 	dev_idx = bfregn_to_uar_index(dev, &c->bfregi, user_idx, true);
1045b633e08cSHans Petter Selasky 	if (dev_idx < 0)
1046b633e08cSHans Petter Selasky 		return dev_idx;
1047b633e08cSHans Petter Selasky 
1048b633e08cSHans Petter Selasky 	if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX,
1049b633e08cSHans Petter Selasky 			   &dev_idx, sizeof(dev_idx)))
1050b633e08cSHans Petter Selasky 		return -EFAULT;
1051b633e08cSHans Petter Selasky 
1052b633e08cSHans Petter Selasky 	return 0;
1053b633e08cSHans Petter Selasky }
1054b633e08cSHans Petter Selasky 
UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)1055b633e08cSHans Petter Selasky static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)(
1056b633e08cSHans Petter Selasky 	struct uverbs_attr_bundle *attrs)
1057b633e08cSHans Petter Selasky {
1058b633e08cSHans Petter Selasky 	struct mlx5_ib_ucontext *c;
1059b633e08cSHans Petter Selasky 	struct mlx5_ib_dev *dev;
1060b633e08cSHans Petter Selasky 	void *cmd_in = uverbs_attr_get_alloced_ptr(
1061b633e08cSHans Petter Selasky 		attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN);
1062b633e08cSHans Petter Selasky 	int cmd_out_len = uverbs_attr_get_len(attrs,
1063b633e08cSHans Petter Selasky 					MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT);
1064b633e08cSHans Petter Selasky 	void *cmd_out;
1065b633e08cSHans Petter Selasky 	int err;
1066b633e08cSHans Petter Selasky 	int uid;
1067b633e08cSHans Petter Selasky 
1068b633e08cSHans Petter Selasky 	c = devx_ufile2uctx(attrs);
1069b633e08cSHans Petter Selasky 	if (IS_ERR(c))
1070b633e08cSHans Petter Selasky 		return PTR_ERR(c);
1071b633e08cSHans Petter Selasky 	dev = to_mdev(c->ibucontext.device);
1072b633e08cSHans Petter Selasky 
1073b633e08cSHans Petter Selasky 	uid = devx_get_uid(c, cmd_in);
1074b633e08cSHans Petter Selasky 	if (uid < 0)
1075b633e08cSHans Petter Selasky 		return uid;
1076b633e08cSHans Petter Selasky 
1077b633e08cSHans Petter Selasky 	/* Only white list of some general HCA commands are allowed for this method. */
1078b633e08cSHans Petter Selasky 	if (!devx_is_general_cmd(cmd_in, dev))
1079b633e08cSHans Petter Selasky 		return -EINVAL;
1080b633e08cSHans Petter Selasky 
1081b633e08cSHans Petter Selasky 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
1082b633e08cSHans Petter Selasky 	if (IS_ERR(cmd_out))
1083b633e08cSHans Petter Selasky 		return PTR_ERR(cmd_out);
1084b633e08cSHans Petter Selasky 
1085b633e08cSHans Petter Selasky 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1086b633e08cSHans Petter Selasky 	err = mlx5_cmd_exec(dev->mdev, cmd_in,
1087b633e08cSHans Petter Selasky 			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN),
1088b633e08cSHans Petter Selasky 			    cmd_out, cmd_out_len);
1089b633e08cSHans Petter Selasky 	if (err)
1090b633e08cSHans Petter Selasky 		return err;
1091b633e08cSHans Petter Selasky 
1092b633e08cSHans Petter Selasky 	return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, cmd_out,
1093b633e08cSHans Petter Selasky 			      cmd_out_len);
1094b633e08cSHans Petter Selasky }
1095b633e08cSHans Petter Selasky 
devx_obj_build_destroy_cmd(void * in,void * out,void * din,u32 * dinlen,u32 * obj_id)1096b633e08cSHans Petter Selasky static void devx_obj_build_destroy_cmd(void *in, void *out, void *din,
1097b633e08cSHans Petter Selasky 				       u32 *dinlen,
1098b633e08cSHans Petter Selasky 				       u32 *obj_id)
1099b633e08cSHans Petter Selasky {
1100b633e08cSHans Petter Selasky 	u16 obj_type = MLX5_GET(general_obj_in_cmd_hdr, in, obj_type);
1101b633e08cSHans Petter Selasky 	u16 uid = MLX5_GET(general_obj_in_cmd_hdr, in, uid);
1102b633e08cSHans Petter Selasky 
1103b633e08cSHans Petter Selasky 	*obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
1104b633e08cSHans Petter Selasky 	*dinlen = MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr);
1105b633e08cSHans Petter Selasky 
1106b633e08cSHans Petter Selasky 	MLX5_SET(general_obj_in_cmd_hdr, din, obj_id, *obj_id);
1107b633e08cSHans Petter Selasky 	MLX5_SET(general_obj_in_cmd_hdr, din, uid, uid);
1108b633e08cSHans Petter Selasky 
1109b633e08cSHans Petter Selasky 	switch (MLX5_GET(general_obj_in_cmd_hdr, in, opcode)) {
1110b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_GENERAL_OBJ:
1111b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJ);
1112b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, obj_type, obj_type);
1113b633e08cSHans Petter Selasky 		break;
1114b633e08cSHans Petter Selasky 
1115b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_UMEM:
1116b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
1117b633e08cSHans Petter Selasky 			 MLX5_CMD_OP_DESTROY_UMEM);
1118b633e08cSHans Petter Selasky 		break;
1119b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_MKEY:
1120b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_MKEY);
1121b633e08cSHans Petter Selasky 		break;
1122b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_CQ:
1123b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_CQ);
1124b633e08cSHans Petter Selasky 		break;
1125b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ALLOC_PD:
1126b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DEALLOC_PD);
1127b633e08cSHans Petter Selasky 		break;
1128b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
1129b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
1130b633e08cSHans Petter Selasky 			 MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN);
1131b633e08cSHans Petter Selasky 		break;
1132b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_RMP:
1133b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RMP);
1134b633e08cSHans Petter Selasky 		break;
1135b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_SQ:
1136b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_SQ);
1137b633e08cSHans Petter Selasky 		break;
1138b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_RQ:
1139b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQ);
1140b633e08cSHans Petter Selasky 		break;
1141b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_RQT:
1142b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQT);
1143b633e08cSHans Petter Selasky 		break;
1144b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_TIR:
1145b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIR);
1146b633e08cSHans Petter Selasky 		break;
1147b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_TIS:
1148b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIS);
1149b633e08cSHans Petter Selasky 		break;
1150b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ALLOC_Q_COUNTER:
1151b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
1152b633e08cSHans Petter Selasky 			 MLX5_CMD_OP_DEALLOC_Q_COUNTER);
1153b633e08cSHans Petter Selasky 		break;
1154b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_FLOW_TABLE:
1155b633e08cSHans Petter Selasky 		*dinlen = MLX5_ST_SZ_BYTES(destroy_flow_table_in);
1156b633e08cSHans Petter Selasky 		*obj_id = MLX5_GET(create_flow_table_out, out, table_id);
1157b633e08cSHans Petter Selasky 		MLX5_SET(destroy_flow_table_in, din, other_vport,
1158b633e08cSHans Petter Selasky 			 MLX5_GET(create_flow_table_in,  in, other_vport));
1159b633e08cSHans Petter Selasky 		MLX5_SET(destroy_flow_table_in, din, vport_number,
1160b633e08cSHans Petter Selasky 			 MLX5_GET(create_flow_table_in,  in, vport_number));
1161b633e08cSHans Petter Selasky 		MLX5_SET(destroy_flow_table_in, din, table_type,
1162b633e08cSHans Petter Selasky 			 MLX5_GET(create_flow_table_in,  in, table_type));
1163b633e08cSHans Petter Selasky 		MLX5_SET(destroy_flow_table_in, din, table_id, *obj_id);
1164b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
1165b633e08cSHans Petter Selasky 			 MLX5_CMD_OP_DESTROY_FLOW_TABLE);
1166b633e08cSHans Petter Selasky 		break;
1167b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_FLOW_GROUP:
1168b633e08cSHans Petter Selasky 		*dinlen = MLX5_ST_SZ_BYTES(destroy_flow_group_in);
1169b633e08cSHans Petter Selasky 		*obj_id = MLX5_GET(create_flow_group_out, out, group_id);
1170b633e08cSHans Petter Selasky 		MLX5_SET(destroy_flow_group_in, din, other_vport,
1171b633e08cSHans Petter Selasky 			 MLX5_GET(create_flow_group_in, in, other_vport));
1172b633e08cSHans Petter Selasky 		MLX5_SET(destroy_flow_group_in, din, vport_number,
1173b633e08cSHans Petter Selasky 			 MLX5_GET(create_flow_group_in, in, vport_number));
1174b633e08cSHans Petter Selasky 		MLX5_SET(destroy_flow_group_in, din, table_type,
1175b633e08cSHans Petter Selasky 			 MLX5_GET(create_flow_group_in, in, table_type));
1176b633e08cSHans Petter Selasky 		MLX5_SET(destroy_flow_group_in, din, table_id,
1177b633e08cSHans Petter Selasky 			 MLX5_GET(create_flow_group_in, in, table_id));
1178b633e08cSHans Petter Selasky 		MLX5_SET(destroy_flow_group_in, din, group_id, *obj_id);
1179b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
1180b633e08cSHans Petter Selasky 			 MLX5_CMD_OP_DESTROY_FLOW_GROUP);
1181b633e08cSHans Petter Selasky 		break;
1182b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
1183b633e08cSHans Petter Selasky 		*dinlen = MLX5_ST_SZ_BYTES(delete_fte_in);
1184b633e08cSHans Petter Selasky 		*obj_id = MLX5_GET(set_fte_in, in, flow_index);
1185b633e08cSHans Petter Selasky 		MLX5_SET(delete_fte_in, din, other_vport,
1186b633e08cSHans Petter Selasky 			 MLX5_GET(set_fte_in,  in, other_vport));
1187b633e08cSHans Petter Selasky 		MLX5_SET(delete_fte_in, din, vport_number,
1188b633e08cSHans Petter Selasky 			 MLX5_GET(set_fte_in, in, vport_number));
1189b633e08cSHans Petter Selasky 		MLX5_SET(delete_fte_in, din, table_type,
1190b633e08cSHans Petter Selasky 			 MLX5_GET(set_fte_in, in, table_type));
1191b633e08cSHans Petter Selasky 		MLX5_SET(delete_fte_in, din, table_id,
1192b633e08cSHans Petter Selasky 			 MLX5_GET(set_fte_in, in, table_id));
1193b633e08cSHans Petter Selasky 		MLX5_SET(delete_fte_in, din, flow_index, *obj_id);
1194b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
1195b633e08cSHans Petter Selasky 			 MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
1196b633e08cSHans Petter Selasky 		break;
1197b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
1198b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
1199b633e08cSHans Petter Selasky 			 MLX5_CMD_OP_DEALLOC_FLOW_COUNTER);
1200b633e08cSHans Petter Selasky 		break;
1201b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT:
1202b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
1203b633e08cSHans Petter Selasky 			 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
1204b633e08cSHans Petter Selasky 		break;
1205b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
1206b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
1207b633e08cSHans Petter Selasky 			 MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT);
1208b633e08cSHans Petter Selasky 		break;
1209b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
1210b633e08cSHans Petter Selasky 		*dinlen = MLX5_ST_SZ_BYTES(destroy_scheduling_element_in);
1211b633e08cSHans Petter Selasky 		*obj_id = MLX5_GET(create_scheduling_element_out, out,
1212b633e08cSHans Petter Selasky 				   scheduling_element_id);
1213b633e08cSHans Petter Selasky 		MLX5_SET(destroy_scheduling_element_in, din,
1214b633e08cSHans Petter Selasky 			 scheduling_hierarchy,
1215b633e08cSHans Petter Selasky 			 MLX5_GET(create_scheduling_element_in, in,
1216b633e08cSHans Petter Selasky 				  scheduling_hierarchy));
1217b633e08cSHans Petter Selasky 		MLX5_SET(destroy_scheduling_element_in, din,
1218b633e08cSHans Petter Selasky 			 scheduling_element_id, *obj_id);
1219b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
1220b633e08cSHans Petter Selasky 			 MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT);
1221b633e08cSHans Petter Selasky 		break;
1222b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
1223b633e08cSHans Petter Selasky 		*dinlen = MLX5_ST_SZ_BYTES(delete_vxlan_udp_dport_in);
1224b633e08cSHans Petter Selasky 		*obj_id = MLX5_GET(add_vxlan_udp_dport_in, in, vxlan_udp_port);
1225b633e08cSHans Petter Selasky 		MLX5_SET(delete_vxlan_udp_dport_in, din, vxlan_udp_port, *obj_id);
1226b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
1227b633e08cSHans Petter Selasky 			 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
1228b633e08cSHans Petter Selasky 		break;
1229b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
1230b633e08cSHans Petter Selasky 		*dinlen = MLX5_ST_SZ_BYTES(delete_l2_table_entry_in);
1231b633e08cSHans Petter Selasky 		*obj_id = MLX5_GET(set_l2_table_entry_in, in, table_index);
1232b633e08cSHans Petter Selasky 		MLX5_SET(delete_l2_table_entry_in, din, table_index, *obj_id);
1233b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
1234b633e08cSHans Petter Selasky 			 MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY);
1235b633e08cSHans Petter Selasky 		break;
1236b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_QP:
1237b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_QP);
1238b633e08cSHans Petter Selasky 		break;
1239b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_SRQ:
1240b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_SRQ);
1241b633e08cSHans Petter Selasky 		break;
1242b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
1243b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
1244b633e08cSHans Petter Selasky 			 MLX5_CMD_OP_DESTROY_XRC_SRQ);
1245b633e08cSHans Petter Selasky 		break;
1246b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_DCT:
1247b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_DCT);
1248b633e08cSHans Petter Selasky 		break;
1249b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_XRQ:
1250b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_XRQ);
1251b633e08cSHans Petter Selasky 		break;
1252b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ATTACH_TO_MCG:
1253b633e08cSHans Petter Selasky 		*dinlen = MLX5_ST_SZ_BYTES(detach_from_mcg_in);
1254b633e08cSHans Petter Selasky 		MLX5_SET(detach_from_mcg_in, din, qpn,
1255b633e08cSHans Petter Selasky 			 MLX5_GET(attach_to_mcg_in, in, qpn));
1256b633e08cSHans Petter Selasky 		memcpy(MLX5_ADDR_OF(detach_from_mcg_in, din, multicast_gid),
1257b633e08cSHans Petter Selasky 		       MLX5_ADDR_OF(attach_to_mcg_in, in, multicast_gid),
1258b633e08cSHans Petter Selasky 		       MLX5_FLD_SZ_BYTES(attach_to_mcg_in, multicast_gid));
1259b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DETACH_FROM_MCG);
1260b633e08cSHans Petter Selasky 		break;
1261b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_ALLOC_XRCD:
1262b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DEALLOC_XRCD);
1263b633e08cSHans Petter Selasky 		break;
1264b633e08cSHans Petter Selasky 	case MLX5_CMD_OP_CREATE_PSV:
1265b633e08cSHans Petter Selasky 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
1266b633e08cSHans Petter Selasky 			 MLX5_CMD_OP_DESTROY_PSV);
1267b633e08cSHans Petter Selasky 		MLX5_SET(destroy_psv_in, din, psvn,
1268b633e08cSHans Petter Selasky 			 MLX5_GET(create_psv_out, out, psv0_index));
1269b633e08cSHans Petter Selasky 		break;
1270b633e08cSHans Petter Selasky 	default:
1271b633e08cSHans Petter Selasky 		/* The entry must match to one of the devx_is_obj_create_cmd */
1272b633e08cSHans Petter Selasky 		WARN_ON(true);
1273b633e08cSHans Petter Selasky 		break;
1274b633e08cSHans Petter Selasky 	}
1275b633e08cSHans Petter Selasky }
1276b633e08cSHans Petter Selasky 
devx_handle_mkey_create(struct mlx5_ib_dev * dev,struct devx_obj * obj,void * in,int in_len)1277b633e08cSHans Petter Selasky static int devx_handle_mkey_create(struct mlx5_ib_dev *dev,
1278b633e08cSHans Petter Selasky 				   struct devx_obj *obj,
1279b633e08cSHans Petter Selasky 				   void *in, int in_len)
1280b633e08cSHans Petter Selasky {
1281b633e08cSHans Petter Selasky 	int min_len = MLX5_BYTE_OFF(create_mkey_in, memory_key_mkey_entry) +
1282b633e08cSHans Petter Selasky 			MLX5_FLD_SZ_BYTES(create_mkey_in,
1283b633e08cSHans Petter Selasky 			memory_key_mkey_entry);
1284b633e08cSHans Petter Selasky 	void *mkc;
1285b633e08cSHans Petter Selasky 	u8 access_mode;
1286b633e08cSHans Petter Selasky 
1287b633e08cSHans Petter Selasky 	if (in_len < min_len)
1288b633e08cSHans Petter Selasky 		return -EINVAL;
1289b633e08cSHans Petter Selasky 
1290b633e08cSHans Petter Selasky 	mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
1291b633e08cSHans Petter Selasky 
1292b633e08cSHans Petter Selasky 	access_mode = MLX5_GET(mkc, mkc, access_mode);
1293b633e08cSHans Petter Selasky 	access_mode |= MLX5_GET(mkc, mkc, access_mode_4_2) << 2;
1294b633e08cSHans Petter Selasky 
1295b633e08cSHans Petter Selasky 	if (access_mode == MLX5_ACCESS_MODE_KLM ||
1296b633e08cSHans Petter Selasky 		access_mode == MLX5_ACCESS_MODE_KSM) {
1297b633e08cSHans Petter Selasky 		return 0;
1298b633e08cSHans Petter Selasky 	}
1299b633e08cSHans Petter Selasky 
1300b633e08cSHans Petter Selasky 	MLX5_SET(create_mkey_in, in, mkey_umem_valid, 1);
1301b633e08cSHans Petter Selasky 	return 0;
1302b633e08cSHans Petter Selasky }
1303b633e08cSHans Petter Selasky 
devx_cleanup_subscription(struct mlx5_ib_dev * dev,struct devx_event_subscription * sub)1304b633e08cSHans Petter Selasky static void devx_cleanup_subscription(struct mlx5_ib_dev *dev,
1305b633e08cSHans Petter Selasky 				      struct devx_event_subscription *sub)
1306b633e08cSHans Petter Selasky {
1307b633e08cSHans Petter Selasky 	struct devx_event *event;
1308b633e08cSHans Petter Selasky 	struct devx_obj_event *xa_val_level2;
1309b633e08cSHans Petter Selasky 
1310b633e08cSHans Petter Selasky 	if (sub->is_cleaned)
1311b633e08cSHans Petter Selasky 		return;
1312b633e08cSHans Petter Selasky 
1313b633e08cSHans Petter Selasky 	sub->is_cleaned = 1;
1314b633e08cSHans Petter Selasky 	list_del_rcu(&sub->xa_list);
1315b633e08cSHans Petter Selasky 
1316b633e08cSHans Petter Selasky 	if (list_empty(&sub->obj_list))
1317b633e08cSHans Petter Selasky 		return;
1318b633e08cSHans Petter Selasky 
1319b633e08cSHans Petter Selasky 	list_del_rcu(&sub->obj_list);
1320b633e08cSHans Petter Selasky 	/* check whether key level 1 for this obj_sub_list is empty */
1321b633e08cSHans Petter Selasky 	event = xa_load(&dev->devx_event_table.event_xa,
1322b633e08cSHans Petter Selasky 			sub->xa_key_level1);
1323b633e08cSHans Petter Selasky 	WARN_ON(!event);
1324b633e08cSHans Petter Selasky 
1325b633e08cSHans Petter Selasky 	xa_val_level2 = xa_load(&event->object_ids, sub->xa_key_level2);
1326b633e08cSHans Petter Selasky 	if (list_empty(&xa_val_level2->obj_sub_list)) {
1327b633e08cSHans Petter Selasky 		xa_erase(&event->object_ids,
1328b633e08cSHans Petter Selasky 			 sub->xa_key_level2);
1329b633e08cSHans Petter Selasky 		kfree_rcu(xa_val_level2, rcu);
1330b633e08cSHans Petter Selasky 	}
1331b633e08cSHans Petter Selasky }
1332b633e08cSHans Petter Selasky 
devx_obj_cleanup(struct ib_uobject * uobject,enum rdma_remove_reason why,struct uverbs_attr_bundle * attrs)1333b633e08cSHans Petter Selasky static int devx_obj_cleanup(struct ib_uobject *uobject,
1334b633e08cSHans Petter Selasky 			    enum rdma_remove_reason why,
1335b633e08cSHans Petter Selasky 			    struct uverbs_attr_bundle *attrs)
1336b633e08cSHans Petter Selasky {
1337b633e08cSHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
1338b633e08cSHans Petter Selasky 	struct mlx5_devx_event_table *devx_event_table;
1339b633e08cSHans Petter Selasky 	struct devx_obj *obj = uobject->object;
1340b633e08cSHans Petter Selasky 	struct devx_event_subscription *sub_entry, *tmp;
1341b633e08cSHans Petter Selasky 	struct mlx5_ib_dev *dev;
1342b633e08cSHans Petter Selasky 	int ret;
1343b633e08cSHans Petter Selasky 
1344b633e08cSHans Petter Selasky 	dev = mlx5_udata_to_mdev(&attrs->driver_udata);
1345b633e08cSHans Petter Selasky 	if (obj->flags & DEVX_OBJ_FLAGS_DCT)
1346b633e08cSHans Petter Selasky 		ret = mlx5_core_destroy_dct(obj->ib_dev->mdev, &obj->core_dct);
1347b633e08cSHans Petter Selasky 	else if (obj->flags & DEVX_OBJ_FLAGS_CQ)
1348b633e08cSHans Petter Selasky 		ret = mlx5_core_destroy_cq(obj->ib_dev->mdev, &obj->core_cq);
1349b633e08cSHans Petter Selasky 	else
1350b633e08cSHans Petter Selasky 		ret = mlx5_cmd_exec(obj->ib_dev->mdev, obj->dinbox,
1351b633e08cSHans Petter Selasky 				    obj->dinlen, out, sizeof(out));
1352b633e08cSHans Petter Selasky 	if (ib_is_destroy_retryable(ret, why, uobject))
1353b633e08cSHans Petter Selasky 		return ret;
1354b633e08cSHans Petter Selasky 
1355b633e08cSHans Petter Selasky 	devx_event_table = &dev->devx_event_table;
1356b633e08cSHans Petter Selasky 
1357b633e08cSHans Petter Selasky 	mutex_lock(&devx_event_table->event_xa_lock);
1358b633e08cSHans Petter Selasky 	list_for_each_entry_safe(sub_entry, tmp, &obj->event_sub, obj_list)
1359b633e08cSHans Petter Selasky 		devx_cleanup_subscription(dev, sub_entry);
1360b633e08cSHans Petter Selasky 	mutex_unlock(&devx_event_table->event_xa_lock);
1361b633e08cSHans Petter Selasky 
1362b633e08cSHans Petter Selasky 	kfree(obj);
1363b633e08cSHans Petter Selasky 	return ret;
1364b633e08cSHans Petter Selasky }
1365b633e08cSHans Petter Selasky 
devx_cq_comp(struct mlx5_core_cq * mcq,struct mlx5_eqe * eqe)1366b633e08cSHans Petter Selasky static void devx_cq_comp(struct mlx5_core_cq *mcq, struct mlx5_eqe *eqe)
1367b633e08cSHans Petter Selasky {
1368b633e08cSHans Petter Selasky 	struct devx_obj *obj = container_of(mcq, struct devx_obj, core_cq);
1369b633e08cSHans Petter Selasky 	struct mlx5_devx_event_table *table;
1370b633e08cSHans Petter Selasky 	struct devx_event *event;
1371b633e08cSHans Petter Selasky 	struct devx_obj_event *obj_event;
1372b633e08cSHans Petter Selasky 	u32 obj_id = mcq->cqn;
1373b633e08cSHans Petter Selasky 
1374b633e08cSHans Petter Selasky 	table = &obj->ib_dev->devx_event_table;
1375b633e08cSHans Petter Selasky 	rcu_read_lock();
1376b633e08cSHans Petter Selasky 	event = xa_load(&table->event_xa, MLX5_EVENT_TYPE_COMP);
1377b633e08cSHans Petter Selasky 	if (!event)
1378b633e08cSHans Petter Selasky 		goto out;
1379b633e08cSHans Petter Selasky 
1380b633e08cSHans Petter Selasky 	obj_event = xa_load(&event->object_ids, obj_id);
1381b633e08cSHans Petter Selasky 	if (!obj_event)
1382b633e08cSHans Petter Selasky 		goto out;
1383b633e08cSHans Petter Selasky 
1384b633e08cSHans Petter Selasky 	dispatch_event_fd(&obj_event->obj_sub_list, eqe);
1385b633e08cSHans Petter Selasky out:
1386b633e08cSHans Petter Selasky 	rcu_read_unlock();
1387b633e08cSHans Petter Selasky }
1388b633e08cSHans Petter Selasky 
UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)1389b633e08cSHans Petter Selasky static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
1390b633e08cSHans Petter Selasky 	struct uverbs_attr_bundle *attrs)
1391b633e08cSHans Petter Selasky {
1392b633e08cSHans Petter Selasky 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN);
1393b633e08cSHans Petter Selasky 	int cmd_out_len =  uverbs_attr_get_len(attrs,
1394b633e08cSHans Petter Selasky 					MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT);
1395b633e08cSHans Petter Selasky 	int cmd_in_len = uverbs_attr_get_len(attrs,
1396b633e08cSHans Petter Selasky 					MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN);
1397b633e08cSHans Petter Selasky 	void *cmd_out;
1398b633e08cSHans Petter Selasky 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
1399b633e08cSHans Petter Selasky 		attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE);
1400b633e08cSHans Petter Selasky 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
1401b633e08cSHans Petter Selasky 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1402b633e08cSHans Petter Selasky 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
1403b633e08cSHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
1404b633e08cSHans Petter Selasky 	struct devx_obj *obj;
1405b633e08cSHans Petter Selasky 	u16 obj_type = 0;
1406b633e08cSHans Petter Selasky 	int err;
1407b633e08cSHans Petter Selasky 	int uid;
1408b633e08cSHans Petter Selasky 	u32 obj_id;
1409b633e08cSHans Petter Selasky 	u16 opcode;
1410b633e08cSHans Petter Selasky 
1411b633e08cSHans Petter Selasky 	if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id))
1412b633e08cSHans Petter Selasky 		return -EINVAL;
1413b633e08cSHans Petter Selasky 
1414b633e08cSHans Petter Selasky 	uid = devx_get_uid(c, cmd_in);
1415b633e08cSHans Petter Selasky 	if (uid < 0)
1416b633e08cSHans Petter Selasky 		return uid;
1417b633e08cSHans Petter Selasky 
1418b633e08cSHans Petter Selasky 	if (!devx_is_obj_create_cmd(cmd_in, &opcode))
1419b633e08cSHans Petter Selasky 		return -EINVAL;
1420b633e08cSHans Petter Selasky 
1421b633e08cSHans Petter Selasky 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
1422b633e08cSHans Petter Selasky 	if (IS_ERR(cmd_out))
1423b633e08cSHans Petter Selasky 		return PTR_ERR(cmd_out);
1424b633e08cSHans Petter Selasky 
1425b633e08cSHans Petter Selasky 	obj = kzalloc(sizeof(struct devx_obj), GFP_KERNEL);
1426b633e08cSHans Petter Selasky 	if (!obj)
1427b633e08cSHans Petter Selasky 		return -ENOMEM;
1428b633e08cSHans Petter Selasky 
1429b633e08cSHans Petter Selasky 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1430b633e08cSHans Petter Selasky 	if (opcode == MLX5_CMD_OP_CREATE_MKEY) {
1431b633e08cSHans Petter Selasky 		err = devx_handle_mkey_create(dev, obj, cmd_in, cmd_in_len);
1432b633e08cSHans Petter Selasky 		if (err)
1433b633e08cSHans Petter Selasky 			goto obj_free;
1434b633e08cSHans Petter Selasky 	} else {
1435b633e08cSHans Petter Selasky 		devx_set_umem_valid(cmd_in);
1436b633e08cSHans Petter Selasky 	}
1437b633e08cSHans Petter Selasky 
1438b633e08cSHans Petter Selasky 	if (opcode == MLX5_CMD_OP_CREATE_DCT) {
1439b633e08cSHans Petter Selasky 		obj->flags |= DEVX_OBJ_FLAGS_DCT;
1440b633e08cSHans Petter Selasky 		err = mlx5_core_create_dct(dev->mdev, &obj->core_dct,
1441b633e08cSHans Petter Selasky 					   cmd_in, cmd_in_len,
1442b633e08cSHans Petter Selasky 					   cmd_out, cmd_out_len);
1443b633e08cSHans Petter Selasky 	} else if (opcode == MLX5_CMD_OP_CREATE_CQ) {
1444b633e08cSHans Petter Selasky 		obj->flags |= DEVX_OBJ_FLAGS_CQ;
1445b633e08cSHans Petter Selasky 		obj->core_cq.comp = devx_cq_comp;
1446b633e08cSHans Petter Selasky 		err = mlx5_core_create_cq(dev->mdev, &obj->core_cq,
1447b633e08cSHans Petter Selasky 					  cmd_in, cmd_in_len, cmd_out,
1448b633e08cSHans Petter Selasky 					  cmd_out_len);
1449b633e08cSHans Petter Selasky 	} else {
1450b633e08cSHans Petter Selasky 		err = mlx5_cmd_exec(dev->mdev, cmd_in,
1451b633e08cSHans Petter Selasky 				    cmd_in_len,
1452b633e08cSHans Petter Selasky 				    cmd_out, cmd_out_len);
1453b633e08cSHans Petter Selasky 	}
1454b633e08cSHans Petter Selasky 
1455b633e08cSHans Petter Selasky 	if (err)
1456b633e08cSHans Petter Selasky 		goto obj_free;
1457b633e08cSHans Petter Selasky 
1458b633e08cSHans Petter Selasky 	if (opcode == MLX5_CMD_OP_ALLOC_FLOW_COUNTER) {
1459b633e08cSHans Petter Selasky 		u8 bulk = MLX5_GET(alloc_flow_counter_in,
1460b633e08cSHans Petter Selasky 				   cmd_in,
1461b633e08cSHans Petter Selasky 				   flow_counter_bulk);
1462b633e08cSHans Petter Selasky 		obj->flow_counter_bulk_size = 128UL * bulk;
1463b633e08cSHans Petter Selasky 	}
1464b633e08cSHans Petter Selasky 
1465b633e08cSHans Petter Selasky 	uobj->object = obj;
1466b633e08cSHans Petter Selasky 	INIT_LIST_HEAD(&obj->event_sub);
1467b633e08cSHans Petter Selasky 	obj->ib_dev = dev;
1468b633e08cSHans Petter Selasky 	devx_obj_build_destroy_cmd(cmd_in, cmd_out, obj->dinbox, &obj->dinlen,
1469b633e08cSHans Petter Selasky 				   &obj_id);
1470b633e08cSHans Petter Selasky 	WARN_ON(obj->dinlen > MLX5_MAX_DESTROY_INBOX_SIZE_DW * sizeof(u32));
1471b633e08cSHans Petter Selasky 
1472b633e08cSHans Petter Selasky 	err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, cmd_out, cmd_out_len);
1473b633e08cSHans Petter Selasky 	if (err)
1474b633e08cSHans Petter Selasky 		goto obj_destroy;
1475b633e08cSHans Petter Selasky 
1476b633e08cSHans Petter Selasky 	if (opcode == MLX5_CMD_OP_CREATE_GENERAL_OBJ)
1477b633e08cSHans Petter Selasky 		obj_type = MLX5_GET(general_obj_in_cmd_hdr, cmd_in, obj_type);
1478b633e08cSHans Petter Selasky 	obj->obj_id = get_enc_obj_id(opcode | obj_type << 16, obj_id);
1479b633e08cSHans Petter Selasky 
1480b633e08cSHans Petter Selasky 	return 0;
1481b633e08cSHans Petter Selasky 
1482b633e08cSHans Petter Selasky obj_destroy:
1483b633e08cSHans Petter Selasky 	if (obj->flags & DEVX_OBJ_FLAGS_DCT)
1484b633e08cSHans Petter Selasky 		mlx5_core_destroy_dct(obj->ib_dev->mdev, &obj->core_dct);
1485b633e08cSHans Petter Selasky 	else if (obj->flags & DEVX_OBJ_FLAGS_CQ)
1486b633e08cSHans Petter Selasky 		mlx5_core_destroy_cq(obj->ib_dev->mdev, &obj->core_cq);
1487b633e08cSHans Petter Selasky 	else
1488b633e08cSHans Petter Selasky 		mlx5_cmd_exec(obj->ib_dev->mdev, obj->dinbox, obj->dinlen, out,
1489b633e08cSHans Petter Selasky 			      sizeof(out));
1490b633e08cSHans Petter Selasky obj_free:
1491b633e08cSHans Petter Selasky 	kfree(obj);
1492b633e08cSHans Petter Selasky 	return err;
1493b633e08cSHans Petter Selasky }
1494b633e08cSHans Petter Selasky 
UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)1495b633e08cSHans Petter Selasky static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)(
1496b633e08cSHans Petter Selasky 	struct uverbs_attr_bundle *attrs)
1497b633e08cSHans Petter Selasky {
1498b633e08cSHans Petter Selasky 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN);
1499b633e08cSHans Petter Selasky 	int cmd_out_len = uverbs_attr_get_len(attrs,
1500b633e08cSHans Petter Selasky 					MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT);
1501b633e08cSHans Petter Selasky 	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
1502b633e08cSHans Petter Selasky 							  MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE);
1503b633e08cSHans Petter Selasky 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
1504b633e08cSHans Petter Selasky 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1505b633e08cSHans Petter Selasky 	struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device);
1506b633e08cSHans Petter Selasky 	void *cmd_out;
1507b633e08cSHans Petter Selasky 	int err;
1508b633e08cSHans Petter Selasky 	int uid;
1509b633e08cSHans Petter Selasky 
1510b633e08cSHans Petter Selasky 	if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id))
1511b633e08cSHans Petter Selasky 		return -EINVAL;
1512b633e08cSHans Petter Selasky 
1513b633e08cSHans Petter Selasky 	uid = devx_get_uid(c, cmd_in);
1514b633e08cSHans Petter Selasky 	if (uid < 0)
1515b633e08cSHans Petter Selasky 		return uid;
1516b633e08cSHans Petter Selasky 
1517b633e08cSHans Petter Selasky 	if (!devx_is_obj_modify_cmd(cmd_in))
1518b633e08cSHans Petter Selasky 		return -EINVAL;
1519b633e08cSHans Petter Selasky 
1520b633e08cSHans Petter Selasky 	if (!devx_is_valid_obj_id(attrs, uobj, cmd_in))
1521b633e08cSHans Petter Selasky 		return -EINVAL;
1522b633e08cSHans Petter Selasky 
1523b633e08cSHans Petter Selasky 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
1524b633e08cSHans Petter Selasky 	if (IS_ERR(cmd_out))
1525b633e08cSHans Petter Selasky 		return PTR_ERR(cmd_out);
1526b633e08cSHans Petter Selasky 
1527b633e08cSHans Petter Selasky 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1528b633e08cSHans Petter Selasky 	devx_set_umem_valid(cmd_in);
1529b633e08cSHans Petter Selasky 
1530b633e08cSHans Petter Selasky 	err = mlx5_cmd_exec(mdev->mdev, cmd_in,
1531b633e08cSHans Petter Selasky 			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN),
1532b633e08cSHans Petter Selasky 			    cmd_out, cmd_out_len);
1533b633e08cSHans Petter Selasky 	if (err)
1534b633e08cSHans Petter Selasky 		return err;
1535b633e08cSHans Petter Selasky 
1536b633e08cSHans Petter Selasky 	return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
1537b633e08cSHans Petter Selasky 			      cmd_out, cmd_out_len);
1538b633e08cSHans Petter Selasky }
1539b633e08cSHans Petter Selasky 
UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)1540b633e08cSHans Petter Selasky static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)(
1541b633e08cSHans Petter Selasky 	struct uverbs_attr_bundle *attrs)
1542b633e08cSHans Petter Selasky {
1543b633e08cSHans Petter Selasky 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN);
1544b633e08cSHans Petter Selasky 	int cmd_out_len = uverbs_attr_get_len(attrs,
1545b633e08cSHans Petter Selasky 					      MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT);
1546b633e08cSHans Petter Selasky 	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
1547b633e08cSHans Petter Selasky 							  MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE);
1548b633e08cSHans Petter Selasky 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
1549b633e08cSHans Petter Selasky 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1550b633e08cSHans Petter Selasky 	void *cmd_out;
1551b633e08cSHans Petter Selasky 	int err;
1552b633e08cSHans Petter Selasky 	int uid;
1553b633e08cSHans Petter Selasky 	struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device);
1554b633e08cSHans Petter Selasky 
1555b633e08cSHans Petter Selasky 	if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id))
1556b633e08cSHans Petter Selasky 		return -EINVAL;
1557b633e08cSHans Petter Selasky 
1558b633e08cSHans Petter Selasky 	uid = devx_get_uid(c, cmd_in);
1559b633e08cSHans Petter Selasky 	if (uid < 0)
1560b633e08cSHans Petter Selasky 		return uid;
1561b633e08cSHans Petter Selasky 
1562b633e08cSHans Petter Selasky 	if (!devx_is_obj_query_cmd(cmd_in))
1563b633e08cSHans Petter Selasky 		return -EINVAL;
1564b633e08cSHans Petter Selasky 
1565b633e08cSHans Petter Selasky 	if (!devx_is_valid_obj_id(attrs, uobj, cmd_in))
1566b633e08cSHans Petter Selasky 		return -EINVAL;
1567b633e08cSHans Petter Selasky 
1568b633e08cSHans Petter Selasky 	cmd_out = uverbs_zalloc(attrs, cmd_out_len);
1569b633e08cSHans Petter Selasky 	if (IS_ERR(cmd_out))
1570b633e08cSHans Petter Selasky 		return PTR_ERR(cmd_out);
1571b633e08cSHans Petter Selasky 
1572b633e08cSHans Petter Selasky 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1573b633e08cSHans Petter Selasky 	err = mlx5_cmd_exec(mdev->mdev, cmd_in,
1574b633e08cSHans Petter Selasky 			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN),
1575b633e08cSHans Petter Selasky 			    cmd_out, cmd_out_len);
1576b633e08cSHans Petter Selasky 	if (err)
1577b633e08cSHans Petter Selasky 		return err;
1578b633e08cSHans Petter Selasky 
1579b633e08cSHans Petter Selasky 	return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
1580b633e08cSHans Petter Selasky 			      cmd_out, cmd_out_len);
1581b633e08cSHans Petter Selasky }
1582b633e08cSHans Petter Selasky 
1583b633e08cSHans Petter Selasky struct devx_async_event_queue {
1584b633e08cSHans Petter Selasky 	spinlock_t		lock;
1585b633e08cSHans Petter Selasky 	wait_queue_head_t	poll_wait;
1586b633e08cSHans Petter Selasky 	struct list_head	event_list;
1587b633e08cSHans Petter Selasky 	atomic_t		bytes_in_use;
1588b633e08cSHans Petter Selasky 	u8			is_destroyed:1;
1589b633e08cSHans Petter Selasky };
1590b633e08cSHans Petter Selasky 
1591b633e08cSHans Petter Selasky struct devx_async_cmd_event_file {
1592b633e08cSHans Petter Selasky 	struct ib_uobject		uobj;
1593b633e08cSHans Petter Selasky 	struct devx_async_event_queue	ev_queue;
1594b633e08cSHans Petter Selasky 	struct mlx5_async_ctx		async_ctx;
1595b633e08cSHans Petter Selasky };
1596b633e08cSHans Petter Selasky 
devx_init_event_queue(struct devx_async_event_queue * ev_queue)1597b633e08cSHans Petter Selasky static void devx_init_event_queue(struct devx_async_event_queue *ev_queue)
1598b633e08cSHans Petter Selasky {
1599b633e08cSHans Petter Selasky 	spin_lock_init(&ev_queue->lock);
1600b633e08cSHans Petter Selasky 	INIT_LIST_HEAD(&ev_queue->event_list);
1601b633e08cSHans Petter Selasky 	init_waitqueue_head(&ev_queue->poll_wait);
1602b633e08cSHans Petter Selasky 	atomic_set(&ev_queue->bytes_in_use, 0);
1603b633e08cSHans Petter Selasky 	ev_queue->is_destroyed = 0;
1604b633e08cSHans Petter Selasky }
1605b633e08cSHans Petter Selasky 
UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC)1606b633e08cSHans Petter Selasky static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC)(
1607b633e08cSHans Petter Selasky 	struct uverbs_attr_bundle *attrs)
1608b633e08cSHans Petter Selasky {
1609b633e08cSHans Petter Selasky 	struct devx_async_cmd_event_file *ev_file;
1610b633e08cSHans Petter Selasky 
1611b633e08cSHans Petter Selasky 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
1612b633e08cSHans Petter Selasky 		attrs, MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE);
1613b633e08cSHans Petter Selasky 	struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata);
1614b633e08cSHans Petter Selasky 
1615b633e08cSHans Petter Selasky 	ev_file = container_of(uobj, struct devx_async_cmd_event_file,
1616b633e08cSHans Petter Selasky 			       uobj);
1617b633e08cSHans Petter Selasky 	devx_init_event_queue(&ev_file->ev_queue);
1618b633e08cSHans Petter Selasky 	mlx5_cmd_init_async_ctx(mdev->mdev, &ev_file->async_ctx);
1619b633e08cSHans Petter Selasky 	return 0;
1620b633e08cSHans Petter Selasky }
1621b633e08cSHans Petter Selasky 
UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC)1622b633e08cSHans Petter Selasky static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC)(
1623b633e08cSHans Petter Selasky 	struct uverbs_attr_bundle *attrs)
1624b633e08cSHans Petter Selasky {
1625b633e08cSHans Petter Selasky 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
1626b633e08cSHans Petter Selasky 		attrs, MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_HANDLE);
1627b633e08cSHans Petter Selasky 	struct devx_async_event_file *ev_file;
1628b633e08cSHans Petter Selasky 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
1629b633e08cSHans Petter Selasky 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1630b633e08cSHans Petter Selasky 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
1631b633e08cSHans Petter Selasky 	u32 flags;
1632b633e08cSHans Petter Selasky 	int err;
1633b633e08cSHans Petter Selasky 
1634b633e08cSHans Petter Selasky 	err = uverbs_get_flags32(&flags, attrs,
1635b633e08cSHans Petter Selasky 		MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_FLAGS,
1636b633e08cSHans Petter Selasky 		MLX5_IB_UAPI_DEVX_CR_EV_CH_FLAGS_OMIT_DATA);
1637b633e08cSHans Petter Selasky 
1638b633e08cSHans Petter Selasky 	if (err)
1639b633e08cSHans Petter Selasky 		return err;
1640b633e08cSHans Petter Selasky 
1641b633e08cSHans Petter Selasky 	ev_file = container_of(uobj, struct devx_async_event_file,
1642b633e08cSHans Petter Selasky 			       uobj);
1643b633e08cSHans Petter Selasky 	spin_lock_init(&ev_file->lock);
1644b633e08cSHans Petter Selasky 	INIT_LIST_HEAD(&ev_file->event_list);
1645b633e08cSHans Petter Selasky 	init_waitqueue_head(&ev_file->poll_wait);
1646b633e08cSHans Petter Selasky 	if (flags & MLX5_IB_UAPI_DEVX_CR_EV_CH_FLAGS_OMIT_DATA)
1647b633e08cSHans Petter Selasky 		ev_file->omit_data = 1;
1648b633e08cSHans Petter Selasky 	INIT_LIST_HEAD(&ev_file->subscribed_events_list);
1649b633e08cSHans Petter Selasky 	ev_file->dev = dev;
1650b633e08cSHans Petter Selasky 	get_device(&dev->ib_dev.dev);
1651b633e08cSHans Petter Selasky 	return 0;
1652b633e08cSHans Petter Selasky }
1653b633e08cSHans Petter Selasky 
devx_query_callback(int status,struct mlx5_async_work * context)1654b633e08cSHans Petter Selasky static void devx_query_callback(int status, struct mlx5_async_work *context)
1655b633e08cSHans Petter Selasky {
1656b633e08cSHans Petter Selasky 	struct devx_async_data *async_data =
1657b633e08cSHans Petter Selasky 		container_of(context, struct devx_async_data, cb_work);
1658b633e08cSHans Petter Selasky 	struct devx_async_cmd_event_file *ev_file = async_data->ev_file;
1659b633e08cSHans Petter Selasky 	struct devx_async_event_queue *ev_queue = &ev_file->ev_queue;
1660b633e08cSHans Petter Selasky 	unsigned long flags;
1661b633e08cSHans Petter Selasky 
1662b633e08cSHans Petter Selasky 	/*
1663b633e08cSHans Petter Selasky 	 * Note that if the struct devx_async_cmd_event_file uobj begins to be
1664b633e08cSHans Petter Selasky 	 * destroyed it will block at mlx5_cmd_cleanup_async_ctx() until this
1665b633e08cSHans Petter Selasky 	 * routine returns, ensuring that it always remains valid here.
1666b633e08cSHans Petter Selasky 	 */
1667b633e08cSHans Petter Selasky 	spin_lock_irqsave(&ev_queue->lock, flags);
1668b633e08cSHans Petter Selasky 	list_add_tail(&async_data->list, &ev_queue->event_list);
1669b633e08cSHans Petter Selasky 	spin_unlock_irqrestore(&ev_queue->lock, flags);
1670b633e08cSHans Petter Selasky 
1671b633e08cSHans Petter Selasky 	wake_up_interruptible(&ev_queue->poll_wait);
1672b633e08cSHans Petter Selasky }
1673b633e08cSHans Petter Selasky 
1674b633e08cSHans Petter Selasky #define MAX_ASYNC_BYTES_IN_USE (1024 * 1024) /* 1MB */
1675b633e08cSHans Petter Selasky 
UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY)1676b633e08cSHans Petter Selasky static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY)(
1677b633e08cSHans Petter Selasky 	struct uverbs_attr_bundle *attrs)
1678b633e08cSHans Petter Selasky {
1679b633e08cSHans Petter Selasky 	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs,
1680b633e08cSHans Petter Selasky 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN);
1681b633e08cSHans Petter Selasky 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
1682b633e08cSHans Petter Selasky 				attrs,
1683b633e08cSHans Petter Selasky 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_HANDLE);
1684b633e08cSHans Petter Selasky 	u16 cmd_out_len;
1685b633e08cSHans Petter Selasky 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
1686b633e08cSHans Petter Selasky 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1687b633e08cSHans Petter Selasky 	struct ib_uobject *fd_uobj;
1688b633e08cSHans Petter Selasky 	int err;
1689b633e08cSHans Petter Selasky 	int uid;
1690b633e08cSHans Petter Selasky 	struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device);
1691b633e08cSHans Petter Selasky 	struct devx_async_cmd_event_file *ev_file;
1692b633e08cSHans Petter Selasky 	struct devx_async_data *async_data;
1693b633e08cSHans Petter Selasky 
1694b633e08cSHans Petter Selasky 	if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id))
1695b633e08cSHans Petter Selasky 		return -EINVAL;
1696b633e08cSHans Petter Selasky 
1697b633e08cSHans Petter Selasky 	uid = devx_get_uid(c, cmd_in);
1698b633e08cSHans Petter Selasky 	if (uid < 0)
1699b633e08cSHans Petter Selasky 		return uid;
1700b633e08cSHans Petter Selasky 
1701b633e08cSHans Petter Selasky 	if (!devx_is_obj_query_cmd(cmd_in))
1702b633e08cSHans Petter Selasky 		return -EINVAL;
1703b633e08cSHans Petter Selasky 
1704b633e08cSHans Petter Selasky 	err = uverbs_get_const(&cmd_out_len, attrs,
1705b633e08cSHans Petter Selasky 			       MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_OUT_LEN);
1706b633e08cSHans Petter Selasky 	if (err)
1707b633e08cSHans Petter Selasky 		return err;
1708b633e08cSHans Petter Selasky 
1709b633e08cSHans Petter Selasky 	if (!devx_is_valid_obj_id(attrs, uobj, cmd_in))
1710b633e08cSHans Petter Selasky 		return -EINVAL;
1711b633e08cSHans Petter Selasky 
1712b633e08cSHans Petter Selasky 	fd_uobj = uverbs_attr_get_uobject(attrs,
1713b633e08cSHans Petter Selasky 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_FD);
1714b633e08cSHans Petter Selasky 	if (IS_ERR(fd_uobj))
1715b633e08cSHans Petter Selasky 		return PTR_ERR(fd_uobj);
1716b633e08cSHans Petter Selasky 
1717b633e08cSHans Petter Selasky 	ev_file = container_of(fd_uobj, struct devx_async_cmd_event_file,
1718b633e08cSHans Petter Selasky 			       uobj);
1719b633e08cSHans Petter Selasky 
1720b633e08cSHans Petter Selasky 	if (atomic_add_return(cmd_out_len, &ev_file->ev_queue.bytes_in_use) >
1721b633e08cSHans Petter Selasky 			MAX_ASYNC_BYTES_IN_USE) {
1722b633e08cSHans Petter Selasky 		atomic_sub(cmd_out_len, &ev_file->ev_queue.bytes_in_use);
1723b633e08cSHans Petter Selasky 		return -EAGAIN;
1724b633e08cSHans Petter Selasky 	}
1725b633e08cSHans Petter Selasky 
1726b633e08cSHans Petter Selasky 	async_data = kvzalloc(struct_size(async_data, hdr.out_data,
1727b633e08cSHans Petter Selasky 					  cmd_out_len), GFP_KERNEL);
1728b633e08cSHans Petter Selasky 	if (!async_data) {
1729b633e08cSHans Petter Selasky 		err = -ENOMEM;
1730b633e08cSHans Petter Selasky 		goto sub_bytes;
1731b633e08cSHans Petter Selasky 	}
1732b633e08cSHans Petter Selasky 
1733b633e08cSHans Petter Selasky 	err = uverbs_copy_from(&async_data->hdr.wr_id, attrs,
1734b633e08cSHans Petter Selasky 			       MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_WR_ID);
1735b633e08cSHans Petter Selasky 	if (err)
1736b633e08cSHans Petter Selasky 		goto free_async;
1737b633e08cSHans Petter Selasky 
1738b633e08cSHans Petter Selasky 	async_data->cmd_out_len = cmd_out_len;
1739b633e08cSHans Petter Selasky 	async_data->mdev = mdev;
1740b633e08cSHans Petter Selasky 	async_data->ev_file = ev_file;
1741b633e08cSHans Petter Selasky 
1742b633e08cSHans Petter Selasky 	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
1743b633e08cSHans Petter Selasky 	err = mlx5_cmd_exec_cb(&ev_file->async_ctx, cmd_in,
1744b633e08cSHans Petter Selasky 		    uverbs_attr_get_len(attrs,
1745b633e08cSHans Petter Selasky 				MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN),
1746b633e08cSHans Petter Selasky 		    async_data->hdr.out_data,
1747b633e08cSHans Petter Selasky 		    async_data->cmd_out_len,
1748b633e08cSHans Petter Selasky 		    devx_query_callback, &async_data->cb_work);
1749b633e08cSHans Petter Selasky 
1750b633e08cSHans Petter Selasky 	if (err)
1751b633e08cSHans Petter Selasky 		goto free_async;
1752b633e08cSHans Petter Selasky 
1753b633e08cSHans Petter Selasky 	return 0;
1754b633e08cSHans Petter Selasky 
1755b633e08cSHans Petter Selasky free_async:
1756b633e08cSHans Petter Selasky 	kvfree(async_data);
1757b633e08cSHans Petter Selasky sub_bytes:
1758b633e08cSHans Petter Selasky 	atomic_sub(cmd_out_len, &ev_file->ev_queue.bytes_in_use);
1759b633e08cSHans Petter Selasky 	return err;
1760b633e08cSHans Petter Selasky }
1761b633e08cSHans Petter Selasky 
1762b633e08cSHans Petter Selasky static void
subscribe_event_xa_dealloc(struct mlx5_devx_event_table * devx_event_table,u32 key_level1,bool is_level2,u32 key_level2)1763b633e08cSHans Petter Selasky subscribe_event_xa_dealloc(struct mlx5_devx_event_table *devx_event_table,
1764b633e08cSHans Petter Selasky 			   u32 key_level1,
1765b633e08cSHans Petter Selasky 			   bool is_level2,
1766b633e08cSHans Petter Selasky 			   u32 key_level2)
1767b633e08cSHans Petter Selasky {
1768b633e08cSHans Petter Selasky 	struct devx_event *event;
1769b633e08cSHans Petter Selasky 	struct devx_obj_event *xa_val_level2;
1770b633e08cSHans Petter Selasky 
1771b633e08cSHans Petter Selasky 	/* Level 1 is valid for future use, no need to free */
1772b633e08cSHans Petter Selasky 	if (!is_level2)
1773b633e08cSHans Petter Selasky 		return;
1774b633e08cSHans Petter Selasky 
1775b633e08cSHans Petter Selasky 	event = xa_load(&devx_event_table->event_xa, key_level1);
1776b633e08cSHans Petter Selasky 	WARN_ON(!event);
1777b633e08cSHans Petter Selasky 
1778b633e08cSHans Petter Selasky 	xa_val_level2 = xa_load(&event->object_ids,
1779b633e08cSHans Petter Selasky 				key_level2);
1780b633e08cSHans Petter Selasky 	if (list_empty(&xa_val_level2->obj_sub_list)) {
1781b633e08cSHans Petter Selasky 		xa_erase(&event->object_ids,
1782b633e08cSHans Petter Selasky 			 key_level2);
1783b633e08cSHans Petter Selasky 		kfree_rcu(xa_val_level2, rcu);
1784b633e08cSHans Petter Selasky 	}
1785b633e08cSHans Petter Selasky }
1786b633e08cSHans Petter Selasky 
1787b633e08cSHans Petter Selasky static int
subscribe_event_xa_alloc(struct mlx5_devx_event_table * devx_event_table,u32 key_level1,bool is_level2,u32 key_level2)1788b633e08cSHans Petter Selasky subscribe_event_xa_alloc(struct mlx5_devx_event_table *devx_event_table,
1789b633e08cSHans Petter Selasky 			 u32 key_level1,
1790b633e08cSHans Petter Selasky 			 bool is_level2,
1791b633e08cSHans Petter Selasky 			 u32 key_level2)
1792b633e08cSHans Petter Selasky {
1793b633e08cSHans Petter Selasky 	struct devx_obj_event *obj_event;
1794b633e08cSHans Petter Selasky 	struct devx_event *event;
1795b633e08cSHans Petter Selasky 	int err;
1796b633e08cSHans Petter Selasky 
1797b633e08cSHans Petter Selasky 	event = xa_load(&devx_event_table->event_xa, key_level1);
1798b633e08cSHans Petter Selasky 	if (!event) {
1799b633e08cSHans Petter Selasky 		event = kzalloc(sizeof(*event), GFP_KERNEL);
1800b633e08cSHans Petter Selasky 		if (!event)
1801b633e08cSHans Petter Selasky 			return -ENOMEM;
1802b633e08cSHans Petter Selasky 
1803b633e08cSHans Petter Selasky 		INIT_LIST_HEAD(&event->unaffiliated_list);
1804b633e08cSHans Petter Selasky 		xa_init_flags(&event->object_ids, 0);
1805b633e08cSHans Petter Selasky 
1806b633e08cSHans Petter Selasky 		err = xa_insert(&devx_event_table->event_xa,
1807b633e08cSHans Petter Selasky 				key_level1,
1808b633e08cSHans Petter Selasky 				event,
1809b633e08cSHans Petter Selasky 				GFP_KERNEL);
1810b633e08cSHans Petter Selasky 		if (err) {
1811b633e08cSHans Petter Selasky 			kfree(event);
1812b633e08cSHans Petter Selasky 			return err;
1813b633e08cSHans Petter Selasky 		}
1814b633e08cSHans Petter Selasky 	}
1815b633e08cSHans Petter Selasky 
1816b633e08cSHans Petter Selasky 	if (!is_level2)
1817b633e08cSHans Petter Selasky 		return 0;
1818b633e08cSHans Petter Selasky 
1819b633e08cSHans Petter Selasky 	obj_event = xa_load(&event->object_ids, key_level2);
1820b633e08cSHans Petter Selasky 	if (!obj_event) {
1821b633e08cSHans Petter Selasky 		obj_event = kzalloc(sizeof(*obj_event), GFP_KERNEL);
1822b633e08cSHans Petter Selasky 		if (!obj_event)
1823b633e08cSHans Petter Selasky 			/* Level1 is valid for future use, no need to free */
1824b633e08cSHans Petter Selasky 			return -ENOMEM;
1825b633e08cSHans Petter Selasky 
1826b633e08cSHans Petter Selasky 		err = xa_insert(&event->object_ids,
1827b633e08cSHans Petter Selasky 				key_level2,
1828b633e08cSHans Petter Selasky 				obj_event,
1829b633e08cSHans Petter Selasky 				GFP_KERNEL);
1830b633e08cSHans Petter Selasky 		if (err)
1831b633e08cSHans Petter Selasky 			return err;
1832b633e08cSHans Petter Selasky 		INIT_LIST_HEAD(&obj_event->obj_sub_list);
1833b633e08cSHans Petter Selasky 	}
1834b633e08cSHans Petter Selasky 
1835b633e08cSHans Petter Selasky 	return 0;
1836b633e08cSHans Petter Selasky }
1837b633e08cSHans Petter Selasky 
is_valid_events_legacy(int num_events,u16 * event_type_num_list,struct devx_obj * obj)1838b633e08cSHans Petter Selasky static bool is_valid_events_legacy(int num_events, u16 *event_type_num_list,
1839b633e08cSHans Petter Selasky 				   struct devx_obj *obj)
1840b633e08cSHans Petter Selasky {
1841b633e08cSHans Petter Selasky 	int i;
1842b633e08cSHans Petter Selasky 
1843b633e08cSHans Petter Selasky 	for (i = 0; i < num_events; i++) {
1844b633e08cSHans Petter Selasky 		if (obj) {
1845b633e08cSHans Petter Selasky 			if (!is_legacy_obj_event_num(event_type_num_list[i]))
1846b633e08cSHans Petter Selasky 				return false;
1847b633e08cSHans Petter Selasky 		} else if (!is_legacy_unaffiliated_event_num(
1848b633e08cSHans Petter Selasky 				event_type_num_list[i])) {
1849b633e08cSHans Petter Selasky 			return false;
1850b633e08cSHans Petter Selasky 		}
1851b633e08cSHans Petter Selasky 	}
1852b633e08cSHans Petter Selasky 
1853b633e08cSHans Petter Selasky 	return true;
1854b633e08cSHans Petter Selasky }
1855b633e08cSHans Petter Selasky 
1856b633e08cSHans Petter Selasky #define MAX_SUPP_EVENT_NUM 255
is_valid_events(struct mlx5_core_dev * dev,int num_events,u16 * event_type_num_list,struct devx_obj * obj)1857b633e08cSHans Petter Selasky static bool is_valid_events(struct mlx5_core_dev *dev,
1858b633e08cSHans Petter Selasky 			    int num_events, u16 *event_type_num_list,
1859b633e08cSHans Petter Selasky 			    struct devx_obj *obj)
1860b633e08cSHans Petter Selasky {
1861b633e08cSHans Petter Selasky 	__be64 *aff_events;
1862b633e08cSHans Petter Selasky 	__be64 *unaff_events;
1863b633e08cSHans Petter Selasky 	int mask_entry;
1864b633e08cSHans Petter Selasky 	int mask_bit;
1865b633e08cSHans Petter Selasky 	int i;
1866b633e08cSHans Petter Selasky 
1867b633e08cSHans Petter Selasky 	if (MLX5_CAP_GEN(dev, event_cap)) {
1868b633e08cSHans Petter Selasky 		aff_events = (__be64 *)MLX5_CAP_DEV_EVENT(dev,
1869b633e08cSHans Petter Selasky 						user_affiliated_events);
1870b633e08cSHans Petter Selasky 		unaff_events = (__be64 *)MLX5_CAP_DEV_EVENT(dev,
1871b633e08cSHans Petter Selasky 						  user_unaffiliated_events);
1872b633e08cSHans Petter Selasky 	} else {
1873b633e08cSHans Petter Selasky 		return is_valid_events_legacy(num_events, event_type_num_list,
1874b633e08cSHans Petter Selasky 					      obj);
1875b633e08cSHans Petter Selasky 	}
1876b633e08cSHans Petter Selasky 
1877b633e08cSHans Petter Selasky 	for (i = 0; i < num_events; i++) {
1878b633e08cSHans Petter Selasky 		if (event_type_num_list[i] > MAX_SUPP_EVENT_NUM)
1879b633e08cSHans Petter Selasky 			return false;
1880b633e08cSHans Petter Selasky 
1881b633e08cSHans Petter Selasky 		mask_entry = event_type_num_list[i] / 64;
1882b633e08cSHans Petter Selasky 		mask_bit = event_type_num_list[i] % 64;
1883b633e08cSHans Petter Selasky 
1884b633e08cSHans Petter Selasky 		if (obj) {
1885b633e08cSHans Petter Selasky 			/* CQ completion */
1886b633e08cSHans Petter Selasky 			if (event_type_num_list[i] == 0)
1887b633e08cSHans Petter Selasky 				continue;
1888b633e08cSHans Petter Selasky 
1889b633e08cSHans Petter Selasky 			if (!(be64_to_cpu(aff_events[mask_entry]) &
1890b633e08cSHans Petter Selasky 					(1ull << mask_bit)))
1891b633e08cSHans Petter Selasky 				return false;
1892b633e08cSHans Petter Selasky 
1893b633e08cSHans Petter Selasky 			continue;
1894b633e08cSHans Petter Selasky 		}
1895b633e08cSHans Petter Selasky 
1896b633e08cSHans Petter Selasky 		if (!(be64_to_cpu(unaff_events[mask_entry]) &
1897b633e08cSHans Petter Selasky 				(1ull << mask_bit)))
1898b633e08cSHans Petter Selasky 			return false;
1899b633e08cSHans Petter Selasky 	}
1900b633e08cSHans Petter Selasky 
1901b633e08cSHans Petter Selasky 	return true;
1902b633e08cSHans Petter Selasky }
1903b633e08cSHans Petter Selasky 
1904b633e08cSHans Petter Selasky #define MAX_NUM_EVENTS 16
UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT)1905b633e08cSHans Petter Selasky static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT)(
1906b633e08cSHans Petter Selasky 	struct uverbs_attr_bundle *attrs)
1907b633e08cSHans Petter Selasky {
1908b633e08cSHans Petter Selasky 	struct ib_uobject *devx_uobj = uverbs_attr_get_uobject(
1909b633e08cSHans Petter Selasky 				attrs,
1910b633e08cSHans Petter Selasky 				MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_OBJ_HANDLE);
1911b633e08cSHans Petter Selasky 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
1912b633e08cSHans Petter Selasky 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
1913b633e08cSHans Petter Selasky 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
1914b633e08cSHans Petter Selasky 	struct ib_uobject *fd_uobj;
1915b633e08cSHans Petter Selasky 	struct devx_obj *obj = NULL;
1916b633e08cSHans Petter Selasky 	struct devx_async_event_file *ev_file;
1917b633e08cSHans Petter Selasky 	struct mlx5_devx_event_table *devx_event_table = &dev->devx_event_table;
1918b633e08cSHans Petter Selasky 	u16 *event_type_num_list;
1919b633e08cSHans Petter Selasky 	struct devx_event_subscription *event_sub, *tmp_sub;
1920b633e08cSHans Petter Selasky 	struct list_head sub_list;
1921b633e08cSHans Petter Selasky 	int redirect_fd;
1922b633e08cSHans Petter Selasky 	bool use_eventfd = false;
1923b633e08cSHans Petter Selasky 	int num_events;
1924b633e08cSHans Petter Selasky 	u16 obj_type = 0;
1925b633e08cSHans Petter Selasky 	u64 cookie = 0;
1926b633e08cSHans Petter Selasky 	u32 obj_id = 0;
1927b633e08cSHans Petter Selasky 	int err;
1928b633e08cSHans Petter Selasky 	int i;
1929b633e08cSHans Petter Selasky 
1930b633e08cSHans Petter Selasky 	if (!c->devx_uid)
1931b633e08cSHans Petter Selasky 		return -EINVAL;
1932b633e08cSHans Petter Selasky 
1933b633e08cSHans Petter Selasky 	if (!IS_ERR(devx_uobj)) {
1934b633e08cSHans Petter Selasky 		obj = (struct devx_obj *)devx_uobj->object;
1935b633e08cSHans Petter Selasky 		if (obj)
1936b633e08cSHans Petter Selasky 			obj_id = get_dec_obj_id(obj->obj_id);
1937b633e08cSHans Petter Selasky 	}
1938b633e08cSHans Petter Selasky 
1939b633e08cSHans Petter Selasky 	fd_uobj = uverbs_attr_get_uobject(attrs,
1940b633e08cSHans Petter Selasky 				MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_HANDLE);
1941b633e08cSHans Petter Selasky 	if (IS_ERR(fd_uobj))
1942b633e08cSHans Petter Selasky 		return PTR_ERR(fd_uobj);
1943b633e08cSHans Petter Selasky 
1944b633e08cSHans Petter Selasky 	ev_file = container_of(fd_uobj, struct devx_async_event_file,
1945b633e08cSHans Petter Selasky 			       uobj);
1946b633e08cSHans Petter Selasky 
1947b633e08cSHans Petter Selasky 	if (uverbs_attr_is_valid(attrs,
1948b633e08cSHans Petter Selasky 				 MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM)) {
1949b633e08cSHans Petter Selasky 		err = uverbs_copy_from(&redirect_fd, attrs,
1950b633e08cSHans Petter Selasky 			       MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM);
1951b633e08cSHans Petter Selasky 		if (err)
1952b633e08cSHans Petter Selasky 			return err;
1953b633e08cSHans Petter Selasky 
1954b633e08cSHans Petter Selasky 		use_eventfd = true;
1955b633e08cSHans Petter Selasky 	}
1956b633e08cSHans Petter Selasky 
1957b633e08cSHans Petter Selasky 	if (uverbs_attr_is_valid(attrs,
1958b633e08cSHans Petter Selasky 				 MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE)) {
1959b633e08cSHans Petter Selasky 		if (use_eventfd)
1960b633e08cSHans Petter Selasky 			return -EINVAL;
1961b633e08cSHans Petter Selasky 
1962b633e08cSHans Petter Selasky 		err = uverbs_copy_from(&cookie, attrs,
1963b633e08cSHans Petter Selasky 				MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE);
1964b633e08cSHans Petter Selasky 		if (err)
1965b633e08cSHans Petter Selasky 			return err;
1966b633e08cSHans Petter Selasky 	}
1967b633e08cSHans Petter Selasky 
1968b633e08cSHans Petter Selasky 	num_events = uverbs_attr_ptr_get_array_size(
1969b633e08cSHans Petter Selasky 		attrs, MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST,
1970b633e08cSHans Petter Selasky 		sizeof(u16));
1971b633e08cSHans Petter Selasky 
1972b633e08cSHans Petter Selasky 	if (num_events < 0)
1973b633e08cSHans Petter Selasky 		return num_events;
1974b633e08cSHans Petter Selasky 
1975b633e08cSHans Petter Selasky 	if (num_events > MAX_NUM_EVENTS)
1976b633e08cSHans Petter Selasky 		return -EINVAL;
1977b633e08cSHans Petter Selasky 
1978b633e08cSHans Petter Selasky 	event_type_num_list = uverbs_attr_get_alloced_ptr(attrs,
1979b633e08cSHans Petter Selasky 			MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST);
1980b633e08cSHans Petter Selasky 
1981b633e08cSHans Petter Selasky 	if (!is_valid_events(dev->mdev, num_events, event_type_num_list, obj))
1982b633e08cSHans Petter Selasky 		return -EINVAL;
1983b633e08cSHans Petter Selasky 
1984b633e08cSHans Petter Selasky 	INIT_LIST_HEAD(&sub_list);
1985b633e08cSHans Petter Selasky 
1986b633e08cSHans Petter Selasky 	/* Protect from concurrent subscriptions to same XA entries to allow
1987b633e08cSHans Petter Selasky 	 * both to succeed
1988b633e08cSHans Petter Selasky 	 */
1989b633e08cSHans Petter Selasky 	mutex_lock(&devx_event_table->event_xa_lock);
1990b633e08cSHans Petter Selasky 	for (i = 0; i < num_events; i++) {
1991b633e08cSHans Petter Selasky 		u32 key_level1;
1992b633e08cSHans Petter Selasky 
1993b633e08cSHans Petter Selasky 		if (obj)
1994b633e08cSHans Petter Selasky 			obj_type = get_dec_obj_type(obj,
1995b633e08cSHans Petter Selasky 						    event_type_num_list[i]);
1996b633e08cSHans Petter Selasky 		key_level1 = event_type_num_list[i] | obj_type << 16;
1997b633e08cSHans Petter Selasky 
1998b633e08cSHans Petter Selasky 		err = subscribe_event_xa_alloc(devx_event_table,
1999b633e08cSHans Petter Selasky 					       key_level1,
2000b633e08cSHans Petter Selasky 					       obj,
2001b633e08cSHans Petter Selasky 					       obj_id);
2002b633e08cSHans Petter Selasky 		if (err)
2003b633e08cSHans Petter Selasky 			goto err;
2004b633e08cSHans Petter Selasky 
2005b633e08cSHans Petter Selasky 		event_sub = kzalloc(sizeof(*event_sub), GFP_KERNEL);
2006b633e08cSHans Petter Selasky 		if (!event_sub)
2007b633e08cSHans Petter Selasky 			goto err;
2008b633e08cSHans Petter Selasky 
2009b633e08cSHans Petter Selasky 		list_add_tail(&event_sub->event_list, &sub_list);
2010b633e08cSHans Petter Selasky 		uverbs_uobject_get(&ev_file->uobj);
2011b633e08cSHans Petter Selasky 		if (use_eventfd) {
2012b633e08cSHans Petter Selasky 			event_sub->eventfd =
2013b633e08cSHans Petter Selasky 				fdget(redirect_fd);
2014b633e08cSHans Petter Selasky 
2015b633e08cSHans Petter Selasky 			if (event_sub->eventfd.file == NULL) {
2016b633e08cSHans Petter Selasky 				err = -EBADF;
2017b633e08cSHans Petter Selasky 				goto err;
2018b633e08cSHans Petter Selasky 			}
2019b633e08cSHans Petter Selasky 		}
2020b633e08cSHans Petter Selasky 
2021b633e08cSHans Petter Selasky 		event_sub->cookie = cookie;
2022b633e08cSHans Petter Selasky 		event_sub->ev_file = ev_file;
2023b633e08cSHans Petter Selasky 		/* May be needed upon cleanup the devx object/subscription */
2024b633e08cSHans Petter Selasky 		event_sub->xa_key_level1 = key_level1;
2025b633e08cSHans Petter Selasky 		event_sub->xa_key_level2 = obj_id;
2026b633e08cSHans Petter Selasky 		INIT_LIST_HEAD(&event_sub->obj_list);
2027b633e08cSHans Petter Selasky 	}
2028b633e08cSHans Petter Selasky 
2029b633e08cSHans Petter Selasky 	/* Once all the allocations and the XA data insertions were done we
2030b633e08cSHans Petter Selasky 	 * can go ahead and add all the subscriptions to the relevant lists
2031b633e08cSHans Petter Selasky 	 * without concern of a failure.
2032b633e08cSHans Petter Selasky 	 */
2033b633e08cSHans Petter Selasky 	list_for_each_entry_safe(event_sub, tmp_sub, &sub_list, event_list) {
2034b633e08cSHans Petter Selasky 		struct devx_event *event;
2035b633e08cSHans Petter Selasky 		struct devx_obj_event *obj_event;
2036b633e08cSHans Petter Selasky 
2037b633e08cSHans Petter Selasky 		list_del_init(&event_sub->event_list);
2038b633e08cSHans Petter Selasky 
2039b633e08cSHans Petter Selasky 		spin_lock_irq(&ev_file->lock);
2040b633e08cSHans Petter Selasky 		list_add_tail_rcu(&event_sub->file_list,
2041b633e08cSHans Petter Selasky 				  &ev_file->subscribed_events_list);
2042b633e08cSHans Petter Selasky 		spin_unlock_irq(&ev_file->lock);
2043b633e08cSHans Petter Selasky 
2044b633e08cSHans Petter Selasky 		event = xa_load(&devx_event_table->event_xa,
2045b633e08cSHans Petter Selasky 				event_sub->xa_key_level1);
2046b633e08cSHans Petter Selasky 		WARN_ON(!event);
2047b633e08cSHans Petter Selasky 
2048b633e08cSHans Petter Selasky 		if (!obj) {
2049b633e08cSHans Petter Selasky 			list_add_tail_rcu(&event_sub->xa_list,
2050b633e08cSHans Petter Selasky 					  &event->unaffiliated_list);
2051b633e08cSHans Petter Selasky 			continue;
2052b633e08cSHans Petter Selasky 		}
2053b633e08cSHans Petter Selasky 
2054b633e08cSHans Petter Selasky 		obj_event = xa_load(&event->object_ids, obj_id);
2055b633e08cSHans Petter Selasky 		WARN_ON(!obj_event);
2056b633e08cSHans Petter Selasky 		list_add_tail_rcu(&event_sub->xa_list,
2057b633e08cSHans Petter Selasky 				  &obj_event->obj_sub_list);
2058b633e08cSHans Petter Selasky 		list_add_tail_rcu(&event_sub->obj_list,
2059b633e08cSHans Petter Selasky 				  &obj->event_sub);
2060b633e08cSHans Petter Selasky 	}
2061b633e08cSHans Petter Selasky 
2062b633e08cSHans Petter Selasky 	mutex_unlock(&devx_event_table->event_xa_lock);
2063b633e08cSHans Petter Selasky 	return 0;
2064b633e08cSHans Petter Selasky 
2065b633e08cSHans Petter Selasky err:
2066b633e08cSHans Petter Selasky 	list_for_each_entry_safe(event_sub, tmp_sub, &sub_list, event_list) {
2067b633e08cSHans Petter Selasky 		list_del(&event_sub->event_list);
2068b633e08cSHans Petter Selasky 
2069b633e08cSHans Petter Selasky 		subscribe_event_xa_dealloc(devx_event_table,
2070b633e08cSHans Petter Selasky 					   event_sub->xa_key_level1,
2071b633e08cSHans Petter Selasky 					   obj,
2072b633e08cSHans Petter Selasky 					   obj_id);
2073b633e08cSHans Petter Selasky 
2074b633e08cSHans Petter Selasky 		if (event_sub->eventfd.file)
2075b633e08cSHans Petter Selasky 			fdput(event_sub->eventfd);
2076b633e08cSHans Petter Selasky 		uverbs_uobject_put(&event_sub->ev_file->uobj);
2077b633e08cSHans Petter Selasky 		kfree(event_sub);
2078b633e08cSHans Petter Selasky 	}
2079b633e08cSHans Petter Selasky 
2080b633e08cSHans Petter Selasky 	mutex_unlock(&devx_event_table->event_xa_lock);
2081b633e08cSHans Petter Selasky 	return err;
2082b633e08cSHans Petter Selasky }
2083b633e08cSHans Petter Selasky 
devx_umem_get(struct mlx5_ib_dev * dev,struct ib_ucontext * ucontext,struct uverbs_attr_bundle * attrs,struct devx_umem * obj)2084b633e08cSHans Petter Selasky static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext,
2085b633e08cSHans Petter Selasky 			 struct uverbs_attr_bundle *attrs,
2086b633e08cSHans Petter Selasky 			 struct devx_umem *obj)
2087b633e08cSHans Petter Selasky {
2088b633e08cSHans Petter Selasky 	u64 addr;
2089b633e08cSHans Petter Selasky 	size_t size;
2090b633e08cSHans Petter Selasky 	u32 access;
2091b633e08cSHans Petter Selasky 	int npages;
2092b633e08cSHans Petter Selasky 	int err;
2093b633e08cSHans Petter Selasky 	u32 page_mask;
2094b633e08cSHans Petter Selasky 
2095b633e08cSHans Petter Selasky 	if (uverbs_copy_from(&addr, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR) ||
2096b633e08cSHans Petter Selasky 	    uverbs_copy_from(&size, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_LEN))
2097b633e08cSHans Petter Selasky 		return -EFAULT;
2098b633e08cSHans Petter Selasky 
2099b633e08cSHans Petter Selasky 	err = uverbs_get_flags32(&access, attrs,
2100b633e08cSHans Petter Selasky 				 MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
2101b633e08cSHans Petter Selasky 				 IB_ACCESS_LOCAL_WRITE |
2102b633e08cSHans Petter Selasky 				 IB_ACCESS_REMOTE_WRITE |
2103b633e08cSHans Petter Selasky 				 IB_ACCESS_REMOTE_READ);
2104b633e08cSHans Petter Selasky 	if (err)
2105b633e08cSHans Petter Selasky 		return err;
2106b633e08cSHans Petter Selasky 
2107b633e08cSHans Petter Selasky 	err = ib_check_mr_access(access);
2108b633e08cSHans Petter Selasky 	if (err)
2109b633e08cSHans Petter Selasky 		return err;
2110b633e08cSHans Petter Selasky 
2111b633e08cSHans Petter Selasky 	obj->umem = ib_umem_get(ucontext, addr, size, access, 0);
2112b633e08cSHans Petter Selasky 	if (IS_ERR(obj->umem))
2113b633e08cSHans Petter Selasky 		return PTR_ERR(obj->umem);
2114b633e08cSHans Petter Selasky 
2115b633e08cSHans Petter Selasky 	mlx5_ib_cont_pages(obj->umem, obj->umem->address,
2116b633e08cSHans Petter Selasky 			   MLX5_MKEY_PAGE_SHIFT_MASK, &npages,
2117b633e08cSHans Petter Selasky 			   &obj->page_shift, &obj->ncont, NULL);
2118b633e08cSHans Petter Selasky 
2119b633e08cSHans Petter Selasky 	if (!npages) {
2120b633e08cSHans Petter Selasky 		ib_umem_release(obj->umem);
2121b633e08cSHans Petter Selasky 		return -EINVAL;
2122b633e08cSHans Petter Selasky 	}
2123b633e08cSHans Petter Selasky 
2124b633e08cSHans Petter Selasky 	page_mask = (1 << obj->page_shift) - 1;
2125b633e08cSHans Petter Selasky 	obj->page_offset = obj->umem->address & page_mask;
2126b633e08cSHans Petter Selasky 
2127b633e08cSHans Petter Selasky 	return 0;
2128b633e08cSHans Petter Selasky }
2129b633e08cSHans Petter Selasky 
devx_umem_reg_cmd_alloc(struct uverbs_attr_bundle * attrs,struct devx_umem * obj,struct devx_umem_reg_cmd * cmd)2130b633e08cSHans Petter Selasky static int devx_umem_reg_cmd_alloc(struct uverbs_attr_bundle *attrs,
2131b633e08cSHans Petter Selasky 				   struct devx_umem *obj,
2132b633e08cSHans Petter Selasky 				   struct devx_umem_reg_cmd *cmd)
2133b633e08cSHans Petter Selasky {
2134b633e08cSHans Petter Selasky 	cmd->inlen = MLX5_ST_SZ_BYTES(create_umem_in) +
2135b633e08cSHans Petter Selasky 		    (MLX5_ST_SZ_BYTES(mtt) * obj->ncont);
2136b633e08cSHans Petter Selasky 	cmd->in = uverbs_zalloc(attrs, cmd->inlen);
2137b633e08cSHans Petter Selasky 	return PTR_ERR_OR_ZERO(cmd->in);
2138b633e08cSHans Petter Selasky }
2139b633e08cSHans Petter Selasky 
devx_umem_reg_cmd_build(struct mlx5_ib_dev * dev,struct devx_umem * obj,struct devx_umem_reg_cmd * cmd)2140b633e08cSHans Petter Selasky static void devx_umem_reg_cmd_build(struct mlx5_ib_dev *dev,
2141b633e08cSHans Petter Selasky 				    struct devx_umem *obj,
2142b633e08cSHans Petter Selasky 				    struct devx_umem_reg_cmd *cmd)
2143b633e08cSHans Petter Selasky {
2144b633e08cSHans Petter Selasky 	void *umem;
2145b633e08cSHans Petter Selasky 	__be64 *mtt;
2146b633e08cSHans Petter Selasky 
2147b633e08cSHans Petter Selasky 	umem = MLX5_ADDR_OF(create_umem_in, cmd->in, umem);
2148b633e08cSHans Petter Selasky 	mtt = (__be64 *)MLX5_ADDR_OF(umem, umem, mtt);
2149b633e08cSHans Petter Selasky 
2150b633e08cSHans Petter Selasky 	MLX5_SET(create_umem_in, cmd->in, opcode, MLX5_CMD_OP_CREATE_UMEM);
2151b633e08cSHans Petter Selasky 	MLX5_SET64(umem, umem, num_of_mtt, obj->ncont);
2152b633e08cSHans Petter Selasky 	MLX5_SET(umem, umem, log_page_size, obj->page_shift -
2153b633e08cSHans Petter Selasky 					    MLX5_ADAPTER_PAGE_SHIFT);
2154b633e08cSHans Petter Selasky 	MLX5_SET(umem, umem, page_offset, obj->page_offset);
2155b633e08cSHans Petter Selasky 	mlx5_ib_populate_pas(dev, obj->umem, obj->page_shift, mtt,
2156b633e08cSHans Petter Selasky 			     (obj->umem->writable ? MLX5_IB_MTT_WRITE : 0) |
2157b633e08cSHans Petter Selasky 			     MLX5_IB_MTT_READ);
2158b633e08cSHans Petter Selasky }
2159b633e08cSHans Petter Selasky 
UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_REG)2160b633e08cSHans Petter Selasky static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_REG)(
2161b633e08cSHans Petter Selasky 	struct uverbs_attr_bundle *attrs)
2162b633e08cSHans Petter Selasky {
2163b633e08cSHans Petter Selasky 	struct devx_umem_reg_cmd cmd;
2164b633e08cSHans Petter Selasky 	struct devx_umem *obj;
2165b633e08cSHans Petter Selasky 	struct ib_uobject *uobj = uverbs_attr_get_uobject(
2166b633e08cSHans Petter Selasky 		attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE);
2167b633e08cSHans Petter Selasky 	u32 obj_id;
2168b633e08cSHans Petter Selasky 	struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
2169b633e08cSHans Petter Selasky 		&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
2170b633e08cSHans Petter Selasky 	struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
2171b633e08cSHans Petter Selasky 	int err;
2172b633e08cSHans Petter Selasky 
2173b633e08cSHans Petter Selasky 	if (!c->devx_uid)
2174b633e08cSHans Petter Selasky 		return -EINVAL;
2175b633e08cSHans Petter Selasky 
2176b633e08cSHans Petter Selasky 	obj = kzalloc(sizeof(struct devx_umem), GFP_KERNEL);
2177b633e08cSHans Petter Selasky 	if (!obj)
2178b633e08cSHans Petter Selasky 		return -ENOMEM;
2179b633e08cSHans Petter Selasky 
2180b633e08cSHans Petter Selasky 	err = devx_umem_get(dev, &c->ibucontext, attrs, obj);
2181b633e08cSHans Petter Selasky 	if (err)
2182b633e08cSHans Petter Selasky 		goto err_obj_free;
2183b633e08cSHans Petter Selasky 
2184b633e08cSHans Petter Selasky 	err = devx_umem_reg_cmd_alloc(attrs, obj, &cmd);
2185b633e08cSHans Petter Selasky 	if (err)
2186b633e08cSHans Petter Selasky 		goto err_umem_release;
2187b633e08cSHans Petter Selasky 
2188b633e08cSHans Petter Selasky 	devx_umem_reg_cmd_build(dev, obj, &cmd);
2189b633e08cSHans Petter Selasky 
2190b633e08cSHans Petter Selasky 	MLX5_SET(create_umem_in, cmd.in, uid, c->devx_uid);
2191b633e08cSHans Petter Selasky 	err = mlx5_cmd_exec(dev->mdev, cmd.in, cmd.inlen, cmd.out,
2192b633e08cSHans Petter Selasky 			    sizeof(cmd.out));
2193b633e08cSHans Petter Selasky 	if (err)
2194b633e08cSHans Petter Selasky 		goto err_umem_release;
2195b633e08cSHans Petter Selasky 
2196b633e08cSHans Petter Selasky 	obj->mdev = dev->mdev;
2197b633e08cSHans Petter Selasky 	uobj->object = obj;
2198b633e08cSHans Petter Selasky 	devx_obj_build_destroy_cmd(cmd.in, cmd.out, obj->dinbox, &obj->dinlen, &obj_id);
2199b633e08cSHans Petter Selasky 	err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, &obj_id, sizeof(obj_id));
2200b633e08cSHans Petter Selasky 	if (err)
2201b633e08cSHans Petter Selasky 		goto err_umem_destroy;
2202b633e08cSHans Petter Selasky 
2203b633e08cSHans Petter Selasky 	return 0;
2204b633e08cSHans Petter Selasky 
2205b633e08cSHans Petter Selasky err_umem_destroy:
2206b633e08cSHans Petter Selasky 	mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, cmd.out, sizeof(cmd.out));
2207b633e08cSHans Petter Selasky err_umem_release:
2208b633e08cSHans Petter Selasky 	ib_umem_release(obj->umem);
2209b633e08cSHans Petter Selasky err_obj_free:
2210b633e08cSHans Petter Selasky 	kfree(obj);
2211b633e08cSHans Petter Selasky 	return err;
2212b633e08cSHans Petter Selasky }
2213b633e08cSHans Petter Selasky 
devx_umem_cleanup(struct ib_uobject * uobject,enum rdma_remove_reason why,struct uverbs_attr_bundle * attrs)2214b633e08cSHans Petter Selasky static int devx_umem_cleanup(struct ib_uobject *uobject,
2215b633e08cSHans Petter Selasky 			     enum rdma_remove_reason why,
2216b633e08cSHans Petter Selasky 			     struct uverbs_attr_bundle *attrs)
2217b633e08cSHans Petter Selasky {
2218b633e08cSHans Petter Selasky 	struct devx_umem *obj = uobject->object;
2219b633e08cSHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
2220b633e08cSHans Petter Selasky 	int err;
2221b633e08cSHans Petter Selasky 
2222b633e08cSHans Petter Selasky 	err = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out));
2223b633e08cSHans Petter Selasky 	if (ib_is_destroy_retryable(err, why, uobject))
2224b633e08cSHans Petter Selasky 		return err;
2225b633e08cSHans Petter Selasky 
2226b633e08cSHans Petter Selasky 	ib_umem_release(obj->umem);
2227b633e08cSHans Petter Selasky 	kfree(obj);
2228b633e08cSHans Petter Selasky 	return 0;
2229b633e08cSHans Petter Selasky }
2230b633e08cSHans Petter Selasky 
is_unaffiliated_event(struct mlx5_core_dev * dev,unsigned long event_type)2231b633e08cSHans Petter Selasky static bool is_unaffiliated_event(struct mlx5_core_dev *dev,
2232b633e08cSHans Petter Selasky 				  unsigned long event_type)
2233b633e08cSHans Petter Selasky {
2234b633e08cSHans Petter Selasky 	__be64 *unaff_events;
2235b633e08cSHans Petter Selasky 	int mask_entry;
2236b633e08cSHans Petter Selasky 	int mask_bit;
2237b633e08cSHans Petter Selasky 
2238b633e08cSHans Petter Selasky 	if (!MLX5_CAP_GEN(dev, event_cap))
2239b633e08cSHans Petter Selasky 		return is_legacy_unaffiliated_event_num(event_type);
2240b633e08cSHans Petter Selasky 
2241b633e08cSHans Petter Selasky 	unaff_events = (__be64 *)MLX5_CAP_DEV_EVENT(dev,
2242b633e08cSHans Petter Selasky 					  user_unaffiliated_events);
2243b633e08cSHans Petter Selasky 	WARN_ON(event_type > MAX_SUPP_EVENT_NUM);
2244b633e08cSHans Petter Selasky 
2245b633e08cSHans Petter Selasky 	mask_entry = event_type / 64;
2246b633e08cSHans Petter Selasky 	mask_bit = event_type % 64;
2247b633e08cSHans Petter Selasky 
2248b633e08cSHans Petter Selasky 	if (!(be64_to_cpu(unaff_events[mask_entry]) & (1ull << mask_bit)))
2249b633e08cSHans Petter Selasky 		return false;
2250b633e08cSHans Petter Selasky 
2251b633e08cSHans Petter Selasky 	return true;
2252b633e08cSHans Petter Selasky }
2253b633e08cSHans Petter Selasky 
devx_get_obj_id_from_event(unsigned long event_type,void * data)2254b633e08cSHans Petter Selasky static u32 devx_get_obj_id_from_event(unsigned long event_type, void *data)
2255b633e08cSHans Petter Selasky {
2256b633e08cSHans Petter Selasky 	struct mlx5_eqe *eqe = data;
2257b633e08cSHans Petter Selasky 	u32 obj_id = 0;
2258b633e08cSHans Petter Selasky 
2259b633e08cSHans Petter Selasky 	switch (event_type) {
2260b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_SRQ_CATAS_ERROR:
2261b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_SRQ_RQ_LIMIT:
2262b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_PATH_MIG:
2263b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_COMM_EST:
2264b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_SQ_DRAINED:
2265b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_SRQ_LAST_WQE:
2266b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_WQ_CATAS_ERROR:
2267b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_PATH_MIG_FAILED:
2268b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR:
2269b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR:
2270b633e08cSHans Petter Selasky 		obj_id = be32_to_cpu(eqe->data.qp_srq.qp_srq_n) & 0xffffff;
2271b633e08cSHans Petter Selasky 		break;
2272b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_XRQ_ERROR:
2273b633e08cSHans Petter Selasky 		obj_id = be32_to_cpu(eqe->data.xrq_err.type_xrqn) & 0xffffff;
2274b633e08cSHans Petter Selasky 		break;
2275b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_DCT_DRAINED:
2276b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_DCT_KEY_VIOLATION:
2277b633e08cSHans Petter Selasky 		obj_id = be32_to_cpu(eqe->data.dct.dctn) & 0xffffff;
2278b633e08cSHans Petter Selasky 		break;
2279b633e08cSHans Petter Selasky 	case MLX5_EVENT_TYPE_CQ_ERROR:
2280b633e08cSHans Petter Selasky 		obj_id = be32_to_cpu(eqe->data.cq_err.cqn) & 0xffffff;
2281b633e08cSHans Petter Selasky 		break;
2282b633e08cSHans Petter Selasky 	default:
2283b633e08cSHans Petter Selasky 		obj_id = MLX5_GET(affiliated_event_header, &eqe->data, obj_id);
2284b633e08cSHans Petter Selasky 		break;
2285b633e08cSHans Petter Selasky 	}
2286b633e08cSHans Petter Selasky 
2287b633e08cSHans Petter Selasky 	return obj_id;
2288b633e08cSHans Petter Selasky }
2289b633e08cSHans Petter Selasky 
deliver_event(struct devx_event_subscription * event_sub,const void * data)2290b633e08cSHans Petter Selasky static int deliver_event(struct devx_event_subscription *event_sub,
2291b633e08cSHans Petter Selasky 			 const void *data)
2292b633e08cSHans Petter Selasky {
2293b633e08cSHans Petter Selasky 	struct devx_async_event_file *ev_file;
2294b633e08cSHans Petter Selasky 	struct devx_async_event_data *event_data;
2295b633e08cSHans Petter Selasky 	unsigned long flags;
2296b633e08cSHans Petter Selasky 
2297b633e08cSHans Petter Selasky 	ev_file = event_sub->ev_file;
2298b633e08cSHans Petter Selasky 
2299b633e08cSHans Petter Selasky 	if (ev_file->omit_data) {
2300b633e08cSHans Petter Selasky 		spin_lock_irqsave(&ev_file->lock, flags);
2301b633e08cSHans Petter Selasky 		if (!list_empty(&event_sub->event_list) ||
2302b633e08cSHans Petter Selasky 		    ev_file->is_destroyed) {
2303b633e08cSHans Petter Selasky 			spin_unlock_irqrestore(&ev_file->lock, flags);
2304b633e08cSHans Petter Selasky 			return 0;
2305b633e08cSHans Petter Selasky 		}
2306b633e08cSHans Petter Selasky 
2307b633e08cSHans Petter Selasky 		list_add_tail(&event_sub->event_list, &ev_file->event_list);
2308b633e08cSHans Petter Selasky 		spin_unlock_irqrestore(&ev_file->lock, flags);
2309b633e08cSHans Petter Selasky 		wake_up_interruptible(&ev_file->poll_wait);
2310b633e08cSHans Petter Selasky 		return 0;
2311b633e08cSHans Petter Selasky 	}
2312b633e08cSHans Petter Selasky 
2313b633e08cSHans Petter Selasky 	event_data = kzalloc(sizeof(*event_data) + sizeof(struct mlx5_eqe),
2314b633e08cSHans Petter Selasky 			     GFP_ATOMIC);
2315b633e08cSHans Petter Selasky 	if (!event_data) {
2316b633e08cSHans Petter Selasky 		spin_lock_irqsave(&ev_file->lock, flags);
2317b633e08cSHans Petter Selasky 		ev_file->is_overflow_err = 1;
2318b633e08cSHans Petter Selasky 		spin_unlock_irqrestore(&ev_file->lock, flags);
2319b633e08cSHans Petter Selasky 		return -ENOMEM;
2320b633e08cSHans Petter Selasky 	}
2321b633e08cSHans Petter Selasky 
2322b633e08cSHans Petter Selasky 	event_data->hdr.cookie = event_sub->cookie;
2323b633e08cSHans Petter Selasky 	memcpy(event_data->hdr.out_data, data, sizeof(struct mlx5_eqe));
2324b633e08cSHans Petter Selasky 
2325b633e08cSHans Petter Selasky 	spin_lock_irqsave(&ev_file->lock, flags);
2326b633e08cSHans Petter Selasky 	if (!ev_file->is_destroyed)
2327b633e08cSHans Petter Selasky 		list_add_tail(&event_data->list, &ev_file->event_list);
2328b633e08cSHans Petter Selasky 	else
2329b633e08cSHans Petter Selasky 		kfree(event_data);
2330b633e08cSHans Petter Selasky 	spin_unlock_irqrestore(&ev_file->lock, flags);
2331b633e08cSHans Petter Selasky 	wake_up_interruptible(&ev_file->poll_wait);
2332b633e08cSHans Petter Selasky 
2333b633e08cSHans Petter Selasky 	return 0;
2334b633e08cSHans Petter Selasky }
2335b633e08cSHans Petter Selasky 
dispatch_event_fd(struct list_head * fd_list,const void * data)2336b633e08cSHans Petter Selasky static void dispatch_event_fd(struct list_head *fd_list,
2337b633e08cSHans Petter Selasky 			      const void *data)
2338b633e08cSHans Petter Selasky {
2339b633e08cSHans Petter Selasky 	struct devx_event_subscription *item;
2340b633e08cSHans Petter Selasky 
2341b633e08cSHans Petter Selasky 	list_for_each_entry_rcu(item, fd_list, xa_list) {
2342b633e08cSHans Petter Selasky 		if (item->eventfd.file != NULL)
2343b633e08cSHans Petter Selasky 			linux_poll_wakeup(item->eventfd.file);
2344b633e08cSHans Petter Selasky 		else
2345b633e08cSHans Petter Selasky 			deliver_event(item, data);
2346b633e08cSHans Petter Selasky 	}
2347b633e08cSHans Petter Selasky }
2348b633e08cSHans Petter Selasky 
mlx5_devx_event_notifier(struct mlx5_core_dev * mdev,uint8_t event_type,void * data)2349b633e08cSHans Petter Selasky static bool mlx5_devx_event_notifier(struct mlx5_core_dev *mdev,
2350b633e08cSHans Petter Selasky 				     uint8_t event_type, void *data)
2351b633e08cSHans Petter Selasky {
2352b633e08cSHans Petter Selasky 	struct mlx5_ib_dev *dev;
2353b633e08cSHans Petter Selasky 	struct mlx5_devx_event_table *table;
2354b633e08cSHans Petter Selasky 	struct devx_event *event;
2355b633e08cSHans Petter Selasky 	struct devx_obj_event *obj_event;
2356b633e08cSHans Petter Selasky 	u16 obj_type = 0;
2357b633e08cSHans Petter Selasky 	bool is_unaffiliated;
2358b633e08cSHans Petter Selasky 	u32 obj_id;
2359b633e08cSHans Petter Selasky 
2360b633e08cSHans Petter Selasky 	/* Explicit filtering to kernel events which may occur frequently */
2361b633e08cSHans Petter Selasky 	if (event_type == MLX5_EVENT_TYPE_CMD ||
2362b633e08cSHans Petter Selasky 	    event_type == MLX5_EVENT_TYPE_PAGE_REQUEST)
2363b633e08cSHans Petter Selasky 		return true;
2364b633e08cSHans Petter Selasky 
2365b633e08cSHans Petter Selasky 	dev = mdev->priv.eq_table.dev;
2366b633e08cSHans Petter Selasky 	table = &dev->devx_event_table;
2367b633e08cSHans Petter Selasky 	is_unaffiliated = is_unaffiliated_event(dev->mdev, event_type);
2368b633e08cSHans Petter Selasky 
2369b633e08cSHans Petter Selasky 	if (!is_unaffiliated)
2370b633e08cSHans Petter Selasky 		obj_type = get_event_obj_type(event_type, data);
2371b633e08cSHans Petter Selasky 
2372b633e08cSHans Petter Selasky 	rcu_read_lock();
2373b633e08cSHans Petter Selasky 	event = xa_load(&table->event_xa, event_type | (obj_type << 16));
2374b633e08cSHans Petter Selasky 	if (!event) {
2375b633e08cSHans Petter Selasky 		rcu_read_unlock();
2376b633e08cSHans Petter Selasky 		return false;
2377b633e08cSHans Petter Selasky 	}
2378b633e08cSHans Petter Selasky 
2379b633e08cSHans Petter Selasky 	if (is_unaffiliated) {
2380b633e08cSHans Petter Selasky 		dispatch_event_fd(&event->unaffiliated_list, data);
2381b633e08cSHans Petter Selasky 		rcu_read_unlock();
2382b633e08cSHans Petter Selasky 		return true;
2383b633e08cSHans Petter Selasky 	}
2384b633e08cSHans Petter Selasky 
2385b633e08cSHans Petter Selasky 	obj_id = devx_get_obj_id_from_event(event_type, data);
2386b633e08cSHans Petter Selasky 	obj_event = xa_load(&event->object_ids, obj_id);
2387b633e08cSHans Petter Selasky 	if (!obj_event) {
2388b633e08cSHans Petter Selasky 		rcu_read_unlock();
2389b633e08cSHans Petter Selasky 		return false;
2390b633e08cSHans Petter Selasky 	}
2391b633e08cSHans Petter Selasky 
2392b633e08cSHans Petter Selasky 	dispatch_event_fd(&obj_event->obj_sub_list, data);
2393b633e08cSHans Petter Selasky 
2394b633e08cSHans Petter Selasky 	rcu_read_unlock();
2395b633e08cSHans Petter Selasky 	return true;
2396b633e08cSHans Petter Selasky }
2397b633e08cSHans Petter Selasky 
mlx5_ib_devx_init_event_table(struct mlx5_ib_dev * dev)2398b633e08cSHans Petter Selasky void mlx5_ib_devx_init_event_table(struct mlx5_ib_dev *dev)
2399b633e08cSHans Petter Selasky {
2400b633e08cSHans Petter Selasky 	struct mlx5_devx_event_table *table = &dev->devx_event_table;
2401b633e08cSHans Petter Selasky 
2402b633e08cSHans Petter Selasky 	xa_init_flags(&table->event_xa, 0);
2403b633e08cSHans Petter Selasky 	mutex_init(&table->event_xa_lock);
2404b633e08cSHans Petter Selasky 	dev->mdev->priv.eq_table.dev = dev;
2405b633e08cSHans Petter Selasky 	dev->mdev->priv.eq_table.cb = mlx5_devx_event_notifier;
2406b633e08cSHans Petter Selasky }
2407b633e08cSHans Petter Selasky 
mlx5_ib_devx_cleanup_event_table(struct mlx5_ib_dev * dev)2408b633e08cSHans Petter Selasky void mlx5_ib_devx_cleanup_event_table(struct mlx5_ib_dev *dev)
2409b633e08cSHans Petter Selasky {
2410b633e08cSHans Petter Selasky 	struct mlx5_devx_event_table *table = &dev->devx_event_table;
2411b633e08cSHans Petter Selasky 	struct devx_event_subscription *sub, *tmp;
2412b633e08cSHans Petter Selasky 	struct devx_event *event;
2413b633e08cSHans Petter Selasky 	void *entry;
2414b633e08cSHans Petter Selasky 	unsigned long id;
2415b633e08cSHans Petter Selasky 
2416b633e08cSHans Petter Selasky 	dev->mdev->priv.eq_table.cb = NULL;
2417b633e08cSHans Petter Selasky 	dev->mdev->priv.eq_table.dev = NULL;
2418b633e08cSHans Petter Selasky 	mutex_lock(&dev->devx_event_table.event_xa_lock);
2419b633e08cSHans Petter Selasky 	xa_for_each(&table->event_xa, id, entry) {
2420b633e08cSHans Petter Selasky 		event = entry;
2421b633e08cSHans Petter Selasky 		list_for_each_entry_safe(sub, tmp, &event->unaffiliated_list,
2422b633e08cSHans Petter Selasky 					 xa_list)
2423b633e08cSHans Petter Selasky 			devx_cleanup_subscription(dev, sub);
2424b633e08cSHans Petter Selasky 		kfree(entry);
2425b633e08cSHans Petter Selasky 	}
2426b633e08cSHans Petter Selasky 	mutex_unlock(&dev->devx_event_table.event_xa_lock);
2427b633e08cSHans Petter Selasky 	xa_destroy(&table->event_xa);
2428b633e08cSHans Petter Selasky }
2429b633e08cSHans Petter Selasky 
devx_async_cmd_event_read(struct file * filp,char __user * buf,size_t count,loff_t * pos)2430b633e08cSHans Petter Selasky static ssize_t devx_async_cmd_event_read(struct file *filp, char __user *buf,
2431b633e08cSHans Petter Selasky 					 size_t count, loff_t *pos)
2432b633e08cSHans Petter Selasky {
2433b633e08cSHans Petter Selasky 	struct devx_async_cmd_event_file *comp_ev_file = filp->private_data;
2434b633e08cSHans Petter Selasky 	struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue;
2435b633e08cSHans Petter Selasky 	struct devx_async_data *event;
2436b633e08cSHans Petter Selasky 	int ret = 0;
2437b633e08cSHans Petter Selasky 	size_t eventsz;
2438b633e08cSHans Petter Selasky 
2439b633e08cSHans Petter Selasky 	spin_lock_irq(&ev_queue->lock);
2440b633e08cSHans Petter Selasky 
2441b633e08cSHans Petter Selasky 	while (list_empty(&ev_queue->event_list)) {
2442b633e08cSHans Petter Selasky 		spin_unlock_irq(&ev_queue->lock);
2443b633e08cSHans Petter Selasky 
2444b633e08cSHans Petter Selasky 		if (filp->f_flags & O_NONBLOCK)
2445b633e08cSHans Petter Selasky 			return -EAGAIN;
2446b633e08cSHans Petter Selasky 
2447b633e08cSHans Petter Selasky 		if (wait_event_interruptible(
2448b633e08cSHans Petter Selasky 			    ev_queue->poll_wait,
2449b633e08cSHans Petter Selasky 			    (!list_empty(&ev_queue->event_list) ||
2450b633e08cSHans Petter Selasky 			     ev_queue->is_destroyed))) {
2451b633e08cSHans Petter Selasky 			return -ERESTARTSYS;
2452b633e08cSHans Petter Selasky 		}
2453b633e08cSHans Petter Selasky 
2454b633e08cSHans Petter Selasky 		spin_lock_irq(&ev_queue->lock);
2455b633e08cSHans Petter Selasky 		if (ev_queue->is_destroyed) {
2456b633e08cSHans Petter Selasky 			spin_unlock_irq(&ev_queue->lock);
2457b633e08cSHans Petter Selasky 			return -EIO;
2458b633e08cSHans Petter Selasky 		}
2459b633e08cSHans Petter Selasky 	}
2460b633e08cSHans Petter Selasky 
2461b633e08cSHans Petter Selasky 	event = list_entry(ev_queue->event_list.next,
2462b633e08cSHans Petter Selasky 			   struct devx_async_data, list);
2463b633e08cSHans Petter Selasky 	eventsz = event->cmd_out_len +
2464b633e08cSHans Petter Selasky 			sizeof(struct mlx5_ib_uapi_devx_async_cmd_hdr);
2465b633e08cSHans Petter Selasky 
2466b633e08cSHans Petter Selasky 	if (eventsz > count) {
2467b633e08cSHans Petter Selasky 		spin_unlock_irq(&ev_queue->lock);
2468b633e08cSHans Petter Selasky 		return -ENOSPC;
2469b633e08cSHans Petter Selasky 	}
2470b633e08cSHans Petter Selasky 
2471b633e08cSHans Petter Selasky 	list_del(ev_queue->event_list.next);
2472b633e08cSHans Petter Selasky 	spin_unlock_irq(&ev_queue->lock);
2473b633e08cSHans Petter Selasky 
2474b633e08cSHans Petter Selasky 	if (copy_to_user(buf, &event->hdr, eventsz))
2475b633e08cSHans Petter Selasky 		ret = -EFAULT;
2476b633e08cSHans Petter Selasky 	else
2477b633e08cSHans Petter Selasky 		ret = eventsz;
2478b633e08cSHans Petter Selasky 
2479b633e08cSHans Petter Selasky 	atomic_sub(event->cmd_out_len, &ev_queue->bytes_in_use);
2480b633e08cSHans Petter Selasky 	kvfree(event);
2481b633e08cSHans Petter Selasky 	return ret;
2482b633e08cSHans Petter Selasky }
2483b633e08cSHans Petter Selasky 
devx_async_cmd_event_poll(struct file * filp,struct poll_table_struct * wait)2484b633e08cSHans Petter Selasky static __poll_t devx_async_cmd_event_poll(struct file *filp,
2485b633e08cSHans Petter Selasky 					  struct poll_table_struct *wait)
2486b633e08cSHans Petter Selasky {
2487b633e08cSHans Petter Selasky 	struct devx_async_cmd_event_file *comp_ev_file = filp->private_data;
2488b633e08cSHans Petter Selasky 	struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue;
2489b633e08cSHans Petter Selasky 	__poll_t pollflags = 0;
2490b633e08cSHans Petter Selasky 
2491b633e08cSHans Petter Selasky 	poll_wait(filp, &ev_queue->poll_wait, wait);
2492b633e08cSHans Petter Selasky 
2493b633e08cSHans Petter Selasky 	spin_lock_irq(&ev_queue->lock);
2494b633e08cSHans Petter Selasky 	if (ev_queue->is_destroyed)
2495b633e08cSHans Petter Selasky 		pollflags = POLLIN | POLLRDNORM | POLLHUP;
2496b633e08cSHans Petter Selasky 	else if (!list_empty(&ev_queue->event_list))
2497b633e08cSHans Petter Selasky 		pollflags = POLLIN | POLLRDNORM;
2498b633e08cSHans Petter Selasky 	spin_unlock_irq(&ev_queue->lock);
2499b633e08cSHans Petter Selasky 
2500b633e08cSHans Petter Selasky 	return pollflags;
2501b633e08cSHans Petter Selasky }
2502b633e08cSHans Petter Selasky 
2503b633e08cSHans Petter Selasky static const struct file_operations devx_async_cmd_event_fops = {
2504b633e08cSHans Petter Selasky 	.owner	 = THIS_MODULE,
2505b633e08cSHans Petter Selasky 	.read	 = devx_async_cmd_event_read,
2506b633e08cSHans Petter Selasky 	.poll    = devx_async_cmd_event_poll,
2507b633e08cSHans Petter Selasky 	.release = uverbs_uobject_fd_release,
2508b633e08cSHans Petter Selasky 	.llseek	 = no_llseek,
2509b633e08cSHans Petter Selasky };
2510b633e08cSHans Petter Selasky 
devx_async_event_read(struct file * filp,char __user * buf,size_t count,loff_t * pos)2511b633e08cSHans Petter Selasky static ssize_t devx_async_event_read(struct file *filp, char __user *buf,
2512b633e08cSHans Petter Selasky 				     size_t count, loff_t *pos)
2513b633e08cSHans Petter Selasky {
2514b633e08cSHans Petter Selasky 	struct devx_async_event_file *ev_file = filp->private_data;
2515b633e08cSHans Petter Selasky 	struct devx_event_subscription *event_sub;
2516b633e08cSHans Petter Selasky 	struct devx_async_event_data *uninitialized_var(event);
2517b633e08cSHans Petter Selasky 	int ret = 0;
2518b633e08cSHans Petter Selasky 	size_t eventsz;
2519b633e08cSHans Petter Selasky 	bool omit_data;
2520b633e08cSHans Petter Selasky 	void *event_data;
2521b633e08cSHans Petter Selasky 
2522b633e08cSHans Petter Selasky 	omit_data = ev_file->omit_data;
2523b633e08cSHans Petter Selasky 
2524b633e08cSHans Petter Selasky 	spin_lock_irq(&ev_file->lock);
2525b633e08cSHans Petter Selasky 
2526b633e08cSHans Petter Selasky 	if (ev_file->is_overflow_err) {
2527b633e08cSHans Petter Selasky 		ev_file->is_overflow_err = 0;
2528b633e08cSHans Petter Selasky 		spin_unlock_irq(&ev_file->lock);
2529b633e08cSHans Petter Selasky 		return -EOVERFLOW;
2530b633e08cSHans Petter Selasky 	}
2531b633e08cSHans Petter Selasky 
2532b633e08cSHans Petter Selasky 
2533b633e08cSHans Petter Selasky 	while (list_empty(&ev_file->event_list)) {
2534b633e08cSHans Petter Selasky 		spin_unlock_irq(&ev_file->lock);
2535b633e08cSHans Petter Selasky 
2536b633e08cSHans Petter Selasky 		if (filp->f_flags & O_NONBLOCK)
2537b633e08cSHans Petter Selasky 			return -EAGAIN;
2538b633e08cSHans Petter Selasky 
2539b633e08cSHans Petter Selasky 		if (wait_event_interruptible(ev_file->poll_wait,
2540b633e08cSHans Petter Selasky 			    (!list_empty(&ev_file->event_list) ||
2541b633e08cSHans Petter Selasky 			     ev_file->is_destroyed))) {
2542b633e08cSHans Petter Selasky 			return -ERESTARTSYS;
2543b633e08cSHans Petter Selasky 		}
2544b633e08cSHans Petter Selasky 
2545b633e08cSHans Petter Selasky 		spin_lock_irq(&ev_file->lock);
2546b633e08cSHans Petter Selasky 		if (ev_file->is_destroyed) {
2547b633e08cSHans Petter Selasky 			spin_unlock_irq(&ev_file->lock);
2548b633e08cSHans Petter Selasky 			return -EIO;
2549b633e08cSHans Petter Selasky 		}
2550b633e08cSHans Petter Selasky 	}
2551b633e08cSHans Petter Selasky 
2552b633e08cSHans Petter Selasky 	if (omit_data) {
2553b633e08cSHans Petter Selasky 		event_sub = list_first_entry(&ev_file->event_list,
2554b633e08cSHans Petter Selasky 					struct devx_event_subscription,
2555b633e08cSHans Petter Selasky 					event_list);
2556b633e08cSHans Petter Selasky 		eventsz = sizeof(event_sub->cookie);
2557b633e08cSHans Petter Selasky 		event_data = &event_sub->cookie;
2558b633e08cSHans Petter Selasky 	} else {
2559b633e08cSHans Petter Selasky 		event = list_first_entry(&ev_file->event_list,
2560b633e08cSHans Petter Selasky 				      struct devx_async_event_data, list);
2561b633e08cSHans Petter Selasky 		eventsz = sizeof(struct mlx5_eqe) +
2562b633e08cSHans Petter Selasky 			sizeof(struct mlx5_ib_uapi_devx_async_event_hdr);
2563b633e08cSHans Petter Selasky 		event_data = &event->hdr;
2564b633e08cSHans Petter Selasky 	}
2565b633e08cSHans Petter Selasky 
2566b633e08cSHans Petter Selasky 	if (eventsz > count) {
2567b633e08cSHans Petter Selasky 		spin_unlock_irq(&ev_file->lock);
2568b633e08cSHans Petter Selasky 		return -EINVAL;
2569b633e08cSHans Petter Selasky 	}
2570b633e08cSHans Petter Selasky 
2571b633e08cSHans Petter Selasky 	if (omit_data)
2572b633e08cSHans Petter Selasky 		list_del_init(&event_sub->event_list);
2573b633e08cSHans Petter Selasky 	else
2574b633e08cSHans Petter Selasky 		list_del(&event->list);
2575b633e08cSHans Petter Selasky 
2576b633e08cSHans Petter Selasky 	spin_unlock_irq(&ev_file->lock);
2577b633e08cSHans Petter Selasky 
2578b633e08cSHans Petter Selasky 	if (copy_to_user(buf, event_data, eventsz))
2579b633e08cSHans Petter Selasky 		/* This points to an application issue, not a kernel concern */
2580b633e08cSHans Petter Selasky 		ret = -EFAULT;
2581b633e08cSHans Petter Selasky 	else
2582b633e08cSHans Petter Selasky 		ret = eventsz;
2583b633e08cSHans Petter Selasky 
2584b633e08cSHans Petter Selasky 	if (!omit_data)
2585b633e08cSHans Petter Selasky 		kfree(event);
2586b633e08cSHans Petter Selasky 	return ret;
2587b633e08cSHans Petter Selasky }
2588b633e08cSHans Petter Selasky 
devx_async_event_poll(struct file * filp,struct poll_table_struct * wait)2589b633e08cSHans Petter Selasky static __poll_t devx_async_event_poll(struct file *filp,
2590b633e08cSHans Petter Selasky 				      struct poll_table_struct *wait)
2591b633e08cSHans Petter Selasky {
2592b633e08cSHans Petter Selasky 	struct devx_async_event_file *ev_file = filp->private_data;
2593b633e08cSHans Petter Selasky 	__poll_t pollflags = 0;
2594b633e08cSHans Petter Selasky 
2595b633e08cSHans Petter Selasky 	poll_wait(filp, &ev_file->poll_wait, wait);
2596b633e08cSHans Petter Selasky 
2597b633e08cSHans Petter Selasky 	spin_lock_irq(&ev_file->lock);
2598b633e08cSHans Petter Selasky 	if (ev_file->is_destroyed)
2599b633e08cSHans Petter Selasky 		pollflags = POLLIN | POLLRDNORM | POLLHUP;
2600b633e08cSHans Petter Selasky 	else if (!list_empty(&ev_file->event_list))
2601b633e08cSHans Petter Selasky 		pollflags = POLLIN | POLLRDNORM;
2602b633e08cSHans Petter Selasky 	spin_unlock_irq(&ev_file->lock);
2603b633e08cSHans Petter Selasky 
2604b633e08cSHans Petter Selasky 	return pollflags;
2605b633e08cSHans Petter Selasky }
2606b633e08cSHans Petter Selasky 
devx_free_subscription(struct rcu_head * rcu)2607b633e08cSHans Petter Selasky static void devx_free_subscription(struct rcu_head *rcu)
2608b633e08cSHans Petter Selasky {
2609b633e08cSHans Petter Selasky 	struct devx_event_subscription *event_sub =
2610b633e08cSHans Petter Selasky 		container_of(rcu, struct devx_event_subscription, rcu);
2611b633e08cSHans Petter Selasky 
2612b633e08cSHans Petter Selasky 	if (event_sub->eventfd.file)
2613b633e08cSHans Petter Selasky 		fdput(event_sub->eventfd);
2614b633e08cSHans Petter Selasky 	uverbs_uobject_put(&event_sub->ev_file->uobj);
2615b633e08cSHans Petter Selasky 	kfree(event_sub);
2616b633e08cSHans Petter Selasky }
2617b633e08cSHans Petter Selasky 
2618b633e08cSHans Petter Selasky static const struct file_operations devx_async_event_fops = {
2619b633e08cSHans Petter Selasky 	.owner	 = THIS_MODULE,
2620b633e08cSHans Petter Selasky 	.read	 = devx_async_event_read,
2621b633e08cSHans Petter Selasky 	.poll    = devx_async_event_poll,
2622b633e08cSHans Petter Selasky 	.release = uverbs_uobject_fd_release,
2623b633e08cSHans Petter Selasky 	.llseek	 = no_llseek,
2624b633e08cSHans Petter Selasky };
2625b633e08cSHans Petter Selasky 
devx_async_cmd_event_destroy_uobj(struct ib_uobject * uobj,enum rdma_remove_reason why)2626b633e08cSHans Petter Selasky static int devx_async_cmd_event_destroy_uobj(struct ib_uobject *uobj,
2627b633e08cSHans Petter Selasky 					     enum rdma_remove_reason why)
2628b633e08cSHans Petter Selasky {
2629b633e08cSHans Petter Selasky 	struct devx_async_cmd_event_file *comp_ev_file =
2630b633e08cSHans Petter Selasky 		container_of(uobj, struct devx_async_cmd_event_file,
2631b633e08cSHans Petter Selasky 			     uobj);
2632b633e08cSHans Petter Selasky 	struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue;
2633b633e08cSHans Petter Selasky 	struct devx_async_data *entry, *tmp;
2634b633e08cSHans Petter Selasky 
2635b633e08cSHans Petter Selasky 	spin_lock_irq(&ev_queue->lock);
2636b633e08cSHans Petter Selasky 	ev_queue->is_destroyed = 1;
2637b633e08cSHans Petter Selasky 	spin_unlock_irq(&ev_queue->lock);
2638b633e08cSHans Petter Selasky 	wake_up_interruptible(&ev_queue->poll_wait);
2639b633e08cSHans Petter Selasky 
2640b633e08cSHans Petter Selasky 	mlx5_cmd_cleanup_async_ctx(&comp_ev_file->async_ctx);
2641b633e08cSHans Petter Selasky 
2642b633e08cSHans Petter Selasky 	spin_lock_irq(&comp_ev_file->ev_queue.lock);
2643b633e08cSHans Petter Selasky 	list_for_each_entry_safe(entry, tmp,
2644b633e08cSHans Petter Selasky 				 &comp_ev_file->ev_queue.event_list, list) {
2645b633e08cSHans Petter Selasky 		list_del(&entry->list);
2646b633e08cSHans Petter Selasky 		kvfree(entry);
2647b633e08cSHans Petter Selasky 	}
2648b633e08cSHans Petter Selasky 	spin_unlock_irq(&comp_ev_file->ev_queue.lock);
2649b633e08cSHans Petter Selasky 	return 0;
2650b633e08cSHans Petter Selasky };
2651b633e08cSHans Petter Selasky 
devx_async_event_destroy_uobj(struct ib_uobject * uobj,enum rdma_remove_reason why)2652b633e08cSHans Petter Selasky static int devx_async_event_destroy_uobj(struct ib_uobject *uobj,
2653b633e08cSHans Petter Selasky 					 enum rdma_remove_reason why)
2654b633e08cSHans Petter Selasky {
2655b633e08cSHans Petter Selasky 	struct devx_async_event_file *ev_file =
2656b633e08cSHans Petter Selasky 		container_of(uobj, struct devx_async_event_file,
2657b633e08cSHans Petter Selasky 			     uobj);
2658b633e08cSHans Petter Selasky 	struct devx_event_subscription *event_sub, *event_sub_tmp;
2659b633e08cSHans Petter Selasky 	struct mlx5_ib_dev *dev = ev_file->dev;
2660b633e08cSHans Petter Selasky 
2661b633e08cSHans Petter Selasky 	spin_lock_irq(&ev_file->lock);
2662b633e08cSHans Petter Selasky 	ev_file->is_destroyed = 1;
2663b633e08cSHans Petter Selasky 
2664b633e08cSHans Petter Selasky 	/* free the pending events allocation */
2665b633e08cSHans Petter Selasky 	if (ev_file->omit_data) {
2666b633e08cSHans Petter Selasky 		struct devx_event_subscription *event_sub, *tmp;
2667b633e08cSHans Petter Selasky 
2668b633e08cSHans Petter Selasky 		list_for_each_entry_safe(event_sub, tmp, &ev_file->event_list,
2669b633e08cSHans Petter Selasky 					 event_list)
2670b633e08cSHans Petter Selasky 			list_del_init(&event_sub->event_list);
2671b633e08cSHans Petter Selasky 
2672b633e08cSHans Petter Selasky 	} else {
2673b633e08cSHans Petter Selasky 		struct devx_async_event_data *entry, *tmp;
2674b633e08cSHans Petter Selasky 
2675b633e08cSHans Petter Selasky 		list_for_each_entry_safe(entry, tmp, &ev_file->event_list,
2676b633e08cSHans Petter Selasky 					 list) {
2677b633e08cSHans Petter Selasky 			list_del(&entry->list);
2678b633e08cSHans Petter Selasky 			kfree(entry);
2679b633e08cSHans Petter Selasky 		}
2680b633e08cSHans Petter Selasky 	}
2681b633e08cSHans Petter Selasky 
2682b633e08cSHans Petter Selasky 	spin_unlock_irq(&ev_file->lock);
2683b633e08cSHans Petter Selasky 	wake_up_interruptible(&ev_file->poll_wait);
2684b633e08cSHans Petter Selasky 
2685b633e08cSHans Petter Selasky 	mutex_lock(&dev->devx_event_table.event_xa_lock);
2686b633e08cSHans Petter Selasky 	/* delete the subscriptions which are related to this FD */
2687b633e08cSHans Petter Selasky 	list_for_each_entry_safe(event_sub, event_sub_tmp,
2688b633e08cSHans Petter Selasky 				 &ev_file->subscribed_events_list, file_list) {
2689b633e08cSHans Petter Selasky 		devx_cleanup_subscription(dev, event_sub);
2690b633e08cSHans Petter Selasky 		list_del_rcu(&event_sub->file_list);
2691b633e08cSHans Petter Selasky 		/* subscription may not be used by the read API any more */
2692b633e08cSHans Petter Selasky 		call_rcu(&event_sub->rcu, devx_free_subscription);
2693b633e08cSHans Petter Selasky 	}
2694b633e08cSHans Petter Selasky 	mutex_unlock(&dev->devx_event_table.event_xa_lock);
2695b633e08cSHans Petter Selasky 
2696b633e08cSHans Petter Selasky 	put_device(&dev->ib_dev.dev);
2697b633e08cSHans Petter Selasky 	return 0;
2698b633e08cSHans Petter Selasky };
2699b633e08cSHans Petter Selasky 
2700b633e08cSHans Petter Selasky DECLARE_UVERBS_NAMED_METHOD(
2701b633e08cSHans Petter Selasky 	MLX5_IB_METHOD_DEVX_UMEM_REG,
2702b633e08cSHans Petter Selasky 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE,
2703b633e08cSHans Petter Selasky 			MLX5_IB_OBJECT_DEVX_UMEM,
2704b633e08cSHans Petter Selasky 			UVERBS_ACCESS_NEW,
2705b633e08cSHans Petter Selasky 			UA_MANDATORY),
2706b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR,
2707b633e08cSHans Petter Selasky 			   UVERBS_ATTR_TYPE(u64),
2708b633e08cSHans Petter Selasky 			   UA_MANDATORY),
2709b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_LEN,
2710b633e08cSHans Petter Selasky 			   UVERBS_ATTR_TYPE(u64),
2711b633e08cSHans Petter Selasky 			   UA_MANDATORY),
2712b633e08cSHans Petter Selasky 	UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
2713b633e08cSHans Petter Selasky 			     enum ib_access_flags),
2714b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID,
2715b633e08cSHans Petter Selasky 			    UVERBS_ATTR_TYPE(u32),
2716b633e08cSHans Petter Selasky 			    UA_MANDATORY));
2717b633e08cSHans Petter Selasky 
2718b633e08cSHans Petter Selasky DECLARE_UVERBS_NAMED_METHOD_DESTROY(
2719b633e08cSHans Petter Selasky 	MLX5_IB_METHOD_DEVX_UMEM_DEREG,
2720b633e08cSHans Petter Selasky 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_DEREG_HANDLE,
2721b633e08cSHans Petter Selasky 			MLX5_IB_OBJECT_DEVX_UMEM,
2722b633e08cSHans Petter Selasky 			UVERBS_ACCESS_DESTROY,
2723b633e08cSHans Petter Selasky 			UA_MANDATORY));
2724b633e08cSHans Petter Selasky 
2725b633e08cSHans Petter Selasky DECLARE_UVERBS_NAMED_METHOD(
2726b633e08cSHans Petter Selasky 	MLX5_IB_METHOD_DEVX_QUERY_EQN,
2727b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC,
2728b633e08cSHans Petter Selasky 			   UVERBS_ATTR_TYPE(u32),
2729b633e08cSHans Petter Selasky 			   UA_MANDATORY),
2730b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN,
2731b633e08cSHans Petter Selasky 			    UVERBS_ATTR_TYPE(u32),
2732b633e08cSHans Petter Selasky 			    UA_MANDATORY));
2733b633e08cSHans Petter Selasky 
2734b633e08cSHans Petter Selasky DECLARE_UVERBS_NAMED_METHOD(
2735b633e08cSHans Petter Selasky 	MLX5_IB_METHOD_DEVX_QUERY_UAR,
2736b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX,
2737b633e08cSHans Petter Selasky 			   UVERBS_ATTR_TYPE(u32),
2738b633e08cSHans Petter Selasky 			   UA_MANDATORY),
2739b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX,
2740b633e08cSHans Petter Selasky 			    UVERBS_ATTR_TYPE(u32),
2741b633e08cSHans Petter Selasky 			    UA_MANDATORY));
2742b633e08cSHans Petter Selasky 
2743b633e08cSHans Petter Selasky DECLARE_UVERBS_NAMED_METHOD(
2744b633e08cSHans Petter Selasky 	MLX5_IB_METHOD_DEVX_OTHER,
2745b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_IN(
2746b633e08cSHans Petter Selasky 		MLX5_IB_ATTR_DEVX_OTHER_CMD_IN,
2747b633e08cSHans Petter Selasky 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
2748b633e08cSHans Petter Selasky 		UA_MANDATORY,
2749b633e08cSHans Petter Selasky 		UA_ALLOC_AND_COPY),
2750b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_OUT(
2751b633e08cSHans Petter Selasky 		MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT,
2752b633e08cSHans Petter Selasky 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
2753b633e08cSHans Petter Selasky 		UA_MANDATORY));
2754b633e08cSHans Petter Selasky 
2755b633e08cSHans Petter Selasky DECLARE_UVERBS_NAMED_METHOD(
2756b633e08cSHans Petter Selasky 	MLX5_IB_METHOD_DEVX_OBJ_CREATE,
2757b633e08cSHans Petter Selasky 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE,
2758b633e08cSHans Petter Selasky 			MLX5_IB_OBJECT_DEVX_OBJ,
2759b633e08cSHans Petter Selasky 			UVERBS_ACCESS_NEW,
2760b633e08cSHans Petter Selasky 			UA_MANDATORY),
2761b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_IN(
2762b633e08cSHans Petter Selasky 		MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN,
2763b633e08cSHans Petter Selasky 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
2764b633e08cSHans Petter Selasky 		UA_MANDATORY,
2765b633e08cSHans Petter Selasky 		UA_ALLOC_AND_COPY),
2766b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_OUT(
2767b633e08cSHans Petter Selasky 		MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT,
2768b633e08cSHans Petter Selasky 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
2769b633e08cSHans Petter Selasky 		UA_MANDATORY));
2770b633e08cSHans Petter Selasky 
2771b633e08cSHans Petter Selasky DECLARE_UVERBS_NAMED_METHOD_DESTROY(
2772b633e08cSHans Petter Selasky 	MLX5_IB_METHOD_DEVX_OBJ_DESTROY,
2773b633e08cSHans Petter Selasky 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_DESTROY_HANDLE,
2774b633e08cSHans Petter Selasky 			MLX5_IB_OBJECT_DEVX_OBJ,
2775b633e08cSHans Petter Selasky 			UVERBS_ACCESS_DESTROY,
2776b633e08cSHans Petter Selasky 			UA_MANDATORY));
2777b633e08cSHans Petter Selasky 
2778b633e08cSHans Petter Selasky DECLARE_UVERBS_NAMED_METHOD(
2779b633e08cSHans Petter Selasky 	MLX5_IB_METHOD_DEVX_OBJ_MODIFY,
2780b633e08cSHans Petter Selasky 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE,
2781b633e08cSHans Petter Selasky 			UVERBS_IDR_ANY_OBJECT,
2782b633e08cSHans Petter Selasky 			UVERBS_ACCESS_WRITE,
2783b633e08cSHans Petter Selasky 			UA_MANDATORY),
2784b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_IN(
2785b633e08cSHans Petter Selasky 		MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN,
2786b633e08cSHans Petter Selasky 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
2787b633e08cSHans Petter Selasky 		UA_MANDATORY,
2788b633e08cSHans Petter Selasky 		UA_ALLOC_AND_COPY),
2789b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_OUT(
2790b633e08cSHans Petter Selasky 		MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
2791b633e08cSHans Petter Selasky 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
2792b633e08cSHans Petter Selasky 		UA_MANDATORY));
2793b633e08cSHans Petter Selasky 
2794b633e08cSHans Petter Selasky DECLARE_UVERBS_NAMED_METHOD(
2795b633e08cSHans Petter Selasky 	MLX5_IB_METHOD_DEVX_OBJ_QUERY,
2796b633e08cSHans Petter Selasky 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE,
2797b633e08cSHans Petter Selasky 			UVERBS_IDR_ANY_OBJECT,
2798b633e08cSHans Petter Selasky 			UVERBS_ACCESS_READ,
2799b633e08cSHans Petter Selasky 			UA_MANDATORY),
2800b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_IN(
2801b633e08cSHans Petter Selasky 		MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN,
2802b633e08cSHans Petter Selasky 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
2803b633e08cSHans Petter Selasky 		UA_MANDATORY,
2804b633e08cSHans Petter Selasky 		UA_ALLOC_AND_COPY),
2805b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_OUT(
2806b633e08cSHans Petter Selasky 		MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
2807b633e08cSHans Petter Selasky 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
2808b633e08cSHans Petter Selasky 		UA_MANDATORY));
2809b633e08cSHans Petter Selasky 
2810b633e08cSHans Petter Selasky DECLARE_UVERBS_NAMED_METHOD(
2811b633e08cSHans Petter Selasky 	MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY,
2812b633e08cSHans Petter Selasky 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE,
2813b633e08cSHans Petter Selasky 			UVERBS_IDR_ANY_OBJECT,
2814b633e08cSHans Petter Selasky 			UVERBS_ACCESS_READ,
2815b633e08cSHans Petter Selasky 			UA_MANDATORY),
2816b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_IN(
2817b633e08cSHans Petter Selasky 		MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN,
2818b633e08cSHans Petter Selasky 		UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
2819b633e08cSHans Petter Selasky 		UA_MANDATORY,
2820b633e08cSHans Petter Selasky 		UA_ALLOC_AND_COPY),
2821b633e08cSHans Petter Selasky 	UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_OUT_LEN,
2822b633e08cSHans Petter Selasky 		u16, UA_MANDATORY),
2823b633e08cSHans Petter Selasky 	UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_FD,
2824b633e08cSHans Petter Selasky 		MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
2825b633e08cSHans Petter Selasky 		UVERBS_ACCESS_READ,
2826b633e08cSHans Petter Selasky 		UA_MANDATORY),
2827b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_WR_ID,
2828b633e08cSHans Petter Selasky 		UVERBS_ATTR_TYPE(u64),
2829b633e08cSHans Petter Selasky 		UA_MANDATORY));
2830b633e08cSHans Petter Selasky 
2831b633e08cSHans Petter Selasky DECLARE_UVERBS_NAMED_METHOD(
2832b633e08cSHans Petter Selasky 	MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT,
2833b633e08cSHans Petter Selasky 	UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_HANDLE,
2834b633e08cSHans Petter Selasky 		MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD,
2835b633e08cSHans Petter Selasky 		UVERBS_ACCESS_READ,
2836b633e08cSHans Petter Selasky 		UA_MANDATORY),
2837b633e08cSHans Petter Selasky 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_OBJ_HANDLE,
2838b633e08cSHans Petter Selasky 		MLX5_IB_OBJECT_DEVX_OBJ,
2839b633e08cSHans Petter Selasky 		UVERBS_ACCESS_READ,
2840b633e08cSHans Petter Selasky 		UA_OPTIONAL),
2841b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_TYPE_NUM_LIST,
2842b633e08cSHans Petter Selasky 		UVERBS_ATTR_MIN_SIZE(sizeof(u16)),
2843b633e08cSHans Petter Selasky 		UA_MANDATORY,
2844b633e08cSHans Petter Selasky 		UA_ALLOC_AND_COPY),
2845b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_COOKIE,
2846b633e08cSHans Petter Selasky 		UVERBS_ATTR_TYPE(u64),
2847b633e08cSHans Petter Selasky 		UA_OPTIONAL),
2848b633e08cSHans Petter Selasky 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_SUBSCRIBE_EVENT_FD_NUM,
2849b633e08cSHans Petter Selasky 		UVERBS_ATTR_TYPE(u32),
2850b633e08cSHans Petter Selasky 		UA_OPTIONAL));
2851b633e08cSHans Petter Selasky 
2852b633e08cSHans Petter Selasky DECLARE_UVERBS_GLOBAL_METHODS(MLX5_IB_OBJECT_DEVX,
2853b633e08cSHans Petter Selasky 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OTHER),
2854b633e08cSHans Petter Selasky 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR),
2855b633e08cSHans Petter Selasky 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_EQN),
2856b633e08cSHans Petter Selasky 			      &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT));
2857b633e08cSHans Petter Selasky 
2858b633e08cSHans Petter Selasky DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ,
2859b633e08cSHans Petter Selasky 			    UVERBS_TYPE_ALLOC_IDR(devx_obj_cleanup),
2860b633e08cSHans Petter Selasky 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_CREATE),
2861b633e08cSHans Petter Selasky 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY),
2862b633e08cSHans Petter Selasky 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_MODIFY),
2863b633e08cSHans Petter Selasky 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY),
2864b633e08cSHans Petter Selasky 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY));
2865b633e08cSHans Petter Selasky 
2866b633e08cSHans Petter Selasky DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM,
2867b633e08cSHans Petter Selasky 			    UVERBS_TYPE_ALLOC_IDR(devx_umem_cleanup),
2868b633e08cSHans Petter Selasky 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG),
2869b633e08cSHans Petter Selasky 			    &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG));
2870b633e08cSHans Petter Selasky 
2871b633e08cSHans Petter Selasky 
2872b633e08cSHans Petter Selasky DECLARE_UVERBS_NAMED_METHOD(
2873b633e08cSHans Petter Selasky 	MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC,
2874b633e08cSHans Petter Selasky 	UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE,
2875b633e08cSHans Petter Selasky 			MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
2876b633e08cSHans Petter Selasky 			UVERBS_ACCESS_NEW,
2877b633e08cSHans Petter Selasky 			UA_MANDATORY));
2878b633e08cSHans Petter Selasky 
2879b633e08cSHans Petter Selasky DECLARE_UVERBS_NAMED_OBJECT(
2880b633e08cSHans Petter Selasky 	MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
2881b633e08cSHans Petter Selasky 	UVERBS_TYPE_ALLOC_FD(sizeof(struct devx_async_cmd_event_file),
2882b633e08cSHans Petter Selasky 			     devx_async_cmd_event_destroy_uobj,
2883b633e08cSHans Petter Selasky 			     &devx_async_cmd_event_fops, "[devx_async_cmd]",
2884b633e08cSHans Petter Selasky 			     FMODE_READ),
2885b633e08cSHans Petter Selasky 	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC));
2886b633e08cSHans Petter Selasky 
2887b633e08cSHans Petter Selasky DECLARE_UVERBS_NAMED_METHOD(
2888b633e08cSHans Petter Selasky 	MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC,
2889b633e08cSHans Petter Selasky 	UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_HANDLE,
2890b633e08cSHans Petter Selasky 			MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD,
2891b633e08cSHans Petter Selasky 			UVERBS_ACCESS_NEW,
2892b633e08cSHans Petter Selasky 			UA_MANDATORY),
2893b633e08cSHans Petter Selasky 	UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_ASYNC_EVENT_FD_ALLOC_FLAGS,
2894b633e08cSHans Petter Selasky 			enum mlx5_ib_uapi_devx_create_event_channel_flags,
2895b633e08cSHans Petter Selasky 			UA_MANDATORY));
2896b633e08cSHans Petter Selasky 
2897b633e08cSHans Petter Selasky DECLARE_UVERBS_NAMED_OBJECT(
2898b633e08cSHans Petter Selasky 	MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD,
2899b633e08cSHans Petter Selasky 	UVERBS_TYPE_ALLOC_FD(sizeof(struct devx_async_event_file),
2900b633e08cSHans Petter Selasky 			     devx_async_event_destroy_uobj,
2901b633e08cSHans Petter Selasky 			     &devx_async_event_fops, "[devx_async_event]",
2902b633e08cSHans Petter Selasky 			     FMODE_READ),
2903b633e08cSHans Petter Selasky 	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_ASYNC_EVENT_FD_ALLOC));
2904b633e08cSHans Petter Selasky 
devx_is_supported(struct ib_device * device)2905b633e08cSHans Petter Selasky static bool devx_is_supported(struct ib_device *device)
2906b633e08cSHans Petter Selasky {
2907b633e08cSHans Petter Selasky 	struct mlx5_ib_dev *dev = to_mdev(device);
2908b633e08cSHans Petter Selasky 
2909b633e08cSHans Petter Selasky 	return MLX5_CAP_GEN(dev->mdev, log_max_uctx);
2910b633e08cSHans Petter Selasky }
2911b633e08cSHans Petter Selasky 
2912b633e08cSHans Petter Selasky const struct uapi_definition mlx5_ib_devx_defs[] = {
2913b633e08cSHans Petter Selasky 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
2914b633e08cSHans Petter Selasky 		MLX5_IB_OBJECT_DEVX,
2915b633e08cSHans Petter Selasky 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
2916b633e08cSHans Petter Selasky 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
2917b633e08cSHans Petter Selasky 		MLX5_IB_OBJECT_DEVX_OBJ,
2918b633e08cSHans Petter Selasky 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
2919b633e08cSHans Petter Selasky 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
2920b633e08cSHans Petter Selasky 		MLX5_IB_OBJECT_DEVX_UMEM,
2921b633e08cSHans Petter Selasky 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
2922b633e08cSHans Petter Selasky 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
2923b633e08cSHans Petter Selasky 		MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
2924b633e08cSHans Petter Selasky 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
2925b633e08cSHans Petter Selasky 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
2926b633e08cSHans Petter Selasky 		MLX5_IB_OBJECT_DEVX_ASYNC_EVENT_FD,
2927b633e08cSHans Petter Selasky 		UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
2928b633e08cSHans Petter Selasky 	{},
2929b633e08cSHans Petter Selasky };
2930