xref: /illumos-gate/usr/src/uts/common/io/ib/ibtl/ibtl_impl.c (revision 7f7322febbcfe774b7270abc3b191c094bfcc517)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * ibtl_impl.c
31  *
32  * This file contains the IBTF module's initialization and
33  * IBTF Clients/Modules registration routines.
34  */
35 
36 #include <sys/modctl.h>
37 #include <sys/sunndi.h>
38 #include <sys/sunmdi.h>
39 #include <sys/ib/ibtl/impl/ibtl.h>
40 #include <sys/ib/ibtl/impl/ibtl_ibnex.h>
41 
42 /*
43  * Globals.
44  */
45 static char ibtf[] = "ibtl_impl";
46 
47 extern ibtl_ibnex_callback_t	ibtl_ibnex_callback_routine;
48 
49 /*
50  * ibtl_clnt_list:
51  *
52  *	Head of the list of IBT Client Instances. The IBT Client List
53  *	is modified by IBTF on an IBT client's ibt_attach/ibt_detach call.
54  *
55  * ibtl_hca_list:
56  *
57  *	Head of the list of HCA devices. The HCA List is modified by IBTF on
58  *	a CI's ibc_attach/ibc_detach call.
59  *	The datap of the list elements points to an ibtl_hca_devinfo_s
60  *	structure.
61  *
62  *				(ibc_attach)
63  *  ibtl_hca_list	-> ibtl_hca_devinfo_t--> ...	-->ibtl_hca_devinfo_t
64  *	[per-hca_dev]		|	^			{nth HCA Dev}
65  *				|	|
66  *				|  ibtl_hca_t (ibt_open_hca)
67  *				|	^  |
68  *				|	|  |
69  *				v	|  V
70  *  ibtl_clnt_list	->	ibtl_clnt_t--> ...--> {n'th Module}
71  *	[per-client_instance]	(ibt_attach)
72  *
73  */
74 
75 /* Global List of IBT Client Instances, and associated mutex. */
76 struct ibtl_clnt_s *ibtl_clnt_list = NULL;
77 kmutex_t ibtl_clnt_list_mutex;
78 
79 /* Lock for the race between the client and CM to free QPs. */
80 kmutex_t ibtl_free_qp_mutex;
81 
82 /* Lock for the race between the client closing the HCA and QPN being freed. */
83 kcondvar_t ibtl_close_hca_cv;
84 
85 /* Global List of HCA Devices, and associated mutex. */
86 struct ibtl_hca_devinfo_s *ibtl_hca_list = NULL;
87 
88 /* Well-known async handlers and associated client private. */
89 ibt_async_handler_t ibtl_cm_async_handler;
90 ibt_async_handler_t ibtl_dm_async_handler;
91 ibt_async_handler_t ibtl_ibma_async_handler;
92 void	*ibtl_cm_clnt_private;
93 void	*ibtl_dm_clnt_private;
94 void	*ibtl_ibma_clnt_private;
95 
96 extern int ib_hw_status;
97 _NOTE(SCHEME_PROTECTS_DATA("Scheme protects data", ib_hw_status))
98 
99 /*
100  * Misc Module Declarations.
101  */
102 extern struct mod_ops mod_miscops;
103 static struct modlmisc modlmisc = {
104 	&mod_miscops,			/* Type of module - misc. */
105 	"IB Transport Layer v%I%"	/* Name of the Module. */
106 };
107 
108 static struct modlinkage modlinkage = {
109 	MODREV_1, (void *)&modlmisc, NULL
110 };
111 
112 
113 /*
114  * IBTF Loadable Module Routines.
115  */
116 
117 int
118 _init(void)
119 {
120 	int rval;
121 
122 	if ((rval = mod_install(&modlinkage)) != 0)
123 		return (rval);
124 
125 	/*
126 	 * initialize IBTL ib2usec table
127 	 */
128 	ibtl_ib2usec_init();
129 
130 	/*
131 	 * Initialize Logging
132 	 */
133 	ibtl_logging_initialization();
134 
135 	/*
136 	 * Initialize the Alloc QP States.
137 	 */
138 	ibtl_init_cep_states();
139 
140 	/*
141 	 * Initialize all Global Link Lists.
142 	 */
143 	mutex_init(&ibtl_clnt_list_mutex, NULL, MUTEX_DEFAULT, NULL);
144 	mutex_init(&ibtl_free_qp_mutex, NULL, MUTEX_DEFAULT, NULL);
145 	cv_init(&ibtl_close_hca_cv, NULL, CV_DEFAULT, NULL);
146 
147 	mutex_init(&ibtl_qp_mutex, NULL, MUTEX_DEFAULT, NULL);
148 	cv_init(&ibtl_qp_cv, NULL, CV_DEFAULT, NULL);
149 
150 	ibtl_thread_init();
151 
152 	return (rval);
153 }
154 
155 
156 /*
157  * The IBTF Module is never unloaded. Actually there is no need of this
158  * routine, but provided just in case.
159  */
160 int
161 _fini(void)
162 {
163 	int rval;
164 
165 	if ((rval = mod_remove(&modlinkage)) != 0) {
166 		return (rval);
167 	}
168 
169 	ibtl_thread_fini();
170 
171 	mutex_destroy(&ibtl_clnt_list_mutex);
172 	mutex_destroy(&ibtl_free_qp_mutex);
173 	cv_destroy(&ibtl_close_hca_cv);
174 	mutex_destroy(&ibtl_qp_mutex);
175 	cv_destroy(&ibtl_qp_cv);
176 
177 	/*
178 	 * Stop Logging
179 	 */
180 	ibtl_logging_destroy();
181 
182 	return (rval);
183 }
184 
185 
186 int
187 _info(struct modinfo *modinfop)
188 {
189 	/* Return the Module Information. */
190 	return (mod_info(&modlinkage, modinfop));
191 }
192 
193 
194 /*
195  * IBTF Client Registration Routines.
196  */
197 
198 /*
199  * Function:
200  *	ibt_attach
201  * Input:
202  *	modinfop	- Client Module info structure.
203  *	arg		- usually client's dip
204  *	clnt_private	- client's private data pointer.
205  * Output:
206  *	ibt_hdl_p	- pointer to client's specific IBT handle,
207  *			 which is opaque to clients.
208  * Returns:
209  *	IBT_SUCCESS
210  *	IBT_INVALID_PARAM
211  * Called by:
212  *	IBTF Client module during its attach() to register its instance
213  *	to IBTF.
214  * Description:
215  *	Registers the IBTF client module instance and returns an opaque
216  *	handler to the client to be used for future calls to IBTF.
217  *	Adds this client module instance to ibtl_clnt_list list.
218  *	Records well-known async handlers.
219  */
220 ibt_status_t
221 ibt_attach(ibt_clnt_modinfo_t *mod_infop, dev_info_t *arg, void *clnt_private,
222     ibt_clnt_hdl_t *ibt_hdl_p)
223 {
224 	dev_info_t	*pdip;
225 	ibtl_clnt_t	*clntp;
226 
227 	IBTF_DPRINTF_L3(ibtf, "ibt_attach(%p, %p, %p)",
228 	    mod_infop, arg, clnt_private);
229 
230 	if (mod_infop->mi_clnt_name == NULL) {
231 		IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
232 		    "IB client needs to specify its name");
233 		return (IBT_INVALID_PARAM);
234 	}
235 
236 	/*
237 	 * Validate the Transport API version.
238 	 */
239 	if (mod_infop->mi_ibt_version != IBTI_V2) {
240 		IBTF_DPRINTF_L1(ibtf, "ibt_attach: IB client '%s' has an "
241 		    "invalid IB TI Version '%d'", mod_infop->mi_clnt_name,
242 		    mod_infop->mi_ibt_version);
243 		return (IBT_NOT_SUPPORTED);
244 	}
245 
246 	if (mod_infop->mi_async_handler == NULL) {
247 		IBTF_DPRINTF_L2(ibtf, "ibt_attach: Client '%s' has not\n"
248 		    "        provided an Asynchronous Event Handler.\n"
249 		    "        This will be required soon.",
250 		    mod_infop->mi_clnt_name);
251 	}
252 
253 	/*
254 	 * Check out Client's Class information. If it is not of mgmt class,
255 	 * we expect 'arg' to be Not NULL and point to client driver's
256 	 * device info struct.
257 	 */
258 	if ((!IBT_CLNT_MGMT_CLASS(mod_infop->mi_clnt_class)) &&
259 	    (arg == NULL)) {
260 		IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
261 		    "arg not set with driver's dip.");
262 		return (IBT_INVALID_PARAM);
263 	}
264 
265 	if (!IBT_CLNT_MGMT_CLASS(mod_infop->mi_clnt_class)) {
266 		pdip = ddi_get_parent(arg);
267 		if (pdip == NULL ||
268 		    ibtl_ibnex_valid_hca_parent(pdip) != IBT_SUCCESS) {
269 			IBTF_DPRINTF_L2(ibtf, "ibt_attach: "
270 			    "client %s is not a child of IB nexus driver.",
271 			    ddi_driver_name(arg));
272 			return (IBT_INVALID_PARAM);
273 		}
274 	}
275 
276 	mutex_enter(&ibtl_clnt_list_mutex);
277 	if (mod_infop->mi_clnt_class == IBT_CM) {
278 		if (ibtl_cm_async_handler != NULL) {
279 			IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
280 			    "CM is already attached.");
281 			mutex_exit(&ibtl_clnt_list_mutex);
282 			return (IBT_INVALID_PARAM);
283 		}
284 		ibtl_cm_async_handler = mod_infop->mi_async_handler;
285 		ibtl_cm_clnt_private = clnt_private;
286 	} else if (mod_infop->mi_clnt_class == IBT_DM) {
287 		if (ibtl_dm_async_handler != NULL) {
288 			IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
289 			    "DM is already attached.");
290 			mutex_exit(&ibtl_clnt_list_mutex);
291 			return (IBT_INVALID_PARAM);
292 		}
293 		ibtl_dm_async_handler = mod_infop->mi_async_handler;
294 		ibtl_dm_clnt_private = clnt_private;
295 	} else if (mod_infop->mi_clnt_class == IBT_IBMA) {
296 		if (ibtl_ibma_async_handler != NULL) {
297 			IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
298 			    "IBMF is already attached.");
299 			mutex_exit(&ibtl_clnt_list_mutex);
300 			return (IBT_INVALID_PARAM);
301 		}
302 		ibtl_ibma_async_handler = mod_infop->mi_async_handler;
303 		ibtl_ibma_clnt_private = clnt_private;
304 	}
305 
306 	/* Allocate the memory for per-client-device info structure */
307 	clntp = kmem_zalloc(sizeof (ibtl_clnt_t), KM_SLEEP);
308 
309 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(clntp->clnt_modinfop,
310 	    clntp->clnt_dip, clntp->clnt_name, clntp->clnt_async_cnt,
311 	    clntp->clnt_private))
312 	/* Update the Client info structure */
313 	clntp->clnt_modinfop = mod_infop;	/* IBT Client's Mod Info */
314 	clntp->clnt_private = clnt_private;	/* IBT Client's private */
315 	clntp->clnt_dip = arg;			/* IBT Client's dip */
316 	clntp->clnt_async_cnt = 0;
317 	/* using a count of 7 below guarantees it is NULL terminated */
318 	(void) strncpy(clntp->clnt_name, mod_infop->mi_clnt_name, 7);
319 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(clntp->clnt_modinfop,
320 	    clntp->clnt_dip, clntp->clnt_name, clntp->clnt_async_cnt,
321 	    clntp->clnt_private))
322 
323 	/*
324 	 * Update Client Device Instance List.
325 	 */
326 	clntp->clnt_list_link = ibtl_clnt_list;
327 	ibtl_clnt_list = clntp;
328 	mutex_exit(&ibtl_clnt_list_mutex);
329 
330 	/*
331 	 * The ibt_hdl_p is a opaque handle which is the address of
332 	 * ibt_clnt_t structure passed back to the clients.
333 	 * The client will pass on this handle in its future calls to IBTF.
334 	 */
335 	*ibt_hdl_p = clntp;
336 
337 	return (IBT_SUCCESS);
338 }
339 
340 
341 /*
342  * Function:
343  *	ibt_detach
344  * Input:
345  *	ibt_hdl - IBT Handle as returned during ibt_attach call.
346  * Output:
347  *	none
348  * Returns:
349  *	IBT_SUCCESS
350  *	IBT_INVALID_PARAM.
351  * Called by:
352  *	IBTF Client module during its detach() to de-register its instance
353  *	from IBTF.
354  * Description:
355  *	Deregisters the IBTF client module instance from the IBTF.
356  *	All resources and any reference to this ibt_hdl will be removed.
357  */
358 ibt_status_t
359 ibt_detach(ibt_clnt_hdl_t ibt_hdl)
360 {
361 	ibtl_clnt_t **clntpp;
362 
363 	IBTF_DPRINTF_L3(ibtf, "ibt_detach(%p)", ibt_hdl);
364 
365 	mutex_enter(&ibtl_clnt_list_mutex);
366 	clntpp = &ibtl_clnt_list;
367 	for (; *clntpp != NULL; clntpp = &(*clntpp)->clnt_list_link)
368 		if (*clntpp == ibt_hdl)
369 			break;
370 	if (*clntpp == NULL) {
371 		IBTF_DPRINTF_L1(ibtf, "ibt_detach: Client @ %p Not Found",
372 		    ibt_hdl);
373 		mutex_exit(&ibtl_clnt_list_mutex);
374 		return (IBT_INVALID_PARAM);
375 	}
376 
377 	/*
378 	 * Check out whether the client has freed all its resources.
379 	 * If not done, then fail the detach.
380 	 *
381 	 * viz. A client has to close all the HCA they have opened,
382 	 * i.e. the HCA List maintained for clients has to be empty.
383 	 * If this list is not empty, then the client has not performed
384 	 * complete clean-up, so fail the detach.
385 	 */
386 	if (ibt_hdl->clnt_hca_list != NULL) {
387 		mutex_exit(&ibtl_clnt_list_mutex);
388 
389 		IBTF_DPRINTF_L2(ibtf, "ibt_detach: "
390 		    "ERROR: Client '%s' has not closed all of its HCAs",
391 		    ibt_hdl->clnt_modinfop->mi_clnt_name);
392 		return (IBT_HCA_RESOURCES_NOT_FREED);
393 	}
394 
395 	if (ibt_hdl->clnt_srv_cnt != 0) {
396 		mutex_exit(&ibtl_clnt_list_mutex);
397 		IBTF_DPRINTF_L2(ibtf, "ibt_detach: client '%s' still has "
398 		    "services or subnet_notices registered",
399 		    ibt_hdl->clnt_modinfop->mi_clnt_name);
400 		return (IBT_HCA_RESOURCES_NOT_FREED);
401 	}
402 
403 	/*
404 	 * Delete the entry of this module from the ibtl_clnt_list List.
405 	 */
406 	*clntpp = ibt_hdl->clnt_list_link;	/* remove us */
407 
408 	/* make sure asyncs complete before freeing */
409 	ibtl_free_clnt_async_check(ibt_hdl);
410 
411 	if (ibt_hdl->clnt_modinfop->mi_clnt_class == IBT_CM) {
412 		ibtl_cm_async_handler = NULL;
413 		ibtl_cm_clnt_private = NULL;
414 	} else if (ibt_hdl->clnt_modinfop->mi_clnt_class == IBT_DM) {
415 		ibtl_dm_async_handler = NULL;
416 		ibtl_dm_clnt_private = NULL;
417 	} else if (ibt_hdl->clnt_modinfop->mi_clnt_class == IBT_IBMA) {
418 		ibtl_ibma_async_handler = NULL;
419 		ibtl_ibma_clnt_private = NULL;
420 	}
421 	mutex_exit(&ibtl_clnt_list_mutex);
422 
423 	/* Free up the memory of per-client info struct. */
424 	kmem_free(ibt_hdl, sizeof (ibtl_clnt_t));
425 
426 	return (IBT_SUCCESS);
427 }
428 
429 static void
430 ibtl_set_ibhw_status()
431 {
432 	ib_hw_status++;
433 }
434 
435 static void
436 ibtl_clear_ibhw_status()
437 {
438 	ib_hw_status--;
439 }
440 
441 /*
442  * Function:
443  *	ibc_init
444  * Input:
445  *	modlp		- Pointer to IBC client module linkage structure
446  * Output:
447  *	None
448  * Returns:
449  *	0 always for now
450  * Called by:
451  *	CI client calls IBTF during its _init() to register HCA with
452  *	Solaris I/O framework.
453  * Description:
454  *	Initializes the CI clients module linkage structure with
455  *	default bus_ops structure
456  */
457 int
458 ibc_init(struct modlinkage *modlp)
459 {
460 	ibtl_ibnex_cb_args_t	cb_args;
461 
462 	mutex_enter(&ibtl_clnt_list_mutex);
463 	cb_args.cb_flag = IBTL_IBNEX_IBC_INIT;
464 	cb_args.cb_modlp = modlp;
465 	if (ibtl_ibnex_callback_routine) {
466 		(void) ((*ibtl_ibnex_callback_routine)(&cb_args));
467 	}
468 	mutex_exit(&ibtl_clnt_list_mutex);
469 	return (0);
470 }
471 
472 
473 /*
474  * Function:
475  *	ibc_fini
476  * Input:
477  *	modlp		- Pointer to IBC client module linkage structure
478  * Output:
479  *	None
480  * Returns:
481  *	None
482  * Called by:
483  *	CI client calls IBTF during its _fini() to remove HCA with
484  *	Solaris I/O framework.
485  * Description:
486  *	Undo what is done during ibc_init
487  */
488 void
489 ibc_fini(struct modlinkage *modlp)
490 {
491 	ibtl_ibnex_cb_args_t	cb_args;
492 
493 	mutex_enter(&ibtl_clnt_list_mutex);
494 	cb_args.cb_flag = IBTL_IBNEX_IBC_FINI;
495 	cb_args.cb_modlp = modlp;
496 	if (ibtl_ibnex_callback_routine) {
497 		(void) ((*ibtl_ibnex_callback_routine)(&cb_args));
498 	}
499 	mutex_exit(&ibtl_clnt_list_mutex);
500 }
501 
502 /*
503  * Function:
504  *	ibc_attach
505  * Input:
506  *	info_p		- IBC HCA Info.
507  * Output:
508  *	ibc_hdl_p	- IBC Client's HCA Handle.
509  * Returns:
510  *	IBC_SUCCESS
511  *	IBC_FAILURE
512  * Called by:
513  *	CI calls IBTF during its attach() to register HCA Device with IBTF.
514  * Description:
515  *	Registers the presence of HCA device by providing the HCA device info
516  *  	structure and provides an opaque HCA handler for future calls to this
517  *  	HCA device.
518  */
519 ibc_status_t
520 ibc_attach(ibc_clnt_hdl_t *ibc_hdl_p, ibc_hca_info_t *info_p)
521 {
522 	ibtl_hca_devinfo_t	*hca_devp;
523 	uint_t			nports;
524 	ibt_status_t		status;
525 
526 	IBTF_DPRINTF_L2(ibtf, "ibc_attach(%p, %p)", ibc_hdl_p, info_p);
527 
528 	/* Validate the Transport API version */
529 	if (info_p->hca_ci_vers != IBCI_V2) {
530 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: Invalid IB CI Version '%d'",
531 		    info_p->hca_ci_vers);
532 		return (IBC_FAILURE);
533 	}
534 
535 	if (info_p->hca_attr == NULL) {
536 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
537 		    "HCA Attributes must be specified.");
538 		return (IBC_FAILURE);
539 	}
540 
541 	nports = info_p->hca_attr->hca_nports;
542 	if (nports == 0) {
543 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
544 		    "Number of ports must be valid");
545 		return (IBC_FAILURE);
546 	}
547 
548 	if (info_p->hca_attr->hca_max_port_pkey_tbl_sz == 0) {
549 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
550 		    "Number of Partitions must be at least 1");
551 		return (IBC_FAILURE);
552 	}
553 
554 	if ((info_p->hca_attr->hca_flags & IBT_HCA_CURRENT_QP_STATE) == 0) {
555 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
556 		    "HCA driver must support QP current state checking");
557 		return (IBC_FAILURE);
558 	}
559 
560 	if ((info_p->hca_attr->hca_flags & IBT_HCA_PORT_UP) == 0) {
561 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
562 		    "HCA driver must support PORT_UP async events");
563 		return (IBC_FAILURE);
564 	}
565 
566 	/*
567 	 * Install IB nexus driver (if not installed already)
568 	 */
569 	ibtl_set_ibhw_status();
570 	if (ndi_devi_config_vhci("ib", 0) == NULL) {
571 		IBTF_DPRINTF_L2(ibtf, "ibc_attach: IB nexus attach failed");
572 		ibtl_clear_ibhw_status();
573 		return (IBC_FAILURE);
574 	}
575 
576 	ibtl_thread_init2();
577 
578 	/* Allocate the memory for per-client info structure */
579 	hca_devp = kmem_zalloc(sizeof (ibtl_hca_devinfo_t) +
580 	    (nports - 1) * sizeof (ibtl_async_port_status_t), KM_SLEEP);
581 
582 	mutex_enter(&ibtl_clnt_list_mutex);
583 
584 	/* Update HCA dev info structure */
585 	hca_devp->hd_ibc_hca_hdl = info_p->hca_handle;
586 	hca_devp->hd_ibc_ops	= info_p->hca_ops;
587 	hca_devp->hd_hca_attr	= info_p->hca_attr;
588 	hca_devp->hd_hca_dip	= info_p->hca_dip;
589 
590 	status = ibtl_init_hca_portinfo(hca_devp);
591 	if (status != IBT_SUCCESS) {
592 		mutex_exit(&ibtl_clnt_list_mutex);
593 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: call to ibc_query_hca_ports "
594 		    "failed: status = %d", status);
595 		kmem_free(hca_devp, sizeof (ibtl_hca_devinfo_t) +
596 		    (nports - 1) * sizeof (ibtl_async_port_status_t));
597 		return (IBC_FAILURE);
598 	}
599 
600 	/* Register the with MPxIO as PHCI */
601 	if (mdi_phci_register(MDI_HCI_CLASS_IB, info_p->hca_dip, 0) !=
602 		MDI_SUCCESS) {
603 		mutex_exit(&ibtl_clnt_list_mutex);
604 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: MPxIO register failed");
605 		kmem_free(hca_devp, sizeof (ibtl_hca_devinfo_t) +
606 		    (nports - 1) * sizeof (ibtl_async_port_status_t));
607 		return (IBC_FAILURE);
608 	}
609 
610 	/* Initialize the Client List for this HCA. */
611 	hca_devp->hd_state	= IBTL_HCA_DEV_ATTACHED;
612 
613 	/* lock out asyncs until after we announce the new HCA */
614 	hca_devp->hd_async_busy = 1;
615 
616 	cv_init(&hca_devp->hd_async_task_cv, NULL, CV_DEFAULT, NULL);
617 	cv_init(&hca_devp->hd_async_busy_cv, NULL, CV_DEFAULT, NULL);
618 
619 	/* init portinfo locking variables */
620 	hca_devp->hd_portinfo_locked_port = 0;
621 	cv_init(&hca_devp->hd_portinfo_cv, NULL, CV_DEFAULT, NULL);
622 
623 	mutex_exit(&ibtl_clnt_list_mutex);
624 
625 	/*
626 	 * The ibc_hdl_p points to an opaque handle which is the address
627 	 * of ibt_hca_devinfo_t structure passed back to the CI.
628 	 * The CI will pass on this handle in its future upcalls to IBTF.
629 	 */
630 	*ibc_hdl_p = hca_devp;
631 
632 	return (IBC_SUCCESS);
633 }
634 
635 
636 /*
637  * Function:
638  *	ibc_post_attach
639  * Input:
640  *	ibc_hdl		- IBC Client's HCA Handle.
641  * Returns:
642  *	none
643  * Called by:
644  *	CI calls IBTF during its attach() after a successful ibc_attach().
645  * Description:
646  *	Announces to all known clients the existence of this HCA (by GUID).
647  */
648 void
649 ibc_post_attach(ibc_clnt_hdl_t ibc_hdl)
650 {
651 	IBTF_DPRINTF_L2(ibtf, "ibc_post_attach(%p)", ibc_hdl);
652 
653 	/*
654 	 * Update the HCA Device List.
655 	 */
656 	mutex_enter(&ibtl_clnt_list_mutex);
657 	ibc_hdl->hd_hca_dev_link = ibtl_hca_list;
658 	ibtl_hca_list = ibc_hdl;
659 	mutex_exit(&ibtl_clnt_list_mutex);
660 
661 	/* notify all IBT Client Device Instances of the new HCA Device */
662 	ibtl_announce_new_hca(ibc_hdl);
663 }
664 
665 
666 /*
667  * Function:
668  *	ibc_pre_detach
669  * Input:
670  *	ibc_clnt_hdl	- IBC HCA Handle as returned during ibc_attach call.
671  *  	cmd		- DDI_DETACH/DDI_SUSPEND command.
672  * Output:
673  *	none
674  * Returns:
675  *	IBC_SUCCESS
676  *	IBC_FAILURE.
677  * Called by:
678  *	CI to try to get all IBTF clients to close the HCA device.
679  * Description:
680  *	Attempts to deregister the HCA device entry from the IBTF.
681  *	If all resources are freed by the IBTF clients and this HCA
682  *	is closed, then IBC_SUCCESS is returned.
683  */
684 ibc_status_t
685 ibc_pre_detach(ibc_clnt_hdl_t hca_devp, ddi_detach_cmd_t cmd)
686 {
687 	ibtl_hca_devinfo_t **hcapp, *hcap;
688 
689 	IBTF_DPRINTF_L2(ibtf, "ibc_pre_detach(%p, 0x%x)", hca_devp, cmd);
690 
691 	/*
692 	 * Return failure, if command is not DDI_DETACH
693 	 */
694 	switch (cmd) {
695 	case DDI_DETACH:
696 		break;
697 	default:
698 		return (IBC_FAILURE); /* TBD: DDI_FAILURE */
699 	}
700 
701 	/* Make sure this HCA is on the HCA Device List.  */
702 	mutex_enter(&ibtl_clnt_list_mutex);
703 	hcap = ibtl_hca_list;
704 	while (hcap != NULL) {
705 		if (hcap == hca_devp)
706 			break;
707 		hcap = hcap->hd_hca_dev_link;
708 	}
709 	if (hcap == NULL) {
710 		mutex_exit(&ibtl_clnt_list_mutex);
711 		return (IBC_FAILURE);
712 	}
713 
714 	/*
715 	 * Initially set the state to "Detaching".
716 	 */
717 	hca_devp->hd_state = IBTL_HCA_DEV_DETACHING;
718 
719 	/*
720 	 * Try to detach all IBTI clients, and continue only if all
721 	 * of the detaches succeed.
722 	 */
723 	if (ibtl_detach_all_clients(hca_devp)) {
724 		hca_devp->hd_state = IBTL_HCA_DEV_ATTACHED; /* fix hd_state */
725 		mutex_exit(&ibtl_clnt_list_mutex);
726 
727 		return (IBC_FAILURE);
728 	}
729 
730 	/*
731 	 * Check to see if all clients closed this HCA, or not.
732 	 * We only succeed if all clients cooperated.
733 	 */
734 	if (hca_devp->hd_clnt_list != NULL) {
735 		hca_devp->hd_state = IBTL_HCA_DEV_ATTACHED;
736 		mutex_exit(&ibtl_clnt_list_mutex);
737 		IBTF_DPRINTF_L2(ibtf, "ibc_pre_detach: HCA still has attached "
738 		    "clients");
739 		return (IBC_FAILURE);
740 	}
741 
742 	/*
743 	 * mark this device as detached
744 	 */
745 	hca_devp->hd_state = IBTL_HCA_DEV_DETACHED;
746 
747 	/* Delete the entry for this hca_devp from hca_head_list */
748 	hcapp = &ibtl_hca_list;
749 	while (*hcapp != NULL) {
750 		if (*hcapp == hca_devp)
751 			break;
752 		hcapp = &(*hcapp)->hd_hca_dev_link;
753 	}
754 
755 	if (mdi_phci_unregister(hca_devp->hd_hca_dip, 0) != MDI_SUCCESS) {
756 		hca_devp->hd_state = IBTL_HCA_DEV_ATTACHED; /* fix hd_state */
757 		mutex_exit(&ibtl_clnt_list_mutex);
758 		IBTF_DPRINTF_L1(ibtf, "ibc_pre_detach: PHCI unregister failed");
759 		return (IBC_FAILURE);
760 	}
761 
762 	if (*hcapp == NULL) {
763 		hca_devp->hd_state = IBTL_HCA_DEV_ATTACHED; /* fix hd_state */
764 		mutex_exit(&ibtl_clnt_list_mutex);
765 		IBTF_DPRINTF_L1(ibtf, "ibc_pre_detach: HCA not attached");
766 		return (IBC_FAILURE);
767 	}
768 	*hcapp = hca_devp->hd_hca_dev_link;
769 	ibtl_fast_gid_cache_valid = B_FALSE;	/* invalidate fast_gid_cache */
770 	mutex_exit(&ibtl_clnt_list_mutex);
771 
772 	return (IBC_SUCCESS);
773 }
774 
775 /*
776  * Function:
777  *	ibc_detach
778  * Input:
779  *	ibc_clnt_hdl	- IBC HCA Handle as returned during ibc_attach call.
780  * Output:
781  *	none
782  * Returns:
783  *	None
784  * Called by:
785  *	CI to detach the HCA device from IBTF.
786  * Description:
787  *	Do the second step of detaching the HCA, which is required
788  *	after a successful ibc_pre_detach.
789  */
790 void
791 ibc_detach(ibc_clnt_hdl_t hca_devp)
792 {
793 	IBTF_DPRINTF_L2(ibtf, "ibc_detach(%p)", hca_devp);
794 
795 	mutex_enter(&ibtl_clnt_list_mutex);
796 	if (hca_devp->hd_state != IBTL_HCA_DEV_DETACHED) {
797 		mutex_exit(&ibtl_clnt_list_mutex);
798 		IBTF_DPRINTF_L0(ibtf, "ibc_detach: HCA has not successfully "
799 		    "pre-detached");
800 		return;
801 	}
802 
803 	cv_destroy(&hca_devp->hd_async_task_cv);
804 	cv_destroy(&hca_devp->hd_async_busy_cv);
805 	cv_destroy(&hca_devp->hd_portinfo_cv);
806 
807 	kmem_free(hca_devp->hd_portinfop, hca_devp->hd_portinfo_len);
808 	mutex_exit(&ibtl_clnt_list_mutex);
809 
810 	/* Free up the memory of per-client info struct */
811 	kmem_free(hca_devp, sizeof (ibtl_hca_devinfo_t) +
812 	    (hca_devp->hd_hca_attr->hca_nports - 1) *
813 	    sizeof (ibtl_async_port_status_t));
814 	ibtl_clear_ibhw_status();
815 }
816 
817 /*
818  * Function:
819  *	ibt_ci_data_in()
820  *
821  * Input:
822  *	hca_hdl			HCA Handle.
823  *	flags			IBT_COMPLETE_ALLOC - Finish a deferred alloc.
824  *      object                  Identifies the type object pointed to by
825  *                              ibt_object_handle.
826  *
827  *      ibt_object_handle       The handle of the object to be associated with
828  *				the data in/out
829  *
830  *	data_p			Pointer data passed in to the CI. The buffer
831  *				should be allocated by the caller.
832  *
833  *	data_sz			The size of the buffer pointed to by
834  *				data_p.
835  * Output:
836  *
837  * Returns:
838  *	IBT_SUCCESS
839  *	IBT_NOT_SUPPORTED	Feature not supported.
840  *	IBT_INVALID_PARAM	Invalid object type specified.
841  *	IBT_HCA_HDL_INVALID
842  *	IBT_AH_HDL_INVALID/IBT_UD_DEST_HDL_INVALID
843  *	IBT_CHAN_HDL_INVALID/IBT_QP_HDL_INVALID
844  *	IBT_CQ_HDL_INVALID
845  *	IBT_EEC_HDL_INVALID
846  *	IBT_RDD_HDL_INVALID
847  *	IBT_MW_HDL_INVALID
848  *	IBT_PD_HDL_INVALID
849  *	IBT_SRQ_HDL_INVALID
850  *
851  * Description:
852  *	Exchange CI private data for the specified CI object.
853  */
854 ibt_status_t
855 ibt_ci_data_in(ibt_hca_hdl_t hca, ibt_ci_data_flags_t flags,
856     ibt_object_type_t object, void *ibt_object_handle, void *data_p,
857     size_t data_sz)
858 {
859 	ibt_status_t		retval;
860 	void			*ci_obj_hdl;
861 
862 	IBTF_DPRINTF_L3(ibtf, "ibt_ci_data_in(%p, %x, %d, %p, %p, %d)",
863 	    hca, flags, object, ibt_object_handle, data_p, data_sz);
864 
865 	switch (object) {
866 	case IBT_HDL_HCA:
867 		ci_obj_hdl = (void *)
868 		    (IBTL_HCA2CIHCA(((ibt_hca_hdl_t)ibt_object_handle)));
869 		break;
870 
871 	case IBT_HDL_CHANNEL:
872 		ci_obj_hdl = (void *)
873 		    (IBTL_CHAN2CIQP(((ibt_channel_hdl_t)ibt_object_handle)));
874 		break;
875 
876 	case IBT_HDL_CQ:
877 		ci_obj_hdl = (void *)
878 		    (((ibt_cq_hdl_t)(ibt_object_handle))->cq_ibc_cq_hdl);
879 		break;
880 
881 	case IBT_HDL_EEC:
882 		ci_obj_hdl = (void *)
883 		    (((ibt_eec_hdl_t)(ibt_object_handle))->eec_ibc_eec_hdl);
884 		break;
885 
886 	case IBT_HDL_UD_DEST:
887 		ci_obj_hdl = (void *)
888 		    (((ibt_ud_dest_hdl_t)(ibt_object_handle))->ud_ah);
889 		break;
890 
891 	case IBT_HDL_SRQ:
892 		ci_obj_hdl = (void *)
893 		    (((ibt_srq_hdl_t)(ibt_object_handle))->srq_ibc_srq_hdl);
894 		break;
895 
896 	default:
897 		ci_obj_hdl = ibt_object_handle;
898 		break;
899 	}
900 
901 	retval = (IBTL_HCA2CIHCAOPS_P(hca)->ibc_ci_data_in)(IBTL_HCA2CIHCA(hca),
902 	    flags, object, ci_obj_hdl, data_p, data_sz);
903 
904 	if (retval != IBT_SUCCESS) {
905 		IBTF_DPRINTF_L2(ibtf, "ibt_ci_data_in: Failed : %d", retval);
906 	}
907 	return (retval);
908 }
909 
910 /*
911  * Function:
912  *	ibt_ci_data_out()
913  *
914  * Input:
915  *	hca_hdl			HCA Handle.
916  *	flags			IBT_COMPLETE_ALLOC - Finish a deferred alloc.
917  *      object                  Identifies the type object pointed to by
918  *                              ibt_object_handle.
919  *
920  *      ibt_object_handle       The handle of the object to be associated with
921  *				the data in/out
922  *
923  *	data_p			Pointer to a buffer in which to return the CI
924  *				private data. The buffer should be allocated
925  *				by the caller.
926  *
927  *	data_sz			The size of the buffer pointed to by
928  *				data_p.
929  * Output:
930  *
931  * Returns:
932  *	IBT_SUCCESS
933  *	IBT_NOT_SUPPORTED	Feature not supported.
934  *	IBT_INSUFF_RESOURCE	The buffer pointed to by data_p was too
935  *				small to hold the data.
936  *	IBT_INVALID_PARAM	Invalid object type specified.
937  *	IBT_HCA_HDL_INVALID
938  *	IBT_AH_HDL_INVALID/IBT_UD_DEST_HDL_INVALID
939  *	IBT_CHAN_HDL_INVALID/IBT_QP_HDL_INVALID
940  *	IBT_CQ_HDL_INVALID
941  *	IBT_EEC_HDL_INVALID
942  *	IBT_RDD_HDL_INVALID
943  *	IBT_MW_HDL_INVALID
944  *	IBT_PD_HDL_INVALID
945  *	IBT_SRQ_HDL_INVALID
946  *
947  * Description:
948  *	Exchange CI private data for the specified CI object.
949  */
950 ibt_status_t
951 ibt_ci_data_out(ibt_hca_hdl_t hca, ibt_ci_data_flags_t flags,
952     ibt_object_type_t object, void *ibt_object_handle, void *data_p,
953     size_t data_sz)
954 {
955 	ibt_status_t		retval;
956 	void			*ci_obj_hdl;
957 
958 	IBTF_DPRINTF_L3(ibtf, "ibt_ci_data_out(%p, %x, %d, %p, %p, %d)",
959 	    hca, flags, object, ibt_object_handle, data_p, data_sz);
960 
961 	switch (object) {
962 	case  IBT_HDL_HCA:
963 		ci_obj_hdl = (void *)
964 		    (IBTL_HCA2CIHCA(((ibt_hca_hdl_t)ibt_object_handle)));
965 		break;
966 
967 	case IBT_HDL_CHANNEL:
968 		ci_obj_hdl = (void *)
969 		    (IBTL_CHAN2CIQP(((ibt_channel_hdl_t)ibt_object_handle)));
970 		break;
971 
972 	case IBT_HDL_CQ:
973 		ci_obj_hdl = (void *)
974 		    (((ibt_cq_hdl_t)(ibt_object_handle))->cq_ibc_cq_hdl);
975 		break;
976 
977 	case IBT_HDL_EEC:
978 		ci_obj_hdl = (void *)
979 		    (((ibt_eec_hdl_t)(ibt_object_handle))->eec_ibc_eec_hdl);
980 		break;
981 
982 	case IBT_HDL_UD_DEST:
983 		ci_obj_hdl = (void *)
984 		    (((ibt_ud_dest_hdl_t)(ibt_object_handle))->ud_ah);
985 		break;
986 
987 	case IBT_HDL_SRQ:
988 		ci_obj_hdl = (void *)
989 		    (((ibt_srq_hdl_t)(ibt_object_handle))->srq_ibc_srq_hdl);
990 		break;
991 
992 	default:
993 		ci_obj_hdl = ibt_object_handle;
994 		break;
995 	}
996 
997 	retval = (IBTL_HCA2CIHCAOPS_P(hca)->ibc_ci_data_out)
998 	    (IBTL_HCA2CIHCA(hca), flags, object, ci_obj_hdl, data_p, data_sz);
999 
1000 	if (retval != IBT_SUCCESS) {
1001 		IBTF_DPRINTF_L2(ibtf, "ibt_ci_data_out: Failed : %d", retval);
1002 	}
1003 	return (retval);
1004 }
1005 
1006 
1007 /*
1008  * FMA Support functions.
1009  */
1010 
1011 #define	IBTL_ENA_MASK		0xC0000000
1012 #define	IBTL_ENA_POSSIBLE	0x80000000
1013 #define	IBTL_TYPE_SHIFT		27
1014 
1015 /*
1016  * Function:
1017  *	ibt_get_module_failure()
1018  *
1019  * Input:
1020  *	type			Identifies the failing IB module.
1021  *	ena			'0' or the data for Fault Management
1022  *				Architecture (ENA).
1023  *
1024  * Returns:
1025  *	status			Special IB failure status.
1026  *
1027  * Description:
1028  *	XXX Just stubbed out to return failures with no data for Fault
1029  *	Management Architecture (ENAs) at the moment XXX
1030  */
1031 ibt_status_t
1032 ibt_get_module_failure(ibt_failure_type_t type, uint64_t ena)
1033 {
1034 	ibt_status_t	ret;
1035 
1036 	IBTF_DPRINTF_L3(ibtf, "ibt_get_module_failure(%d, 0x%llX)", type, ena);
1037 
1038 	switch (type) {
1039 	case IBT_FAILURE_CI:
1040 	case IBT_FAILURE_IBMF:
1041 	case IBT_FAILURE_IBCM:
1042 	case IBT_FAILURE_IBDM:
1043 	case IBT_FAILURE_IBTL:
1044 	case IBT_FAILURE_IBSM:
1045 		ret = IBTL_ENA_POSSIBLE | (type << IBTL_TYPE_SHIFT);
1046 		break;
1047 	default:
1048 		ret = IBT_FAILURE;
1049 	}
1050 	IBTF_DPRINTF_L3(ibtf, "ibt_get_module_failure: ret = 0x%lX", ret);
1051 	return (ret);
1052 }
1053 
1054 
1055 /*
1056  * Function:
1057  *	ibc_get_ci_failure()
1058  *
1059  * Input:
1060  *	ena			'0' or the data for Fault Management
1061  *				Architecture (ENA).
1062  *
1063  * Returns:
1064  *	status			Special CI failure status.
1065  *
1066  * Description:
1067  *	Just use the function above to do the job.
1068  */
1069 ibt_status_t
1070 ibc_get_ci_failure(uint64_t ena)
1071 {
1072 	return (ibt_get_module_failure(IBT_FAILURE_CI, ena));
1073 }
1074 
1075 
1076 /*
1077  * ibt_check_failure()
1078  *	Function to test for special case failures.
1079  *
1080  *	status		An ibt_status_t returned from an IBTF function call.
1081  *
1082  *	reserved_p	NULL, or a pointer to where we store the data for
1083  *			Fault Management Architecture (ENA).
1084  *
1085  * Description:
1086  *	XXX Still need to determine the data for Fault Management Architecture
1087  *	(ENA), using 0 for now XXX
1088  */
1089 ibt_failure_type_t
1090 ibt_check_failure(ibt_status_t status, uint64_t *reserved_p)
1091 {
1092 	ibt_failure_type_t type;
1093 
1094 	IBTF_DPRINTF_L3(ibtf, "ibt_check_failure(%X)", status);
1095 
1096 	if ((status & IBTL_ENA_MASK) == IBTL_ENA_POSSIBLE) {
1097 		type = status & ~IBTL_ENA_POSSIBLE >> IBTL_TYPE_SHIFT;
1098 
1099 		/* XXX Need more work here... */
1100 		if (reserved_p != NULL)
1101 			*reserved_p = 0;
1102 	} else {
1103 		type = IBT_FAILURE_STANDARD;
1104 		if (reserved_p != NULL)
1105 			*reserved_p = 0;	/* No FMA Data Available. */
1106 	}
1107 	IBTF_DPRINTF_L3(ibtf, "ibt_check_failure: type = 0x%X", type);
1108 	return (type);
1109 }
1110