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
31extern "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 */
42typedef 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 */
63typedef 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 */
74typedef 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
80typedef struct daplka_hash_bucket {
81	uint32_t			hb_count;
82	daplka_hash_entry_t		*hb_entries;
83} daplka_hash_bucket_t;
84
85typedef 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 */
108typedef 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
132typedef 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 */
142typedef 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
149typedef 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
181typedef 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 */
199typedef 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 */
210typedef 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
225typedef 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 */
236typedef 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
246typedef 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
253typedef 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
283typedef 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
304typedef 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
327typedef 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
333typedef 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
349typedef 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 */
363typedef enum {
364	DAPLKA_SPCP_INIT = 0,
365	DAPLKA_SPCP_PENDING
366} daplka_spcp_state_t;
367
368typedef 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
378typedef 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
396typedef 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
410typedef 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
426typedef 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
431struct 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