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