1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 #ifndef _SYS_IB_CLIENTS_OF_SOL_UVERBS_SOL_UVERBS_H
27 #define	_SYS_IB_CLIENTS_OF_SOL_UVERBS_SOL_UVERBS_H
28 
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32 
33 /*
34  *
35  * NAME: sol_uverbs.h
36  *
37  * DESC: Solaris OFED User Verbs Kernel Agent header file.
38  *
39  */
40 #include <sys/ib/clients/of/ofed_kernel.h>
41 #include <sys/ib/clients/of/rdma/ib_user_verbs.h>
42 #include <sys/ib/clients/of/sol_uverbs/sol_uverbs_hca.h>
43 #include <sys/ib/clients/of/sol_ofs/sol_ofs_common.h>
44 #include <sys/ib/clients/of/sol_uverbs/sol_uverbs2ucma.h>
45 
46 /*
47  * Definitions
48  */
49 #define	SOL_UVERBS_DRIVER_MAX_HCA_MINOR	(16)
50 #define	SOL_UVERBS_DRIVER_EVENT_MINOR	(17)
51 #define	SOL_UVERBS_DRIVER_MAX_MINOR	(18)
52 
53 
54 /*
55  * Structures
56  */
57 
58 /*
59  * Kernel User Verbs Events.
60  *
61  * User verbs kernel events (asynchronous and completion) representation.
62  * IBT events are mapped back to OFA events.
63  */
64 typedef struct uverbs_event {
65 
66 	union {
67 		struct ib_uverbs_async_event_desc	async;
68 		struct ib_uverbs_comp_event_desc	comp;
69 	} ev_desc;
70 
71 	llist_head_t	ev_list;
72 	llist_head_t	ev_obj_list;
73 	uint32_t	*ev_counter;
74 } uverbs_event_t;
75 
76 
77 /*
78  * Module Context.
79  *
80  * There is a single module context which maintains the list
81  * of HCA's retrieved from IBT. A user process indicates the
82  * target HCA open via the uverbs unique minor device number
83  * associated with the HCA.
84  */
85 typedef struct {
86 	kmutex_t		lock;
87 	dev_info_t		*dip;
88 
89 	/*
90 	 * Underlying IBT HCA Info
91 	 */
92 
93 	ibt_clnt_modinfo_t	clnt_modinfo;
94 	ibt_clnt_hdl_t		clnt_hdl;
95 	uint32_t		hca_count;
96 	ib_guid_t		*hca_guid_list;
97 	sol_uverbs_hca_t	*hcas;
98 
99 	/*
100 	 * Support user asyncrhonous and completion event delivery via
101 	 * user event filesystem.
102 	 */
103 	dev_t			dev;
104 } uverbs_module_context_t;
105 
106 /*
107  * User Event File.
108  *
109  * Used for delivery of asynchronous and synchronous events to the user.
110  * An asynchronous event file is created during the allocation of
111  * a user verbs consumer context, a completion event file is created
112  * when the user verbs consumer creates a completion channel.
113  */
114 typedef struct uverbs_ufile_uobj {
115 	sol_ofs_uobj_t			uobj;
116 	kmutex_t			lock;
117 	int				ref;
118 	kcondvar_t			poll_wait;
119 	pollhead_t			poll_head;
120 	struct uverbs_uctxt_uobj	*uctxt;
121 	int				is_async;
122 	llist_head_t			event_list;
123 	sol_uverbs_cq_ctrl_t		ufile_notify_enabled;
124 	uint32_t			ufile_cq_cnt;
125 } uverbs_ufile_uobj_t;
126 
127 /*
128  * Type of user context -
129  */
130 #define		SOL_UVERBS_UCTXT_VERBS		0x001
131 #define		SOL_UVERBS_UCTXT_EVENT		0x100
132 #define		SOL_UVERBS_UCTXT_ASYNC		0x101
133 #define		SOL_UVERBS_UCTXT_COMPL		0x110
134 
135 /*
136  * User Context.
137  *
138  * A user context is created when a user process opens a specific minor
139  * device.  The context maintains a list of resources created by this
140  * user that allows the resources to be cleaned up on user close.
141  */
142 typedef struct uverbs_uctxt_uobj {
143 	sol_ofs_uobj_t		uobj;
144 	kmutex_t		lock;
145 	uverbs_module_context_t	*mod_ctxt;
146 	sol_uverbs_hca_t	*hca;		/* short cut to specific hca */
147 
148 	/*
149 	 * List of user resource objects created by this context.  The
150 	 * objects themselves live in the associated object table, and
151 	 * the code should use the table to access and use resources.
152 	 * Any objects that remain in these list will be destroyed at
153 	 * user close to free the associated resources.
154 	 *
155 	 * The user context "lock" should be held when invoking
156 	 * routines to manipulate the lists.
157 	 */
158 	genlist_t		pd_list;
159 	genlist_t		mr_list;
160 	genlist_t		cq_list;
161 	genlist_t		qp_list;
162 	genlist_t		srq_list;
163 	genlist_t		ah_list;
164 
165 	/*
166 	 * Event filesystem interfaces for IB asyncrhonous events
167 	 * and completion events.
168 	 */
169 	uverbs_ufile_uobj_t    *comp_evfile;
170 	uverbs_ufile_uobj_t    *async_evfile;
171 
172 	/*
173 	 * User context can be created for :
174 	 *	1. All Verbs API
175 	 *	2. For getting a file for async events.
176 	 *	3. For getting a file for completion events.
177 	 * For (1) - pointers to (2) & (3) will be updated. For (2) and (3)
178 	 * pointer to (1) will be maintained.
179 	 */
180 	uint16_t		uctxt_type;
181 	uint32_t		uctxt_verbs_id;
182 	uint32_t		uctxt_async_id;
183 	uint32_t		uctxt_comp_id;
184 	uint8_t			uctxt_free_pending;
185 } uverbs_uctxt_uobj_t;
186 
187 /*
188  * User PD objects created at PD allocation
189  */
190 typedef struct uverbs_upd_uobj {
191 	sol_ofs_uobj_t		uobj;
192 	ibt_pd_hdl_t		pd;
193 	genlist_entry_t		*list_entry;	/* per user ctx list entry */
194 	uint32_t		active_qp_cnt;
195 	uint8_t			free_pending;
196 } uverbs_upd_uobj_t;
197 
198 /*
199  * User MR objects created at MR registration
200  */
201 typedef struct uverbs_umr_uobj {
202 	sol_ofs_uobj_t	uobj;
203 	ibt_mr_hdl_t	mr;
204 	genlist_entry_t	*list_entry;	/* per user ctx list entry */
205 } uverbs_umr_uobj_t;
206 
207 /*
208  * User CQ objects created at CQ allocation
209  */
210 typedef struct uverbs_ucq_uobj {
211 	sol_ofs_uobj_t		uobj;
212 	ibt_cq_hdl_t		cq;
213 	genlist_entry_t		*list_entry;	/* per user ctx list entry */
214 	uverbs_uctxt_uobj_t	*uctxt;
215 	uverbs_ufile_uobj_t	*comp_chan;
216 	uint32_t		comp_events_reported;
217 	uint32_t		async_events_reported;
218 	llist_head_t		async_list;
219 	llist_head_t		comp_list;
220 	uint32_t		active_qp_cnt;
221 	uint8_t			free_pending;
222 } uverbs_ucq_uobj_t;
223 
224 /*
225  * User Shared Receive CQ objects created at SRQ allocation
226  */
227 typedef struct uverbs_usrq_uobj {
228 	sol_ofs_uobj_t		uobj;
229 	ibt_srq_hdl_t		srq;
230 	genlist_entry_t		*list_entry;	/* per user ctx list entry */
231 	uverbs_uctxt_uobj_t	*uctxt;
232 	uint32_t		async_events_reported;
233 	llist_head_t		async_list;
234 	uint32_t		active_qp_cnt;
235 	uint8_t			free_pending;
236 } uverbs_usrq_uobj_t;
237 
238 /*
239  * User address handle objects created at AH allocation
240  */
241 typedef struct uverbs_uah_uobj {
242 	sol_ofs_uobj_t	uobj;
243 	ibt_ah_hdl_t	ah;
244 	genlist_entry_t	*list_entry;	/* per user ctx list entry */
245 } uverbs_uah_uobj_t;
246 
247 /*
248  * User QP objects created at QP allocation
249  */
250 #define	SOL_UVERBS_UQP_RCQ_VALID	0x01
251 #define	SOL_UVERBS_UQP_SRQ_VALID	0x02
252 
253 typedef struct uverbs_uqp_uobj {
254 	sol_ofs_uobj_t			uobj;
255 	ibt_qp_hdl_t			qp;
256 	genlist_entry_t			*list_entry;	/* per uctx list */
257 	uint32_t			max_inline_data;
258 	uverbs_uctxt_uobj_t		*uctxt;
259 	uint32_t			qp_num;		/* 24 bits valid */
260 	uint32_t			disable_qp_mod;
261 	enum ib_qp_type			ofa_qp_type;
262 	llist_head_t			mcast_list;
263 	llist_head_t			async_list;
264 	uint32_t			async_events_reported;
265 	uverbs_ucq_uobj_t		*uqp_rcq;
266 	uverbs_ucq_uobj_t		*uqp_scq;
267 
268 	uint32_t			uqp_pd_hdl;
269 	uint32_t			uqp_scq_hdl;
270 	uint32_t			uqp_rcq_hdl;
271 	uint32_t			uqp_srq_hdl;
272 	uint8_t				uqp_rcq_srq_valid;
273 
274 	sol_uverbs_qp_free_state_t	uqp_free_state;
275 } uverbs_uqp_uobj_t;
276 
277 extern sol_ofs_uobj_table_t uverbs_uctxt_uo_tbl;
278 extern sol_ofs_uobj_table_t uverbs_upd_uo_tbl;
279 extern sol_ofs_uobj_table_t uverbs_uah_uo_tbl;
280 extern sol_ofs_uobj_table_t uverbs_umr_uo_tbl;
281 extern sol_ofs_uobj_table_t uverbs_ucq_uo_tbl;
282 extern sol_ofs_uobj_table_t uverbs_usrq_uo_tbl;
283 extern sol_ofs_uobj_table_t uverbs_uqp_uo_tbl;
284 extern sol_ofs_uobj_table_t uverbs_ufile_uo_tbl;
285 
286 /*
287  * The following structure is used currently to pass data back to
288  * libmthca on user allocation context.  This should be passed opaquely
289  * to maintain a true hal, we'll look for a generic way to get this information
290  * and deliver it opaquely post EA-1.
291  */
292 struct mthca_alloc_ucontext_resp {
293 	uint32_t	qp_tab_size;
294 	uint32_t	uarc_size;
295 };
296 
297 struct ib_udata {
298 	void	*inbuf;
299 	void	*outbuf;
300 	size_t	inlen;
301 	size_t	outlen;
302 };
303 
304 int sol_uverbs_dummy_command(uverbs_uctxt_uobj_t *uctxt, char *buf,
305     int in_len, int out_len);
306 int sol_uverbs_get_context(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
307     int out_len);
308 int sol_uverbs_alloc_pd(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
309     int out_len);
310 int sol_uverbs_dealloc_pd(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
311     int out_len);
312 int sol_uverbs_create_ah(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
313     int out_len);
314 int sol_uverbs_destroy_ah(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
315     int out_len);
316 int sol_uverbs_query_device(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
317     int out_len);
318 int sol_uverbs_query_port(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
319     int out_len);
320 int sol_uverbs_query_gid(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
321     int out_len);
322 int sol_uverbs_query_pkey(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
323     int out_len);
324 int sol_uverbs_reg_mr(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
325     int out_len);
326 int sol_uverbs_dereg_mr(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
327     int out_len);
328 int sol_uverbs_create_comp_channel(uverbs_uctxt_uobj_t *uctxt, char *buf,
329     int in_len, int out_len);
330 
331 uint32_t
332 sol_uverbs_ibt_to_of_device_cap_flags(ibt_hca_flags_t flags,
333     ibt_hca_flags2_t flags2);
334 
335 uint64_t
336 sol_uverbs_ibt_to_of_page_sz(ibt_page_sizes_t page_szs);
337 
338 int sol_uverbs_ibt_to_kernel_status(ibt_status_t  status);
339 uint32_t sol_uverbs_qpnum2uqpid(uint32_t qp_num);
340 
341 int uverbs_upd_free(uverbs_upd_uobj_t *, uverbs_uctxt_uobj_t *);
342 int uverbs_uqp_free(uverbs_uqp_uobj_t *, uverbs_uctxt_uobj_t *);
343 int uverbs_usrq_free(uverbs_usrq_uobj_t *, uverbs_uctxt_uobj_t *);
344 int uverbs_ucq_free(uverbs_ucq_uobj_t *, uverbs_uctxt_uobj_t *);
345 
346 /*
347  * The following helpers simply provide easy access for acquiring and locking
348  * User Objects.
349  */
350 static inline uverbs_uctxt_uobj_t *
uverbs_uobj_get_uctxt_read(uint32_t id)351 uverbs_uobj_get_uctxt_read(uint32_t id)
352 {
353 	return (uverbs_uctxt_uobj_t *)
354 	    sol_ofs_uobj_get_read(&uverbs_uctxt_uo_tbl, id);
355 }
356 static inline uverbs_uctxt_uobj_t *
uverbs_uobj_get_uctxt_write(uint32_t id)357 uverbs_uobj_get_uctxt_write(uint32_t id)
358 {
359 	return (uverbs_uctxt_uobj_t *)
360 	    sol_ofs_uobj_get_write(&uverbs_uctxt_uo_tbl, id);
361 }
362 static inline uverbs_upd_uobj_t *
uverbs_uobj_get_upd_read(uint32_t id)363 uverbs_uobj_get_upd_read(uint32_t id)
364 {
365 	return (uverbs_upd_uobj_t *)
366 	    sol_ofs_uobj_get_read(&uverbs_upd_uo_tbl, id);
367 }
368 static inline uverbs_upd_uobj_t *
uverbs_uobj_get_upd_write(uint32_t id)369 uverbs_uobj_get_upd_write(uint32_t id)
370 {
371 	return (uverbs_upd_uobj_t *)
372 	    sol_ofs_uobj_get_write(&uverbs_upd_uo_tbl, id);
373 }
374 static inline uverbs_umr_uobj_t *
uverbs_uobj_get_umr_read(uint32_t id)375 uverbs_uobj_get_umr_read(uint32_t id)
376 {
377 	return (uverbs_umr_uobj_t *)
378 	    sol_ofs_uobj_get_read(&uverbs_umr_uo_tbl, id);
379 }
380 static inline uverbs_umr_uobj_t *
uverbs_uobj_get_umr_write(uint32_t id)381 uverbs_uobj_get_umr_write(uint32_t id)
382 {
383 	return (uverbs_umr_uobj_t *)
384 	    sol_ofs_uobj_get_write(&uverbs_umr_uo_tbl, id);
385 }
386 static inline uverbs_ucq_uobj_t *
uverbs_uobj_get_ucq_read(uint32_t id)387 uverbs_uobj_get_ucq_read(uint32_t id)
388 {
389 	return (uverbs_ucq_uobj_t *)
390 	    sol_ofs_uobj_get_read(&uverbs_ucq_uo_tbl, id);
391 }
392 static inline uverbs_ucq_uobj_t *
uverbs_uobj_get_ucq_write(uint32_t id)393 uverbs_uobj_get_ucq_write(uint32_t id)
394 {
395 	return (uverbs_ucq_uobj_t *)
396 	    sol_ofs_uobj_get_write(&uverbs_ucq_uo_tbl, (int)id);
397 }
398 static inline uverbs_usrq_uobj_t *
uverbs_uobj_get_usrq_read(uint32_t id)399 uverbs_uobj_get_usrq_read(uint32_t id)
400 {
401 	return (uverbs_usrq_uobj_t *)
402 	    sol_ofs_uobj_get_read(&uverbs_usrq_uo_tbl, id);
403 }
404 static inline uverbs_usrq_uobj_t *
uverbs_uobj_get_usrq_write(uint32_t id)405 uverbs_uobj_get_usrq_write(uint32_t id)
406 {
407 	return (uverbs_usrq_uobj_t *)
408 	    sol_ofs_uobj_get_write(&uverbs_usrq_uo_tbl, id);
409 }
410 static inline uverbs_uah_uobj_t *
uverbs_uobj_get_uah_read(uint32_t id)411 uverbs_uobj_get_uah_read(uint32_t id)
412 {
413 	return (uverbs_uah_uobj_t *)
414 	    sol_ofs_uobj_get_read(&uverbs_uah_uo_tbl, id);
415 }
416 static inline uverbs_uah_uobj_t *
uverbs_uobj_get_uah_write(uint32_t id)417 uverbs_uobj_get_uah_write(uint32_t id)
418 {
419 	return (uverbs_uah_uobj_t *)
420 	    sol_ofs_uobj_get_write(&uverbs_uah_uo_tbl, id);
421 }
422 static inline uverbs_uqp_uobj_t *
uverbs_uobj_get_uqp_read(uint32_t id)423 uverbs_uobj_get_uqp_read(uint32_t id)
424 {
425 	return (uverbs_uqp_uobj_t *)
426 	    sol_ofs_uobj_get_read(&uverbs_uqp_uo_tbl, id);
427 }
428 static inline uverbs_uqp_uobj_t *
uverbs_uobj_get_uqp_write(uint32_t id)429 uverbs_uobj_get_uqp_write(uint32_t id)
430 {
431 	return (uverbs_uqp_uobj_t *)
432 	    sol_ofs_uobj_get_write(&uverbs_uqp_uo_tbl, id);
433 }
434 
435 #ifdef __cplusplus
436 }
437 #endif
438 #endif /* _SYS_IB_CLIENTS_OF_SOL_UVERBS_SOL_UVERBS_H */
439