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
41extern "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 */
55typedef 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. */
74typedef 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
88typedef 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 */
99typedef 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 */
117typedef 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 */
125typedef 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 */
147typedef 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 */
206typedef 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 */
252typedef 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 */
290typedef 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 */
326typedef 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 */
351typedef 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 */
380typedef 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 */
396typedef 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 */
404typedef 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 */
414typedef 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 */
440typedef 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 */
551ibtl_hca_devinfo_t *ibtl_get_hcadevinfo(ib_guid_t hca_guid);
552ibt_status_t ibtl_init_hca_portinfo(ibtl_hca_devinfo_t *hca_devp);
553void	ibtl_reinit_hca_portinfo(ibtl_hca_devinfo_t *hca_devp, uint8_t port);
554
555void	ibtl_init_cep_states(void);
556void	ibtl_ib2usec_init(void);
557void	ibtl_logging_initialization(void);
558void	ibtl_logging_destroy(void);
559void	ibtl_thread_init(void);
560void	ibtl_thread_init2(void);
561void	ibtl_thread_fini(void);
562void	ibtl_announce_new_hca(ibtl_hca_devinfo_t *hca_devp);
563void	ibtl_another_cq_handler_in_thread(void);
564int	ibtl_detach_all_clients(ibtl_hca_devinfo_t *hcap);
565void	ibtl_qp_flow_control_enter(void);
566void	ibtl_qp_flow_control_exit(void);
567
568/* synchronization of asyncs when freeing an object */
569void	ibtl_free_qp_async_check(ibtl_qp_t *ibtl_qp);
570void	ibtl_free_cq_async_check(ibtl_cq_t *ibtl_cq);
571void	ibtl_free_srq_async_check(ibtl_srq_t *ibtl_srq);
572void	ibtl_free_eec_async_check(ibtl_eec_t *ibtl_eec);
573void	ibtl_free_hca_async_check(ibt_hca_hdl_t ibt_hca);
574void	ibtl_free_clnt_async_check(ibtl_clnt_t *clntp);
575
576/* synchronization of cq_handler callbacks and free_cq */
577void	ibtl_free_cq_check(ibtl_cq_t *ibtl_cq);
578
579/* release_qpn and close_hca synchronization */
580void	ibtl_close_hca_check(ibt_hca_hdl_t ibt_hca);
581
582/* Global List of HCA devices, and associated lock. */
583extern 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. */
586extern struct ibtl_clnt_s *ibtl_clnt_list; /* link is clnt_list_link */
587extern kmutex_t ibtl_clnt_list_mutex;
588
589/* Lock for the race between the client and CM to free QPs. */
590extern kmutex_t ibtl_free_qp_mutex;
591
592/* Lock for the race between the client closing the HCA and QPN being freed. */
593extern kcondvar_t ibtl_close_hca_cv;
594
595/* Limit the flow of QP verb calls */
596extern kmutex_t ibtl_qp_mutex;
597extern kcondvar_t ibtl_qp_cv;
598
599/* Async handlers and client private for well known clients of IBTL */
600extern ibt_async_handler_t ibtl_cm_async_handler;
601extern ibt_async_handler_t ibtl_dm_async_handler;
602extern ibt_async_handler_t ibtl_ibma_async_handler;
603extern void *ibtl_cm_clnt_private;
604extern void *ibtl_dm_clnt_private;
605extern void *ibtl_ibma_clnt_private;
606
607/* cache for fast GID => portinfo lookup */
608extern 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