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