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