xref: /freebsd/sys/ofed/drivers/infiniband/core/uverbs.h (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
1fe267a55SPedro F. Giffuni /*-
2fe267a55SPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3fe267a55SPedro F. Giffuni  *
4aa0a1e58SJeff Roberson  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
5aa0a1e58SJeff Roberson  * Copyright (c) 2005, 2006 Cisco Systems.  All rights reserved.
6aa0a1e58SJeff Roberson  * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
7aa0a1e58SJeff Roberson  * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
8aa0a1e58SJeff Roberson  * Copyright (c) 2005 PathScale, Inc. All rights reserved.
9aa0a1e58SJeff Roberson  *
10aa0a1e58SJeff Roberson  * This software is available to you under a choice of one of two
11aa0a1e58SJeff Roberson  * licenses.  You may choose to be licensed under the terms of the GNU
12aa0a1e58SJeff Roberson  * General Public License (GPL) Version 2, available from the file
13aa0a1e58SJeff Roberson  * COPYING in the main directory of this source tree, or the
14aa0a1e58SJeff Roberson  * OpenIB.org BSD license below:
15aa0a1e58SJeff Roberson  *
16aa0a1e58SJeff Roberson  *     Redistribution and use in source and binary forms, with or
17aa0a1e58SJeff Roberson  *     without modification, are permitted provided that the following
18aa0a1e58SJeff Roberson  *     conditions are met:
19aa0a1e58SJeff Roberson  *
20aa0a1e58SJeff Roberson  *      - Redistributions of source code must retain the above
21aa0a1e58SJeff Roberson  *        copyright notice, this list of conditions and the following
22aa0a1e58SJeff Roberson  *        disclaimer.
23aa0a1e58SJeff Roberson  *
24aa0a1e58SJeff Roberson  *      - Redistributions in binary form must reproduce the above
25aa0a1e58SJeff Roberson  *        copyright notice, this list of conditions and the following
26aa0a1e58SJeff Roberson  *        disclaimer in the documentation and/or other materials
27aa0a1e58SJeff Roberson  *        provided with the distribution.
28aa0a1e58SJeff Roberson  *
29aa0a1e58SJeff Roberson  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30aa0a1e58SJeff Roberson  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31aa0a1e58SJeff Roberson  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32aa0a1e58SJeff Roberson  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
33aa0a1e58SJeff Roberson  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
34aa0a1e58SJeff Roberson  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
35aa0a1e58SJeff Roberson  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36aa0a1e58SJeff Roberson  * SOFTWARE.
37aa0a1e58SJeff Roberson  */
38aa0a1e58SJeff Roberson 
39aa0a1e58SJeff Roberson #ifndef UVERBS_H
40aa0a1e58SJeff Roberson #define UVERBS_H
41aa0a1e58SJeff Roberson 
42aa0a1e58SJeff Roberson #include <linux/kref.h>
43aa0a1e58SJeff Roberson #include <linux/idr.h>
44aa0a1e58SJeff Roberson #include <linux/mutex.h>
45aa0a1e58SJeff Roberson #include <linux/completion.h>
46b5c1e0cbSHans Petter Selasky #include <linux/cdev.h>
47478d3005SHans Petter Selasky #include <linux/srcu.h>
48478d3005SHans Petter Selasky #include <linux/rcupdate.h>
49b5c1e0cbSHans Petter Selasky #include <linux/rbtree.h>
50*b633e08cSHans Petter Selasky #include <linux/wait.h>
51aa0a1e58SJeff Roberson 
52aa0a1e58SJeff Roberson #include <rdma/ib_verbs.h>
53aa0a1e58SJeff Roberson #include <rdma/ib_umem.h>
54aa0a1e58SJeff Roberson #include <rdma/ib_user_verbs.h>
55*b633e08cSHans Petter Selasky #include <rdma/uverbs_std_types.h>
56*b633e08cSHans Petter Selasky 
57*b633e08cSHans Petter Selasky #define UVERBS_MODULE_NAME ib_uverbs
58*b633e08cSHans Petter Selasky #include <rdma/uverbs_named_ioctl.h>
59478d3005SHans Petter Selasky 
6005f46919SHans Petter Selasky static inline void
ib_uverbs_init_udata(struct ib_udata * udata,const void __user * ibuf,void __user * obuf,size_t ilen,size_t olen)6105f46919SHans Petter Selasky ib_uverbs_init_udata(struct ib_udata *udata,
6205f46919SHans Petter Selasky 		     const void __user *ibuf,
6305f46919SHans Petter Selasky 		     void __user *obuf,
6405f46919SHans Petter Selasky 		     size_t ilen, size_t olen)
6505f46919SHans Petter Selasky {
6605f46919SHans Petter Selasky 	udata->inbuf  = ibuf;
6705f46919SHans Petter Selasky 	udata->outbuf = obuf;
6805f46919SHans Petter Selasky 	udata->inlen  = ilen;
6905f46919SHans Petter Selasky 	udata->outlen = olen;
7005f46919SHans Petter Selasky }
71478d3005SHans Petter Selasky 
7205f46919SHans Petter Selasky static inline void
ib_uverbs_init_udata_buf_or_null(struct ib_udata * udata,const void __user * ibuf,void __user * obuf,size_t ilen,size_t olen)7305f46919SHans Petter Selasky ib_uverbs_init_udata_buf_or_null(struct ib_udata *udata,
7405f46919SHans Petter Selasky 				 const void __user *ibuf,
7505f46919SHans Petter Selasky 				 void __user *obuf,
7605f46919SHans Petter Selasky 				 size_t ilen, size_t olen)
7705f46919SHans Petter Selasky {
7805f46919SHans Petter Selasky 	ib_uverbs_init_udata(udata,
7905f46919SHans Petter Selasky 			     ilen ? ibuf : NULL, olen ? obuf : NULL,
8005f46919SHans Petter Selasky 			     ilen, olen);
8105f46919SHans Petter Selasky }
82aa0a1e58SJeff Roberson 
83aa0a1e58SJeff Roberson /*
84aa0a1e58SJeff Roberson  * Our lifetime rules for these structs are the following:
85aa0a1e58SJeff Roberson  *
86aa0a1e58SJeff Roberson  * struct ib_uverbs_device: One reference is held by the module and
87aa0a1e58SJeff Roberson  * released in ib_uverbs_remove_one().  Another reference is taken by
88aa0a1e58SJeff Roberson  * ib_uverbs_open() each time the character special file is opened,
89aa0a1e58SJeff Roberson  * and released in ib_uverbs_release_file() when the file is released.
90aa0a1e58SJeff Roberson  *
91aa0a1e58SJeff Roberson  * struct ib_uverbs_file: One reference is held by the VFS and
92aa0a1e58SJeff Roberson  * released when the file is closed.  Another reference is taken when
93aa0a1e58SJeff Roberson  * an asynchronous event queue file is created and released when the
94aa0a1e58SJeff Roberson  * event file is closed.
95aa0a1e58SJeff Roberson  *
96*b633e08cSHans Petter Selasky  * struct ib_uverbs_event_queue: Base structure for
97*b633e08cSHans Petter Selasky  * struct ib_uverbs_async_event_file and struct ib_uverbs_completion_event_file.
98*b633e08cSHans Petter Selasky  * One reference is held by the VFS and released when the file is closed.
99*b633e08cSHans Petter Selasky  * For asynchronous event files, another reference is held by the corresponding
100*b633e08cSHans Petter Selasky  * main context file and released when that file is closed.  For completion
101*b633e08cSHans Petter Selasky  * event files, a reference is taken when a CQ is created that uses the file,
102*b633e08cSHans Petter Selasky  * and released when the CQ is destroyed.
103aa0a1e58SJeff Roberson  */
104aa0a1e58SJeff Roberson 
105aa0a1e58SJeff Roberson struct ib_uverbs_device {
106478d3005SHans Petter Selasky 	atomic_t				refcount;
107*b633e08cSHans Petter Selasky 	u32					num_comp_vectors;
108aa0a1e58SJeff Roberson 	struct completion			comp;
109*b633e08cSHans Petter Selasky 	struct device				dev;
110478d3005SHans Petter Selasky 	struct ib_device	__rcu	       *ib_dev;
111b5c1e0cbSHans Petter Selasky 	int					devnum;
112b5c1e0cbSHans Petter Selasky 	struct cdev			        cdev;
113b5c1e0cbSHans Petter Selasky 	struct rb_root				xrcd_tree;
114b5c1e0cbSHans Petter Selasky 	struct mutex				xrcd_tree_mutex;
115478d3005SHans Petter Selasky 	struct srcu_struct			disassociate_srcu;
116478d3005SHans Petter Selasky 	struct mutex				lists_mutex; /* protect lists */
117478d3005SHans Petter Selasky 	struct list_head			uverbs_file_list;
118*b633e08cSHans Petter Selasky 	struct uverbs_api			*uapi;
119aa0a1e58SJeff Roberson };
120aa0a1e58SJeff Roberson 
121*b633e08cSHans Petter Selasky struct ib_uverbs_event_queue {
122aa0a1e58SJeff Roberson 	spinlock_t				lock;
123b5c1e0cbSHans Petter Selasky 	int					is_closed;
124aa0a1e58SJeff Roberson 	wait_queue_head_t			poll_wait;
125aa0a1e58SJeff Roberson 	struct fasync_struct		       *async_queue;
126aa0a1e58SJeff Roberson 	struct list_head			event_list;
127*b633e08cSHans Petter Selasky };
128*b633e08cSHans Petter Selasky 
129*b633e08cSHans Petter Selasky struct ib_uverbs_async_event_file {
130*b633e08cSHans Petter Selasky 	struct ib_uobject			uobj;
131*b633e08cSHans Petter Selasky 	struct ib_uverbs_event_queue		ev_queue;
132*b633e08cSHans Petter Selasky 	struct ib_event_handler			event_handler;
133*b633e08cSHans Petter Selasky };
134*b633e08cSHans Petter Selasky 
135*b633e08cSHans Petter Selasky struct ib_uverbs_completion_event_file {
136*b633e08cSHans Petter Selasky 	struct ib_uobject			uobj;
137*b633e08cSHans Petter Selasky 	struct ib_uverbs_event_queue		ev_queue;
138aa0a1e58SJeff Roberson };
139aa0a1e58SJeff Roberson 
140aa0a1e58SJeff Roberson struct ib_uverbs_file {
141aa0a1e58SJeff Roberson 	struct kref				ref;
142aa0a1e58SJeff Roberson 	struct ib_uverbs_device		       *device;
143*b633e08cSHans Petter Selasky 	struct mutex				ucontext_lock;
144*b633e08cSHans Petter Selasky 	/*
145*b633e08cSHans Petter Selasky 	 * ucontext must be accessed via ib_uverbs_get_ucontext() or with
146*b633e08cSHans Petter Selasky 	 * ucontext_lock held
147*b633e08cSHans Petter Selasky 	 */
148aa0a1e58SJeff Roberson 	struct ib_ucontext		       *ucontext;
149*b633e08cSHans Petter Selasky 	struct ib_uverbs_async_event_file      *async_file;
150478d3005SHans Petter Selasky 	struct list_head			list;
151*b633e08cSHans Petter Selasky 
152*b633e08cSHans Petter Selasky 	/*
153*b633e08cSHans Petter Selasky 	 * To access the uobjects list hw_destroy_rwsem must be held for write
154*b633e08cSHans Petter Selasky 	 * OR hw_destroy_rwsem held for read AND uobjects_lock held.
155*b633e08cSHans Petter Selasky 	 * hw_destroy_rwsem should be called across any destruction of the HW
156*b633e08cSHans Petter Selasky 	 * object of an associated uobject.
157*b633e08cSHans Petter Selasky 	 */
158*b633e08cSHans Petter Selasky 	struct rw_semaphore	hw_destroy_rwsem;
159*b633e08cSHans Petter Selasky 	spinlock_t		uobjects_lock;
160*b633e08cSHans Petter Selasky 	struct list_head	uobjects;
161*b633e08cSHans Petter Selasky 
162*b633e08cSHans Petter Selasky 	struct mutex umap_lock;
163*b633e08cSHans Petter Selasky 	struct list_head umaps;
164*b633e08cSHans Petter Selasky 
165*b633e08cSHans Petter Selasky 	struct xarray		idr;
166aa0a1e58SJeff Roberson };
167aa0a1e58SJeff Roberson 
168aa0a1e58SJeff Roberson struct ib_uverbs_event {
169aa0a1e58SJeff Roberson 	union {
170aa0a1e58SJeff Roberson 		struct ib_uverbs_async_event_desc	async;
171aa0a1e58SJeff Roberson 		struct ib_uverbs_comp_event_desc	comp;
172aa0a1e58SJeff Roberson 	}					desc;
173aa0a1e58SJeff Roberson 	struct list_head			list;
174aa0a1e58SJeff Roberson 	struct list_head			obj_list;
175aa0a1e58SJeff Roberson 	u32				       *counter;
176aa0a1e58SJeff Roberson };
177aa0a1e58SJeff Roberson 
178aa0a1e58SJeff Roberson struct ib_uverbs_mcast_entry {
179aa0a1e58SJeff Roberson 	struct list_head	list;
180aa0a1e58SJeff Roberson 	union ib_gid 		gid;
181aa0a1e58SJeff Roberson 	u16 			lid;
182aa0a1e58SJeff Roberson };
183aa0a1e58SJeff Roberson 
184aa0a1e58SJeff Roberson struct ib_uevent_object {
185aa0a1e58SJeff Roberson 	struct ib_uobject	uobject;
186*b633e08cSHans Petter Selasky 	/* List member for ib_uverbs_async_event_file list */
187aa0a1e58SJeff Roberson 	struct list_head	event_list;
188aa0a1e58SJeff Roberson 	u32			events_reported;
189aa0a1e58SJeff Roberson };
190aa0a1e58SJeff Roberson 
191b5c1e0cbSHans Petter Selasky struct ib_uxrcd_object {
192b5c1e0cbSHans Petter Selasky 	struct ib_uobject	uobject;
193b5c1e0cbSHans Petter Selasky 	atomic_t		refcnt;
194b5c1e0cbSHans Petter Selasky };
195b5c1e0cbSHans Petter Selasky 
196b5c1e0cbSHans Petter Selasky struct ib_usrq_object {
197b5c1e0cbSHans Petter Selasky 	struct ib_uevent_object	uevent;
198b5c1e0cbSHans Petter Selasky 	struct ib_uxrcd_object *uxrcd;
199b5c1e0cbSHans Petter Selasky };
200b5c1e0cbSHans Petter Selasky 
201aa0a1e58SJeff Roberson struct ib_uqp_object {
202aa0a1e58SJeff Roberson 	struct ib_uevent_object	uevent;
203ef24f058SHans Petter Selasky 	/* lock for mcast list */
204ef24f058SHans Petter Selasky 	struct mutex		mcast_lock;
205aa0a1e58SJeff Roberson 	struct list_head 	mcast_list;
206b5c1e0cbSHans Petter Selasky 	struct ib_uxrcd_object *uxrcd;
207aa0a1e58SJeff Roberson };
208aa0a1e58SJeff Roberson 
209478d3005SHans Petter Selasky struct ib_uwq_object {
210478d3005SHans Petter Selasky 	struct ib_uevent_object	uevent;
211478d3005SHans Petter Selasky };
212478d3005SHans Petter Selasky 
213aa0a1e58SJeff Roberson struct ib_ucq_object {
214*b633e08cSHans Petter Selasky 	struct ib_uevent_object uevent;
215aa0a1e58SJeff Roberson 	struct list_head	comp_list;
216aa0a1e58SJeff Roberson 	u32			comp_events_reported;
217aa0a1e58SJeff Roberson };
218aa0a1e58SJeff Roberson 
219*b633e08cSHans Petter Selasky extern const struct file_operations uverbs_event_fops;
220*b633e08cSHans Petter Selasky extern const struct file_operations uverbs_async_event_fops;
221*b633e08cSHans Petter Selasky void ib_uverbs_init_event_queue(struct ib_uverbs_event_queue *ev_queue);
222*b633e08cSHans Petter Selasky void ib_uverbs_init_async_event_file(struct ib_uverbs_async_event_file *ev_file);
223*b633e08cSHans Petter Selasky void ib_uverbs_free_event_queue(struct ib_uverbs_event_queue *event_queue);
224*b633e08cSHans Petter Selasky void ib_uverbs_flow_resources_free(struct ib_uflow_resources *uflow_res);
225aa0a1e58SJeff Roberson 
226*b633e08cSHans Petter Selasky int ib_alloc_ucontext(struct uverbs_attr_bundle *attrs);
227*b633e08cSHans Petter Selasky int ib_init_ucontext(struct uverbs_attr_bundle *attrs);
228aa0a1e58SJeff Roberson 
229*b633e08cSHans Petter Selasky void ib_uverbs_release_ucq(struct ib_uverbs_completion_event_file *ev_file,
230aa0a1e58SJeff Roberson 			   struct ib_ucq_object *uobj);
231*b633e08cSHans Petter Selasky void ib_uverbs_release_uevent(struct ib_uevent_object *uobj);
232*b633e08cSHans Petter Selasky void ib_uverbs_release_file(struct kref *ref);
233aa0a1e58SJeff Roberson 
234aa0a1e58SJeff Roberson void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context);
235aa0a1e58SJeff Roberson void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr);
236aa0a1e58SJeff Roberson void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
237478d3005SHans Petter Selasky void ib_uverbs_wq_event_handler(struct ib_event *event, void *context_ptr);
238aa0a1e58SJeff Roberson void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
239*b633e08cSHans Petter Selasky int ib_uverbs_dealloc_xrcd(struct ib_uobject *uobject, struct ib_xrcd *xrcd,
240*b633e08cSHans Petter Selasky 			   enum rdma_remove_reason why,
241*b633e08cSHans Petter Selasky 			   struct uverbs_attr_bundle *attrs);
242b5c1e0cbSHans Petter Selasky 
243478d3005SHans Petter Selasky int uverbs_dealloc_mw(struct ib_mw *mw);
244*b633e08cSHans Petter Selasky void ib_uverbs_detach_umcast(struct ib_qp *qp,
245*b633e08cSHans Petter Selasky 			     struct ib_uqp_object *uobj);
246*b633e08cSHans Petter Selasky 
247*b633e08cSHans Petter Selasky long ib_uverbs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
248478d3005SHans Petter Selasky 
249b5c1e0cbSHans Petter Selasky struct ib_uverbs_flow_spec {
250b5c1e0cbSHans Petter Selasky 	union {
251b5c1e0cbSHans Petter Selasky 		union {
252b5c1e0cbSHans Petter Selasky 			struct ib_uverbs_flow_spec_hdr hdr;
253b5c1e0cbSHans Petter Selasky 			struct {
254b5c1e0cbSHans Petter Selasky 				__u32 type;
255b5c1e0cbSHans Petter Selasky 				__u16 size;
256b5c1e0cbSHans Petter Selasky 				__u16 reserved;
257b5c1e0cbSHans Petter Selasky 			};
258b5c1e0cbSHans Petter Selasky 		};
259b5c1e0cbSHans Petter Selasky 		struct ib_uverbs_flow_spec_eth     eth;
260b5c1e0cbSHans Petter Selasky 		struct ib_uverbs_flow_spec_ipv4    ipv4;
261*b633e08cSHans Petter Selasky 		struct ib_uverbs_flow_spec_esp     esp;
262b5c1e0cbSHans Petter Selasky 		struct ib_uverbs_flow_spec_tcp_udp tcp_udp;
263478d3005SHans Petter Selasky 		struct ib_uverbs_flow_spec_ipv6    ipv6;
264*b633e08cSHans Petter Selasky 		struct ib_uverbs_flow_spec_action_tag	flow_tag;
265*b633e08cSHans Petter Selasky 		struct ib_uverbs_flow_spec_action_drop	drop;
266*b633e08cSHans Petter Selasky 		struct ib_uverbs_flow_spec_action_handle action;
267*b633e08cSHans Petter Selasky 		struct ib_uverbs_flow_spec_action_count flow_count;
268b5c1e0cbSHans Petter Selasky 	};
269b5c1e0cbSHans Petter Selasky };
270aa0a1e58SJeff Roberson 
271*b633e08cSHans Petter Selasky int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
272*b633e08cSHans Petter Selasky 					  const void *kern_spec_mask,
273*b633e08cSHans Petter Selasky 					  const void *kern_spec_val,
274*b633e08cSHans Petter Selasky 					  size_t kern_filter_sz,
275*b633e08cSHans Petter Selasky 					  union ib_flow_spec *ib_spec);
276aa0a1e58SJeff Roberson 
277*b633e08cSHans Petter Selasky /*
278*b633e08cSHans Petter Selasky  * ib_uverbs_query_port_resp.port_cap_flags started out as just a copy of the
279*b633e08cSHans Petter Selasky  * PortInfo CapabilityMask, but was extended with unique bits.
280*b633e08cSHans Petter Selasky  */
make_port_cap_flags(const struct ib_port_attr * attr)281*b633e08cSHans Petter Selasky static inline u32 make_port_cap_flags(const struct ib_port_attr *attr)
282*b633e08cSHans Petter Selasky {
283*b633e08cSHans Petter Selasky 	u32 res;
284aa0a1e58SJeff Roberson 
285*b633e08cSHans Petter Selasky 	/* All IBA CapabilityMask bits are passed through here, except bit 26,
286*b633e08cSHans Petter Selasky 	 * which is overridden with IP_BASED_GIDS. This is due to a historical
287*b633e08cSHans Petter Selasky 	 * mistake in the implementation of IP_BASED_GIDS. Otherwise all other
288*b633e08cSHans Petter Selasky 	 * bits match the IBA definition across all kernel versions.
289*b633e08cSHans Petter Selasky 	 */
290*b633e08cSHans Petter Selasky 	res = attr->port_cap_flags & ~(u32)IB_UVERBS_PCF_IP_BASED_GIDS;
291b5c1e0cbSHans Petter Selasky 
292*b633e08cSHans Petter Selasky 	if (attr->ip_gids)
293*b633e08cSHans Petter Selasky 		res |= IB_UVERBS_PCF_IP_BASED_GIDS;
294aa0a1e58SJeff Roberson 
295*b633e08cSHans Petter Selasky 	return res;
296*b633e08cSHans Petter Selasky }
297*b633e08cSHans Petter Selasky 
298*b633e08cSHans Petter Selasky 
299*b633e08cSHans Petter Selasky void copy_port_attr_to_resp(struct ib_port_attr *attr,
300*b633e08cSHans Petter Selasky 			    struct ib_uverbs_query_port_resp *resp,
301*b633e08cSHans Petter Selasky 			    struct ib_device *ib_dev, u8 port_num);
302aa0a1e58SJeff Roberson #endif /* UVERBS_H */
303