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 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef	_DAPL_H_
28 #define	_DAPL_H_
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 #define	DAPLKA_VERSION		(1)
35 #define	DAPLKA_TQ_NTHREADS	16
36 #define	DAPLKA_STATE_DETACHED	0x0000
37 #define	DAPLKA_STATE_ATTACHED	0x0001
38 
39 /*
40  * HCA structure
41  */
42 typedef struct daplka_hca {
43 	ib_guid_t		hca_guid;
44 	ibt_hca_hdl_t		hca_hdl;
45 	ibt_hca_attr_t		hca_attr;
46 	uint32_t		hca_nports;
47 	ibt_hca_portinfo_t	*hca_ports;
48 	size_t			hca_pinfosz;
49 	uint32_t		hca_qp_count;
50 	uint32_t		hca_cq_count;
51 	uint32_t		hca_pd_count;
52 	uint32_t		hca_mw_count;
53 	uint32_t		hca_mr_count;
54 	uint32_t		hca_srq_count;
55 	int			hca_ref_cnt;
56 	struct daplka_hca	*hca_next;
57 } daplka_hca_t;
58 _NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_hca))
59 
60 /*
61  * Per-Device instance state information.
62  */
63 typedef struct daplka {
64 	kmutex_t		daplka_mutex;
65 	dev_info_t		*daplka_dip;
66 	ibt_clnt_hdl_t		daplka_clnt_hdl;
67 	daplka_hca_t		*daplka_hca_list_head;
68 	uint32_t		daplka_status;
69 } daplka_t;
70 
71 /*
72  * generic hash table
73  */
74 typedef struct daplka_hash_entry {
75 	uint64_t			he_hkey;
76 	void				*he_objp;
77 	struct daplka_hash_entry	*he_next;
78 } daplka_hash_entry_t;
79 
80 typedef struct daplka_hash_bucket {
81 	uint32_t			hb_count;
82 	daplka_hash_entry_t		*hb_entries;
83 } daplka_hash_bucket_t;
84 
85 typedef struct daplka_hash_table {
86 	boolean_t			ht_initialized;
87 	uint32_t			ht_count;
88 	uint32_t			ht_nbuckets;
89 	uint64_t			ht_next_hkey;
90 	krwlock_t			ht_table_lock;
91 	kmutex_t			ht_key_lock;
92 	daplka_hash_bucket_t		*ht_buckets;
93 	void				(*ht_free_func)(void *);
94 	void				(*ht_lookup_func)(void *);
95 } daplka_hash_table_t;
96 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_hash_entry))
97 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_hash_bucket))
98 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_hash_table))
99 _NOTE(MUTEX_PROTECTS_DATA(daplka_hash_table::ht_key_lock,
100     daplka_hash_table::ht_next_hkey))
101 _NOTE(RWLOCK_PROTECTS_DATA(daplka_hash_table::ht_table_lock,
102     daplka_hash_table::ht_buckets
103     daplka_hash_table::ht_count))
104 
105 /*
106  * resource structure header
107  */
108 typedef struct daplka_resource {
109 	uint_t			rs_type;
110 	minor_t			rs_rnum;
111 	kmutex_t 		rs_reflock;
112 	uint32_t		rs_refcnt;
113 	uint32_t		rs_charged;
114 	int			(*rs_free)(struct daplka_resource *);
115 } daplka_resource_t;
116 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_resource))
117 _NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_resource::rs_charged))
118 _NOTE(MUTEX_PROTECTS_DATA(daplka_resource::rs_reflock,
119     daplka_resource::rs_refcnt))
120 
121 #define	DAPLKA_EP_HTBL_SZ	128
122 #define	DAPLKA_MR_HTBL_SZ	64
123 #define	DAPLKA_MW_HTBL_SZ	64
124 #define	DAPLKA_PD_HTBL_SZ	32
125 #define	DAPLKA_SP_HTBL_SZ	32
126 #define	DAPLKA_EVD_HTBL_SZ	32
127 #define	DAPLKA_G_SP_HTBL_SZ	512
128 #define	DAPLKA_TIMER_HTBL_SZ	512
129 #define	DAPLKA_CNO_HTBL_SZ	16
130 #define	DAPLKA_SRQ_HTBL_SZ	32
131 
132 typedef struct daplka_async_evd_hkey_s {
133 	struct daplka_async_evd_hkey_s	*aeh_next;
134 	uint64_t			aeh_evd_hkey;
135 } daplka_async_evd_hkey_t;
136 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_async_evd_hkey_s))
137 
138 /*
139  * Various states IA can be in, this is primarily for handling race
140  * between MW allocation and MR cleanup callback.
141  */
142 typedef enum daplka_ia_state_e {
143 	DAPLKA_IA_INIT = 0,
144 	DAPLKA_IA_MW_ALLOC_IN_PROGRESS,
145 	DAPLKA_IA_MW_FREEZE_IN_PROGRESS,
146 	DAPLKA_IA_MW_FROZEN
147 } daplka_ia_state_t;
148 
149 typedef struct daplka_ia_resource {
150 	daplka_resource_t	header;
151 	kmutex_t		ia_lock;
152 	kcondvar_t		ia_cv;
153 	daplka_ia_state_t	ia_state;
154 	ibt_hca_hdl_t		ia_hca_hdl;
155 	ib_gid_t		ia_hca_sgid;
156 	daplka_hca_t		*ia_hca;
157 	uint8_t			ia_port_num;
158 	uint32_t		ia_port_pkey;
159 	pid_t			ia_pid;
160 	uint32_t		ia_mw_alloccnt; /* # mw allocs in progress */
161 	daplka_async_evd_hkey_t	*ia_async_evd_hkeys; /* hash key of async evd */
162 	daplka_hash_table_t	ia_ep_htbl;
163 	daplka_hash_table_t	ia_mr_htbl;
164 	daplka_hash_table_t	ia_mw_htbl;
165 	daplka_hash_table_t	ia_pd_htbl;
166 	daplka_hash_table_t	ia_evd_htbl;
167 	daplka_hash_table_t	ia_sp_htbl;
168 	daplka_hash_table_t	ia_cno_htbl;
169 	daplka_hash_table_t	ia_srq_htbl;
170 	uint8_t			ia_sadata[DAPL_ATS_NBYTES]; /* SA data */
171 	boolean_t		ia_ar_registered;
172 } daplka_ia_resource_t;
173 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_ia_resource))
174 _NOTE(MUTEX_PROTECTS_DATA(daplka_ia_resource::ia_lock,
175     daplka_ia_resource::ia_cv
176     daplka_ia_resource::ia_async_evd_hkeys
177     daplka_ia_resource::ia_mw_alloccnt
178     daplka_ia_resource::ia_state
179     daplka_async_evd_hkey_s))
180 
181 typedef struct daplka_pd_resource {
182 	daplka_resource_t	header;
183 	daplka_hca_t		*pd_hca;
184 	ibt_hca_hdl_t		pd_hca_hdl;
185 	ibt_pd_hdl_t		pd_hdl;
186 } daplka_pd_resource_t;
187 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_pd_resource))
188 
189 /*
190  * Passive side EP cookies - this is generated at the connection request
191  * time and unique for every CR. It gets associated with the EP that
192  * is passed to the CR accept.
193  *
194  * daplka_psep_cookie contains the following information
195  *   - 48 bit timestamp (unit = 1/10us)
196  *   - 16 bit index in the psp backlog array corr to this CR event
197  * this makes it unique for every CR.
198  */
199 typedef uint64_t daplka_psep_cookie_t;
200 #define	DAPLKA_CREATE_PSEP_COOKIE(index)	\
201 			((uint64_t)((gethrtime()/100)<<16 | (index)))
202 #define	DAPLKA_GET_PSEP_INDEX(cookie)					\
203 					((uint16_t)((uint64_t)(cookie) &\
204 						0xffff))
205 
206 /*
207  * daplka_evd_cme_t defines connection manager events that can be
208  * chained to the daplka_evd_cme_list_t.
209  */
210 typedef struct daplka_evd_cme_s {
211 	dapl_ib_cm_event_type_t	ec_cm_ev_type;
212 	/* ec_cm_cookie is the SP(passive)/EP(active) cookie */
213 	uint64_t		ec_cm_cookie;
214 	/* ec_cm_ev_session_id is the cookie for DEFER processing */
215 	void			*ec_cm_ev_session_id;
216 	/* true - passive side event, false - active side event */
217 	boolean_t		ec_cm_is_passive;
218 	daplka_psep_cookie_t	ec_cm_psep_cookie;
219 	ib_gid_t		ec_cm_req_prim_addr; /* requestor gid */
220 	ibt_priv_data_len_t	ec_cm_ev_priv_data_len;
221 	void			*ec_cm_ev_priv_data;
222 } daplka_evd_cme_t;
223 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_evd_cme_s))
224 
225 typedef enum daplka_evd_event_type_e {
226 	DAPLKA_EVD_NO_EVENTS = 0x00,
227 	DAPLKA_EVD_ULAND_EVENTS = 0x01, /* userland events ie. CQ or SE */
228 	DAPLKA_EVD_CM_EVENTS = 0x02,
229 	DAPLKA_EVD_ASYNC_EVENTS = 0x04
230 } daplka_evd_event_type_t;
231 
232 /*
233  * daplka_evd_event_t defines elements in the event list - this is
234  * used for both async as well as connection manager events
235  */
236 typedef struct daplka_evd_event_s {
237 	struct daplka_evd_event_s	*ee_next;
238 	union {
239 		dapl_ib_async_event_t		aev;
240 		daplka_evd_cme_t		cmev;
241 	} ee_event;
242 #define	ee_aev	ee_event.aev
243 #define	ee_cmev	ee_event.cmev
244 } daplka_evd_event_t;
245 
246 typedef struct daplka_evd_event_list_s {
247 	daplka_evd_event_type_t	eel_event_type;
248 	uint32_t		eel_num_elements;
249 	daplka_evd_event_t	*eel_head;
250 	daplka_evd_event_t	*eel_tail;
251 } daplka_evd_event_list_t;
252 
253 typedef struct daplka_evd_resource {
254 	daplka_resource_t	header;
255 	kmutex_t		evd_lock;
256 	kcondvar_t		evd_cv;
257 	DAT_EVD_FLAGS		evd_flags;
258 	daplka_evd_event_type_t	evd_newevents; /* DAPLKA_EVD_*_EVENTS */
259 	ibt_cq_hdl_t		evd_cq_hdl;
260 	uint32_t		evd_cq_real_size;
261 	daplka_evd_event_list_t	evd_cr_events; /* connect request event */
262 	daplka_evd_event_list_t	evd_conn_events; /* connection events */
263 	daplka_evd_event_list_t	evd_async_events; /* aysnc events list */
264 	ibt_hca_hdl_t		evd_hca_hdl;
265 	daplka_hca_t		*evd_hca;
266 	uint32_t		evd_waiters;
267 	uint64_t		evd_cookie;
268 	struct daplka_cno_resource	*evd_cno_res;
269 } daplka_evd_resource_t;
270 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_evd_event_s))
271 _NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_evd_event_s))
272 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_evd_event_list_s))
273 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_evd_resource))
274 _NOTE(MUTEX_PROTECTS_DATA(daplka_evd_resource::evd_lock,
275     daplka_evd_resource::evd_cv
276     daplka_evd_resource::evd_flags
277     daplka_evd_resource::evd_newevents
278     daplka_evd_resource::evd_cr_events
279     daplka_evd_resource::evd_conn_events
280     daplka_evd_resource::evd_async_events
281     daplka_evd_resource::evd_waiters))
282 
283 typedef struct daplka_srq_resource {
284 	daplka_resource_t	header;
285 	kmutex_t		srq_lock;
286 	daplka_hca_t		*srq_hca;
287 	ibt_hca_hdl_t		srq_hca_hdl;
288 	daplka_pd_resource_t	*srq_pd_res;
289 	ibt_srq_hdl_t		srq_hdl;
290 	uint32_t		srq_real_size;
291 } daplka_srq_resource_t;
292 _NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_srq_resource))
293 
294 #define	DAPLKA_EP_STATE_CLOSED		0x0001
295 #define	DAPLKA_EP_STATE_CONNECTING	0x0002
296 #define	DAPLKA_EP_STATE_ACCEPTING	0x0003
297 #define	DAPLKA_EP_STATE_CONNECTED	0x0004
298 #define	DAPLKA_EP_STATE_DISCONNECTING	0x0005
299 #define	DAPLKA_EP_STATE_ABORTING	0x0006
300 #define	DAPLKA_EP_STATE_DISCONNECTED	0x0007
301 #define	DAPLKA_EP_STATE_TRANSITIONING	0x0008
302 #define	DAPLKA_EP_STATE_FREED		0x0009
303 
304 typedef struct daplka_ep_resource {
305 	daplka_resource_t	header;
306 	kmutex_t		ep_lock;
307 	kcondvar_t		ep_cv;
308 	uint64_t		ep_cookie; /* userland ep pointer */
309 	daplka_hca_t		*ep_hca;
310 	ibt_channel_hdl_t	ep_chan_hdl;
311 	daplka_evd_resource_t	*ep_snd_evd;
312 	daplka_evd_resource_t	*ep_rcv_evd;
313 	daplka_evd_resource_t	*ep_conn_evd;
314 	daplka_evd_resource_t	*ep_bind_evd;
315 	daplka_pd_resource_t	*ep_pd_res;
316 	daplka_srq_resource_t	*ep_srq_res;
317 	uint32_t		ep_state;
318 	uint64_t		ep_timer_hkey;
319 	daplka_psep_cookie_t	ep_psep_cookie; /* passive side ep cookie */
320 	ibt_priv_data_len_t	ep_priv_len;
321 	uint8_t			ep_priv_data[IBT_REP_PRIV_DATA_SZ];
322 	ib_gid_t		ep_sgid;
323 	ib_gid_t		ep_dgid;
324 } daplka_ep_resource_t;
325 _NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_ep_resource))
326 
327 typedef struct daplka_timer_info {
328 	daplka_ep_resource_t	*ti_ep_res;
329 	timeout_id_t		ti_tmo_id;
330 } daplka_timer_info_t;
331 _NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_timer_info))
332 
333 typedef struct daplka_mr_resource {
334 	daplka_resource_t		header;
335 	daplka_pd_resource_t		*mr_pd_res;
336 	daplka_hca_t			*mr_hca;
337 	ibt_hca_hdl_t			mr_hca_hdl;
338 	ibt_mr_hdl_t			mr_hdl;
339 	ibt_mr_attr_t			mr_attr;
340 	ibt_mr_desc_t			mr_desc;
341 	kmutex_t			mr_lock;
342 	struct daplka_mr_resource	*mr_next;
343 	struct daplka_shared_mr		*mr_shared_mr;
344 } daplka_mr_resource_t;
345 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_mr_resource))
346 _NOTE(MUTEX_PROTECTS_DATA(daplka_mr_resource::mr_lock,
347     daplka_mr_resource::mr_shared_mr))
348 
349 typedef struct daplka_mw_resource {
350 	daplka_resource_t	header;
351 	daplka_pd_resource_t	*mw_pd_res;
352 	daplka_hca_t		*mw_hca;
353 	ibt_hca_hdl_t		mw_hca_hdl;
354 	ibt_mw_hdl_t		mw_hdl;
355 	kmutex_t		mw_lock;
356 } daplka_mw_resource_t;
357 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_mw_resource))
358 
359 /*
360  * This describes the elements in a connection pending list that each SP
361  * maintains. Fields are protected using the sp_lock.
362  */
363 typedef enum {
364 	DAPLKA_SPCP_INIT = 0,
365 	DAPLKA_SPCP_PENDING
366 } daplka_spcp_state_t;
367 
368 typedef struct daplka_sp_conn_pend_s {
369 	daplka_spcp_state_t	spcp_state;
370 	void			*spcp_sid; /* session id for cm_proceed */
371 	uint32_t		spcp_req_len; /* used by cr_handoff */
372 	char			spcp_req_data[DAPL_MAX_PRIVATE_DATA_SIZE];
373 	uint8_t			spcp_rdma_ra_out;
374 	uint8_t			spcp_rdma_ra_in;
375 } daplka_sp_conn_pend_t;
376 
377 #define	DAPLKA_DEFAULT_SP_BACKLOG	256
378 typedef struct daplka_sp_resource {
379 	daplka_resource_t	header;
380 	kmutex_t		sp_lock;
381 	ibt_srv_hdl_t		sp_srv_hdl;
382 	ibt_sbind_hdl_t		sp_bind_hdl;
383 	uint64_t		sp_cookie; /* userland sp pointer */
384 	int			sp_backlog_size; /* # elements backlog */
385 	daplka_sp_conn_pend_t	*sp_backlog; /* pending conn backlog array */
386 	daplka_evd_resource_t	*sp_evd_res;
387 	ib_svc_id_t		sp_conn_qual;
388 	uint64_t		sp_global_hkey;
389 	uid_t			sp_ruid;
390 } daplka_sp_resource_t;
391 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_sp_resource))
392 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_sp_conn_pend_s))
393 _NOTE(MUTEX_PROTECTS_DATA(daplka_sp_resource::sp_lock,
394     daplka_sp_resource::sp_backlog))
395 
396 typedef struct daplka_cno_resource {
397 	daplka_resource_t	header;
398 	kmutex_t		cno_lock;
399 	kcondvar_t		cno_cv;
400 	uint64_t		cno_evd_cookie;
401 } daplka_cno_resource_t;
402 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_cno_resource))
403 _NOTE(MUTEX_PROTECTS_DATA(daplka_cno_resource::cno_lock,
404     daplka_cno_resource::cno_cv
405     daplka_cno_resource::cno_evd_cookie))
406 
407 #define	DAPLKA_SMR_FREED		0x0000
408 #define	DAPLKA_SMR_TRANSITIONING	0x0001
409 #define	DAPLKA_SMR_READY		0x0002
410 typedef struct daplka_shared_mr {
411 	avl_node_t		smr_node;
412 	uint32_t		smr_refcnt;
413 	uint32_t		smr_state;
414 	daplka_mr_resource_t	*smr_mr_list;
415 	kcondvar_t		smr_cv;
416 	dapl_mr_cookie_t	smr_cookie;
417 } daplka_shared_mr_t;
418 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_shared_mr))
419 _NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_shared_mr::smr_mr_list))
420 
421 /*
422  * resource table data structures
423  */
424 #define	DAPLKA_RC_BLKSZ		16
425 #define	DAPLKA_RC_RESERVED	0xff
426 typedef struct daplka_resource_blk {
427 	int			daplka_rcblk_avail;
428 	daplka_resource_t	*daplka_rcblk_blks[DAPLKA_RC_BLKSZ];
429 } daplka_resource_blk_t;
430 
431 struct daplka_resource_table {
432 	krwlock_t	daplka_rct_lock;
433 	int		daplka_rc_len;
434 	int		daplka_rc_sz;
435 	int		daplka_rc_cnt;
436 	ushort_t	daplka_rc_flag;
437 	daplka_resource_blk_t **daplka_rc_root;
438 };
439 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_resource_table))
440 _NOTE(RWLOCK_PROTECTS_DATA(daplka_resource_table::daplka_rct_lock,
441     daplka_resource_table::daplka_rc_root))
442 
443 #ifdef __cplusplus
444 }
445 #endif
446 
447 #endif	/* _DAPL_H_ */
448