xref: /onnv-gate/usr/src/uts/common/io/ib/ibtl/ibtl_impl.c (revision 12965:b65a8427f8fe)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57862SRichard.Bean@Sun.COM  * Common Development and Distribution License (the "License").
67862SRichard.Bean@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
2212163SRamaswamy.Tummala@Sun.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate /*
260Sstevel@tonic-gate  * ibtl_impl.c
270Sstevel@tonic-gate  *
280Sstevel@tonic-gate  * This file contains the IBTF module's initialization and
290Sstevel@tonic-gate  * IBTF Clients/Modules registration routines.
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <sys/modctl.h>
330Sstevel@tonic-gate #include <sys/sunndi.h>
340Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl.h>
350Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl_ibnex.h>
360Sstevel@tonic-gate 
370Sstevel@tonic-gate /*
380Sstevel@tonic-gate  * Globals.
390Sstevel@tonic-gate  */
400Sstevel@tonic-gate static char ibtf[] = "ibtl_impl";
410Sstevel@tonic-gate 
420Sstevel@tonic-gate extern ibtl_ibnex_callback_t	ibtl_ibnex_callback_routine;
430Sstevel@tonic-gate 
440Sstevel@tonic-gate /*
450Sstevel@tonic-gate  * ibtl_clnt_list:
460Sstevel@tonic-gate  *
470Sstevel@tonic-gate  *	Head of the list of IBT Client Instances. The IBT Client List
480Sstevel@tonic-gate  *	is modified by IBTF on an IBT client's ibt_attach/ibt_detach call.
490Sstevel@tonic-gate  *
500Sstevel@tonic-gate  * ibtl_hca_list:
510Sstevel@tonic-gate  *
520Sstevel@tonic-gate  *	Head of the list of HCA devices. The HCA List is modified by IBTF on
530Sstevel@tonic-gate  *	a CI's ibc_attach/ibc_detach call.
540Sstevel@tonic-gate  *	The datap of the list elements points to an ibtl_hca_devinfo_s
550Sstevel@tonic-gate  *	structure.
560Sstevel@tonic-gate  *
570Sstevel@tonic-gate  *				(ibc_attach)
580Sstevel@tonic-gate  *  ibtl_hca_list	-> ibtl_hca_devinfo_t--> ...	-->ibtl_hca_devinfo_t
590Sstevel@tonic-gate  *	[per-hca_dev]		|	^			{nth HCA Dev}
600Sstevel@tonic-gate  *				|	|
610Sstevel@tonic-gate  *				|  ibtl_hca_t (ibt_open_hca)
620Sstevel@tonic-gate  *				|	^  |
630Sstevel@tonic-gate  *				|	|  |
640Sstevel@tonic-gate  *				v	|  V
650Sstevel@tonic-gate  *  ibtl_clnt_list	->	ibtl_clnt_t--> ...--> {n'th Module}
660Sstevel@tonic-gate  *	[per-client_instance]	(ibt_attach)
670Sstevel@tonic-gate  *
680Sstevel@tonic-gate  */
690Sstevel@tonic-gate 
700Sstevel@tonic-gate /* Global List of IBT Client Instances, and associated mutex. */
710Sstevel@tonic-gate struct ibtl_clnt_s *ibtl_clnt_list = NULL;
720Sstevel@tonic-gate kmutex_t ibtl_clnt_list_mutex;
730Sstevel@tonic-gate 
740Sstevel@tonic-gate /* Lock for the race between the client and CM to free QPs. */
750Sstevel@tonic-gate kmutex_t ibtl_free_qp_mutex;
760Sstevel@tonic-gate 
770Sstevel@tonic-gate /* Lock for the race between the client closing the HCA and QPN being freed. */
780Sstevel@tonic-gate kcondvar_t ibtl_close_hca_cv;
790Sstevel@tonic-gate 
800Sstevel@tonic-gate /* Global List of HCA Devices, and associated mutex. */
810Sstevel@tonic-gate struct ibtl_hca_devinfo_s *ibtl_hca_list = NULL;
820Sstevel@tonic-gate 
830Sstevel@tonic-gate /* Well-known async handlers and associated client private. */
840Sstevel@tonic-gate ibt_async_handler_t ibtl_cm_async_handler;
850Sstevel@tonic-gate ibt_async_handler_t ibtl_dm_async_handler;
860Sstevel@tonic-gate ibt_async_handler_t ibtl_ibma_async_handler;
870Sstevel@tonic-gate void	*ibtl_cm_clnt_private;
880Sstevel@tonic-gate void	*ibtl_dm_clnt_private;
890Sstevel@tonic-gate void	*ibtl_ibma_clnt_private;
900Sstevel@tonic-gate 
910Sstevel@tonic-gate extern int ib_hw_status;
920Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("Scheme protects data", ib_hw_status))
930Sstevel@tonic-gate 
940Sstevel@tonic-gate /*
950Sstevel@tonic-gate  * Misc Module Declarations.
960Sstevel@tonic-gate  */
970Sstevel@tonic-gate extern struct mod_ops mod_miscops;
980Sstevel@tonic-gate static struct modlmisc modlmisc = {
990Sstevel@tonic-gate 	&mod_miscops,			/* Type of module - misc. */
1007862SRichard.Bean@Sun.COM 	"IB Transport Layer"		/* Name of the Module. */
1010Sstevel@tonic-gate };
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate static struct modlinkage modlinkage = {
1040Sstevel@tonic-gate 	MODREV_1, (void *)&modlmisc, NULL
1050Sstevel@tonic-gate };
1060Sstevel@tonic-gate 
1079879SRamaswamy.Tummala@Sun.COM static void ibtl_kstat_init(ibtl_hca_devinfo_t *);
1089879SRamaswamy.Tummala@Sun.COM static void ibtl_kstat_fini(ibtl_hca_devinfo_t *);
1099879SRamaswamy.Tummala@Sun.COM static void ibtl_kstat_stats_create(ibtl_hca_devinfo_t *, uint_t);
1109879SRamaswamy.Tummala@Sun.COM static void ibtl_kstat_pkeys_create(ibtl_hca_devinfo_t *, uint_t);
1110Sstevel@tonic-gate 
11212163SRamaswamy.Tummala@Sun.COM extern kmutex_t ibtl_part_attr_mutex;
11312163SRamaswamy.Tummala@Sun.COM 
1140Sstevel@tonic-gate /*
1150Sstevel@tonic-gate  * IBTF Loadable Module Routines.
1160Sstevel@tonic-gate  */
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate int
_init(void)1190Sstevel@tonic-gate _init(void)
1200Sstevel@tonic-gate {
1210Sstevel@tonic-gate 	int rval;
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	if ((rval = mod_install(&modlinkage)) != 0)
1240Sstevel@tonic-gate 		return (rval);
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 	/*
1270Sstevel@tonic-gate 	 * initialize IBTL ib2usec table
1280Sstevel@tonic-gate 	 */
1290Sstevel@tonic-gate 	ibtl_ib2usec_init();
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate 	/*
1320Sstevel@tonic-gate 	 * Initialize Logging
1330Sstevel@tonic-gate 	 */
1340Sstevel@tonic-gate 	ibtl_logging_initialization();
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	/*
1370Sstevel@tonic-gate 	 * Initialize the Alloc QP States.
1380Sstevel@tonic-gate 	 */
1390Sstevel@tonic-gate 	ibtl_init_cep_states();
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	/*
1420Sstevel@tonic-gate 	 * Initialize all Global Link Lists.
1430Sstevel@tonic-gate 	 */
1440Sstevel@tonic-gate 	mutex_init(&ibtl_clnt_list_mutex, NULL, MUTEX_DEFAULT, NULL);
1450Sstevel@tonic-gate 	mutex_init(&ibtl_free_qp_mutex, NULL, MUTEX_DEFAULT, NULL);
1460Sstevel@tonic-gate 	cv_init(&ibtl_close_hca_cv, NULL, CV_DEFAULT, NULL);
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 	mutex_init(&ibtl_qp_mutex, NULL, MUTEX_DEFAULT, NULL);
1490Sstevel@tonic-gate 	cv_init(&ibtl_qp_cv, NULL, CV_DEFAULT, NULL);
1500Sstevel@tonic-gate 
15112163SRamaswamy.Tummala@Sun.COM 	mutex_init(&ibtl_part_attr_mutex, NULL, MUTEX_DEFAULT, NULL);
15212163SRamaswamy.Tummala@Sun.COM 
1530Sstevel@tonic-gate 	ibtl_thread_init();
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	return (rval);
1560Sstevel@tonic-gate }
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate int
_fini(void)1600Sstevel@tonic-gate _fini(void)
1610Sstevel@tonic-gate {
1620Sstevel@tonic-gate 	int rval;
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 	if ((rval = mod_remove(&modlinkage)) != 0) {
1650Sstevel@tonic-gate 		return (rval);
1660Sstevel@tonic-gate 	}
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	ibtl_thread_fini();
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate 	mutex_destroy(&ibtl_clnt_list_mutex);
1710Sstevel@tonic-gate 	mutex_destroy(&ibtl_free_qp_mutex);
1720Sstevel@tonic-gate 	cv_destroy(&ibtl_close_hca_cv);
1730Sstevel@tonic-gate 	mutex_destroy(&ibtl_qp_mutex);
1740Sstevel@tonic-gate 	cv_destroy(&ibtl_qp_cv);
17512163SRamaswamy.Tummala@Sun.COM 	mutex_destroy(&ibtl_part_attr_mutex);
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	/*
1780Sstevel@tonic-gate 	 * Stop Logging
1790Sstevel@tonic-gate 	 */
1800Sstevel@tonic-gate 	ibtl_logging_destroy();
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 	return (rval);
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate int
_info(struct modinfo * modinfop)1870Sstevel@tonic-gate _info(struct modinfo *modinfop)
1880Sstevel@tonic-gate {
1890Sstevel@tonic-gate 	/* Return the Module Information. */
1900Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
1910Sstevel@tonic-gate }
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate /*
1950Sstevel@tonic-gate  * IBTF Client Registration Routines.
1960Sstevel@tonic-gate  */
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate /*
1990Sstevel@tonic-gate  * Function:
2000Sstevel@tonic-gate  *	ibt_attach
2010Sstevel@tonic-gate  * Input:
2020Sstevel@tonic-gate  *	modinfop	- Client Module info structure.
2030Sstevel@tonic-gate  *	arg		- usually client's dip
2040Sstevel@tonic-gate  *	clnt_private	- client's private data pointer.
2050Sstevel@tonic-gate  * Output:
2060Sstevel@tonic-gate  *	ibt_hdl_p	- pointer to client's specific IBT handle,
2070Sstevel@tonic-gate  *			 which is opaque to clients.
2080Sstevel@tonic-gate  * Returns:
2090Sstevel@tonic-gate  *	IBT_SUCCESS
2100Sstevel@tonic-gate  *	IBT_INVALID_PARAM
2110Sstevel@tonic-gate  * Called by:
2120Sstevel@tonic-gate  *	IBTF Client module during its attach() to register its instance
2130Sstevel@tonic-gate  *	to IBTF.
2140Sstevel@tonic-gate  * Description:
2150Sstevel@tonic-gate  *	Registers the IBTF client module instance and returns an opaque
2160Sstevel@tonic-gate  *	handler to the client to be used for future calls to IBTF.
2170Sstevel@tonic-gate  *	Adds this client module instance to ibtl_clnt_list list.
2180Sstevel@tonic-gate  *	Records well-known async handlers.
2190Sstevel@tonic-gate  */
2200Sstevel@tonic-gate ibt_status_t
ibt_attach(ibt_clnt_modinfo_t * mod_infop,dev_info_t * arg,void * clnt_private,ibt_clnt_hdl_t * ibt_hdl_p)2210Sstevel@tonic-gate ibt_attach(ibt_clnt_modinfo_t *mod_infop, dev_info_t *arg, void *clnt_private,
2220Sstevel@tonic-gate     ibt_clnt_hdl_t *ibt_hdl_p)
2230Sstevel@tonic-gate {
2240Sstevel@tonic-gate 	dev_info_t	*pdip;
2250Sstevel@tonic-gate 	ibtl_clnt_t	*clntp;
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf, "ibt_attach(%p, %p, %p)",
2280Sstevel@tonic-gate 	    mod_infop, arg, clnt_private);
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 	if (mod_infop->mi_clnt_name == NULL) {
2310Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
2320Sstevel@tonic-gate 		    "IB client needs to specify its name");
2330Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
2340Sstevel@tonic-gate 	}
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 	/*
2370Sstevel@tonic-gate 	 * Validate the Transport API version.
2380Sstevel@tonic-gate 	 */
2398580SBill.Taylor@Sun.COM 	if (mod_infop->mi_ibt_version != IBTI_V_CURR) {
2400Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibt_attach: IB client '%s' has an "
2410Sstevel@tonic-gate 		    "invalid IB TI Version '%d'", mod_infop->mi_clnt_name,
2420Sstevel@tonic-gate 		    mod_infop->mi_ibt_version);
243929Ssrust 		return (IBT_NOT_SUPPORTED);
2440Sstevel@tonic-gate 	}
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 	if (mod_infop->mi_async_handler == NULL) {
2470Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf, "ibt_attach: Client '%s' has not\n"
2480Sstevel@tonic-gate 		    "        provided an Asynchronous Event Handler.\n"
2490Sstevel@tonic-gate 		    "        This will be required soon.",
2500Sstevel@tonic-gate 		    mod_infop->mi_clnt_name);
2510Sstevel@tonic-gate 	}
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 	/*
2540Sstevel@tonic-gate 	 * Check out Client's Class information. If it is not of mgmt class,
2550Sstevel@tonic-gate 	 * we expect 'arg' to be Not NULL and point to client driver's
2560Sstevel@tonic-gate 	 * device info struct.
2570Sstevel@tonic-gate 	 */
2589076SRajkumar.Sivaprakasam@Sun.COM 	if ((!IBT_MISCMOD_CLIENTS(mod_infop->mi_clnt_class)) &&
2590Sstevel@tonic-gate 	    (arg == NULL)) {
2600Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
2610Sstevel@tonic-gate 		    "arg not set with driver's dip.");
2620Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
2630Sstevel@tonic-gate 	}
2640Sstevel@tonic-gate 
2659076SRajkumar.Sivaprakasam@Sun.COM 	if (!IBT_MISCMOD_CLIENTS(mod_infop->mi_clnt_class)) {
2660Sstevel@tonic-gate 		pdip = ddi_get_parent(arg);
2670Sstevel@tonic-gate 		if (pdip == NULL ||
2680Sstevel@tonic-gate 		    ibtl_ibnex_valid_hca_parent(pdip) != IBT_SUCCESS) {
2690Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtf, "ibt_attach: "
2700Sstevel@tonic-gate 			    "client %s is not a child of IB nexus driver.",
2710Sstevel@tonic-gate 			    ddi_driver_name(arg));
2720Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
2730Sstevel@tonic-gate 		}
2740Sstevel@tonic-gate 	}
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
2770Sstevel@tonic-gate 	if (mod_infop->mi_clnt_class == IBT_CM) {
2780Sstevel@tonic-gate 		if (ibtl_cm_async_handler != NULL) {
2790Sstevel@tonic-gate 			IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
2800Sstevel@tonic-gate 			    "CM is already attached.");
2810Sstevel@tonic-gate 			mutex_exit(&ibtl_clnt_list_mutex);
2820Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
2830Sstevel@tonic-gate 		}
2840Sstevel@tonic-gate 		ibtl_cm_async_handler = mod_infop->mi_async_handler;
2850Sstevel@tonic-gate 		ibtl_cm_clnt_private = clnt_private;
2860Sstevel@tonic-gate 	} else if (mod_infop->mi_clnt_class == IBT_DM) {
2870Sstevel@tonic-gate 		if (ibtl_dm_async_handler != NULL) {
2880Sstevel@tonic-gate 			IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
2890Sstevel@tonic-gate 			    "DM is already attached.");
2900Sstevel@tonic-gate 			mutex_exit(&ibtl_clnt_list_mutex);
2910Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
2920Sstevel@tonic-gate 		}
2930Sstevel@tonic-gate 		ibtl_dm_async_handler = mod_infop->mi_async_handler;
2940Sstevel@tonic-gate 		ibtl_dm_clnt_private = clnt_private;
2950Sstevel@tonic-gate 	} else if (mod_infop->mi_clnt_class == IBT_IBMA) {
2960Sstevel@tonic-gate 		if (ibtl_ibma_async_handler != NULL) {
2970Sstevel@tonic-gate 			IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
2980Sstevel@tonic-gate 			    "IBMF is already attached.");
2990Sstevel@tonic-gate 			mutex_exit(&ibtl_clnt_list_mutex);
3000Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
3010Sstevel@tonic-gate 		}
3020Sstevel@tonic-gate 		ibtl_ibma_async_handler = mod_infop->mi_async_handler;
3030Sstevel@tonic-gate 		ibtl_ibma_clnt_private = clnt_private;
3040Sstevel@tonic-gate 	}
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 	/* Allocate the memory for per-client-device info structure */
3070Sstevel@tonic-gate 	clntp = kmem_zalloc(sizeof (ibtl_clnt_t), KM_SLEEP);
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(clntp->clnt_modinfop,
3100Sstevel@tonic-gate 	    clntp->clnt_dip, clntp->clnt_name, clntp->clnt_async_cnt,
3110Sstevel@tonic-gate 	    clntp->clnt_private))
3120Sstevel@tonic-gate 	/* Update the Client info structure */
3130Sstevel@tonic-gate 	clntp->clnt_modinfop = mod_infop;	/* IBT Client's Mod Info */
3140Sstevel@tonic-gate 	clntp->clnt_private = clnt_private;	/* IBT Client's private */
3150Sstevel@tonic-gate 	clntp->clnt_dip = arg;			/* IBT Client's dip */
3160Sstevel@tonic-gate 	clntp->clnt_async_cnt = 0;
3170Sstevel@tonic-gate 	/* using a count of 7 below guarantees it is NULL terminated */
3180Sstevel@tonic-gate 	(void) strncpy(clntp->clnt_name, mod_infop->mi_clnt_name, 7);
3190Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(clntp->clnt_modinfop,
3200Sstevel@tonic-gate 	    clntp->clnt_dip, clntp->clnt_name, clntp->clnt_async_cnt,
3210Sstevel@tonic-gate 	    clntp->clnt_private))
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 	/*
3240Sstevel@tonic-gate 	 * Update Client Device Instance List.
3250Sstevel@tonic-gate 	 */
3260Sstevel@tonic-gate 	clntp->clnt_list_link = ibtl_clnt_list;
3270Sstevel@tonic-gate 	ibtl_clnt_list = clntp;
3280Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	/*
3310Sstevel@tonic-gate 	 * The ibt_hdl_p is a opaque handle which is the address of
3320Sstevel@tonic-gate 	 * ibt_clnt_t structure passed back to the clients.
3330Sstevel@tonic-gate 	 * The client will pass on this handle in its future calls to IBTF.
3340Sstevel@tonic-gate 	 */
3350Sstevel@tonic-gate 	*ibt_hdl_p = clntp;
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 	return (IBT_SUCCESS);
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate /*
3420Sstevel@tonic-gate  * Function:
3430Sstevel@tonic-gate  *	ibt_detach
3440Sstevel@tonic-gate  * Input:
3450Sstevel@tonic-gate  *	ibt_hdl - IBT Handle as returned during ibt_attach call.
3460Sstevel@tonic-gate  * Output:
3470Sstevel@tonic-gate  *	none
3480Sstevel@tonic-gate  * Returns:
3490Sstevel@tonic-gate  *	IBT_SUCCESS
3500Sstevel@tonic-gate  *	IBT_INVALID_PARAM.
3510Sstevel@tonic-gate  * Called by:
3520Sstevel@tonic-gate  *	IBTF Client module during its detach() to de-register its instance
3530Sstevel@tonic-gate  *	from IBTF.
3540Sstevel@tonic-gate  * Description:
3550Sstevel@tonic-gate  *	Deregisters the IBTF client module instance from the IBTF.
3560Sstevel@tonic-gate  *	All resources and any reference to this ibt_hdl will be removed.
3570Sstevel@tonic-gate  */
3580Sstevel@tonic-gate ibt_status_t
ibt_detach(ibt_clnt_hdl_t ibt_hdl)3590Sstevel@tonic-gate ibt_detach(ibt_clnt_hdl_t ibt_hdl)
3600Sstevel@tonic-gate {
3610Sstevel@tonic-gate 	ibtl_clnt_t **clntpp;
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf, "ibt_detach(%p)", ibt_hdl);
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
3660Sstevel@tonic-gate 	clntpp = &ibtl_clnt_list;
3670Sstevel@tonic-gate 	for (; *clntpp != NULL; clntpp = &(*clntpp)->clnt_list_link)
3680Sstevel@tonic-gate 		if (*clntpp == ibt_hdl)
3690Sstevel@tonic-gate 			break;
3700Sstevel@tonic-gate 	if (*clntpp == NULL) {
3710Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibt_detach: Client @ %p Not Found",
3720Sstevel@tonic-gate 		    ibt_hdl);
3730Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
3740Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
3750Sstevel@tonic-gate 	}
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate 	/*
3780Sstevel@tonic-gate 	 * Check out whether the client has freed all its resources.
3790Sstevel@tonic-gate 	 * If not done, then fail the detach.
3800Sstevel@tonic-gate 	 *
3810Sstevel@tonic-gate 	 * viz. A client has to close all the HCA they have opened,
3820Sstevel@tonic-gate 	 * i.e. the HCA List maintained for clients has to be empty.
3830Sstevel@tonic-gate 	 * If this list is not empty, then the client has not performed
3840Sstevel@tonic-gate 	 * complete clean-up, so fail the detach.
3850Sstevel@tonic-gate 	 */
3860Sstevel@tonic-gate 	if (ibt_hdl->clnt_hca_list != NULL) {
3870Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf, "ibt_detach: "
3900Sstevel@tonic-gate 		    "ERROR: Client '%s' has not closed all of its HCAs",
3910Sstevel@tonic-gate 		    ibt_hdl->clnt_modinfop->mi_clnt_name);
39212574SWilliam.Taylor@Oracle.COM 		cmn_err(CE_CONT, "IBT DETACH failed: resources not yet "
39312574SWilliam.Taylor@Oracle.COM 		    "freed by client '%s'\n",
39412574SWilliam.Taylor@Oracle.COM 		    ibt_hdl->clnt_modinfop->mi_clnt_name);
3950Sstevel@tonic-gate 		return (IBT_HCA_RESOURCES_NOT_FREED);
3960Sstevel@tonic-gate 	}
3970Sstevel@tonic-gate 
3980Sstevel@tonic-gate 	if (ibt_hdl->clnt_srv_cnt != 0) {
3990Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
4000Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf, "ibt_detach: client '%s' still has "
4010Sstevel@tonic-gate 		    "services or subnet_notices registered",
4020Sstevel@tonic-gate 		    ibt_hdl->clnt_modinfop->mi_clnt_name);
40312574SWilliam.Taylor@Oracle.COM 		cmn_err(CE_CONT, "IBT DETACH failed: resources not yet "
40412574SWilliam.Taylor@Oracle.COM 		    "freed by client '%s'\n",
40512574SWilliam.Taylor@Oracle.COM 		    ibt_hdl->clnt_modinfop->mi_clnt_name);
4060Sstevel@tonic-gate 		return (IBT_HCA_RESOURCES_NOT_FREED);
4070Sstevel@tonic-gate 	}
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 	/*
4100Sstevel@tonic-gate 	 * Delete the entry of this module from the ibtl_clnt_list List.
4110Sstevel@tonic-gate 	 */
4120Sstevel@tonic-gate 	*clntpp = ibt_hdl->clnt_list_link;	/* remove us */
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate 	/* make sure asyncs complete before freeing */
4150Sstevel@tonic-gate 	ibtl_free_clnt_async_check(ibt_hdl);
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 	if (ibt_hdl->clnt_modinfop->mi_clnt_class == IBT_CM) {
4180Sstevel@tonic-gate 		ibtl_cm_async_handler = NULL;
4190Sstevel@tonic-gate 		ibtl_cm_clnt_private = NULL;
4200Sstevel@tonic-gate 	} else if (ibt_hdl->clnt_modinfop->mi_clnt_class == IBT_DM) {
4210Sstevel@tonic-gate 		ibtl_dm_async_handler = NULL;
4220Sstevel@tonic-gate 		ibtl_dm_clnt_private = NULL;
4230Sstevel@tonic-gate 	} else if (ibt_hdl->clnt_modinfop->mi_clnt_class == IBT_IBMA) {
4240Sstevel@tonic-gate 		ibtl_ibma_async_handler = NULL;
4250Sstevel@tonic-gate 		ibtl_ibma_clnt_private = NULL;
4260Sstevel@tonic-gate 	}
4270Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate 	/* Free up the memory of per-client info struct. */
4300Sstevel@tonic-gate 	kmem_free(ibt_hdl, sizeof (ibtl_clnt_t));
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 	return (IBT_SUCCESS);
4330Sstevel@tonic-gate }
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate static void
ibtl_set_ibhw_status()4360Sstevel@tonic-gate ibtl_set_ibhw_status()
4370Sstevel@tonic-gate {
4380Sstevel@tonic-gate 	ib_hw_status++;
4390Sstevel@tonic-gate }
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate static void
ibtl_clear_ibhw_status()4420Sstevel@tonic-gate ibtl_clear_ibhw_status()
4430Sstevel@tonic-gate {
4440Sstevel@tonic-gate 	ib_hw_status--;
4450Sstevel@tonic-gate }
4460Sstevel@tonic-gate 
4470Sstevel@tonic-gate /*
4480Sstevel@tonic-gate  * Function:
4490Sstevel@tonic-gate  *	ibc_init
4500Sstevel@tonic-gate  * Input:
4510Sstevel@tonic-gate  *	modlp		- Pointer to IBC client module linkage structure
4520Sstevel@tonic-gate  * Output:
4530Sstevel@tonic-gate  *	None
4540Sstevel@tonic-gate  * Returns:
4550Sstevel@tonic-gate  *	0 always for now
4560Sstevel@tonic-gate  * Called by:
4570Sstevel@tonic-gate  *	CI client calls IBTF during its _init() to register HCA with
4580Sstevel@tonic-gate  *	Solaris I/O framework.
4590Sstevel@tonic-gate  * Description:
4600Sstevel@tonic-gate  *	Initializes the CI clients module linkage structure with
4610Sstevel@tonic-gate  *	default bus_ops structure
4620Sstevel@tonic-gate  */
4630Sstevel@tonic-gate int
ibc_init(struct modlinkage * modlp)4640Sstevel@tonic-gate ibc_init(struct modlinkage *modlp)
4650Sstevel@tonic-gate {
4660Sstevel@tonic-gate 	ibtl_ibnex_cb_args_t	cb_args;
4670Sstevel@tonic-gate 
4680Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
4690Sstevel@tonic-gate 	cb_args.cb_flag = IBTL_IBNEX_IBC_INIT;
4700Sstevel@tonic-gate 	cb_args.cb_modlp = modlp;
4710Sstevel@tonic-gate 	if (ibtl_ibnex_callback_routine) {
4720Sstevel@tonic-gate 		(void) ((*ibtl_ibnex_callback_routine)(&cb_args));
4730Sstevel@tonic-gate 	}
4740Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
4750Sstevel@tonic-gate 	return (0);
4760Sstevel@tonic-gate }
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate /*
4800Sstevel@tonic-gate  * Function:
4810Sstevel@tonic-gate  *	ibc_fini
4820Sstevel@tonic-gate  * Input:
4830Sstevel@tonic-gate  *	modlp		- Pointer to IBC client module linkage structure
4840Sstevel@tonic-gate  * Output:
4850Sstevel@tonic-gate  *	None
4860Sstevel@tonic-gate  * Returns:
4870Sstevel@tonic-gate  *	None
4880Sstevel@tonic-gate  * Called by:
4890Sstevel@tonic-gate  *	CI client calls IBTF during its _fini() to remove HCA with
4900Sstevel@tonic-gate  *	Solaris I/O framework.
4910Sstevel@tonic-gate  * Description:
4920Sstevel@tonic-gate  *	Undo what is done during ibc_init
4930Sstevel@tonic-gate  */
4940Sstevel@tonic-gate void
ibc_fini(struct modlinkage * modlp)4950Sstevel@tonic-gate ibc_fini(struct modlinkage *modlp)
4960Sstevel@tonic-gate {
4970Sstevel@tonic-gate 	ibtl_ibnex_cb_args_t	cb_args;
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
5000Sstevel@tonic-gate 	cb_args.cb_flag = IBTL_IBNEX_IBC_FINI;
5010Sstevel@tonic-gate 	cb_args.cb_modlp = modlp;
5020Sstevel@tonic-gate 	if (ibtl_ibnex_callback_routine) {
5030Sstevel@tonic-gate 		(void) ((*ibtl_ibnex_callback_routine)(&cb_args));
5040Sstevel@tonic-gate 	}
5050Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
5060Sstevel@tonic-gate }
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate /*
5090Sstevel@tonic-gate  * Function:
5100Sstevel@tonic-gate  *	ibc_attach
5110Sstevel@tonic-gate  * Input:
5120Sstevel@tonic-gate  *	info_p		- IBC HCA Info.
5130Sstevel@tonic-gate  * Output:
5140Sstevel@tonic-gate  *	ibc_hdl_p	- IBC Client's HCA Handle.
5150Sstevel@tonic-gate  * Returns:
5160Sstevel@tonic-gate  *	IBC_SUCCESS
5170Sstevel@tonic-gate  *	IBC_FAILURE
5180Sstevel@tonic-gate  * Called by:
5190Sstevel@tonic-gate  *	CI calls IBTF during its attach() to register HCA Device with IBTF.
5200Sstevel@tonic-gate  * Description:
5210Sstevel@tonic-gate  *	Registers the presence of HCA device by providing the HCA device info
5220Sstevel@tonic-gate  *  	structure and provides an opaque HCA handler for future calls to this
5230Sstevel@tonic-gate  *  	HCA device.
5240Sstevel@tonic-gate  */
5250Sstevel@tonic-gate ibc_status_t
ibc_attach(ibc_clnt_hdl_t * ibc_hdl_p,ibc_hca_info_t * info_p)5260Sstevel@tonic-gate ibc_attach(ibc_clnt_hdl_t *ibc_hdl_p, ibc_hca_info_t *info_p)
5270Sstevel@tonic-gate {
5280Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;
5290Sstevel@tonic-gate 	uint_t			nports;
5300Sstevel@tonic-gate 	ibt_status_t		status;
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate 	IBTF_DPRINTF_L2(ibtf, "ibc_attach(%p, %p)", ibc_hdl_p, info_p);
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 	/* Validate the Transport API version */
535*12965SWilliam.Taylor@Oracle.COM 	if (info_p->hca_ci_vers != IBCI_V4) {
536929Ssrust 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: Invalid IB CI Version '%d'",
537929Ssrust 		    info_p->hca_ci_vers);
5380Sstevel@tonic-gate 		return (IBC_FAILURE);
5390Sstevel@tonic-gate 	}
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 	if (info_p->hca_attr == NULL) {
5420Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
5430Sstevel@tonic-gate 		    "HCA Attributes must be specified.");
5440Sstevel@tonic-gate 		return (IBC_FAILURE);
5450Sstevel@tonic-gate 	}
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 	nports = info_p->hca_attr->hca_nports;
5480Sstevel@tonic-gate 	if (nports == 0) {
5490Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
5500Sstevel@tonic-gate 		    "Number of ports must be valid");
5510Sstevel@tonic-gate 		return (IBC_FAILURE);
5520Sstevel@tonic-gate 	}
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 	if (info_p->hca_attr->hca_max_port_pkey_tbl_sz == 0) {
5550Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
5560Sstevel@tonic-gate 		    "Number of Partitions must be at least 1");
5570Sstevel@tonic-gate 		return (IBC_FAILURE);
5580Sstevel@tonic-gate 	}
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate 	if ((info_p->hca_attr->hca_flags & IBT_HCA_CURRENT_QP_STATE) == 0) {
5610Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
5620Sstevel@tonic-gate 		    "HCA driver must support QP current state checking");
5630Sstevel@tonic-gate 		return (IBC_FAILURE);
5640Sstevel@tonic-gate 	}
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate 	if ((info_p->hca_attr->hca_flags & IBT_HCA_PORT_UP) == 0) {
5670Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
5680Sstevel@tonic-gate 		    "HCA driver must support PORT_UP async events");
5690Sstevel@tonic-gate 		return (IBC_FAILURE);
5700Sstevel@tonic-gate 	}
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 	/*
5730Sstevel@tonic-gate 	 * Install IB nexus driver (if not installed already)
5740Sstevel@tonic-gate 	 */
5751093Shiremath 	ibtl_set_ibhw_status();
5760Sstevel@tonic-gate 	if (ndi_devi_config_vhci("ib", 0) == NULL) {
5770Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf, "ibc_attach: IB nexus attach failed");
5781093Shiremath 		ibtl_clear_ibhw_status();
5790Sstevel@tonic-gate 		return (IBC_FAILURE);
5800Sstevel@tonic-gate 	}
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate 	ibtl_thread_init2();
5830Sstevel@tonic-gate 
5840Sstevel@tonic-gate 	/* Allocate the memory for per-client info structure */
5850Sstevel@tonic-gate 	hca_devp = kmem_zalloc(sizeof (ibtl_hca_devinfo_t) +
5869891SRajkumar.Sivaprakasam@Sun.COM 	    (nports - 1) * sizeof (ibtl_async_port_event_t), KM_SLEEP);
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
5890Sstevel@tonic-gate 
5900Sstevel@tonic-gate 	/* Update HCA dev info structure */
5910Sstevel@tonic-gate 	hca_devp->hd_ibc_hca_hdl = info_p->hca_handle;
5920Sstevel@tonic-gate 	hca_devp->hd_ibc_ops	= info_p->hca_ops;
5930Sstevel@tonic-gate 	hca_devp->hd_hca_attr	= info_p->hca_attr;
594*12965SWilliam.Taylor@Oracle.COM 	hca_devp->hd_hca_dip	= info_p->hca_attr->hca_dip;
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate 	status = ibtl_init_hca_portinfo(hca_devp);
5970Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
5980Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
5990Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: call to ibc_query_hca_ports "
6000Sstevel@tonic-gate 		    "failed: status = %d", status);
6010Sstevel@tonic-gate 		kmem_free(hca_devp, sizeof (ibtl_hca_devinfo_t) +
6029891SRajkumar.Sivaprakasam@Sun.COM 		    (nports - 1) * sizeof (ibtl_async_port_event_t));
6030Sstevel@tonic-gate 		return (IBC_FAILURE);
6040Sstevel@tonic-gate 	}
6050Sstevel@tonic-gate 
6060Sstevel@tonic-gate 	/* Register the with MPxIO as PHCI */
607*12965SWilliam.Taylor@Oracle.COM 	if (ibtl_ibnex_phci_register(hca_devp->hd_hca_dip) != IBT_SUCCESS) {
6080Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
6090Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: MPxIO register failed");
6100Sstevel@tonic-gate 		kmem_free(hca_devp, sizeof (ibtl_hca_devinfo_t) +
6119891SRajkumar.Sivaprakasam@Sun.COM 		    (nports - 1) * sizeof (ibtl_async_port_event_t));
6120Sstevel@tonic-gate 		return (IBC_FAILURE);
6130Sstevel@tonic-gate 	}
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate 	/* Initialize the Client List for this HCA. */
6160Sstevel@tonic-gate 	hca_devp->hd_state	= IBTL_HCA_DEV_ATTACHED;
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate 	/* lock out asyncs until after we announce the new HCA */
6190Sstevel@tonic-gate 	hca_devp->hd_async_busy = 1;
6200Sstevel@tonic-gate 
6210Sstevel@tonic-gate 	cv_init(&hca_devp->hd_async_task_cv, NULL, CV_DEFAULT, NULL);
6220Sstevel@tonic-gate 	cv_init(&hca_devp->hd_async_busy_cv, NULL, CV_DEFAULT, NULL);
6230Sstevel@tonic-gate 
6240Sstevel@tonic-gate 	/* init portinfo locking variables */
6250Sstevel@tonic-gate 	hca_devp->hd_portinfo_locked_port = 0;
6260Sstevel@tonic-gate 	cv_init(&hca_devp->hd_portinfo_cv, NULL, CV_DEFAULT, NULL);
6270Sstevel@tonic-gate 
6289879SRamaswamy.Tummala@Sun.COM 	ibtl_kstat_init(hca_devp);
6299879SRamaswamy.Tummala@Sun.COM 
6300Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
6310Sstevel@tonic-gate 
6320Sstevel@tonic-gate 	/*
6330Sstevel@tonic-gate 	 * The ibc_hdl_p points to an opaque handle which is the address
6340Sstevel@tonic-gate 	 * of ibt_hca_devinfo_t structure passed back to the CI.
6350Sstevel@tonic-gate 	 * The CI will pass on this handle in its future upcalls to IBTF.
6360Sstevel@tonic-gate 	 */
6370Sstevel@tonic-gate 	*ibc_hdl_p = hca_devp;
6380Sstevel@tonic-gate 
6390Sstevel@tonic-gate 	return (IBC_SUCCESS);
6400Sstevel@tonic-gate }
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate 
6430Sstevel@tonic-gate /*
6440Sstevel@tonic-gate  * Function:
6450Sstevel@tonic-gate  *	ibc_post_attach
6460Sstevel@tonic-gate  * Input:
6470Sstevel@tonic-gate  *	ibc_hdl		- IBC Client's HCA Handle.
6480Sstevel@tonic-gate  * Returns:
6490Sstevel@tonic-gate  *	none
6500Sstevel@tonic-gate  * Called by:
6510Sstevel@tonic-gate  *	CI calls IBTF during its attach() after a successful ibc_attach().
6520Sstevel@tonic-gate  * Description:
6530Sstevel@tonic-gate  *	Announces to all known clients the existence of this HCA (by GUID).
6540Sstevel@tonic-gate  */
6550Sstevel@tonic-gate void
ibc_post_attach(ibc_clnt_hdl_t ibc_hdl)6560Sstevel@tonic-gate ibc_post_attach(ibc_clnt_hdl_t ibc_hdl)
6570Sstevel@tonic-gate {
6580Sstevel@tonic-gate 	IBTF_DPRINTF_L2(ibtf, "ibc_post_attach(%p)", ibc_hdl);
6590Sstevel@tonic-gate 
6600Sstevel@tonic-gate 	/*
6610Sstevel@tonic-gate 	 * Update the HCA Device List.
6620Sstevel@tonic-gate 	 */
6630Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
6640Sstevel@tonic-gate 	ibc_hdl->hd_hca_dev_link = ibtl_hca_list;
6650Sstevel@tonic-gate 	ibtl_hca_list = ibc_hdl;
6660Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate 	/* notify all IBT Client Device Instances of the new HCA Device */
6690Sstevel@tonic-gate 	ibtl_announce_new_hca(ibc_hdl);
6700Sstevel@tonic-gate }
6710Sstevel@tonic-gate 
6720Sstevel@tonic-gate 
6730Sstevel@tonic-gate /*
6740Sstevel@tonic-gate  * Function:
6750Sstevel@tonic-gate  *	ibc_pre_detach
6760Sstevel@tonic-gate  * Input:
6770Sstevel@tonic-gate  *	ibc_clnt_hdl	- IBC HCA Handle as returned during ibc_attach call.
6780Sstevel@tonic-gate  *  	cmd		- DDI_DETACH/DDI_SUSPEND command.
6790Sstevel@tonic-gate  * Output:
6800Sstevel@tonic-gate  *	none
6810Sstevel@tonic-gate  * Returns:
6820Sstevel@tonic-gate  *	IBC_SUCCESS
6830Sstevel@tonic-gate  *	IBC_FAILURE.
6840Sstevel@tonic-gate  * Called by:
6850Sstevel@tonic-gate  *	CI to try to get all IBTF clients to close the HCA device.
6860Sstevel@tonic-gate  * Description:
6870Sstevel@tonic-gate  *	Attempts to deregister the HCA device entry from the IBTF.
6880Sstevel@tonic-gate  *	If all resources are freed by the IBTF clients and this HCA
6890Sstevel@tonic-gate  *	is closed, then IBC_SUCCESS is returned.
6900Sstevel@tonic-gate  */
6910Sstevel@tonic-gate ibc_status_t
ibc_pre_detach(ibc_clnt_hdl_t hca_devp,ddi_detach_cmd_t cmd)6920Sstevel@tonic-gate ibc_pre_detach(ibc_clnt_hdl_t hca_devp, ddi_detach_cmd_t cmd)
6930Sstevel@tonic-gate {
6940Sstevel@tonic-gate 	ibtl_hca_devinfo_t **hcapp, *hcap;
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 	IBTF_DPRINTF_L2(ibtf, "ibc_pre_detach(%p, 0x%x)", hca_devp, cmd);
6970Sstevel@tonic-gate 
6980Sstevel@tonic-gate 	/*
6990Sstevel@tonic-gate 	 * Return failure, if command is not DDI_DETACH
7000Sstevel@tonic-gate 	 */
7010Sstevel@tonic-gate 	switch (cmd) {
7020Sstevel@tonic-gate 	case DDI_DETACH:
7030Sstevel@tonic-gate 		break;
7040Sstevel@tonic-gate 	default:
7050Sstevel@tonic-gate 		return (IBC_FAILURE); /* TBD: DDI_FAILURE */
7060Sstevel@tonic-gate 	}
7070Sstevel@tonic-gate 
7080Sstevel@tonic-gate 	/* Make sure this HCA is on the HCA Device List.  */
7090Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
7100Sstevel@tonic-gate 	hcap = ibtl_hca_list;
7110Sstevel@tonic-gate 	while (hcap != NULL) {
7120Sstevel@tonic-gate 		if (hcap == hca_devp)
7130Sstevel@tonic-gate 			break;
7140Sstevel@tonic-gate 		hcap = hcap->hd_hca_dev_link;
7150Sstevel@tonic-gate 	}
7160Sstevel@tonic-gate 	if (hcap == NULL) {
7170Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
7180Sstevel@tonic-gate 		return (IBC_FAILURE);
7190Sstevel@tonic-gate 	}
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 	/*
7220Sstevel@tonic-gate 	 * Initially set the state to "Detaching".
7230Sstevel@tonic-gate 	 */
7240Sstevel@tonic-gate 	hca_devp->hd_state = IBTL_HCA_DEV_DETACHING;
7250Sstevel@tonic-gate 
7260Sstevel@tonic-gate 	/*
7270Sstevel@tonic-gate 	 * Try to detach all IBTI clients, and continue only if all
7280Sstevel@tonic-gate 	 * of the detaches succeed.
7290Sstevel@tonic-gate 	 */
7300Sstevel@tonic-gate 	if (ibtl_detach_all_clients(hca_devp)) {
7310Sstevel@tonic-gate 		hca_devp->hd_state = IBTL_HCA_DEV_ATTACHED; /* fix hd_state */
7320Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 		return (IBC_FAILURE);
7350Sstevel@tonic-gate 	}
7360Sstevel@tonic-gate 
7370Sstevel@tonic-gate 	/*
7380Sstevel@tonic-gate 	 * Check to see if all clients closed this HCA, or not.
7390Sstevel@tonic-gate 	 * We only succeed if all clients cooperated.
7400Sstevel@tonic-gate 	 */
7410Sstevel@tonic-gate 	if (hca_devp->hd_clnt_list != NULL) {
7420Sstevel@tonic-gate 		hca_devp->hd_state = IBTL_HCA_DEV_ATTACHED;
7430Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
7440Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf, "ibc_pre_detach: HCA still has attached "
7450Sstevel@tonic-gate 		    "clients");
7460Sstevel@tonic-gate 		return (IBC_FAILURE);
7470Sstevel@tonic-gate 	}
7480Sstevel@tonic-gate 
7490Sstevel@tonic-gate 	/*
7500Sstevel@tonic-gate 	 * mark this device as detached
7510Sstevel@tonic-gate 	 */
7520Sstevel@tonic-gate 	hca_devp->hd_state = IBTL_HCA_DEV_DETACHED;
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate 	/* Delete the entry for this hca_devp from hca_head_list */
7550Sstevel@tonic-gate 	hcapp = &ibtl_hca_list;
7560Sstevel@tonic-gate 	while (*hcapp != NULL) {
7570Sstevel@tonic-gate 		if (*hcapp == hca_devp)
7580Sstevel@tonic-gate 			break;
7590Sstevel@tonic-gate 		hcapp = &(*hcapp)->hd_hca_dev_link;
7600Sstevel@tonic-gate 	}
7610Sstevel@tonic-gate 
7628082SRamaswamy.Tummala@Sun.COM 	if (ibtl_ibnex_phci_unregister(hca_devp->hd_hca_dip) != IBT_SUCCESS) {
7630Sstevel@tonic-gate 		hca_devp->hd_state = IBTL_HCA_DEV_ATTACHED; /* fix hd_state */
7640Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
7650Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibc_pre_detach: PHCI unregister failed");
7660Sstevel@tonic-gate 		return (IBC_FAILURE);
7670Sstevel@tonic-gate 	}
7680Sstevel@tonic-gate 
7690Sstevel@tonic-gate 	if (*hcapp == NULL) {
7700Sstevel@tonic-gate 		hca_devp->hd_state = IBTL_HCA_DEV_ATTACHED; /* fix hd_state */
7710Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
7720Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibc_pre_detach: HCA not attached");
7730Sstevel@tonic-gate 		return (IBC_FAILURE);
7740Sstevel@tonic-gate 	}
7750Sstevel@tonic-gate 	*hcapp = hca_devp->hd_hca_dev_link;
7760Sstevel@tonic-gate 	ibtl_fast_gid_cache_valid = B_FALSE;	/* invalidate fast_gid_cache */
7770Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
7780Sstevel@tonic-gate 
7790Sstevel@tonic-gate 	return (IBC_SUCCESS);
7800Sstevel@tonic-gate }
7810Sstevel@tonic-gate 
7820Sstevel@tonic-gate /*
7830Sstevel@tonic-gate  * Function:
7840Sstevel@tonic-gate  *	ibc_detach
7850Sstevel@tonic-gate  * Input:
7860Sstevel@tonic-gate  *	ibc_clnt_hdl	- IBC HCA Handle as returned during ibc_attach call.
7870Sstevel@tonic-gate  * Output:
7880Sstevel@tonic-gate  *	none
7890Sstevel@tonic-gate  * Returns:
7900Sstevel@tonic-gate  *	None
7910Sstevel@tonic-gate  * Called by:
7920Sstevel@tonic-gate  *	CI to detach the HCA device from IBTF.
7930Sstevel@tonic-gate  * Description:
7940Sstevel@tonic-gate  *	Do the second step of detaching the HCA, which is required
7950Sstevel@tonic-gate  *	after a successful ibc_pre_detach.
7960Sstevel@tonic-gate  */
7970Sstevel@tonic-gate void
ibc_detach(ibc_clnt_hdl_t hca_devp)7980Sstevel@tonic-gate ibc_detach(ibc_clnt_hdl_t hca_devp)
7990Sstevel@tonic-gate {
8000Sstevel@tonic-gate 	IBTF_DPRINTF_L2(ibtf, "ibc_detach(%p)", hca_devp);
8010Sstevel@tonic-gate 
8020Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
8030Sstevel@tonic-gate 	if (hca_devp->hd_state != IBTL_HCA_DEV_DETACHED) {
8040Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
8050Sstevel@tonic-gate 		IBTF_DPRINTF_L0(ibtf, "ibc_detach: HCA has not successfully "
8060Sstevel@tonic-gate 		    "pre-detached");
8070Sstevel@tonic-gate 		return;
8080Sstevel@tonic-gate 	}
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate 	cv_destroy(&hca_devp->hd_async_task_cv);
8110Sstevel@tonic-gate 	cv_destroy(&hca_devp->hd_async_busy_cv);
8120Sstevel@tonic-gate 	cv_destroy(&hca_devp->hd_portinfo_cv);
8130Sstevel@tonic-gate 
8140Sstevel@tonic-gate 	kmem_free(hca_devp->hd_portinfop, hca_devp->hd_portinfo_len);
8150Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
8160Sstevel@tonic-gate 
8179879SRamaswamy.Tummala@Sun.COM 	ibtl_kstat_fini(hca_devp);
8189879SRamaswamy.Tummala@Sun.COM 
8190Sstevel@tonic-gate 	/* Free up the memory of per-client info struct */
8200Sstevel@tonic-gate 	kmem_free(hca_devp, sizeof (ibtl_hca_devinfo_t) +
8210Sstevel@tonic-gate 	    (hca_devp->hd_hca_attr->hca_nports - 1) *
8229891SRajkumar.Sivaprakasam@Sun.COM 	    sizeof (ibtl_async_port_event_t));
8230Sstevel@tonic-gate 	ibtl_clear_ibhw_status();
8240Sstevel@tonic-gate }
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate /*
8270Sstevel@tonic-gate  * Function:
8280Sstevel@tonic-gate  *	ibt_ci_data_in()
8290Sstevel@tonic-gate  *
8300Sstevel@tonic-gate  * Input:
8310Sstevel@tonic-gate  *	hca_hdl			HCA Handle.
8320Sstevel@tonic-gate  *	flags			IBT_COMPLETE_ALLOC - Finish a deferred alloc.
8330Sstevel@tonic-gate  *      object                  Identifies the type object pointed to by
8340Sstevel@tonic-gate  *                              ibt_object_handle.
8350Sstevel@tonic-gate  *
8360Sstevel@tonic-gate  *      ibt_object_handle       The handle of the object to be associated with
8370Sstevel@tonic-gate  *				the data in/out
8380Sstevel@tonic-gate  *
8390Sstevel@tonic-gate  *	data_p			Pointer data passed in to the CI. The buffer
8400Sstevel@tonic-gate  *				should be allocated by the caller.
8410Sstevel@tonic-gate  *
8420Sstevel@tonic-gate  *	data_sz			The size of the buffer pointed to by
8430Sstevel@tonic-gate  *				data_p.
8440Sstevel@tonic-gate  * Output:
8450Sstevel@tonic-gate  *
8460Sstevel@tonic-gate  * Returns:
8470Sstevel@tonic-gate  *	IBT_SUCCESS
8480Sstevel@tonic-gate  *	IBT_NOT_SUPPORTED	Feature not supported.
8490Sstevel@tonic-gate  *	IBT_INVALID_PARAM	Invalid object type specified.
8500Sstevel@tonic-gate  *	IBT_HCA_HDL_INVALID
8510Sstevel@tonic-gate  *	IBT_AH_HDL_INVALID/IBT_UD_DEST_HDL_INVALID
8520Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID/IBT_QP_HDL_INVALID
8530Sstevel@tonic-gate  *	IBT_CQ_HDL_INVALID
8540Sstevel@tonic-gate  *	IBT_EEC_HDL_INVALID
8550Sstevel@tonic-gate  *	IBT_RDD_HDL_INVALID
8560Sstevel@tonic-gate  *	IBT_MW_HDL_INVALID
8570Sstevel@tonic-gate  *	IBT_PD_HDL_INVALID
8580Sstevel@tonic-gate  *	IBT_SRQ_HDL_INVALID
8590Sstevel@tonic-gate  *
8600Sstevel@tonic-gate  * Description:
8610Sstevel@tonic-gate  *	Exchange CI private data for the specified CI object.
8620Sstevel@tonic-gate  */
8630Sstevel@tonic-gate ibt_status_t
ibt_ci_data_in(ibt_hca_hdl_t hca,ibt_ci_data_flags_t flags,ibt_object_type_t object,void * ibt_object_handle,void * data_p,size_t data_sz)8640Sstevel@tonic-gate ibt_ci_data_in(ibt_hca_hdl_t hca, ibt_ci_data_flags_t flags,
8650Sstevel@tonic-gate     ibt_object_type_t object, void *ibt_object_handle, void *data_p,
8660Sstevel@tonic-gate     size_t data_sz)
8670Sstevel@tonic-gate {
8680Sstevel@tonic-gate 	ibt_status_t		retval;
8690Sstevel@tonic-gate 	void			*ci_obj_hdl;
8700Sstevel@tonic-gate 
8710Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf, "ibt_ci_data_in(%p, %x, %d, %p, %p, %d)",
8720Sstevel@tonic-gate 	    hca, flags, object, ibt_object_handle, data_p, data_sz);
8730Sstevel@tonic-gate 
8740Sstevel@tonic-gate 	switch (object) {
8750Sstevel@tonic-gate 	case IBT_HDL_HCA:
8760Sstevel@tonic-gate 		ci_obj_hdl = (void *)
8770Sstevel@tonic-gate 		    (IBTL_HCA2CIHCA(((ibt_hca_hdl_t)ibt_object_handle)));
8780Sstevel@tonic-gate 		break;
8790Sstevel@tonic-gate 
8800Sstevel@tonic-gate 	case IBT_HDL_CHANNEL:
8810Sstevel@tonic-gate 		ci_obj_hdl = (void *)
8820Sstevel@tonic-gate 		    (IBTL_CHAN2CIQP(((ibt_channel_hdl_t)ibt_object_handle)));
8830Sstevel@tonic-gate 		break;
8840Sstevel@tonic-gate 
8850Sstevel@tonic-gate 	case IBT_HDL_CQ:
8860Sstevel@tonic-gate 		ci_obj_hdl = (void *)
8870Sstevel@tonic-gate 		    (((ibt_cq_hdl_t)(ibt_object_handle))->cq_ibc_cq_hdl);
8880Sstevel@tonic-gate 		break;
8890Sstevel@tonic-gate 
8900Sstevel@tonic-gate 	case IBT_HDL_EEC:
8910Sstevel@tonic-gate 		ci_obj_hdl = (void *)
8920Sstevel@tonic-gate 		    (((ibt_eec_hdl_t)(ibt_object_handle))->eec_ibc_eec_hdl);
8930Sstevel@tonic-gate 		break;
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate 	case IBT_HDL_UD_DEST:
8960Sstevel@tonic-gate 		ci_obj_hdl = (void *)
8970Sstevel@tonic-gate 		    (((ibt_ud_dest_hdl_t)(ibt_object_handle))->ud_ah);
8980Sstevel@tonic-gate 		break;
8990Sstevel@tonic-gate 
9000Sstevel@tonic-gate 	case IBT_HDL_SRQ:
9010Sstevel@tonic-gate 		ci_obj_hdl = (void *)
9020Sstevel@tonic-gate 		    (((ibt_srq_hdl_t)(ibt_object_handle))->srq_ibc_srq_hdl);
9030Sstevel@tonic-gate 		break;
9040Sstevel@tonic-gate 
9050Sstevel@tonic-gate 	default:
9060Sstevel@tonic-gate 		ci_obj_hdl = ibt_object_handle;
9070Sstevel@tonic-gate 		break;
9080Sstevel@tonic-gate 	}
9090Sstevel@tonic-gate 
9100Sstevel@tonic-gate 	retval = (IBTL_HCA2CIHCAOPS_P(hca)->ibc_ci_data_in)(IBTL_HCA2CIHCA(hca),
9110Sstevel@tonic-gate 	    flags, object, ci_obj_hdl, data_p, data_sz);
9120Sstevel@tonic-gate 
9130Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
9140Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf, "ibt_ci_data_in: Failed : %d", retval);
9150Sstevel@tonic-gate 	}
9160Sstevel@tonic-gate 	return (retval);
9170Sstevel@tonic-gate }
9180Sstevel@tonic-gate 
9190Sstevel@tonic-gate /*
9200Sstevel@tonic-gate  * Function:
9210Sstevel@tonic-gate  *	ibt_ci_data_out()
9220Sstevel@tonic-gate  *
9230Sstevel@tonic-gate  * Input:
9240Sstevel@tonic-gate  *	hca_hdl			HCA Handle.
9250Sstevel@tonic-gate  *	flags			IBT_COMPLETE_ALLOC - Finish a deferred alloc.
9260Sstevel@tonic-gate  *      object                  Identifies the type object pointed to by
9270Sstevel@tonic-gate  *                              ibt_object_handle.
9280Sstevel@tonic-gate  *
9290Sstevel@tonic-gate  *      ibt_object_handle       The handle of the object to be associated with
9300Sstevel@tonic-gate  *				the data in/out
9310Sstevel@tonic-gate  *
9320Sstevel@tonic-gate  *	data_p			Pointer to a buffer in which to return the CI
9330Sstevel@tonic-gate  *				private data. The buffer should be allocated
9340Sstevel@tonic-gate  *				by the caller.
9350Sstevel@tonic-gate  *
9360Sstevel@tonic-gate  *	data_sz			The size of the buffer pointed to by
9370Sstevel@tonic-gate  *				data_p.
9380Sstevel@tonic-gate  * Output:
9390Sstevel@tonic-gate  *
9400Sstevel@tonic-gate  * Returns:
9410Sstevel@tonic-gate  *	IBT_SUCCESS
9420Sstevel@tonic-gate  *	IBT_NOT_SUPPORTED	Feature not supported.
9430Sstevel@tonic-gate  *	IBT_INSUFF_RESOURCE	The buffer pointed to by data_p was too
9440Sstevel@tonic-gate  *				small to hold the data.
9450Sstevel@tonic-gate  *	IBT_INVALID_PARAM	Invalid object type specified.
9460Sstevel@tonic-gate  *	IBT_HCA_HDL_INVALID
9470Sstevel@tonic-gate  *	IBT_AH_HDL_INVALID/IBT_UD_DEST_HDL_INVALID
9480Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID/IBT_QP_HDL_INVALID
9490Sstevel@tonic-gate  *	IBT_CQ_HDL_INVALID
9500Sstevel@tonic-gate  *	IBT_EEC_HDL_INVALID
9510Sstevel@tonic-gate  *	IBT_RDD_HDL_INVALID
9520Sstevel@tonic-gate  *	IBT_MW_HDL_INVALID
9530Sstevel@tonic-gate  *	IBT_PD_HDL_INVALID
9540Sstevel@tonic-gate  *	IBT_SRQ_HDL_INVALID
9550Sstevel@tonic-gate  *
9560Sstevel@tonic-gate  * Description:
9570Sstevel@tonic-gate  *	Exchange CI private data for the specified CI object.
9580Sstevel@tonic-gate  */
9590Sstevel@tonic-gate ibt_status_t
ibt_ci_data_out(ibt_hca_hdl_t hca,ibt_ci_data_flags_t flags,ibt_object_type_t object,void * ibt_object_handle,void * data_p,size_t data_sz)9600Sstevel@tonic-gate ibt_ci_data_out(ibt_hca_hdl_t hca, ibt_ci_data_flags_t flags,
9610Sstevel@tonic-gate     ibt_object_type_t object, void *ibt_object_handle, void *data_p,
9620Sstevel@tonic-gate     size_t data_sz)
9630Sstevel@tonic-gate {
9640Sstevel@tonic-gate 	ibt_status_t		retval;
9650Sstevel@tonic-gate 	void			*ci_obj_hdl;
9660Sstevel@tonic-gate 
9670Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf, "ibt_ci_data_out(%p, %x, %d, %p, %p, %d)",
9680Sstevel@tonic-gate 	    hca, flags, object, ibt_object_handle, data_p, data_sz);
9690Sstevel@tonic-gate 
9700Sstevel@tonic-gate 	switch (object) {
9710Sstevel@tonic-gate 	case  IBT_HDL_HCA:
9720Sstevel@tonic-gate 		ci_obj_hdl = (void *)
9730Sstevel@tonic-gate 		    (IBTL_HCA2CIHCA(((ibt_hca_hdl_t)ibt_object_handle)));
9740Sstevel@tonic-gate 		break;
9750Sstevel@tonic-gate 
9760Sstevel@tonic-gate 	case IBT_HDL_CHANNEL:
9770Sstevel@tonic-gate 		ci_obj_hdl = (void *)
9780Sstevel@tonic-gate 		    (IBTL_CHAN2CIQP(((ibt_channel_hdl_t)ibt_object_handle)));
9790Sstevel@tonic-gate 		break;
9800Sstevel@tonic-gate 
9810Sstevel@tonic-gate 	case IBT_HDL_CQ:
9820Sstevel@tonic-gate 		ci_obj_hdl = (void *)
9830Sstevel@tonic-gate 		    (((ibt_cq_hdl_t)(ibt_object_handle))->cq_ibc_cq_hdl);
9840Sstevel@tonic-gate 		break;
9850Sstevel@tonic-gate 
9860Sstevel@tonic-gate 	case IBT_HDL_EEC:
9870Sstevel@tonic-gate 		ci_obj_hdl = (void *)
9880Sstevel@tonic-gate 		    (((ibt_eec_hdl_t)(ibt_object_handle))->eec_ibc_eec_hdl);
9890Sstevel@tonic-gate 		break;
9900Sstevel@tonic-gate 
9910Sstevel@tonic-gate 	case IBT_HDL_UD_DEST:
9920Sstevel@tonic-gate 		ci_obj_hdl = (void *)
9930Sstevel@tonic-gate 		    (((ibt_ud_dest_hdl_t)(ibt_object_handle))->ud_ah);
9940Sstevel@tonic-gate 		break;
9950Sstevel@tonic-gate 
9960Sstevel@tonic-gate 	case IBT_HDL_SRQ:
9970Sstevel@tonic-gate 		ci_obj_hdl = (void *)
9980Sstevel@tonic-gate 		    (((ibt_srq_hdl_t)(ibt_object_handle))->srq_ibc_srq_hdl);
9990Sstevel@tonic-gate 		break;
10000Sstevel@tonic-gate 
10010Sstevel@tonic-gate 	default:
10020Sstevel@tonic-gate 		ci_obj_hdl = ibt_object_handle;
10030Sstevel@tonic-gate 		break;
10040Sstevel@tonic-gate 	}
10050Sstevel@tonic-gate 
10060Sstevel@tonic-gate 	retval = (IBTL_HCA2CIHCAOPS_P(hca)->ibc_ci_data_out)
10070Sstevel@tonic-gate 	    (IBTL_HCA2CIHCA(hca), flags, object, ci_obj_hdl, data_p, data_sz);
10080Sstevel@tonic-gate 
10090Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
10100Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf, "ibt_ci_data_out: Failed : %d", retval);
10110Sstevel@tonic-gate 	}
10120Sstevel@tonic-gate 	return (retval);
10130Sstevel@tonic-gate }
10140Sstevel@tonic-gate 
10150Sstevel@tonic-gate 
10160Sstevel@tonic-gate /*
10170Sstevel@tonic-gate  * FMA Support functions.
10180Sstevel@tonic-gate  */
10190Sstevel@tonic-gate 
10200Sstevel@tonic-gate #define	IBTL_ENA_MASK		0xC0000000
10210Sstevel@tonic-gate #define	IBTL_ENA_POSSIBLE	0x80000000
10220Sstevel@tonic-gate #define	IBTL_TYPE_SHIFT		27
10230Sstevel@tonic-gate 
10240Sstevel@tonic-gate /*
10250Sstevel@tonic-gate  * Function:
10260Sstevel@tonic-gate  *	ibt_get_module_failure()
10270Sstevel@tonic-gate  *
10280Sstevel@tonic-gate  * Input:
10290Sstevel@tonic-gate  *	type			Identifies the failing IB module.
10300Sstevel@tonic-gate  *	ena			'0' or the data for Fault Management
10310Sstevel@tonic-gate  *				Architecture (ENA).
10320Sstevel@tonic-gate  *
10330Sstevel@tonic-gate  * Returns:
10340Sstevel@tonic-gate  *	status			Special IB failure status.
10350Sstevel@tonic-gate  *
10360Sstevel@tonic-gate  * Description:
10370Sstevel@tonic-gate  *	XXX Just stubbed out to return failures with no data for Fault
10380Sstevel@tonic-gate  *	Management Architecture (ENAs) at the moment XXX
10390Sstevel@tonic-gate  */
10400Sstevel@tonic-gate ibt_status_t
ibt_get_module_failure(ibt_failure_type_t type,uint64_t ena)10410Sstevel@tonic-gate ibt_get_module_failure(ibt_failure_type_t type, uint64_t ena)
10420Sstevel@tonic-gate {
10430Sstevel@tonic-gate 	ibt_status_t	ret;
10440Sstevel@tonic-gate 
10450Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf, "ibt_get_module_failure(%d, 0x%llX)", type, ena);
10460Sstevel@tonic-gate 
10470Sstevel@tonic-gate 	switch (type) {
10480Sstevel@tonic-gate 	case IBT_FAILURE_CI:
10490Sstevel@tonic-gate 	case IBT_FAILURE_IBMF:
10500Sstevel@tonic-gate 	case IBT_FAILURE_IBCM:
10510Sstevel@tonic-gate 	case IBT_FAILURE_IBDM:
10520Sstevel@tonic-gate 	case IBT_FAILURE_IBTL:
1053929Ssrust 	case IBT_FAILURE_IBSM:
10540Sstevel@tonic-gate 		ret = IBTL_ENA_POSSIBLE | (type << IBTL_TYPE_SHIFT);
10550Sstevel@tonic-gate 		break;
10560Sstevel@tonic-gate 	default:
10570Sstevel@tonic-gate 		ret = IBT_FAILURE;
10580Sstevel@tonic-gate 	}
10590Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf, "ibt_get_module_failure: ret = 0x%lX", ret);
10600Sstevel@tonic-gate 	return (ret);
10610Sstevel@tonic-gate }
10620Sstevel@tonic-gate 
10630Sstevel@tonic-gate 
10640Sstevel@tonic-gate /*
10650Sstevel@tonic-gate  * Function:
10660Sstevel@tonic-gate  *	ibc_get_ci_failure()
10670Sstevel@tonic-gate  *
10680Sstevel@tonic-gate  * Input:
10690Sstevel@tonic-gate  *	ena			'0' or the data for Fault Management
10700Sstevel@tonic-gate  *				Architecture (ENA).
10710Sstevel@tonic-gate  *
10720Sstevel@tonic-gate  * Returns:
10730Sstevel@tonic-gate  *	status			Special CI failure status.
10740Sstevel@tonic-gate  *
10750Sstevel@tonic-gate  * Description:
10760Sstevel@tonic-gate  *	Just use the function above to do the job.
10770Sstevel@tonic-gate  */
10780Sstevel@tonic-gate ibt_status_t
ibc_get_ci_failure(uint64_t ena)10790Sstevel@tonic-gate ibc_get_ci_failure(uint64_t ena)
10800Sstevel@tonic-gate {
10810Sstevel@tonic-gate 	return (ibt_get_module_failure(IBT_FAILURE_CI, ena));
10820Sstevel@tonic-gate }
10830Sstevel@tonic-gate 
10840Sstevel@tonic-gate 
10850Sstevel@tonic-gate /*
10860Sstevel@tonic-gate  * ibt_check_failure()
10870Sstevel@tonic-gate  *	Function to test for special case failures.
10880Sstevel@tonic-gate  *
10890Sstevel@tonic-gate  *	status		An ibt_status_t returned from an IBTF function call.
10900Sstevel@tonic-gate  *
10910Sstevel@tonic-gate  *	reserved_p	NULL, or a pointer to where we store the data for
10920Sstevel@tonic-gate  *			Fault Management Architecture (ENA).
10930Sstevel@tonic-gate  *
10940Sstevel@tonic-gate  * Description:
10950Sstevel@tonic-gate  *	XXX Still need to determine the data for Fault Management Architecture
10960Sstevel@tonic-gate  *	(ENA), using 0 for now XXX
10970Sstevel@tonic-gate  */
10980Sstevel@tonic-gate ibt_failure_type_t
ibt_check_failure(ibt_status_t status,uint64_t * reserved_p)10990Sstevel@tonic-gate ibt_check_failure(ibt_status_t status, uint64_t *reserved_p)
11000Sstevel@tonic-gate {
11010Sstevel@tonic-gate 	ibt_failure_type_t type;
11020Sstevel@tonic-gate 
11030Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf, "ibt_check_failure(%X)", status);
11040Sstevel@tonic-gate 
11050Sstevel@tonic-gate 	if ((status & IBTL_ENA_MASK) == IBTL_ENA_POSSIBLE) {
11060Sstevel@tonic-gate 		type = status & ~IBTL_ENA_POSSIBLE >> IBTL_TYPE_SHIFT;
11070Sstevel@tonic-gate 
11080Sstevel@tonic-gate 		/* XXX Need more work here... */
11090Sstevel@tonic-gate 		if (reserved_p != NULL)
11100Sstevel@tonic-gate 			*reserved_p = 0;
11110Sstevel@tonic-gate 	} else {
11120Sstevel@tonic-gate 		type = IBT_FAILURE_STANDARD;
11130Sstevel@tonic-gate 		if (reserved_p != NULL)
11140Sstevel@tonic-gate 			*reserved_p = 0;	/* No FMA Data Available. */
11150Sstevel@tonic-gate 	}
11160Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf, "ibt_check_failure: type = 0x%X", type);
11170Sstevel@tonic-gate 	return (type);
11180Sstevel@tonic-gate }
11199879SRamaswamy.Tummala@Sun.COM 
11209879SRamaswamy.Tummala@Sun.COM /*
11219879SRamaswamy.Tummala@Sun.COM  * Initialize and create kstats.
11229879SRamaswamy.Tummala@Sun.COM  *
11239879SRamaswamy.Tummala@Sun.COM  * We create the following kstats on all ports of the HCA:
11249879SRamaswamy.Tummala@Sun.COM  *	<hca_driver_name><instance_number>/port<port_num>/stats
11259879SRamaswamy.Tummala@Sun.COM  *	<hca_driver_name><instance_number>/port<port_num>/pkeys
11269879SRamaswamy.Tummala@Sun.COM  */
11279879SRamaswamy.Tummala@Sun.COM static void
ibtl_kstat_init(ibtl_hca_devinfo_t * hca_devp)11289879SRamaswamy.Tummala@Sun.COM ibtl_kstat_init(ibtl_hca_devinfo_t *hca_devp)
11299879SRamaswamy.Tummala@Sun.COM {
11309879SRamaswamy.Tummala@Sun.COM 	uint_t			nports = hca_devp->hd_hca_attr->hca_nports;
11319879SRamaswamy.Tummala@Sun.COM 	ibtl_hca_port_kstat_t	*pks;
11329879SRamaswamy.Tummala@Sun.COM 	int			i;
11339879SRamaswamy.Tummala@Sun.COM 
11349879SRamaswamy.Tummala@Sun.COM 	IBTF_DPRINTF_L3(ibtf, "ibtl_kstat_init(hca_devp = 0x%p)", hca_devp);
11359879SRamaswamy.Tummala@Sun.COM 
11369879SRamaswamy.Tummala@Sun.COM 	hca_devp->hd_hca_port_ks_info_len =
11379879SRamaswamy.Tummala@Sun.COM 	    sizeof (ibtl_hca_port_kstat_t) * nports;
11389879SRamaswamy.Tummala@Sun.COM 	pks = kmem_zalloc(hca_devp->hd_hca_port_ks_info_len, KM_SLEEP);
11399879SRamaswamy.Tummala@Sun.COM 	hca_devp->hd_hca_port_ks_info = pks;
11409879SRamaswamy.Tummala@Sun.COM 
11419879SRamaswamy.Tummala@Sun.COM 	for (i = 0; i < nports; i++, pks++) {
11429879SRamaswamy.Tummala@Sun.COM 		pks->pks_hca_devp = hca_devp;
11439879SRamaswamy.Tummala@Sun.COM 		pks->pks_port_num = i + 1;
11449879SRamaswamy.Tummala@Sun.COM 		ibtl_kstat_stats_create(hca_devp, i + 1);
11459879SRamaswamy.Tummala@Sun.COM 		ibtl_kstat_pkeys_create(hca_devp, i + 1);
11469879SRamaswamy.Tummala@Sun.COM 	}
11479879SRamaswamy.Tummala@Sun.COM }
11489879SRamaswamy.Tummala@Sun.COM 
11499879SRamaswamy.Tummala@Sun.COM /*
11509879SRamaswamy.Tummala@Sun.COM  * Delete kstats on all ports of the HCA.
11519879SRamaswamy.Tummala@Sun.COM  */
11529879SRamaswamy.Tummala@Sun.COM static void
ibtl_kstat_fini(ibtl_hca_devinfo_t * hca_devp)11539879SRamaswamy.Tummala@Sun.COM ibtl_kstat_fini(ibtl_hca_devinfo_t *hca_devp)
11549879SRamaswamy.Tummala@Sun.COM {
11559879SRamaswamy.Tummala@Sun.COM 	ibtl_hca_port_kstat_t	*pks;
11569879SRamaswamy.Tummala@Sun.COM 	int			i;
11579879SRamaswamy.Tummala@Sun.COM 
11589879SRamaswamy.Tummala@Sun.COM 	IBTF_DPRINTF_L3(ibtf, "ibtl_kstat_fini(hca_devp = 0x%p)", hca_devp);
11599879SRamaswamy.Tummala@Sun.COM 
11609879SRamaswamy.Tummala@Sun.COM 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*hca_devp))
11619879SRamaswamy.Tummala@Sun.COM 
11629879SRamaswamy.Tummala@Sun.COM 	pks = hca_devp->hd_hca_port_ks_info;
11639879SRamaswamy.Tummala@Sun.COM 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*pks))
11649879SRamaswamy.Tummala@Sun.COM 
11659879SRamaswamy.Tummala@Sun.COM 	if (pks == NULL)
11669879SRamaswamy.Tummala@Sun.COM 		return;
11679879SRamaswamy.Tummala@Sun.COM 
11689879SRamaswamy.Tummala@Sun.COM 	for (i = 0; i < hca_devp->hd_hca_attr->hca_nports; i++, pks++) {
11699879SRamaswamy.Tummala@Sun.COM 		if (pks->pks_stats_ksp)
11709879SRamaswamy.Tummala@Sun.COM 			kstat_delete(pks->pks_stats_ksp);
11719879SRamaswamy.Tummala@Sun.COM 
11729879SRamaswamy.Tummala@Sun.COM 		if (pks->pks_pkeys_ksp) {
11739879SRamaswamy.Tummala@Sun.COM 			ASSERT(!MUTEX_HELD(&ibtl_clnt_list_mutex));
11749879SRamaswamy.Tummala@Sun.COM 			kstat_delete(pks->pks_pkeys_ksp);
11759879SRamaswamy.Tummala@Sun.COM 		}
11769879SRamaswamy.Tummala@Sun.COM 	}
11779879SRamaswamy.Tummala@Sun.COM 
11789879SRamaswamy.Tummala@Sun.COM 	kmem_free(hca_devp->hd_hca_port_ks_info,
11799879SRamaswamy.Tummala@Sun.COM 	    hca_devp->hd_hca_port_ks_info_len);
11809879SRamaswamy.Tummala@Sun.COM }
11819879SRamaswamy.Tummala@Sun.COM 
11829879SRamaswamy.Tummala@Sun.COM /*
11839879SRamaswamy.Tummala@Sun.COM  * Update "stats" kstat.
11849879SRamaswamy.Tummala@Sun.COM  * Called by kstat framework.
11859879SRamaswamy.Tummala@Sun.COM  */
11869879SRamaswamy.Tummala@Sun.COM static int
ibtl_kstat_stats_update(kstat_t * ksp,int rw)11879879SRamaswamy.Tummala@Sun.COM ibtl_kstat_stats_update(kstat_t *ksp, int rw)
11889879SRamaswamy.Tummala@Sun.COM {
11899879SRamaswamy.Tummala@Sun.COM 	ibtl_hca_port_kstat_t	*pks;
11909879SRamaswamy.Tummala@Sun.COM 	ibtl_hca_devinfo_t	*hca_devp;
11919879SRamaswamy.Tummala@Sun.COM 	ibt_hca_portinfo_t	*p;
11929879SRamaswamy.Tummala@Sun.COM 	struct kstat_named	*data;
11939879SRamaswamy.Tummala@Sun.COM 
11949879SRamaswamy.Tummala@Sun.COM 	IBTF_DPRINTF_L4(ibtf, "ibtl_kstat_stats_update(ksp = 0x%p, rw = %d)",
11959879SRamaswamy.Tummala@Sun.COM 	    ksp, rw);
11969879SRamaswamy.Tummala@Sun.COM 
11979879SRamaswamy.Tummala@Sun.COM 	if (rw == KSTAT_WRITE)
11989879SRamaswamy.Tummala@Sun.COM 		return (EACCES);
11999879SRamaswamy.Tummala@Sun.COM 
12009879SRamaswamy.Tummala@Sun.COM 	mutex_enter(&ibtl_clnt_list_mutex);
12019879SRamaswamy.Tummala@Sun.COM 
12029879SRamaswamy.Tummala@Sun.COM 	/*
12039879SRamaswamy.Tummala@Sun.COM 	 * Update the link_state kstat using the value from portinfo cache.
12049879SRamaswamy.Tummala@Sun.COM 	 */
12059879SRamaswamy.Tummala@Sun.COM 	pks = ksp->ks_private;
12069879SRamaswamy.Tummala@Sun.COM 	hca_devp = pks->pks_hca_devp;
12079879SRamaswamy.Tummala@Sun.COM 	data = (struct kstat_named *)(ksp->ks_data);
12089879SRamaswamy.Tummala@Sun.COM 	p = hca_devp->hd_portinfop + pks->pks_port_num - 1;
12099879SRamaswamy.Tummala@Sun.COM 	data[0].value.ui32 = (uint32_t)p->p_linkstate;
12109879SRamaswamy.Tummala@Sun.COM 
12119879SRamaswamy.Tummala@Sun.COM 	mutex_exit(&ibtl_clnt_list_mutex);
12129879SRamaswamy.Tummala@Sun.COM 
12139879SRamaswamy.Tummala@Sun.COM 	return (0);
12149879SRamaswamy.Tummala@Sun.COM }
12159879SRamaswamy.Tummala@Sun.COM 
12169879SRamaswamy.Tummala@Sun.COM /*
12179879SRamaswamy.Tummala@Sun.COM  * Create "stats" kstat for the specified HCA port in the form:
12189879SRamaswamy.Tummala@Sun.COM  *	<hca_driver_name><instance_number>/port<port_num>/stats
12199879SRamaswamy.Tummala@Sun.COM  *	At preset it contains only one named data of "link_state"
12209879SRamaswamy.Tummala@Sun.COM  */
12219879SRamaswamy.Tummala@Sun.COM static void
ibtl_kstat_stats_create(ibtl_hca_devinfo_t * hca_devp,uint_t port_num)12229879SRamaswamy.Tummala@Sun.COM ibtl_kstat_stats_create(ibtl_hca_devinfo_t *hca_devp, uint_t port_num)
12239879SRamaswamy.Tummala@Sun.COM {
12249879SRamaswamy.Tummala@Sun.COM 	struct kstat		*ksp;
12259879SRamaswamy.Tummala@Sun.COM 	struct kstat_named	*named_data;
12269879SRamaswamy.Tummala@Sun.COM 	char			*drv_name;
12279879SRamaswamy.Tummala@Sun.COM 	int			drv_instance;
12289879SRamaswamy.Tummala@Sun.COM 	ibtl_hca_port_kstat_t	*pks;
12299879SRamaswamy.Tummala@Sun.COM 	char			kname[40];
12309879SRamaswamy.Tummala@Sun.COM 
12319879SRamaswamy.Tummala@Sun.COM 	IBTF_DPRINTF_L3(ibtf, "ibtl_kstat_stats_create(hca_devp = 0x%p, "
12329879SRamaswamy.Tummala@Sun.COM 	    "port_num = 0x%u)", hca_devp, port_num);
12339879SRamaswamy.Tummala@Sun.COM 
12349879SRamaswamy.Tummala@Sun.COM 	drv_name = (char *)ddi_driver_name(hca_devp->hd_hca_dip);
12359879SRamaswamy.Tummala@Sun.COM 	drv_instance = ddi_get_instance(hca_devp->hd_hca_dip);
12369879SRamaswamy.Tummala@Sun.COM 	(void) snprintf(kname, sizeof (kname), "%s%d/port%d/stats",
12379879SRamaswamy.Tummala@Sun.COM 	    drv_name, drv_instance, port_num);
12389879SRamaswamy.Tummala@Sun.COM 
12399879SRamaswamy.Tummala@Sun.COM 	ksp = kstat_create("ibtf", 0, kname, "ib", KSTAT_TYPE_NAMED, 1, 0);
12409879SRamaswamy.Tummala@Sun.COM 	if (ksp == NULL) {
12419879SRamaswamy.Tummala@Sun.COM 		IBTF_DPRINTF_L2(ibtf,
12429879SRamaswamy.Tummala@Sun.COM 		    "ibtl_kstat_stats_create: kstat_create() failed");
12439879SRamaswamy.Tummala@Sun.COM 		return;
12449879SRamaswamy.Tummala@Sun.COM 	}
12459879SRamaswamy.Tummala@Sun.COM 
12469879SRamaswamy.Tummala@Sun.COM 	named_data = (struct kstat_named *)(ksp->ks_data);
12479879SRamaswamy.Tummala@Sun.COM 	kstat_named_init(&named_data[0], "link_state", KSTAT_DATA_UINT32);
12489879SRamaswamy.Tummala@Sun.COM 
12499879SRamaswamy.Tummala@Sun.COM 	pks = hca_devp->hd_hca_port_ks_info + port_num - 1;
12509879SRamaswamy.Tummala@Sun.COM 	pks->pks_stats_ksp = ksp;
12519879SRamaswamy.Tummala@Sun.COM 
12529879SRamaswamy.Tummala@Sun.COM 	ksp->ks_private = pks;
12539879SRamaswamy.Tummala@Sun.COM 	ksp->ks_update = ibtl_kstat_stats_update;
12549879SRamaswamy.Tummala@Sun.COM 
12559879SRamaswamy.Tummala@Sun.COM 	/* Install the kstat */
12569879SRamaswamy.Tummala@Sun.COM 	kstat_install(ksp);
12579879SRamaswamy.Tummala@Sun.COM }
12589879SRamaswamy.Tummala@Sun.COM 
12599879SRamaswamy.Tummala@Sun.COM /*
12609879SRamaswamy.Tummala@Sun.COM  * Update "pkeys" kstat.
12619879SRamaswamy.Tummala@Sun.COM  *
12629879SRamaswamy.Tummala@Sun.COM  * Called by kstat framework. Since ks_lock was set to ibtl_clnt_list_mutex
12639879SRamaswamy.Tummala@Sun.COM  * at the time of the kstat creation, kstat framework will hold this lock
12649879SRamaswamy.Tummala@Sun.COM  * while calling this function.
12659879SRamaswamy.Tummala@Sun.COM  */
12669879SRamaswamy.Tummala@Sun.COM static int
ibtl_kstat_pkeys_update(kstat_t * ksp,int rw)12679879SRamaswamy.Tummala@Sun.COM ibtl_kstat_pkeys_update(kstat_t *ksp, int rw)
12689879SRamaswamy.Tummala@Sun.COM {
12699879SRamaswamy.Tummala@Sun.COM 	ibtl_hca_port_kstat_t	*pks;
12709879SRamaswamy.Tummala@Sun.COM 	ibtl_hca_devinfo_t	*hca_devp;
12719879SRamaswamy.Tummala@Sun.COM 	ibt_hca_portinfo_t	*p;
12729879SRamaswamy.Tummala@Sun.COM 
12739879SRamaswamy.Tummala@Sun.COM 	IBTF_DPRINTF_L4(ibtf, "ibtl_kstat_pkeys_update(ksp = 0x%p, rw = %d)",
12749879SRamaswamy.Tummala@Sun.COM 	    ksp, rw);
12759879SRamaswamy.Tummala@Sun.COM 
12769879SRamaswamy.Tummala@Sun.COM #ifndef	__lock_lint
12779879SRamaswamy.Tummala@Sun.COM 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
12789879SRamaswamy.Tummala@Sun.COM #endif
12799879SRamaswamy.Tummala@Sun.COM 
12809879SRamaswamy.Tummala@Sun.COM 	if (rw == KSTAT_WRITE)
12819879SRamaswamy.Tummala@Sun.COM 		return (EACCES);
12829879SRamaswamy.Tummala@Sun.COM 
12839879SRamaswamy.Tummala@Sun.COM 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ksp))
12849879SRamaswamy.Tummala@Sun.COM 
12859879SRamaswamy.Tummala@Sun.COM 	pks = ksp->ks_private;
12869879SRamaswamy.Tummala@Sun.COM 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*pks))
12879879SRamaswamy.Tummala@Sun.COM 
12889879SRamaswamy.Tummala@Sun.COM 	hca_devp = pks->pks_hca_devp;
12899879SRamaswamy.Tummala@Sun.COM 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*hca_devp))
12909879SRamaswamy.Tummala@Sun.COM 
12919879SRamaswamy.Tummala@Sun.COM 	/*
12929879SRamaswamy.Tummala@Sun.COM 	 * Point kstat data to the pkey table in the portinfo cache.
12939879SRamaswamy.Tummala@Sun.COM 	 */
12949879SRamaswamy.Tummala@Sun.COM 
12959879SRamaswamy.Tummala@Sun.COM 	p = hca_devp->hd_portinfop + pks->pks_port_num - 1;
12969879SRamaswamy.Tummala@Sun.COM 
12979879SRamaswamy.Tummala@Sun.COM 	ksp->ks_data = p->p_pkey_tbl;
12989879SRamaswamy.Tummala@Sun.COM 	ksp->ks_ndata = p->p_pkey_tbl_sz;
12999879SRamaswamy.Tummala@Sun.COM 	ksp->ks_data_size = p->p_pkey_tbl_sz * sizeof (ib_pkey_t);
13009879SRamaswamy.Tummala@Sun.COM 
13019879SRamaswamy.Tummala@Sun.COM 	return (0);
13029879SRamaswamy.Tummala@Sun.COM }
13039879SRamaswamy.Tummala@Sun.COM 
13049879SRamaswamy.Tummala@Sun.COM /*
13059879SRamaswamy.Tummala@Sun.COM  * Create "pkeys" kstat for the specified HCA port in the form:
13069879SRamaswamy.Tummala@Sun.COM  *	<hca_driver_name><instance_number>/port<port_num>/pkeys
13079879SRamaswamy.Tummala@Sun.COM  *
13089879SRamaswamy.Tummala@Sun.COM  * Currently kstat framework allows only some fixed data types as named
13099879SRamaswamy.Tummala@Sun.COM  * data components under a named kstat. Due to this limitation it is not
13109879SRamaswamy.Tummala@Sun.COM  * possible to add "pkeys" as a named data under the "stats" kstat.
13119879SRamaswamy.Tummala@Sun.COM  */
13129879SRamaswamy.Tummala@Sun.COM static void
ibtl_kstat_pkeys_create(ibtl_hca_devinfo_t * hca_devp,uint_t port_num)13139879SRamaswamy.Tummala@Sun.COM ibtl_kstat_pkeys_create(ibtl_hca_devinfo_t *hca_devp, uint_t port_num)
13149879SRamaswamy.Tummala@Sun.COM {
13159879SRamaswamy.Tummala@Sun.COM 	struct kstat		*ksp;
13169879SRamaswamy.Tummala@Sun.COM 	char			*drv_name;
13179879SRamaswamy.Tummala@Sun.COM 	int			drv_instance;
13189879SRamaswamy.Tummala@Sun.COM 	char			kname[40];
13199879SRamaswamy.Tummala@Sun.COM 	ibtl_hca_port_kstat_t	*pks;
13209879SRamaswamy.Tummala@Sun.COM 
13219879SRamaswamy.Tummala@Sun.COM 	IBTF_DPRINTF_L3(ibtf, "ibtl_kstat_stats_create(hca_devp = 0x%p, "
13229879SRamaswamy.Tummala@Sun.COM 	    "port_num = 0x%u)", hca_devp, port_num);
13239879SRamaswamy.Tummala@Sun.COM 
13249879SRamaswamy.Tummala@Sun.COM 	drv_name = (char *)ddi_driver_name(hca_devp->hd_hca_dip);
13259879SRamaswamy.Tummala@Sun.COM 	drv_instance = ddi_get_instance(hca_devp->hd_hca_dip);
13269879SRamaswamy.Tummala@Sun.COM 	(void) snprintf(kname, sizeof (kname), "%s%d/port%d/pkeys",
13279879SRamaswamy.Tummala@Sun.COM 	    drv_name, drv_instance, port_num);
13289879SRamaswamy.Tummala@Sun.COM 
13299879SRamaswamy.Tummala@Sun.COM 	ksp = kstat_create("ibtf", 0, kname, "ib", KSTAT_TYPE_RAW, 0,
13309879SRamaswamy.Tummala@Sun.COM 	    KSTAT_FLAG_VAR_SIZE | KSTAT_FLAG_VIRTUAL);
13319879SRamaswamy.Tummala@Sun.COM 	if (ksp == NULL) {
13329879SRamaswamy.Tummala@Sun.COM 		IBTF_DPRINTF_L2(ibtf,
13339879SRamaswamy.Tummala@Sun.COM 		    "ibtl_kstat_pkeys_create: kstat_create() failed");
13349879SRamaswamy.Tummala@Sun.COM 		return;
13359879SRamaswamy.Tummala@Sun.COM 	}
13369879SRamaswamy.Tummala@Sun.COM 
13379879SRamaswamy.Tummala@Sun.COM 	pks = hca_devp->hd_hca_port_ks_info + port_num - 1;
13389879SRamaswamy.Tummala@Sun.COM 	pks->pks_pkeys_ksp = ksp;
13399879SRamaswamy.Tummala@Sun.COM 
13409879SRamaswamy.Tummala@Sun.COM 	ksp->ks_private = pks;
13419879SRamaswamy.Tummala@Sun.COM 	ksp->ks_update = ibtl_kstat_pkeys_update;
13429879SRamaswamy.Tummala@Sun.COM 	ksp->ks_lock = &ibtl_clnt_list_mutex;
13439879SRamaswamy.Tummala@Sun.COM 
13449879SRamaswamy.Tummala@Sun.COM 	/*
13459879SRamaswamy.Tummala@Sun.COM 	 * We just go with the default_kstat_snapshot().
13469879SRamaswamy.Tummala@Sun.COM 	 * So there is no need to set ks_snapshot field.
13479879SRamaswamy.Tummala@Sun.COM 	 */
13489879SRamaswamy.Tummala@Sun.COM 
13499879SRamaswamy.Tummala@Sun.COM 	/* Install the kstat */
13509879SRamaswamy.Tummala@Sun.COM 	kstat_install(ksp);
13519879SRamaswamy.Tummala@Sun.COM }
1352