xref: /illumos-gate/usr/src/uts/common/sys/ib/ibtl/impl/ibtl.h (revision d8a7fe16f62711cdc5c4267da8b34ff24a6b668c)
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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef _SYS_IB_IBTL_IMPL_IBTL_H
27 #define	_SYS_IB_IBTL_IMPL_IBTL_H
28 
29 /*
30  * ibtl.h
31  *
32  * All data structures and function prototypes that are specific to the
33  * IBTL implementation.
34  */
35 #include <sys/note.h>
36 #include <sys/ib/ibtl/ibvti.h>
37 #include <sys/ib/ibtl/ibti.h>
38 #include <sys/ib/ibtl/ibci.h>
39 #include <sys/ib/ibtl/impl/ibtl_util.h>
40 
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44 
45 /*
46  * Define a per IBT Client state structure. Its address is returned
47  * to the IBT client as an opaque IBT Client Handle - ibt_clnt_hdl_t.
48  *
49  * ibt_attach() allocates one of these structures.
50  *
51  * For each IBT Client registered with the IBTL, we maintain a list
52  * of HCAs, clnt_hca_list, that this IBT Client is using.
53  *
54  * This list is updated by ibt_open_hca().
55  */
56 typedef struct ibtl_clnt_s {
57 	char			clnt_name[8];	/* (just a debugging aid) */
58 	ibt_clnt_modinfo_t	*clnt_modinfop;	/* Pointer to IBT client's */
59 						/* module information */
60 	void			*clnt_private;	/* IBT Client's private ptr */
61 	dev_info_t		*clnt_dip;	/* IBT Client's dip */
62 	struct	ibtl_clnt_s	*clnt_list_link;
63 	uint32_t		clnt_async_cnt;
64 	uint32_t		clnt_srv_cnt;	/* Service resource counter */
65 	struct	ibtl_hca_s	*clnt_hca_list;	/* HCAs this client is using. */
66 						/* link is ha_hca_link */
67 	ibt_sm_notice_handler_t	clnt_sm_trap_handler; /* may be NULL */
68 	void			*clnt_sm_trap_handler_arg;
69 } ibtl_clnt_t;
70 
71 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibtl_clnt_s::{clnt_name clnt_modinfop
72     clnt_private clnt_dip}))
73 
74 /* HCA Device State. */
75 typedef enum ibtl_hca_state_e {
76 	IBTL_HCA_DEV_ATTACHED	= 1,	/* new HCA attached */
77 	IBTL_HCA_DEV_DETACHED	= 2,	/* detached */
78 	IBTL_HCA_DEV_DETACHING	= 3	/* not detached yet */
79 } ibtl_hca_state_t;
80 
81 /*
82  * Define a type to record hca async PORT_UP and PORT_DOWN events for
83  * processing by async thread(s). At the time an async is made by an
84  * HCA driver (presumably at interrupt level), a call is made to IBTL.
85  * IBTL marks this field, and wakes up an async thread for delivery
86  * to IBT clients as appropriate.
87  */
88 
89 typedef enum ibtl_async_port_status_e {
90 	IBTL_HCA_PORT_UNKNOWN		= 0x000,	/* initial state */
91 	IBTL_HCA_PORT_UP		= 0x001,
92 	IBTL_HCA_PORT_DOWN		= 0x002,
93 	IBTL_HCA_PORT_CHG		= 0x004,
94 	IBTL_HCA_PORT_ASYNC_CLNT_REREG	= 0x008,
95 } ibtl_async_port_status_t;
96 
97 /*
98  * Define a type to record the PORT async events and port change flags.
99  */
100 typedef struct ibtl_async_port_event_s {
101 	ibtl_async_port_status_t	status;
102 	ibt_port_change_t		flags;
103 } ibtl_async_port_event_t;
104 
105 /*
106  * Bit definition(s) for {qp,cq,eec,hd,ha,srq}_async_flags.
107  *
108  *	IBTL_ASYNC_PENDING	This structure is known by the async_threads.
109  *				It will be checked for additional async work
110  *				before this bit is cleared, so new async
111  *				events/errors do not require this structure
112  *				to be linked onto its async list.
113  *
114  *	IBTL_ASYNC_FREE_OBJECT  Client has called ibt_free_*, and the
115  *				the structure should be kmem_freed when
116  *				the outstanding asyncs complete.
117  */
118 typedef enum ibtl_async_flags_e {
119 	IBTL_ASYNC_PENDING	= 0x1,
120 	IBTL_ASYNC_FREE_OBJECT	= 0x2
121 } ibtl_async_flags_t;
122 
123 /*
124  * Keeps track of all data associated with HCA port kstats.
125  */
126 typedef struct ibtl_hca_port_kstat_s {
127 	struct ibtl_hca_devinfo_s *pks_hca_devp;
128 	uint_t			pks_port_num;
129 	struct kstat		*pks_stats_ksp;
130 	struct kstat		*pks_pkeys_ksp;
131 } ibtl_hca_port_kstat_t;
132 
133 /*
134  * Define a per CI HCA Device structure. Its address is returned
135  * to the CI as an opaque IBTL HCA Handle - ibc_hdl_t.
136  *
137  * ibc_ci_attach() allocates one of these and adds it to ibtl_hca_list.
138  *
139  * The hd_hca_dev_link is the link for the ibtl_hca_list. It is the
140  * list of HCA devices registered with the IBTL.
141  *
142  * The hd_clnt_list is a list of IBT Clients using this HCA.
143  * The hd_clnt_list->l_head points to the ha_clnt_link field of a client's
144  * ibtl_hca_s structure.
145  *
146  * This list is updated by ibt_open_hca().
147  */
148 typedef struct ibtl_hca_devinfo_s {
149 	struct ibtl_hca_devinfo_s *hd_hca_dev_link; /* Next HCA Device */
150 	ibtl_hca_state_t	hd_state;	/* HCA device state: */
151 						/* attached/detached */
152 	uint_t			hd_portinfo_len; /* #bytes of portinfo */
153 	ibt_hca_portinfo_t	*hd_portinfop;	/* ptr to portinfo cache */
154 	struct ibtl_hca_s	*hd_clnt_list;	/* IBT Client using this HCA. */
155 	ibc_hca_hdl_t		hd_ibc_hca_hdl;	/* CI HCA handle */
156 	ibc_operations_t	*hd_ibc_ops;	/* operations vector */
157 	ibt_hca_attr_t		*hd_hca_attr;	/* hca attributes */
158 	dev_info_t		*hd_hca_dip;	/* HCA devinfo pointer */
159 	struct ibtl_hca_devinfo_s *hd_async_link; /* async list link */
160 	kcondvar_t		hd_portinfo_cv;	/* waiting for ibc_query */
161 	int			hd_portinfo_waiters; /* any waiters */
162 	uint8_t			hd_portinfo_locked_port;
163 						/* port whose info is queried */
164 	kcondvar_t		hd_async_busy_cv; /* wakeup when #clients = 0 */
165 	int			hd_async_busy;	/* only 1 async at a time */
166 	ibt_async_code_t	hd_async_codes;	/* all codes for this HCA */
167 	ibt_async_code_t	hd_async_code;	/* current code being run */
168 	ibt_async_event_t	hd_async_event;	/* current event being run */
169 	ibtl_async_flags_t	hd_async_flags;	/* see *_async_flags above */
170 	uint64_t		hd_fma_ena;	/* FMA data for LOCAL CATASTR */
171 	uint32_t		hd_async_task_cnt; /* #clients doing asyncs */
172 	kcondvar_t		hd_async_task_cv; /* wakeup when #clients = 0 */
173 	uint_t			hd_multism;	/* 1 - MultiSM, 0 - Single SM */
174 	ibtl_hca_port_kstat_t	*hd_hca_port_ks_info;	/* port kstat ptr */
175 	uint_t			hd_hca_port_ks_info_len; /* port kstat size */
176 		/* The following must be at the end of this struct */
177 	ibtl_async_port_event_t hd_async_port[1]; /* per-port async data */
178 } ibtl_hca_devinfo_t;
179 
180 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibtl_hca_devinfo_s::hd_ibc_ops))
181 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibtl_hca_devinfo_s::hd_ibc_hca_hdl))
182 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibtl_hca_devinfo_s::hd_hca_attr))
183 _NOTE(SCHEME_PROTECTS_DATA("hd_async_busy and hd_async_busy_cv",
184     ibtl_hca_devinfo_s::{hd_async_code hd_async_event}))
185 
186 /*
187  * Define a HCA info structure.
188  *
189  * The IBTL function ibt_open_hca() allocates one of these.
190  *
191  * For each client instance registered with the IBTL, we maintain a list
192  * of HCAs that it is using.  The elements of that list include the
193  * address of the CI HCA device structure, a pointer to the client
194  * structure, and reference counts of HCA resources that this client
195  * device is using.
196  *
197  * Note: ha_qpn_cnt is protected by a global mutex to deal with a client
198  * trying to open the HCA while it is actively being closed.
199  *
200  * ha_hca_link is the link to the next HCA info struct that this client is
201  * using.
202  *
203  * ha_clnt_link is the link to the next IBT client (ibtl_clnt_t) that is using
204  * the same CI HCA (ibtl_hca_devinfo_t). The link points to that client's
205  * ibtl_hca_t because an IBT client can use more than one CI HCA.
206  */
207 typedef struct ibtl_hca_s {
208 	struct ibtl_hca_s	*ha_hca_link;	/* Next HCA used by client */
209 	struct ibtl_hca_s	*ha_clnt_link;	/* Next client using same HCA */
210 	ibtl_hca_devinfo_t	*ha_hca_devp;	/* CI HCA device structure. */
211 	ibtl_clnt_t		*ha_clnt_devp;	/* Client state struct */
212 	void			*ha_clnt_private;
213 	kmutex_t		ha_mutex;	/* Mutex to protect resource */
214 						/* counters. */
215 	int			ha_flags;	/* misc. flags */
216 	uint32_t		ha_qp_cnt;	/* QP resource counter */
217 	uint32_t		ha_eec_cnt;	/* EEC resource counter */
218 	uint32_t		ha_cq_cnt;	/* CQ resource counter */
219 	uint32_t		ha_pd_cnt;	/* PD resource counter */
220 	uint32_t		ha_ah_cnt;	/* AH resource counter */
221 	uint32_t		ha_mr_cnt;	/* Mem Region resource count */
222 	uint32_t		ha_mw_cnt;	/* Mem Window resource count */
223 	uint32_t		ha_qpn_cnt;	/* QPN resource counter */
224 	uint32_t		ha_srq_cnt;	/* SRQ resource counter */
225 	ibtl_async_flags_t	ha_async_flags;	/* see *_async_flags above */
226 	uint32_t		ha_async_cnt;	/* #asyncs in progress */
227 	uint32_t		ha_fmr_pool_cnt; /* FMR Pool resource count */
228 	uint32_t		ha_ma_cnt;	/* Mem Area resource count */
229 } ibtl_hca_t;
230 
231 /* ha_flags values */
232 #define	IBTL_HA_CLOSING	1	/* In process of closing, so don't allow open */
233 
234 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibtl_hca_s::ha_clnt_devp))
235 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibtl_hca_s::ha_hca_devp))
236 
237 /*
238  * Bit definition(s) for cq_impl_flags.
239  *
240  *	IBTL_CQ_PENDING		This CQ is known by the ibtl_cq_threads,
241  *				and it will be checked for additional work
242  *				before this bit is cleared, so new work
243  *				will be seen without this cq being added
244  *				to the cq list.
245  *
246  *	IBTL_CQ_CALL_CLIENT	Mark that the HCA driver has called
247  *				ibc_cq_handler with new work on this CQ,
248  *				so IBTL should call the client handler
249  *				again before it is considered done.
250  *
251  *	IBTL_CQ_FREE		Mark that ibt_free_cq is sleeping until
252  *				ibtl_cq_threads is done with this CQ.
253  */
254 typedef enum ibtl_cq_impl_flags_e {
255 	IBTL_CQ_PENDING		= 0x1,
256 	IBTL_CQ_CALL_CLIENT	= 0x2,
257 	IBTL_CQ_FREE		= 0x4
258 } ibtl_cq_impl_flags_t;
259 
260 
261 /*
262  * Define a per CQ state structure.
263  *
264  * The ibt_alloc_cq() allocates one of these. A CQ is associated with a
265  * particular HCA, whose handle is recorded in the cq_hca field.
266  * The cq_ibc_cq_hdl field is initialized with the CI CQ handle returned
267  * from the ibc_alloc_cq() call to the HCA driver.
268  *
269  * In order to set/get the client's private data, cq_clnt_private, clients
270  * need to use ibt_set_cq_private() and ibt_get_cq_private() calls.
271  *
272  * An IBT client registers a CQ completion handler callback and private
273  * callback argument (probably the client instance soft state structure) using
274  * the ibt_set_cq_handler() IBT routine. The comp_handler, arg fields of the
275  * structure are initialized with the values passed in by the IBTL client.
276  * These two fields are the only fields protected by the cq_mutex.
277  *
278  * When a completion event is posted to an IBT client, the
279  * client completion handler is called with the following arguments:
280  *
281  *	- The Client Handle, that is passed into the IBTL on ibt_attach call.
282  *	- The CQ Handle upon which the completion occurred.
283  *	- The private client argument, set during handler registration via
284  *	  ibt_set_cq_handler() call.
285  *
286  * The address of the ibtl_cq_s structure is passed in as the ibt_cq_hdl_t
287  * (callback arg) in the CI ibc_alloc_cq() function. Thus when a CI calls
288  * the IBTL completion handler (ibc_ci_cq_handler()) we can de-mux
289  * directly to the targeted IBT client.
290  *
291  */
292 typedef struct ibtl_cq_s {
293 	ibc_cq_hdl_t		cq_ibc_cq_hdl;	/* CI CQ handle */
294 	ibtl_hca_t		*cq_hca;	/* IBTL HCA hdl */
295 	ibt_cq_handler_t	cq_comp_handler; /* Completion handler */
296 	void			*cq_arg;	/* CQ handler's argument */
297 	kmutex_t		cq_mutex;	/* Mutex. */
298 	void			*cq_clnt_private; /* Client's Private. */
299 	struct ibtl_cq_s	*cq_link;	/* link for queuing cq to */
300 						/* to be handled in a thread */
301 	struct ibtl_cq_s	*cq_async_link;	/* list link for asyncs */
302 	ibtl_cq_impl_flags_t	cq_impl_flags;	/* dynamic bits if cq */
303 						/* handler runs in a thread */
304 	int			cq_in_thread;	/* mark if cq handler is to */
305 						/* be called in a thread */
306 	ibt_async_code_t	cq_async_codes;
307 	ibtl_async_flags_t	cq_async_flags;	/* see *_async_flags above */
308 	uint64_t		cq_fma_ena;	/* FMA data */
309 } ibtl_cq_t;
310 
311 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibtl_cq_s::{cq_in_thread cq_hca
312     cq_ibc_cq_hdl}))
313 
314 /*
315  * Define a per SRQ state structure.
316  *
317  * ibt_alloc_srq() allocates one of these. A SRQ is associated with a
318  * particular HCA, whose handle is recorded in the srq_hca field.
319  * The srq_ibc_srq_hdl field is initialized with the CI SRQ handle returned
320  * from the ibc_alloc_srq() call to the HCA driver.
321  *
322  * In order to set/get the client's private data, srq_clnt_private, clients
323  * need to use ibt_set_srq_private() and ibt_get_srq_private() calls.
324  *
325  * The address of the ibtl_srq_s structure is passed in as the ibt_srq_hdl_t
326  * (callback arg) in the CI ibc_alloc_srq() function.
327  */
328 typedef struct ibtl_srq_s {
329 	ibc_srq_hdl_t		srq_ibc_srq_hdl;	/* CI SRQ handle */
330 	ibtl_hca_t		*srq_hca;		/* IBTL HCA hdl */
331 	void			*srq_clnt_private;	/* Client's Private. */
332 	struct ibtl_srq_s	*srq_async_link;	/* Async Link list */
333 	ibt_async_code_t	srq_async_codes;
334 	ibtl_async_flags_t	srq_async_flags;	/* Async_flags */
335 	uint64_t		srq_fma_ena;		/* FMA data */
336 } ibtl_srq_t;
337 
338 /*
339  * Define a per QP state structure.
340  *
341  * The qp_hca field is initialized with the ibtl_hca_hdl_t of the HCA in
342  * which the QP was allocated. The qp_ibc_qp_hdl field is initialized with
343  * the CI QP handle.
344  *
345  * The ibtl_qp_t structure also maintains a channel connection state
346  * structure that is only valid for RC and RD QP's. The information about
347  * the respective Send and Receive CQ, the RDD and PD Handles are also stored.
348  *
349  * The IBTA spec does not include the signal type or PD on a QP query
350  * operation. In order to implement the "CLONE" feature of the alloc rc|ud
351  * channel functions we need to cache these values.
352  */
353 typedef struct ibtl_qp_s {
354 	ibt_tran_srv_t		qp_type;	/* QP type */
355 	ibt_attr_flags_t	qp_flags;
356 	ibc_qp_hdl_t		qp_ibc_qp_hdl;	/* CI QP handle */
357 	ibc_pd_hdl_t		qp_pd_hdl;	/* CI PD Hdl */
358 	ibtl_hca_t		*qp_hca;	/* IBTL HCA handle */
359 	ibtl_cq_t		*qp_send_cq;	/* IBTL CQ handle */
360 	ibtl_cq_t		*qp_recv_cq;	/* IBTL CQ handle */
361 	struct ibtl_qp_s	*qp_async_link;	/* async list link */
362 	ibt_async_code_t	qp_async_codes;
363 	ibtl_async_flags_t	qp_async_flags;	/* see *_async_flags above */
364 	uint64_t		qp_cat_fma_ena;	/* FMA data */
365 	uint64_t		qp_pth_fma_ena;	/* FMA data */
366 	uint64_t		qp_inv_fma_ena;	/* FMA data */
367 	uint64_t		qp_acc_fma_ena;	/* FMA data */
368 } ibtl_qp_t;
369 
370 
371 /*
372  * Define a per EEC state structure.
373  *
374  * The ibt_alloc_eec() allocates an ibt_eec_s structure and initializes
375  * the eec_hca field with the ibtl_hca_hdl_t of the HCA in which the EEC
376  * was allocated. The eec_ibc_eec_hdl field is initialized with the
377  * CI EEC handle.
378  *
379  * The information about CI's RDD Handle and channel connection state structure
380  * is also maintained.
381  */
382 typedef struct ibtl_eec_s {
383 	ibc_eec_hdl_t		eec_ibc_eec_hdl;	/* CI EEC Handle. */
384 	ibtl_hca_t		*eec_hca;		/* IBTL HCA Hdl */
385 	ibc_rdd_hdl_t		eec_ibc_rdd_hdl;	/* CI RDD Handle. */
386 	struct ibtl_channel_s	*eec_channel;
387 	struct ibtl_eec_s	*eec_async_link;	/* async list link */
388 	ibt_async_code_t	eec_async_codes;
389 	ibtl_async_flags_t	eec_async_flags;
390 	uint64_t		eec_cat_fma_ena;	/* FMA data */
391 	uint64_t		eec_pth_fma_ena;	/* FMA data */
392 } ibtl_eec_t;
393 
394 /*
395  * Define an ibt RD communication channel struct. This holds information
396  * specific to an RD QP.
397  */
398 typedef struct ibtl_rd_chan_s {
399 	ibtl_eec_t		*rd_eec;	/* point to the EEC */
400 } ibtl_rd_chan_t;
401 
402 /*
403  * Define an ibt UD communication channel struct. This holds information
404  * specific to a UD QP.
405  */
406 typedef struct ibtl_ud_chan_s {
407 	uint8_t			ud_port_num;	/* track the port number for */
408 						/* ibt_modify_reply_ud_dest() */
409 	ib_qkey_t		ud_qkey;	/* track the qkey */
410 } ibtl_ud_chan_t;
411 
412 /*
413  * Define an ibt RC communication channel struct. This holds information
414  * specific to an RC QP.
415  */
416 typedef struct ibtl_rc_chan_s {
417 	int			rc_free_flags;	/* Track connection state as */
418 						/* we will need to delay for */
419 						/* TIMEWAIT before freeing. */
420 	ibc_qpn_hdl_t		rc_qpn_hdl;	/* Store qpn_hdl while in */
421 						/* TIMEWAIT delay. */
422 } ibtl_rc_chan_t;
423 
424 /* bit definitions for rc_free_flags */
425 #define	IBTL_RC_QP_CONNECTED	0x1
426 #define	IBTL_RC_QP_CLOSING	0x2
427 #define	IBTL_RC_QP_CLOSED	0x4
428 #define	IBTL_RC_QP_FREED	0x8
429 #define	IBTL_RC_QP_CONNECTING	0x10
430 
431 /*
432  * Define a per Channel state structure.
433  *
434  * A ibtl_channel_s is allocated each time a TI client calls a
435  * channel allocation routine ibt_alloc_rc_channel() or ibt_alloc_ud_channel()
436  * or VTI client calls ibt_alloc_qp() or ibt_alloc_special_qp().
437  *
438  * In order to set/get the client's private data, ch_clnt_private,
439  * TI client's need to use ibt_set_chan_private() and ibt_get_chan_private()
440  * or VTI clients need to use ibt_set_qp_private() and ibt_get_qp_private().
441  */
442 typedef struct ibtl_channel_s {
443 	/* The ibtl_qp_t must be at the first of this struct */
444 	ibtl_qp_t		ch_qp;		/* IBTL QP handle */
445 	union {					/* transport specific */
446 		ibtl_rc_chan_t	rc;		/* RC Channel specific */
447 		ibtl_rd_chan_t	rd;		/* RD Channel specific */
448 		ibtl_ud_chan_t	ud;		/* UD Channel specific */
449 	} ch_transport;
450 	ibt_cep_state_t		ch_current_state; /* track the current state */
451 	void			*ch_clnt_private; /* Client's Private data */
452 	kmutex_t		ch_cm_mutex;	/* for ch_cm_private, etc. */
453 	kcondvar_t		ch_cm_cv;	/* for recycle_rc */
454 	void			*ch_cm_private;	/* Ptr to CM state */
455 } ibtl_channel_t;
456 
457 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibtl_channel_s))
458 
459 /*
460  * MACROS
461  */
462 #define	IBTL_CHAN2QP(ibt_chan)		(&(ibt_chan)->ch_qp)
463 #define	IBTL_CHAN2HCA(ibt_chan)		(ibt_chan)->ch_qp.qp_hca
464 
465 #define	IBTL_CHAN2CIQP(ibt_chan)	(ibt_chan->ch_qp.qp_ibc_qp_hdl)
466 
467 #define	IBTL_QP2CHAN(ibtl_qp)		(ibtl_channel_t *)(ibtl_qp)
468 #define	IBTL_EEC2CHAN(ibtl_eec)		(ibtl_eec)->eec_channel
469 
470 /*
471  * Get IBC HCA Handle from IBT Handles.
472  */
473 #define	IBTL_HDIP2CIHCA(hca_devp)	(hca_devp)->hd_ibc_hca_hdl
474 #define	IBTL_HCA2CIHCA(ibtl_hca)	IBTL_HDIP2CIHCA(ibtl_hca->ha_hca_devp)
475 #define	IBTL_ECC2CIHCA(ibtl_eec)	IBTL_HCA2CIHCA((ibtl_eec)->eec_hca)
476 #define	IBTL_CQ2CIHCA(ibtl_cq)		IBTL_HCA2CIHCA((ibtl_cq)->cq_hca)
477 #define	IBTL_CHAN2CIHCA(ibt_chan)	IBTL_HCA2CIHCA((ibt_chan)->ch_qp.qp_hca)
478 #define	IBTL_SRQ2CIHCA(ibtl_srq)	IBTL_HCA2CIHCA((ibtl_srq)->srq_hca)
479 
480 /*
481  * Get a pointer to the HCA ops structure from IBT handles.
482  */
483 #define	IBTL_HDIP2CIHCAOPS_P(hca_devp)	(hca_devp)->hd_ibc_ops
484 #define	IBTL_HCA2CIHCAOPS_P(ibtl_hca)	\
485 	IBTL_HDIP2CIHCAOPS_P(ibtl_hca->ha_hca_devp)
486 #define	IBTL_CQ2CIHCAOPS_P(ibtl_cq)	IBTL_HCA2CIHCAOPS_P((ibtl_cq)->cq_hca)
487 #define	IBTL_CHAN2CIHCAOPS_P(ibt_chan)	\
488 	IBTL_HCA2CIHCAOPS_P((ibt_chan)->ch_qp.qp_hca)
489 #define	IBTL_SRQ2CIHCAOPS_P(ibtl_srq)	\
490 	IBTL_HCA2CIHCAOPS_P((ibtl_srq)->srq_hca)
491 
492 /*
493  * Get Client Handle from IBT Handles.
494  */
495 #define	IBTL_HCA2CLNT(ibtl_hca)		(ibtl_hca)->ha_clnt_devp
496 #define	IBTL_ECC2CLNT(ibtl_eec)		IBTL_HCA2CLNT((ibtl_eec)->eec_hca)
497 #define	IBTL_CQ2CLNT(ibtl_cq)		IBTL_HCA2CLNT((ibtl_cq)->cq_hca)
498 #define	IBTL_CHAN2CLNT(ibt_chan)	IBTL_HCA2CLNT((ibt_chan)->ch_qp.qp_hca)
499 
500 /*
501  * Get a Pointer to the client modinfo from IBT Handles.
502  */
503 #define	IBTL_HCA2MODI_P(ibtl_hca)	\
504 	((IBTL_HCA2CLNT(ibtl_hca))->clnt_modinfop)
505 
506 #define	IBTL_EEC2MODI_P(ibtl_eec)	\
507 	((IBTL_EEC2CLNT(ibtl_eec))->clnt_modinfop)
508 
509 #define	IBTL_CQ2MODI_P(ibtl_cq)		((IBTL_CQ2CLNT(ibtl_cq))->clnt_modinfop)
510 
511 #define	IBTL_CHAN2MODI_P(chan)		((IBTL_CHAN2CLNT(chan))->clnt_modinfop)
512 
513 /*
514  * Using HCA Device Info Pointer, access HCA Attributes values for
515  *	Max SGID Table Size, Max PKEY Table Size.
516  */
517 #define	IBTL_HDIP2SGIDTBLSZ(hca)	\
518 		(hca)->hd_hca_attr->hca_max_port_sgid_tbl_sz
519 #define	IBTL_HDIP2PKEYTBLSZ(hca)	\
520 		(hca)->hd_hca_attr->hca_max_port_pkey_tbl_sz
521 
522 /*
523  * Using IBTL HCA Handle, access HCA Attributes values.
524  *			viz.	HCA Node GUID,
525  *				Number of Ports on this HCA Device,
526  *				Max SGID Table Size
527  *				Max PKEY Table Size
528  */
529 #define	IBTL_HCA2HCAGUID(hca_hdl) \
530 	(hca_hdl)->ha_hca_devp->hd_hca_attr->hca_node_guid
531 #define	IBTL_HCA2NPORTS(hca_hdl) \
532 	(hca_hdl)->ha_hca_devp->hd_hca_attr->hca_nports
533 #define	IBTL_HCA2SGIDTBLSZ(hca_hdl) \
534 	(hca_hdl)->ha_hca_devp->hd_hca_attr->hca_max_port_sgid_tbl_sz
535 #define	IBTL_HCA2PKEYTBLSZ(hca_hdl) \
536 	(hca_hdl)->ha_hca_devp->hd_hca_attr->hca_max_port_pkey_tbl_sz
537 
538 /* possible strlen of a IB driver's name */
539 #define	IBTL_DRVNAME_LEN	40
540 
541 /* strings passed to ib_dprintfN() are this long */
542 #define	IBTL_PRINT_BUF_LEN	4096
543 
544 /* Check if client isn't CM/DM/IBMA */
545 #define	IBTL_GENERIC_CLIENT(clntp) \
546 	(((clntp)->clnt_modinfop->mi_clnt_class != IBT_CM) && \
547 	    ((clntp)->clnt_modinfop->mi_clnt_class != IBT_DM) && \
548 	    ((clntp)->clnt_modinfop->mi_clnt_class != IBT_IBMA))
549 
550 /*
551  * Function Prototypes that are specific to the IBTL implementation.
552  */
553 ibtl_hca_devinfo_t *ibtl_get_hcadevinfo(ib_guid_t hca_guid);
554 ibt_status_t ibtl_init_hca_portinfo(ibtl_hca_devinfo_t *hca_devp);
555 void	ibtl_reinit_hca_portinfo(ibtl_hca_devinfo_t *hca_devp, uint8_t port);
556 
557 void	ibtl_init_cep_states(void);
558 void	ibtl_ib2usec_init(void);
559 void	ibtl_logging_initialization(void);
560 void	ibtl_logging_destroy(void);
561 void	ibtl_thread_init(void);
562 void	ibtl_thread_init2(void);
563 void	ibtl_thread_fini(void);
564 void	ibtl_announce_new_hca(ibtl_hca_devinfo_t *hca_devp);
565 void	ibtl_another_cq_handler_in_thread(void);
566 int	ibtl_detach_all_clients(ibtl_hca_devinfo_t *hcap);
567 void	ibtl_qp_flow_control_enter(void);
568 void	ibtl_qp_flow_control_exit(void);
569 
570 /* synchronization of asyncs when freeing an object */
571 void	ibtl_free_qp_async_check(ibtl_qp_t *ibtl_qp);
572 void	ibtl_free_cq_async_check(ibtl_cq_t *ibtl_cq);
573 void	ibtl_free_srq_async_check(ibtl_srq_t *ibtl_srq);
574 void	ibtl_free_eec_async_check(ibtl_eec_t *ibtl_eec);
575 void	ibtl_free_hca_async_check(ibt_hca_hdl_t ibt_hca);
576 void	ibtl_free_clnt_async_check(ibtl_clnt_t *clntp);
577 
578 /* synchronization of cq_handler callbacks and free_cq */
579 void	ibtl_free_cq_check(ibtl_cq_t *ibtl_cq);
580 
581 /* release_qpn and close_hca synchronization */
582 void	ibtl_close_hca_check(ibt_hca_hdl_t ibt_hca);
583 
584 /* Global List of HCA devices, and associated lock. */
585 extern struct ibtl_hca_devinfo_s *ibtl_hca_list; /* link is hd_hca_dev_link */
586 
587 /* Global List of IBT Client Instances, and associated lock. */
588 extern struct ibtl_clnt_s *ibtl_clnt_list; /* link is clnt_list_link */
589 extern kmutex_t ibtl_clnt_list_mutex;
590 
591 /* Lock for the race between the client and CM to free QPs. */
592 extern kmutex_t ibtl_free_qp_mutex;
593 
594 /* Lock for the race between the client closing the HCA and QPN being freed. */
595 extern kcondvar_t ibtl_close_hca_cv;
596 
597 /* Limit the flow of QP verb calls */
598 extern kmutex_t ibtl_qp_mutex;
599 extern kcondvar_t ibtl_qp_cv;
600 
601 /* Async handlers and client private for well known clients of IBTL */
602 extern ibt_async_handler_t ibtl_cm_async_handler;
603 extern ibt_async_handler_t ibtl_dm_async_handler;
604 extern ibt_async_handler_t ibtl_ibma_async_handler;
605 extern void *ibtl_cm_clnt_private;
606 extern void *ibtl_dm_clnt_private;
607 extern void *ibtl_ibma_clnt_private;
608 
609 /* cache for fast GID => portinfo lookup */
610 extern boolean_t ibtl_fast_gid_cache_valid;
611 
612 
613 /* The following structs are used to pass info in and out of the APIs */
614 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibt_rc_chan_alloc_args_s))
615 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibt_rc_chan_query_attr_s))
616 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibt_rc_chan_modify_attr_s))
617 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibt_ud_dest_query_attr_s))
618 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibt_ud_chan_alloc_args_s))
619 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibt_ud_chan_query_attr_s))
620 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibt_ud_chan_modify_attr_s))
621 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibt_ud_dest_s))
622 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibt_qp_alloc_attr_s))
623 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibt_qp_info_s))
624 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibt_hca_portinfo_s))
625 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibt_adds_vect_s))
626 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibt_cep_path_s))
627 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibt_mr_desc_s))
628 _NOTE(SCHEME_PROTECTS_DATA("GIDs are transient", ib_gid_s))
629 
630 #ifdef __cplusplus
631 }
632 #endif
633 
634 #endif /* _SYS_IB_IBTL_IMPL_IBTL_H */
635