17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
539b361b2SRichard Bean  * Common Development and Distribution License (the "License").
639b361b2SRichard Bean  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
221cfa752fSRamaswamy Tummala  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate /*
267c478bd9Sstevel@tonic-gate  * ibtl_impl.c
277c478bd9Sstevel@tonic-gate  *
287c478bd9Sstevel@tonic-gate  * This file contains the IBTF module's initialization and
297c478bd9Sstevel@tonic-gate  * IBTF Clients/Modules registration routines.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
337c478bd9Sstevel@tonic-gate #include <sys/sunndi.h>
347c478bd9Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl.h>
357c478bd9Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl_ibnex.h>
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /*
387c478bd9Sstevel@tonic-gate  * Globals.
397c478bd9Sstevel@tonic-gate  */
407c478bd9Sstevel@tonic-gate static char ibtf[] = "ibtl_impl";
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate extern ibtl_ibnex_callback_t	ibtl_ibnex_callback_routine;
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /*
457c478bd9Sstevel@tonic-gate  * ibtl_clnt_list:
467c478bd9Sstevel@tonic-gate  *
477c478bd9Sstevel@tonic-gate  *	Head of the list of IBT Client Instances. The IBT Client List
487c478bd9Sstevel@tonic-gate  *	is modified by IBTF on an IBT client's ibt_attach/ibt_detach call.
497c478bd9Sstevel@tonic-gate  *
507c478bd9Sstevel@tonic-gate  * ibtl_hca_list:
517c478bd9Sstevel@tonic-gate  *
527c478bd9Sstevel@tonic-gate  *	Head of the list of HCA devices. The HCA List is modified by IBTF on
537c478bd9Sstevel@tonic-gate  *	a CI's ibc_attach/ibc_detach call.
547c478bd9Sstevel@tonic-gate  *	The datap of the list elements points to an ibtl_hca_devinfo_s
557c478bd9Sstevel@tonic-gate  *	structure.
567c478bd9Sstevel@tonic-gate  *
577c478bd9Sstevel@tonic-gate  *				(ibc_attach)
587c478bd9Sstevel@tonic-gate  *  ibtl_hca_list	-> ibtl_hca_devinfo_t--> ...	-->ibtl_hca_devinfo_t
597c478bd9Sstevel@tonic-gate  *	[per-hca_dev]		|	^			{nth HCA Dev}
607c478bd9Sstevel@tonic-gate  *				|	|
617c478bd9Sstevel@tonic-gate  *				|  ibtl_hca_t (ibt_open_hca)
627c478bd9Sstevel@tonic-gate  *				|	^  |
637c478bd9Sstevel@tonic-gate  *				|	|  |
647c478bd9Sstevel@tonic-gate  *				v	|  V
657c478bd9Sstevel@tonic-gate  *  ibtl_clnt_list	->	ibtl_clnt_t--> ...--> {n'th Module}
667c478bd9Sstevel@tonic-gate  *	[per-client_instance]	(ibt_attach)
677c478bd9Sstevel@tonic-gate  *
687c478bd9Sstevel@tonic-gate  */
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate /* Global List of IBT Client Instances, and associated mutex. */
717c478bd9Sstevel@tonic-gate struct ibtl_clnt_s *ibtl_clnt_list = NULL;
727c478bd9Sstevel@tonic-gate kmutex_t ibtl_clnt_list_mutex;
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate /* Lock for the race between the client and CM to free QPs. */
757c478bd9Sstevel@tonic-gate kmutex_t ibtl_free_qp_mutex;
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate /* Lock for the race between the client closing the HCA and QPN being freed. */
787c478bd9Sstevel@tonic-gate kcondvar_t ibtl_close_hca_cv;
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate /* Global List of HCA Devices, and associated mutex. */
817c478bd9Sstevel@tonic-gate struct ibtl_hca_devinfo_s *ibtl_hca_list = NULL;
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate /* Well-known async handlers and associated client private. */
847c478bd9Sstevel@tonic-gate ibt_async_handler_t ibtl_cm_async_handler;
857c478bd9Sstevel@tonic-gate ibt_async_handler_t ibtl_dm_async_handler;
867c478bd9Sstevel@tonic-gate ibt_async_handler_t ibtl_ibma_async_handler;
877c478bd9Sstevel@tonic-gate void	*ibtl_cm_clnt_private;
887c478bd9Sstevel@tonic-gate void	*ibtl_dm_clnt_private;
897c478bd9Sstevel@tonic-gate void	*ibtl_ibma_clnt_private;
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate extern int ib_hw_status;
927c478bd9Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("Scheme protects data", ib_hw_status))
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate /*
957c478bd9Sstevel@tonic-gate  * Misc Module Declarations.
967c478bd9Sstevel@tonic-gate  */
977c478bd9Sstevel@tonic-gate extern struct mod_ops mod_miscops;
987c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = {
997c478bd9Sstevel@tonic-gate 	&mod_miscops,			/* Type of module - misc. */
10039b361b2SRichard Bean 	"IB Transport Layer"		/* Name of the Module. */
1017c478bd9Sstevel@tonic-gate };
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
1047c478bd9Sstevel@tonic-gate 	MODREV_1, (void *)&modlmisc, NULL
1057c478bd9Sstevel@tonic-gate };
1067c478bd9Sstevel@tonic-gate 
107d1a5c838SRamaswamy Tummala static void ibtl_kstat_init(ibtl_hca_devinfo_t *);
108d1a5c838SRamaswamy Tummala static void ibtl_kstat_fini(ibtl_hca_devinfo_t *);
109d1a5c838SRamaswamy Tummala static void ibtl_kstat_stats_create(ibtl_hca_devinfo_t *, uint_t);
110d1a5c838SRamaswamy Tummala static void ibtl_kstat_pkeys_create(ibtl_hca_devinfo_t *, uint_t);
1117c478bd9Sstevel@tonic-gate 
1121cfa752fSRamaswamy Tummala extern kmutex_t ibtl_part_attr_mutex;
1131cfa752fSRamaswamy Tummala 
1147c478bd9Sstevel@tonic-gate /*
1157c478bd9Sstevel@tonic-gate  * IBTF Loadable Module Routines.
1167c478bd9Sstevel@tonic-gate  */
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate int
_init(void)1197c478bd9Sstevel@tonic-gate _init(void)
1207c478bd9Sstevel@tonic-gate {
1217c478bd9Sstevel@tonic-gate 	int rval;
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	if ((rval = mod_install(&modlinkage)) != 0)
1247c478bd9Sstevel@tonic-gate 		return (rval);
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 	/*
1277c478bd9Sstevel@tonic-gate 	 * initialize IBTL ib2usec table
1287c478bd9Sstevel@tonic-gate 	 */
1297c478bd9Sstevel@tonic-gate 	ibtl_ib2usec_init();
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	/*
1327c478bd9Sstevel@tonic-gate 	 * Initialize Logging
1337c478bd9Sstevel@tonic-gate 	 */
1347c478bd9Sstevel@tonic-gate 	ibtl_logging_initialization();
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	/*
1377c478bd9Sstevel@tonic-gate 	 * Initialize the Alloc QP States.
1387c478bd9Sstevel@tonic-gate 	 */
1397c478bd9Sstevel@tonic-gate 	ibtl_init_cep_states();
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	/*
1427c478bd9Sstevel@tonic-gate 	 * Initialize all Global Link Lists.
1437c478bd9Sstevel@tonic-gate 	 */
1447c478bd9Sstevel@tonic-gate 	mutex_init(&ibtl_clnt_list_mutex, NULL, MUTEX_DEFAULT, NULL);
1457c478bd9Sstevel@tonic-gate 	mutex_init(&ibtl_free_qp_mutex, NULL, MUTEX_DEFAULT, NULL);
1467c478bd9Sstevel@tonic-gate 	cv_init(&ibtl_close_hca_cv, NULL, CV_DEFAULT, NULL);
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	mutex_init(&ibtl_qp_mutex, NULL, MUTEX_DEFAULT, NULL);
1497c478bd9Sstevel@tonic-gate 	cv_init(&ibtl_qp_cv, NULL, CV_DEFAULT, NULL);
1507c478bd9Sstevel@tonic-gate 
1511cfa752fSRamaswamy Tummala 	mutex_init(&ibtl_part_attr_mutex, NULL, MUTEX_DEFAULT, NULL);
1521cfa752fSRamaswamy Tummala 
1537c478bd9Sstevel@tonic-gate 	ibtl_thread_init();
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	return (rval);
1567c478bd9Sstevel@tonic-gate }
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate int
_fini(void)1607c478bd9Sstevel@tonic-gate _fini(void)
1617c478bd9Sstevel@tonic-gate {
1627c478bd9Sstevel@tonic-gate 	int rval;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	if ((rval = mod_remove(&modlinkage)) != 0) {
1657c478bd9Sstevel@tonic-gate 		return (rval);
1667c478bd9Sstevel@tonic-gate 	}
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	ibtl_thread_fini();
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	mutex_destroy(&ibtl_clnt_list_mutex);
1717c478bd9Sstevel@tonic-gate 	mutex_destroy(&ibtl_free_qp_mutex);
1727c478bd9Sstevel@tonic-gate 	cv_destroy(&ibtl_close_hca_cv);
1737c478bd9Sstevel@tonic-gate 	mutex_destroy(&ibtl_qp_mutex);
1747c478bd9Sstevel@tonic-gate 	cv_destroy(&ibtl_qp_cv);
1751cfa752fSRamaswamy Tummala 	mutex_destroy(&ibtl_part_attr_mutex);
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	/*
1787c478bd9Sstevel@tonic-gate 	 * Stop Logging
1797c478bd9Sstevel@tonic-gate 	 */
1807c478bd9Sstevel@tonic-gate 	ibtl_logging_destroy();
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 	return (rval);
1837c478bd9Sstevel@tonic-gate }
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)1877c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
1887c478bd9Sstevel@tonic-gate {
1897c478bd9Sstevel@tonic-gate 	/* Return the Module Information. */
1907c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
1917c478bd9Sstevel@tonic-gate }
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate /*
1957c478bd9Sstevel@tonic-gate  * IBTF Client Registration Routines.
1967c478bd9Sstevel@tonic-gate  */
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate /*
1997c478bd9Sstevel@tonic-gate  * Function:
2007c478bd9Sstevel@tonic-gate  *	ibt_attach
2017c478bd9Sstevel@tonic-gate  * Input:
2027c478bd9Sstevel@tonic-gate  *	modinfop	- Client Module info structure.
2037c478bd9Sstevel@tonic-gate  *	arg		- usually client's dip
2047c478bd9Sstevel@tonic-gate  *	clnt_private	- client's private data pointer.
2057c478bd9Sstevel@tonic-gate  * Output:
2067c478bd9Sstevel@tonic-gate  *	ibt_hdl_p	- pointer to client's specific IBT handle,
2077c478bd9Sstevel@tonic-gate  *			 which is opaque to clients.
2087c478bd9Sstevel@tonic-gate  * Returns:
2097c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
2107c478bd9Sstevel@tonic-gate  *	IBT_INVALID_PARAM
2117c478bd9Sstevel@tonic-gate  * Called by:
2127c478bd9Sstevel@tonic-gate  *	IBTF Client module during its attach() to register its instance
2137c478bd9Sstevel@tonic-gate  *	to IBTF.
2147c478bd9Sstevel@tonic-gate  * Description:
2157c478bd9Sstevel@tonic-gate  *	Registers the IBTF client module instance and returns an opaque
2167c478bd9Sstevel@tonic-gate  *	handler to the client to be used for future calls to IBTF.
2177c478bd9Sstevel@tonic-gate  *	Adds this client module instance to ibtl_clnt_list list.
2187c478bd9Sstevel@tonic-gate  *	Records well-known async handlers.
2197c478bd9Sstevel@tonic-gate  */
2207c478bd9Sstevel@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)2217c478bd9Sstevel@tonic-gate ibt_attach(ibt_clnt_modinfo_t *mod_infop, dev_info_t *arg, void *clnt_private,
2227c478bd9Sstevel@tonic-gate     ibt_clnt_hdl_t *ibt_hdl_p)
2237c478bd9Sstevel@tonic-gate {
2247c478bd9Sstevel@tonic-gate 	dev_info_t	*pdip;
2257c478bd9Sstevel@tonic-gate 	ibtl_clnt_t	*clntp;
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf, "ibt_attach(%p, %p, %p)",
2287c478bd9Sstevel@tonic-gate 	    mod_infop, arg, clnt_private);
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	if (mod_infop->mi_clnt_name == NULL) {
2317c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
2327c478bd9Sstevel@tonic-gate 		    "IB client needs to specify its name");
2337c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
2347c478bd9Sstevel@tonic-gate 	}
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	/*
2377c478bd9Sstevel@tonic-gate 	 * Validate the Transport API version.
2387c478bd9Sstevel@tonic-gate 	 */
23903494a98SBill Taylor 	if (mod_infop->mi_ibt_version != IBTI_V_CURR) {
2407c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibt_attach: IB client '%s' has an "
2417c478bd9Sstevel@tonic-gate 		    "invalid IB TI Version '%d'", mod_infop->mi_clnt_name,
2427c478bd9Sstevel@tonic-gate 		    mod_infop->mi_ibt_version);
24343ed929aSsrust 		return (IBT_NOT_SUPPORTED);
2447c478bd9Sstevel@tonic-gate 	}
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	if (mod_infop->mi_async_handler == NULL) {
2477c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf, "ibt_attach: Client '%s' has not\n"
2487c478bd9Sstevel@tonic-gate 		    "        provided an Asynchronous Event Handler.\n"
2497c478bd9Sstevel@tonic-gate 		    "        This will be required soon.",
2507c478bd9Sstevel@tonic-gate 		    mod_infop->mi_clnt_name);
2517c478bd9Sstevel@tonic-gate 	}
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 	/*
2547c478bd9Sstevel@tonic-gate 	 * Check out Client's Class information. If it is not of mgmt class,
2557c478bd9Sstevel@tonic-gate 	 * we expect 'arg' to be Not NULL and point to client driver's
2567c478bd9Sstevel@tonic-gate 	 * device info struct.
2577c478bd9Sstevel@tonic-gate 	 */
25867d84f12SRajkumar Sivaprakasam 	if ((!IBT_MISCMOD_CLIENTS(mod_infop->mi_clnt_class)) &&
2597c478bd9Sstevel@tonic-gate 	    (arg == NULL)) {
2607c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
2617c478bd9Sstevel@tonic-gate 		    "arg not set with driver's dip.");
2627c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
2637c478bd9Sstevel@tonic-gate 	}
2647c478bd9Sstevel@tonic-gate 
26567d84f12SRajkumar Sivaprakasam 	if (!IBT_MISCMOD_CLIENTS(mod_infop->mi_clnt_class)) {
2667c478bd9Sstevel@tonic-gate 		pdip = ddi_get_parent(arg);
2677c478bd9Sstevel@tonic-gate 		if (pdip == NULL ||
2687c478bd9Sstevel@tonic-gate 		    ibtl_ibnex_valid_hca_parent(pdip) != IBT_SUCCESS) {
2697c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtf, "ibt_attach: "
2707c478bd9Sstevel@tonic-gate 			    "client %s is not a child of IB nexus driver.",
2717c478bd9Sstevel@tonic-gate 			    ddi_driver_name(arg));
2727c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
2737c478bd9Sstevel@tonic-gate 		}
2747c478bd9Sstevel@tonic-gate 	}
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
2777c478bd9Sstevel@tonic-gate 	if (mod_infop->mi_clnt_class == IBT_CM) {
2787c478bd9Sstevel@tonic-gate 		if (ibtl_cm_async_handler != NULL) {
2797c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
2807c478bd9Sstevel@tonic-gate 			    "CM is already attached.");
2817c478bd9Sstevel@tonic-gate 			mutex_exit(&ibtl_clnt_list_mutex);
2827c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
2837c478bd9Sstevel@tonic-gate 		}
2847c478bd9Sstevel@tonic-gate 		ibtl_cm_async_handler = mod_infop->mi_async_handler;
2857c478bd9Sstevel@tonic-gate 		ibtl_cm_clnt_private = clnt_private;
2867c478bd9Sstevel@tonic-gate 	} else if (mod_infop->mi_clnt_class == IBT_DM) {
2877c478bd9Sstevel@tonic-gate 		if (ibtl_dm_async_handler != NULL) {
2887c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
2897c478bd9Sstevel@tonic-gate 			    "DM is already attached.");
2907c478bd9Sstevel@tonic-gate 			mutex_exit(&ibtl_clnt_list_mutex);
2917c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
2927c478bd9Sstevel@tonic-gate 		}
2937c478bd9Sstevel@tonic-gate 		ibtl_dm_async_handler = mod_infop->mi_async_handler;
2947c478bd9Sstevel@tonic-gate 		ibtl_dm_clnt_private = clnt_private;
2957c478bd9Sstevel@tonic-gate 	} else if (mod_infop->mi_clnt_class == IBT_IBMA) {
2967c478bd9Sstevel@tonic-gate 		if (ibtl_ibma_async_handler != NULL) {
2977c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
2987c478bd9Sstevel@tonic-gate 			    "IBMF is already attached.");
2997c478bd9Sstevel@tonic-gate 			mutex_exit(&ibtl_clnt_list_mutex);
3007c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
3017c478bd9Sstevel@tonic-gate 		}
3027c478bd9Sstevel@tonic-gate 		ibtl_ibma_async_handler = mod_infop->mi_async_handler;
3037c478bd9Sstevel@tonic-gate 		ibtl_ibma_clnt_private = clnt_private;
3047c478bd9Sstevel@tonic-gate 	}
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	/* Allocate the memory for per-client-device info structure */
3077c478bd9Sstevel@tonic-gate 	clntp = kmem_zalloc(sizeof (ibtl_clnt_t), KM_SLEEP);
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(clntp->clnt_modinfop,
3107c478bd9Sstevel@tonic-gate 	    clntp->clnt_dip, clntp->clnt_name, clntp->clnt_async_cnt,
3117c478bd9Sstevel@tonic-gate 	    clntp->clnt_private))
3127c478bd9Sstevel@tonic-gate 	/* Update the Client info structure */
3137c478bd9Sstevel@tonic-gate 	clntp->clnt_modinfop = mod_infop;	/* IBT Client's Mod Info */
3147c478bd9Sstevel@tonic-gate 	clntp->clnt_private = clnt_private;	/* IBT Client's private */
3157c478bd9Sstevel@tonic-gate 	clntp->clnt_dip = arg;			/* IBT Client's dip */
3167c478bd9Sstevel@tonic-gate 	clntp->clnt_async_cnt = 0;
3177c478bd9Sstevel@tonic-gate 	/* using a count of 7 below guarantees it is NULL terminated */
3187c478bd9Sstevel@tonic-gate 	(void) strncpy(clntp->clnt_name, mod_infop->mi_clnt_name, 7);
3197c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(clntp->clnt_modinfop,
3207c478bd9Sstevel@tonic-gate 	    clntp->clnt_dip, clntp->clnt_name, clntp->clnt_async_cnt,
3217c478bd9Sstevel@tonic-gate 	    clntp->clnt_private))
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 	/*
3247c478bd9Sstevel@tonic-gate 	 * Update Client Device Instance List.
3257c478bd9Sstevel@tonic-gate 	 */
3267c478bd9Sstevel@tonic-gate 	clntp->clnt_list_link = ibtl_clnt_list;
3277c478bd9Sstevel@tonic-gate 	ibtl_clnt_list = clntp;
3287c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	/*
3317c478bd9Sstevel@tonic-gate 	 * The ibt_hdl_p is a opaque handle which is the address of
3327c478bd9Sstevel@tonic-gate 	 * ibt_clnt_t structure passed back to the clients.
3337c478bd9Sstevel@tonic-gate 	 * The client will pass on this handle in its future calls to IBTF.
3347c478bd9Sstevel@tonic-gate 	 */
3357c478bd9Sstevel@tonic-gate 	*ibt_hdl_p = clntp;
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	return (IBT_SUCCESS);
3387c478bd9Sstevel@tonic-gate }
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate /*
3427c478bd9Sstevel@tonic-gate  * Function:
3437c478bd9Sstevel@tonic-gate  *	ibt_detach
3447c478bd9Sstevel@tonic-gate  * Input:
3457c478bd9Sstevel@tonic-gate  *	ibt_hdl - IBT Handle as returned during ibt_attach call.
3467c478bd9Sstevel@tonic-gate  * Output:
3477c478bd9Sstevel@tonic-gate  *	none
3487c478bd9Sstevel@tonic-gate  * Returns:
3497c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
3507c478bd9Sstevel@tonic-gate  *	IBT_INVALID_PARAM.
3517c478bd9Sstevel@tonic-gate  * Called by:
3527c478bd9Sstevel@tonic-gate  *	IBTF Client module during its detach() to de-register its instance
3537c478bd9Sstevel@tonic-gate  *	from IBTF.
3547c478bd9Sstevel@tonic-gate  * Description:
3557c478bd9Sstevel@tonic-gate  *	Deregisters the IBTF client module instance from the IBTF.
3567c478bd9Sstevel@tonic-gate  *	All resources and any reference to this ibt_hdl will be removed.
3577c478bd9Sstevel@tonic-gate  */
3587c478bd9Sstevel@tonic-gate ibt_status_t
ibt_detach(ibt_clnt_hdl_t ibt_hdl)3597c478bd9Sstevel@tonic-gate ibt_detach(ibt_clnt_hdl_t ibt_hdl)
3607c478bd9Sstevel@tonic-gate {
3617c478bd9Sstevel@tonic-gate 	ibtl_clnt_t **clntpp;
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf, "ibt_detach(%p)", ibt_hdl);
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
3667c478bd9Sstevel@tonic-gate 	clntpp = &ibtl_clnt_list;
3677c478bd9Sstevel@tonic-gate 	for (; *clntpp != NULL; clntpp = &(*clntpp)->clnt_list_link)
3687c478bd9Sstevel@tonic-gate 		if (*clntpp == ibt_hdl)
3697c478bd9Sstevel@tonic-gate 			break;
3707c478bd9Sstevel@tonic-gate 	if (*clntpp == NULL) {
3717c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibt_detach: Client @ %p Not Found",
3727c478bd9Sstevel@tonic-gate 		    ibt_hdl);
3737c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
3747c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
3757c478bd9Sstevel@tonic-gate 	}
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	/*
3787c478bd9Sstevel@tonic-gate 	 * Check out whether the client has freed all its resources.
3797c478bd9Sstevel@tonic-gate 	 * If not done, then fail the detach.
3807c478bd9Sstevel@tonic-gate 	 *
3817c478bd9Sstevel@tonic-gate 	 * viz. A client has to close all the HCA they have opened,
3827c478bd9Sstevel@tonic-gate 	 * i.e. the HCA List maintained for clients has to be empty.
3837c478bd9Sstevel@tonic-gate 	 * If this list is not empty, then the client has not performed
3847c478bd9Sstevel@tonic-gate 	 * complete clean-up, so fail the detach.
3857c478bd9Sstevel@tonic-gate 	 */
3867c478bd9Sstevel@tonic-gate 	if (ibt_hdl->clnt_hca_list != NULL) {
3877c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf, "ibt_detach: "
3907c478bd9Sstevel@tonic-gate 		    "ERROR: Client '%s' has not closed all of its HCAs",
3917c478bd9Sstevel@tonic-gate 		    ibt_hdl->clnt_modinfop->mi_clnt_name);
392f7327bbdSBill Taylor 		cmn_err(CE_CONT, "IBT DETACH failed: resources not yet "
393f7327bbdSBill Taylor 		    "freed by client '%s'\n",
394f7327bbdSBill Taylor 		    ibt_hdl->clnt_modinfop->mi_clnt_name);
3957c478bd9Sstevel@tonic-gate 		return (IBT_HCA_RESOURCES_NOT_FREED);
3967c478bd9Sstevel@tonic-gate 	}
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	if (ibt_hdl->clnt_srv_cnt != 0) {
3997c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
4007c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf, "ibt_detach: client '%s' still has "
4017c478bd9Sstevel@tonic-gate 		    "services or subnet_notices registered",
4027c478bd9Sstevel@tonic-gate 		    ibt_hdl->clnt_modinfop->mi_clnt_name);
403f7327bbdSBill Taylor 		cmn_err(CE_CONT, "IBT DETACH failed: resources not yet "
404f7327bbdSBill Taylor 		    "freed by client '%s'\n",
405f7327bbdSBill Taylor 		    ibt_hdl->clnt_modinfop->mi_clnt_name);
4067c478bd9Sstevel@tonic-gate 		return (IBT_HCA_RESOURCES_NOT_FREED);
4077c478bd9Sstevel@tonic-gate 	}
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	/*
4107c478bd9Sstevel@tonic-gate 	 * Delete the entry of this module from the ibtl_clnt_list List.
4117c478bd9Sstevel@tonic-gate 	 */
4127c478bd9Sstevel@tonic-gate 	*clntpp = ibt_hdl->clnt_list_link;	/* remove us */
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	/* make sure asyncs complete before freeing */
4157c478bd9Sstevel@tonic-gate 	ibtl_free_clnt_async_check(ibt_hdl);
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 	if (ibt_hdl->clnt_modinfop->mi_clnt_class == IBT_CM) {
4187c478bd9Sstevel@tonic-gate 		ibtl_cm_async_handler = NULL;
4197c478bd9Sstevel@tonic-gate 		ibtl_cm_clnt_private = NULL;
4207c478bd9Sstevel@tonic-gate 	} else if (ibt_hdl->clnt_modinfop->mi_clnt_class == IBT_DM) {
4217c478bd9Sstevel@tonic-gate 		ibtl_dm_async_handler = NULL;
4227c478bd9Sstevel@tonic-gate 		ibtl_dm_clnt_private = NULL;
4237c478bd9Sstevel@tonic-gate 	} else if (ibt_hdl->clnt_modinfop->mi_clnt_class == IBT_IBMA) {
4247c478bd9Sstevel@tonic-gate 		ibtl_ibma_async_handler = NULL;
4257c478bd9Sstevel@tonic-gate 		ibtl_ibma_clnt_private = NULL;
4267c478bd9Sstevel@tonic-gate 	}
4277c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate 	/* Free up the memory of per-client info struct. */
4307c478bd9Sstevel@tonic-gate 	kmem_free(ibt_hdl, sizeof (ibtl_clnt_t));
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	return (IBT_SUCCESS);
4337c478bd9Sstevel@tonic-gate }
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate static void
ibtl_set_ibhw_status()4367c478bd9Sstevel@tonic-gate ibtl_set_ibhw_status()
4377c478bd9Sstevel@tonic-gate {
4387c478bd9Sstevel@tonic-gate 	ib_hw_status++;
4397c478bd9Sstevel@tonic-gate }
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate static void
ibtl_clear_ibhw_status()4427c478bd9Sstevel@tonic-gate ibtl_clear_ibhw_status()
4437c478bd9Sstevel@tonic-gate {
4447c478bd9Sstevel@tonic-gate 	ib_hw_status--;
4457c478bd9Sstevel@tonic-gate }
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate /*
4487c478bd9Sstevel@tonic-gate  * Function:
4497c478bd9Sstevel@tonic-gate  *	ibc_init
4507c478bd9Sstevel@tonic-gate  * Input:
4517c478bd9Sstevel@tonic-gate  *	modlp		- Pointer to IBC client module linkage structure
4527c478bd9Sstevel@tonic-gate  * Output:
4537c478bd9Sstevel@tonic-gate  *	None
4547c478bd9Sstevel@tonic-gate  * Returns:
4557c478bd9Sstevel@tonic-gate  *	0 always for now
4567c478bd9Sstevel@tonic-gate  * Called by:
4577c478bd9Sstevel@tonic-gate  *	CI client calls IBTF during its _init() to register HCA with
4587c478bd9Sstevel@tonic-gate  *	Solaris I/O framework.
4597c478bd9Sstevel@tonic-gate  * Description:
4607c478bd9Sstevel@tonic-gate  *	Initializes the CI clients module linkage structure with
4617c478bd9Sstevel@tonic-gate  *	default bus_ops structure
4627c478bd9Sstevel@tonic-gate  */
4637c478bd9Sstevel@tonic-gate int
ibc_init(struct modlinkage * modlp)4647c478bd9Sstevel@tonic-gate ibc_init(struct modlinkage *modlp)
4657c478bd9Sstevel@tonic-gate {
4667c478bd9Sstevel@tonic-gate 	ibtl_ibnex_cb_args_t	cb_args;
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
4697c478bd9Sstevel@tonic-gate 	cb_args.cb_flag = IBTL_IBNEX_IBC_INIT;
4707c478bd9Sstevel@tonic-gate 	cb_args.cb_modlp = modlp;
4717c478bd9Sstevel@tonic-gate 	if (ibtl_ibnex_callback_routine) {
4727c478bd9Sstevel@tonic-gate 		(void) ((*ibtl_ibnex_callback_routine)(&cb_args));
4737c478bd9Sstevel@tonic-gate 	}
4747c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
4757c478bd9Sstevel@tonic-gate 	return (0);
4767c478bd9Sstevel@tonic-gate }
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate /*
4807c478bd9Sstevel@tonic-gate  * Function:
4817c478bd9Sstevel@tonic-gate  *	ibc_fini
4827c478bd9Sstevel@tonic-gate  * Input:
4837c478bd9Sstevel@tonic-gate  *	modlp		- Pointer to IBC client module linkage structure
4847c478bd9Sstevel@tonic-gate  * Output:
4857c478bd9Sstevel@tonic-gate  *	None
4867c478bd9Sstevel@tonic-gate  * Returns:
4877c478bd9Sstevel@tonic-gate  *	None
4887c478bd9Sstevel@tonic-gate  * Called by:
4897c478bd9Sstevel@tonic-gate  *	CI client calls IBTF during its _fini() to remove HCA with
4907c478bd9Sstevel@tonic-gate  *	Solaris I/O framework.
4917c478bd9Sstevel@tonic-gate  * Description:
4927c478bd9Sstevel@tonic-gate  *	Undo what is done during ibc_init
4937c478bd9Sstevel@tonic-gate  */
4947c478bd9Sstevel@tonic-gate void
ibc_fini(struct modlinkage * modlp)4957c478bd9Sstevel@tonic-gate ibc_fini(struct modlinkage *modlp)
4967c478bd9Sstevel@tonic-gate {
4977c478bd9Sstevel@tonic-gate 	ibtl_ibnex_cb_args_t	cb_args;
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
5007c478bd9Sstevel@tonic-gate 	cb_args.cb_flag = IBTL_IBNEX_IBC_FINI;
5017c478bd9Sstevel@tonic-gate 	cb_args.cb_modlp = modlp;
5027c478bd9Sstevel@tonic-gate 	if (ibtl_ibnex_callback_routine) {
5037c478bd9Sstevel@tonic-gate 		(void) ((*ibtl_ibnex_callback_routine)(&cb_args));
5047c478bd9Sstevel@tonic-gate 	}
5057c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
5067c478bd9Sstevel@tonic-gate }
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate /*
5097c478bd9Sstevel@tonic-gate  * Function:
5107c478bd9Sstevel@tonic-gate  *	ibc_attach
5117c478bd9Sstevel@tonic-gate  * Input:
5127c478bd9Sstevel@tonic-gate  *	info_p		- IBC HCA Info.
5137c478bd9Sstevel@tonic-gate  * Output:
5147c478bd9Sstevel@tonic-gate  *	ibc_hdl_p	- IBC Client's HCA Handle.
5157c478bd9Sstevel@tonic-gate  * Returns:
5167c478bd9Sstevel@tonic-gate  *	IBC_SUCCESS
5177c478bd9Sstevel@tonic-gate  *	IBC_FAILURE
5187c478bd9Sstevel@tonic-gate  * Called by:
5197c478bd9Sstevel@tonic-gate  *	CI calls IBTF during its attach() to register HCA Device with IBTF.
5207c478bd9Sstevel@tonic-gate  * Description:
5217c478bd9Sstevel@tonic-gate  *	Registers the presence of HCA device by providing the HCA device info
5227c478bd9Sstevel@tonic-gate  *  	structure and provides an opaque HCA handler for future calls to this
5237c478bd9Sstevel@tonic-gate  *  	HCA device.
5247c478bd9Sstevel@tonic-gate  */
5257c478bd9Sstevel@tonic-gate ibc_status_t
ibc_attach(ibc_clnt_hdl_t * ibc_hdl_p,ibc_hca_info_t * info_p)5267c478bd9Sstevel@tonic-gate ibc_attach(ibc_clnt_hdl_t *ibc_hdl_p, ibc_hca_info_t *info_p)
5277c478bd9Sstevel@tonic-gate {
5287c478bd9Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;
5297c478bd9Sstevel@tonic-gate 	uint_t			nports;
5307c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L2(ibtf, "ibc_attach(%p, %p)", ibc_hdl_p, info_p);
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 	/* Validate the Transport API version */
535*17a2b317SBill Taylor 	if (info_p->hca_ci_vers != IBCI_V4) {
53643ed929aSsrust 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: Invalid IB CI Version '%d'",
53743ed929aSsrust 		    info_p->hca_ci_vers);
5387c478bd9Sstevel@tonic-gate 		return (IBC_FAILURE);
5397c478bd9Sstevel@tonic-gate 	}
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 	if (info_p->hca_attr == NULL) {
5427c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
5437c478bd9Sstevel@tonic-gate 		    "HCA Attributes must be specified.");
5447c478bd9Sstevel@tonic-gate 		return (IBC_FAILURE);
5457c478bd9Sstevel@tonic-gate 	}
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	nports = info_p->hca_attr->hca_nports;
5487c478bd9Sstevel@tonic-gate 	if (nports == 0) {
5497c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
5507c478bd9Sstevel@tonic-gate 		    "Number of ports must be valid");
5517c478bd9Sstevel@tonic-gate 		return (IBC_FAILURE);
5527c478bd9Sstevel@tonic-gate 	}
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	if (info_p->hca_attr->hca_max_port_pkey_tbl_sz == 0) {
5557c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
5567c478bd9Sstevel@tonic-gate 		    "Number of Partitions must be at least 1");
5577c478bd9Sstevel@tonic-gate 		return (IBC_FAILURE);
5587c478bd9Sstevel@tonic-gate 	}
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	if ((info_p->hca_attr->hca_flags & IBT_HCA_CURRENT_QP_STATE) == 0) {
5617c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
5627c478bd9Sstevel@tonic-gate 		    "HCA driver must support QP current state checking");
5637c478bd9Sstevel@tonic-gate 		return (IBC_FAILURE);
5647c478bd9Sstevel@tonic-gate 	}
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 	if ((info_p->hca_attr->hca_flags & IBT_HCA_PORT_UP) == 0) {
5677c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
5687c478bd9Sstevel@tonic-gate 		    "HCA driver must support PORT_UP async events");
5697c478bd9Sstevel@tonic-gate 		return (IBC_FAILURE);
5707c478bd9Sstevel@tonic-gate 	}
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 	/*
5737c478bd9Sstevel@tonic-gate 	 * Install IB nexus driver (if not installed already)
5747c478bd9Sstevel@tonic-gate 	 */
5759d3d2ed0Shiremath 	ibtl_set_ibhw_status();
5767c478bd9Sstevel@tonic-gate 	if (ndi_devi_config_vhci("ib", 0) == NULL) {
5777c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf, "ibc_attach: IB nexus attach failed");
5789d3d2ed0Shiremath 		ibtl_clear_ibhw_status();
5797c478bd9Sstevel@tonic-gate 		return (IBC_FAILURE);
5807c478bd9Sstevel@tonic-gate 	}
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 	ibtl_thread_init2();
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	/* Allocate the memory for per-client info structure */
5857c478bd9Sstevel@tonic-gate 	hca_devp = kmem_zalloc(sizeof (ibtl_hca_devinfo_t) +
58676c04273SRajkumar Sivaprakasam 	    (nports - 1) * sizeof (ibtl_async_port_event_t), KM_SLEEP);
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 	/* Update HCA dev info structure */
5917c478bd9Sstevel@tonic-gate 	hca_devp->hd_ibc_hca_hdl = info_p->hca_handle;
5927c478bd9Sstevel@tonic-gate 	hca_devp->hd_ibc_ops	= info_p->hca_ops;
5937c478bd9Sstevel@tonic-gate 	hca_devp->hd_hca_attr	= info_p->hca_attr;
594*17a2b317SBill Taylor 	hca_devp->hd_hca_dip	= info_p->hca_attr->hca_dip;
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	status = ibtl_init_hca_portinfo(hca_devp);
5977c478bd9Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
5987c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
5997c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: call to ibc_query_hca_ports "
6007c478bd9Sstevel@tonic-gate 		    "failed: status = %d", status);
6017c478bd9Sstevel@tonic-gate 		kmem_free(hca_devp, sizeof (ibtl_hca_devinfo_t) +
60276c04273SRajkumar Sivaprakasam 		    (nports - 1) * sizeof (ibtl_async_port_event_t));
6037c478bd9Sstevel@tonic-gate 		return (IBC_FAILURE);
6047c478bd9Sstevel@tonic-gate 	}
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 	/* Register the with MPxIO as PHCI */
607*17a2b317SBill Taylor 	if (ibtl_ibnex_phci_register(hca_devp->hd_hca_dip) != IBT_SUCCESS) {
6087c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
6097c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibc_attach: MPxIO register failed");
6107c478bd9Sstevel@tonic-gate 		kmem_free(hca_devp, sizeof (ibtl_hca_devinfo_t) +
61176c04273SRajkumar Sivaprakasam 		    (nports - 1) * sizeof (ibtl_async_port_event_t));
6127c478bd9Sstevel@tonic-gate 		return (IBC_FAILURE);
6137c478bd9Sstevel@tonic-gate 	}
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 	/* Initialize the Client List for this HCA. */
6167c478bd9Sstevel@tonic-gate 	hca_devp->hd_state	= IBTL_HCA_DEV_ATTACHED;
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 	/* lock out asyncs until after we announce the new HCA */
6197c478bd9Sstevel@tonic-gate 	hca_devp->hd_async_busy = 1;
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 	cv_init(&hca_devp->hd_async_task_cv, NULL, CV_DEFAULT, NULL);
6227c478bd9Sstevel@tonic-gate 	cv_init(&hca_devp->hd_async_busy_cv, NULL, CV_DEFAULT, NULL);
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 	/* init portinfo locking variables */
6257c478bd9Sstevel@tonic-gate 	hca_devp->hd_portinfo_locked_port = 0;
6267c478bd9Sstevel@tonic-gate 	cv_init(&hca_devp->hd_portinfo_cv, NULL, CV_DEFAULT, NULL);
6277c478bd9Sstevel@tonic-gate 
628d1a5c838SRamaswamy Tummala 	ibtl_kstat_init(hca_devp);
629d1a5c838SRamaswamy Tummala 
6307c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 	/*
6337c478bd9Sstevel@tonic-gate 	 * The ibc_hdl_p points to an opaque handle which is the address
6347c478bd9Sstevel@tonic-gate 	 * of ibt_hca_devinfo_t structure passed back to the CI.
6357c478bd9Sstevel@tonic-gate 	 * The CI will pass on this handle in its future upcalls to IBTF.
6367c478bd9Sstevel@tonic-gate 	 */
6377c478bd9Sstevel@tonic-gate 	*ibc_hdl_p = hca_devp;
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 	return (IBC_SUCCESS);
6407c478bd9Sstevel@tonic-gate }
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate /*
6447c478bd9Sstevel@tonic-gate  * Function:
6457c478bd9Sstevel@tonic-gate  *	ibc_post_attach
6467c478bd9Sstevel@tonic-gate  * Input:
6477c478bd9Sstevel@tonic-gate  *	ibc_hdl		- IBC Client's HCA Handle.
6487c478bd9Sstevel@tonic-gate  * Returns:
6497c478bd9Sstevel@tonic-gate  *	none
6507c478bd9Sstevel@tonic-gate  * Called by:
6517c478bd9Sstevel@tonic-gate  *	CI calls IBTF during its attach() after a successful ibc_attach().
6527c478bd9Sstevel@tonic-gate  * Description:
6537c478bd9Sstevel@tonic-gate  *	Announces to all known clients the existence of this HCA (by GUID).
6547c478bd9Sstevel@tonic-gate  */
6557c478bd9Sstevel@tonic-gate void
ibc_post_attach(ibc_clnt_hdl_t ibc_hdl)6567c478bd9Sstevel@tonic-gate ibc_post_attach(ibc_clnt_hdl_t ibc_hdl)
6577c478bd9Sstevel@tonic-gate {
6587c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L2(ibtf, "ibc_post_attach(%p)", ibc_hdl);
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 	/*
6617c478bd9Sstevel@tonic-gate 	 * Update the HCA Device List.
6627c478bd9Sstevel@tonic-gate 	 */
6637c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
6647c478bd9Sstevel@tonic-gate 	ibc_hdl->hd_hca_dev_link = ibtl_hca_list;
6657c478bd9Sstevel@tonic-gate 	ibtl_hca_list = ibc_hdl;
6667c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 	/* notify all IBT Client Device Instances of the new HCA Device */
6697c478bd9Sstevel@tonic-gate 	ibtl_announce_new_hca(ibc_hdl);
6707c478bd9Sstevel@tonic-gate }
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate /*
6747c478bd9Sstevel@tonic-gate  * Function:
6757c478bd9Sstevel@tonic-gate  *	ibc_pre_detach
6767c478bd9Sstevel@tonic-gate  * Input:
6777c478bd9Sstevel@tonic-gate  *	ibc_clnt_hdl	- IBC HCA Handle as returned during ibc_attach call.
6787c478bd9Sstevel@tonic-gate  *  	cmd		- DDI_DETACH/DDI_SUSPEND command.
6797c478bd9Sstevel@tonic-gate  * Output:
6807c478bd9Sstevel@tonic-gate  *	none
6817c478bd9Sstevel@tonic-gate  * Returns:
6827c478bd9Sstevel@tonic-gate  *	IBC_SUCCESS
6837c478bd9Sstevel@tonic-gate  *	IBC_FAILURE.
6847c478bd9Sstevel@tonic-gate  * Called by:
6857c478bd9Sstevel@tonic-gate  *	CI to try to get all IBTF clients to close the HCA device.
6867c478bd9Sstevel@tonic-gate  * Description:
6877c478bd9Sstevel@tonic-gate  *	Attempts to deregister the HCA device entry from the IBTF.
6887c478bd9Sstevel@tonic-gate  *	If all resources are freed by the IBTF clients and this HCA
6897c478bd9Sstevel@tonic-gate  *	is closed, then IBC_SUCCESS is returned.
6907c478bd9Sstevel@tonic-gate  */
6917c478bd9Sstevel@tonic-gate ibc_status_t
ibc_pre_detach(ibc_clnt_hdl_t hca_devp,ddi_detach_cmd_t cmd)6927c478bd9Sstevel@tonic-gate ibc_pre_detach(ibc_clnt_hdl_t hca_devp, ddi_detach_cmd_t cmd)
6937c478bd9Sstevel@tonic-gate {
6947c478bd9Sstevel@tonic-gate 	ibtl_hca_devinfo_t **hcapp, *hcap;
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L2(ibtf, "ibc_pre_detach(%p, 0x%x)", hca_devp, cmd);
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate 	/*
6997c478bd9Sstevel@tonic-gate 	 * Return failure, if command is not DDI_DETACH
7007c478bd9Sstevel@tonic-gate 	 */
7017c478bd9Sstevel@tonic-gate 	switch (cmd) {
7027c478bd9Sstevel@tonic-gate 	case DDI_DETACH:
7037c478bd9Sstevel@tonic-gate 		break;
7047c478bd9Sstevel@tonic-gate 	default:
7057c478bd9Sstevel@tonic-gate 		return (IBC_FAILURE); /* TBD: DDI_FAILURE */
7067c478bd9Sstevel@tonic-gate 	}
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 	/* Make sure this HCA is on the HCA Device List.  */
7097c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
7107c478bd9Sstevel@tonic-gate 	hcap = ibtl_hca_list;
7117c478bd9Sstevel@tonic-gate 	while (hcap != NULL) {
7127c478bd9Sstevel@tonic-gate 		if (hcap == hca_devp)
7137c478bd9Sstevel@tonic-gate 			break;
7147c478bd9Sstevel@tonic-gate 		hcap = hcap->hd_hca_dev_link;
7157c478bd9Sstevel@tonic-gate 	}
7167c478bd9Sstevel@tonic-gate 	if (hcap == NULL) {
7177c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
7187c478bd9Sstevel@tonic-gate 		return (IBC_FAILURE);
7197c478bd9Sstevel@tonic-gate 	}
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate 	/*
7227c478bd9Sstevel@tonic-gate 	 * Initially set the state to "Detaching".
7237c478bd9Sstevel@tonic-gate 	 */
7247c478bd9Sstevel@tonic-gate 	hca_devp->hd_state = IBTL_HCA_DEV_DETACHING;
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate 	/*
7277c478bd9Sstevel@tonic-gate 	 * Try to detach all IBTI clients, and continue only if all
7287c478bd9Sstevel@tonic-gate 	 * of the detaches succeed.
7297c478bd9Sstevel@tonic-gate 	 */
7307c478bd9Sstevel@tonic-gate 	if (ibtl_detach_all_clients(hca_devp)) {
7317c478bd9Sstevel@tonic-gate 		hca_devp->hd_state = IBTL_HCA_DEV_ATTACHED; /* fix hd_state */
7327c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate 		return (IBC_FAILURE);
7357c478bd9Sstevel@tonic-gate 	}
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate 	/*
7387c478bd9Sstevel@tonic-gate 	 * Check to see if all clients closed this HCA, or not.
7397c478bd9Sstevel@tonic-gate 	 * We only succeed if all clients cooperated.
7407c478bd9Sstevel@tonic-gate 	 */
7417c478bd9Sstevel@tonic-gate 	if (hca_devp->hd_clnt_list != NULL) {
7427c478bd9Sstevel@tonic-gate 		hca_devp->hd_state = IBTL_HCA_DEV_ATTACHED;
7437c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
7447c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf, "ibc_pre_detach: HCA still has attached "
7457c478bd9Sstevel@tonic-gate 		    "clients");
7467c478bd9Sstevel@tonic-gate 		return (IBC_FAILURE);
7477c478bd9Sstevel@tonic-gate 	}
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 	/*
7507c478bd9Sstevel@tonic-gate 	 * mark this device as detached
7517c478bd9Sstevel@tonic-gate 	 */
7527c478bd9Sstevel@tonic-gate 	hca_devp->hd_state = IBTL_HCA_DEV_DETACHED;
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate 	/* Delete the entry for this hca_devp from hca_head_list */
7557c478bd9Sstevel@tonic-gate 	hcapp = &ibtl_hca_list;
7567c478bd9Sstevel@tonic-gate 	while (*hcapp != NULL) {
7577c478bd9Sstevel@tonic-gate 		if (*hcapp == hca_devp)
7587c478bd9Sstevel@tonic-gate 			break;
7597c478bd9Sstevel@tonic-gate 		hcapp = &(*hcapp)->hd_hca_dev_link;
7607c478bd9Sstevel@tonic-gate 	}
7617c478bd9Sstevel@tonic-gate 
76200a3eaf3SRamaswamy Tummala 	if (ibtl_ibnex_phci_unregister(hca_devp->hd_hca_dip) != IBT_SUCCESS) {
7637c478bd9Sstevel@tonic-gate 		hca_devp->hd_state = IBTL_HCA_DEV_ATTACHED; /* fix hd_state */
7647c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
7657c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibc_pre_detach: PHCI unregister failed");
7667c478bd9Sstevel@tonic-gate 		return (IBC_FAILURE);
7677c478bd9Sstevel@tonic-gate 	}
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 	if (*hcapp == NULL) {
7707c478bd9Sstevel@tonic-gate 		hca_devp->hd_state = IBTL_HCA_DEV_ATTACHED; /* fix hd_state */
7717c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
7727c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf, "ibc_pre_detach: HCA not attached");
7737c478bd9Sstevel@tonic-gate 		return (IBC_FAILURE);
7747c478bd9Sstevel@tonic-gate 	}
7757c478bd9Sstevel@tonic-gate 	*hcapp = hca_devp->hd_hca_dev_link;
7767c478bd9Sstevel@tonic-gate 	ibtl_fast_gid_cache_valid = B_FALSE;	/* invalidate fast_gid_cache */
7777c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 	return (IBC_SUCCESS);
7807c478bd9Sstevel@tonic-gate }
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate /*
7837c478bd9Sstevel@tonic-gate  * Function:
7847c478bd9Sstevel@tonic-gate  *	ibc_detach
7857c478bd9Sstevel@tonic-gate  * Input:
7867c478bd9Sstevel@tonic-gate  *	ibc_clnt_hdl	- IBC HCA Handle as returned during ibc_attach call.
7877c478bd9Sstevel@tonic-gate  * Output:
7887c478bd9Sstevel@tonic-gate  *	none
7897c478bd9Sstevel@tonic-gate  * Returns:
7907c478bd9Sstevel@tonic-gate  *	None
7917c478bd9Sstevel@tonic-gate  * Called by:
7927c478bd9Sstevel@tonic-gate  *	CI to detach the HCA device from IBTF.
7937c478bd9Sstevel@tonic-gate  * Description:
7947c478bd9Sstevel@tonic-gate  *	Do the second step of detaching the HCA, which is required
7957c478bd9Sstevel@tonic-gate  *	after a successful ibc_pre_detach.
7967c478bd9Sstevel@tonic-gate  */
7977c478bd9Sstevel@tonic-gate void
ibc_detach(ibc_clnt_hdl_t hca_devp)7987c478bd9Sstevel@tonic-gate ibc_detach(ibc_clnt_hdl_t hca_devp)
7997c478bd9Sstevel@tonic-gate {
8007c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L2(ibtf, "ibc_detach(%p)", hca_devp);
8017c478bd9Sstevel@tonic-gate 
8027c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
8037c478bd9Sstevel@tonic-gate 	if (hca_devp->hd_state != IBTL_HCA_DEV_DETACHED) {
8047c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
8057c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L0(ibtf, "ibc_detach: HCA has not successfully "
8067c478bd9Sstevel@tonic-gate 		    "pre-detached");
8077c478bd9Sstevel@tonic-gate 		return;
8087c478bd9Sstevel@tonic-gate 	}
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate 	cv_destroy(&hca_devp->hd_async_task_cv);
8117c478bd9Sstevel@tonic-gate 	cv_destroy(&hca_devp->hd_async_busy_cv);
8127c478bd9Sstevel@tonic-gate 	cv_destroy(&hca_devp->hd_portinfo_cv);
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 	kmem_free(hca_devp->hd_portinfop, hca_devp->hd_portinfo_len);
8157c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
8167c478bd9Sstevel@tonic-gate 
817d1a5c838SRamaswamy Tummala 	ibtl_kstat_fini(hca_devp);
818d1a5c838SRamaswamy Tummala 
8197c478bd9Sstevel@tonic-gate 	/* Free up the memory of per-client info struct */
8207c478bd9Sstevel@tonic-gate 	kmem_free(hca_devp, sizeof (ibtl_hca_devinfo_t) +
8217c478bd9Sstevel@tonic-gate 	    (hca_devp->hd_hca_attr->hca_nports - 1) *
82276c04273SRajkumar Sivaprakasam 	    sizeof (ibtl_async_port_event_t));
8237c478bd9Sstevel@tonic-gate 	ibtl_clear_ibhw_status();
8247c478bd9Sstevel@tonic-gate }
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate /*
8277c478bd9Sstevel@tonic-gate  * Function:
8287c478bd9Sstevel@tonic-gate  *	ibt_ci_data_in()
8297c478bd9Sstevel@tonic-gate  *
8307c478bd9Sstevel@tonic-gate  * Input:
8317c478bd9Sstevel@tonic-gate  *	hca_hdl			HCA Handle.
8327c478bd9Sstevel@tonic-gate  *	flags			IBT_COMPLETE_ALLOC - Finish a deferred alloc.
8337c478bd9Sstevel@tonic-gate  *      object                  Identifies the type object pointed to by
8347c478bd9Sstevel@tonic-gate  *                              ibt_object_handle.
8357c478bd9Sstevel@tonic-gate  *
8367c478bd9Sstevel@tonic-gate  *      ibt_object_handle       The handle of the object to be associated with
8377c478bd9Sstevel@tonic-gate  *				the data in/out
8387c478bd9Sstevel@tonic-gate  *
8397c478bd9Sstevel@tonic-gate  *	data_p			Pointer data passed in to the CI. The buffer
8407c478bd9Sstevel@tonic-gate  *				should be allocated by the caller.
8417c478bd9Sstevel@tonic-gate  *
8427c478bd9Sstevel@tonic-gate  *	data_sz			The size of the buffer pointed to by
8437c478bd9Sstevel@tonic-gate  *				data_p.
8447c478bd9Sstevel@tonic-gate  * Output:
8457c478bd9Sstevel@tonic-gate  *
8467c478bd9Sstevel@tonic-gate  * Returns:
8477c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
8487c478bd9Sstevel@tonic-gate  *	IBT_NOT_SUPPORTED	Feature not supported.
8497c478bd9Sstevel@tonic-gate  *	IBT_INVALID_PARAM	Invalid object type specified.
8507c478bd9Sstevel@tonic-gate  *	IBT_HCA_HDL_INVALID
8517c478bd9Sstevel@tonic-gate  *	IBT_AH_HDL_INVALID/IBT_UD_DEST_HDL_INVALID
8527c478bd9Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID/IBT_QP_HDL_INVALID
8537c478bd9Sstevel@tonic-gate  *	IBT_CQ_HDL_INVALID
8547c478bd9Sstevel@tonic-gate  *	IBT_EEC_HDL_INVALID
8557c478bd9Sstevel@tonic-gate  *	IBT_RDD_HDL_INVALID
8567c478bd9Sstevel@tonic-gate  *	IBT_MW_HDL_INVALID
8577c478bd9Sstevel@tonic-gate  *	IBT_PD_HDL_INVALID
8587c478bd9Sstevel@tonic-gate  *	IBT_SRQ_HDL_INVALID
8597c478bd9Sstevel@tonic-gate  *
8607c478bd9Sstevel@tonic-gate  * Description:
8617c478bd9Sstevel@tonic-gate  *	Exchange CI private data for the specified CI object.
8627c478bd9Sstevel@tonic-gate  */
8637c478bd9Sstevel@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)8647c478bd9Sstevel@tonic-gate ibt_ci_data_in(ibt_hca_hdl_t hca, ibt_ci_data_flags_t flags,
8657c478bd9Sstevel@tonic-gate     ibt_object_type_t object, void *ibt_object_handle, void *data_p,
8667c478bd9Sstevel@tonic-gate     size_t data_sz)
8677c478bd9Sstevel@tonic-gate {
8687c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
8697c478bd9Sstevel@tonic-gate 	void			*ci_obj_hdl;
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf, "ibt_ci_data_in(%p, %x, %d, %p, %p, %d)",
8727c478bd9Sstevel@tonic-gate 	    hca, flags, object, ibt_object_handle, data_p, data_sz);
8737c478bd9Sstevel@tonic-gate 
8747c478bd9Sstevel@tonic-gate 	switch (object) {
8757c478bd9Sstevel@tonic-gate 	case IBT_HDL_HCA:
8767c478bd9Sstevel@tonic-gate 		ci_obj_hdl = (void *)
8777c478bd9Sstevel@tonic-gate 		    (IBTL_HCA2CIHCA(((ibt_hca_hdl_t)ibt_object_handle)));
8787c478bd9Sstevel@tonic-gate 		break;
8797c478bd9Sstevel@tonic-gate 
8807c478bd9Sstevel@tonic-gate 	case IBT_HDL_CHANNEL:
8817c478bd9Sstevel@tonic-gate 		ci_obj_hdl = (void *)
8827c478bd9Sstevel@tonic-gate 		    (IBTL_CHAN2CIQP(((ibt_channel_hdl_t)ibt_object_handle)));
8837c478bd9Sstevel@tonic-gate 		break;
8847c478bd9Sstevel@tonic-gate 
8857c478bd9Sstevel@tonic-gate 	case IBT_HDL_CQ:
8867c478bd9Sstevel@tonic-gate 		ci_obj_hdl = (void *)
8877c478bd9Sstevel@tonic-gate 		    (((ibt_cq_hdl_t)(ibt_object_handle))->cq_ibc_cq_hdl);
8887c478bd9Sstevel@tonic-gate 		break;
8897c478bd9Sstevel@tonic-gate 
8907c478bd9Sstevel@tonic-gate 	case IBT_HDL_EEC:
8917c478bd9Sstevel@tonic-gate 		ci_obj_hdl = (void *)
8927c478bd9Sstevel@tonic-gate 		    (((ibt_eec_hdl_t)(ibt_object_handle))->eec_ibc_eec_hdl);
8937c478bd9Sstevel@tonic-gate 		break;
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate 	case IBT_HDL_UD_DEST:
8967c478bd9Sstevel@tonic-gate 		ci_obj_hdl = (void *)
8977c478bd9Sstevel@tonic-gate 		    (((ibt_ud_dest_hdl_t)(ibt_object_handle))->ud_ah);
8987c478bd9Sstevel@tonic-gate 		break;
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate 	case IBT_HDL_SRQ:
9017c478bd9Sstevel@tonic-gate 		ci_obj_hdl = (void *)
9027c478bd9Sstevel@tonic-gate 		    (((ibt_srq_hdl_t)(ibt_object_handle))->srq_ibc_srq_hdl);
9037c478bd9Sstevel@tonic-gate 		break;
9047c478bd9Sstevel@tonic-gate 
9057c478bd9Sstevel@tonic-gate 	default:
9067c478bd9Sstevel@tonic-gate 		ci_obj_hdl = ibt_object_handle;
9077c478bd9Sstevel@tonic-gate 		break;
9087c478bd9Sstevel@tonic-gate 	}
9097c478bd9Sstevel@tonic-gate 
9107c478bd9Sstevel@tonic-gate 	retval = (IBTL_HCA2CIHCAOPS_P(hca)->ibc_ci_data_in)(IBTL_HCA2CIHCA(hca),
9117c478bd9Sstevel@tonic-gate 	    flags, object, ci_obj_hdl, data_p, data_sz);
9127c478bd9Sstevel@tonic-gate 
9137c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
9147c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf, "ibt_ci_data_in: Failed : %d", retval);
9157c478bd9Sstevel@tonic-gate 	}
9167c478bd9Sstevel@tonic-gate 	return (retval);
9177c478bd9Sstevel@tonic-gate }
9187c478bd9Sstevel@tonic-gate 
9197c478bd9Sstevel@tonic-gate /*
9207c478bd9Sstevel@tonic-gate  * Function:
9217c478bd9Sstevel@tonic-gate  *	ibt_ci_data_out()
9227c478bd9Sstevel@tonic-gate  *
9237c478bd9Sstevel@tonic-gate  * Input:
9247c478bd9Sstevel@tonic-gate  *	hca_hdl			HCA Handle.
9257c478bd9Sstevel@tonic-gate  *	flags			IBT_COMPLETE_ALLOC - Finish a deferred alloc.
9267c478bd9Sstevel@tonic-gate  *      object                  Identifies the type object pointed to by
9277c478bd9Sstevel@tonic-gate  *                              ibt_object_handle.
9287c478bd9Sstevel@tonic-gate  *
9297c478bd9Sstevel@tonic-gate  *      ibt_object_handle       The handle of the object to be associated with
9307c478bd9Sstevel@tonic-gate  *				the data in/out
9317c478bd9Sstevel@tonic-gate  *
9327c478bd9Sstevel@tonic-gate  *	data_p			Pointer to a buffer in which to return the CI
9337c478bd9Sstevel@tonic-gate  *				private data. The buffer should be allocated
9347c478bd9Sstevel@tonic-gate  *				by the caller.
9357c478bd9Sstevel@tonic-gate  *
9367c478bd9Sstevel@tonic-gate  *	data_sz			The size of the buffer pointed to by
9377c478bd9Sstevel@tonic-gate  *				data_p.
9387c478bd9Sstevel@tonic-gate  * Output:
9397c478bd9Sstevel@tonic-gate  *
9407c478bd9Sstevel@tonic-gate  * Returns:
9417c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
9427c478bd9Sstevel@tonic-gate  *	IBT_NOT_SUPPORTED	Feature not supported.
9437c478bd9Sstevel@tonic-gate  *	IBT_INSUFF_RESOURCE	The buffer pointed to by data_p was too
9447c478bd9Sstevel@tonic-gate  *				small to hold the data.
9457c478bd9Sstevel@tonic-gate  *	IBT_INVALID_PARAM	Invalid object type specified.
9467c478bd9Sstevel@tonic-gate  *	IBT_HCA_HDL_INVALID
9477c478bd9Sstevel@tonic-gate  *	IBT_AH_HDL_INVALID/IBT_UD_DEST_HDL_INVALID
9487c478bd9Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID/IBT_QP_HDL_INVALID
9497c478bd9Sstevel@tonic-gate  *	IBT_CQ_HDL_INVALID
9507c478bd9Sstevel@tonic-gate  *	IBT_EEC_HDL_INVALID
9517c478bd9Sstevel@tonic-gate  *	IBT_RDD_HDL_INVALID
9527c478bd9Sstevel@tonic-gate  *	IBT_MW_HDL_INVALID
9537c478bd9Sstevel@tonic-gate  *	IBT_PD_HDL_INVALID
9547c478bd9Sstevel@tonic-gate  *	IBT_SRQ_HDL_INVALID
9557c478bd9Sstevel@tonic-gate  *
9567c478bd9Sstevel@tonic-gate  * Description:
9577c478bd9Sstevel@tonic-gate  *	Exchange CI private data for the specified CI object.
9587c478bd9Sstevel@tonic-gate  */
9597c478bd9Sstevel@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)9607c478bd9Sstevel@tonic-gate ibt_ci_data_out(ibt_hca_hdl_t hca, ibt_ci_data_flags_t flags,
9617c478bd9Sstevel@tonic-gate     ibt_object_type_t object, void *ibt_object_handle, void *data_p,
9627c478bd9Sstevel@tonic-gate     size_t data_sz)
9637c478bd9Sstevel@tonic-gate {
9647c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
9657c478bd9Sstevel@tonic-gate 	void			*ci_obj_hdl;
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf, "ibt_ci_data_out(%p, %x, %d, %p, %p, %d)",
9687c478bd9Sstevel@tonic-gate 	    hca, flags, object, ibt_object_handle, data_p, data_sz);
9697c478bd9Sstevel@tonic-gate 
9707c478bd9Sstevel@tonic-gate 	switch (object) {
9717c478bd9Sstevel@tonic-gate 	case  IBT_HDL_HCA:
9727c478bd9Sstevel@tonic-gate 		ci_obj_hdl = (void *)
9737c478bd9Sstevel@tonic-gate 		    (IBTL_HCA2CIHCA(((ibt_hca_hdl_t)ibt_object_handle)));
9747c478bd9Sstevel@tonic-gate 		break;
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate 	case IBT_HDL_CHANNEL:
9777c478bd9Sstevel@tonic-gate 		ci_obj_hdl = (void *)
9787c478bd9Sstevel@tonic-gate 		    (IBTL_CHAN2CIQP(((ibt_channel_hdl_t)ibt_object_handle)));
9797c478bd9Sstevel@tonic-gate 		break;
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate 	case IBT_HDL_CQ:
9827c478bd9Sstevel@tonic-gate 		ci_obj_hdl = (void *)
9837c478bd9Sstevel@tonic-gate 		    (((ibt_cq_hdl_t)(ibt_object_handle))->cq_ibc_cq_hdl);
9847c478bd9Sstevel@tonic-gate 		break;
9857c478bd9Sstevel@tonic-gate 
9867c478bd9Sstevel@tonic-gate 	case IBT_HDL_EEC:
9877c478bd9Sstevel@tonic-gate 		ci_obj_hdl = (void *)
9887c478bd9Sstevel@tonic-gate 		    (((ibt_eec_hdl_t)(ibt_object_handle))->eec_ibc_eec_hdl);
9897c478bd9Sstevel@tonic-gate 		break;
9907c478bd9Sstevel@tonic-gate 
9917c478bd9Sstevel@tonic-gate 	case IBT_HDL_UD_DEST:
9927c478bd9Sstevel@tonic-gate 		ci_obj_hdl = (void *)
9937c478bd9Sstevel@tonic-gate 		    (((ibt_ud_dest_hdl_t)(ibt_object_handle))->ud_ah);
9947c478bd9Sstevel@tonic-gate 		break;
9957c478bd9Sstevel@tonic-gate 
9967c478bd9Sstevel@tonic-gate 	case IBT_HDL_SRQ:
9977c478bd9Sstevel@tonic-gate 		ci_obj_hdl = (void *)
9987c478bd9Sstevel@tonic-gate 		    (((ibt_srq_hdl_t)(ibt_object_handle))->srq_ibc_srq_hdl);
9997c478bd9Sstevel@tonic-gate 		break;
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate 	default:
10027c478bd9Sstevel@tonic-gate 		ci_obj_hdl = ibt_object_handle;
10037c478bd9Sstevel@tonic-gate 		break;
10047c478bd9Sstevel@tonic-gate 	}
10057c478bd9Sstevel@tonic-gate 
10067c478bd9Sstevel@tonic-gate 	retval = (IBTL_HCA2CIHCAOPS_P(hca)->ibc_ci_data_out)
10077c478bd9Sstevel@tonic-gate 	    (IBTL_HCA2CIHCA(hca), flags, object, ci_obj_hdl, data_p, data_sz);
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
10107c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf, "ibt_ci_data_out: Failed : %d", retval);
10117c478bd9Sstevel@tonic-gate 	}
10127c478bd9Sstevel@tonic-gate 	return (retval);
10137c478bd9Sstevel@tonic-gate }
10147c478bd9Sstevel@tonic-gate 
10157c478bd9Sstevel@tonic-gate 
10167c478bd9Sstevel@tonic-gate /*
10177c478bd9Sstevel@tonic-gate  * FMA Support functions.
10187c478bd9Sstevel@tonic-gate  */
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate #define	IBTL_ENA_MASK		0xC0000000
10217c478bd9Sstevel@tonic-gate #define	IBTL_ENA_POSSIBLE	0x80000000
10227c478bd9Sstevel@tonic-gate #define	IBTL_TYPE_SHIFT		27
10237c478bd9Sstevel@tonic-gate 
10247c478bd9Sstevel@tonic-gate /*
10257c478bd9Sstevel@tonic-gate  * Function:
10267c478bd9Sstevel@tonic-gate  *	ibt_get_module_failure()
10277c478bd9Sstevel@tonic-gate  *
10287c478bd9Sstevel@tonic-gate  * Input:
10297c478bd9Sstevel@tonic-gate  *	type			Identifies the failing IB module.
10307c478bd9Sstevel@tonic-gate  *	ena			'0' or the data for Fault Management
10317c478bd9Sstevel@tonic-gate  *				Architecture (ENA).
10327c478bd9Sstevel@tonic-gate  *
10337c478bd9Sstevel@tonic-gate  * Returns:
10347c478bd9Sstevel@tonic-gate  *	status			Special IB failure status.
10357c478bd9Sstevel@tonic-gate  *
10367c478bd9Sstevel@tonic-gate  * Description:
10377c478bd9Sstevel@tonic-gate  *	XXX Just stubbed out to return failures with no data for Fault
10387c478bd9Sstevel@tonic-gate  *	Management Architecture (ENAs) at the moment XXX
10397c478bd9Sstevel@tonic-gate  */
10407c478bd9Sstevel@tonic-gate ibt_status_t
ibt_get_module_failure(ibt_failure_type_t type,uint64_t ena)10417c478bd9Sstevel@tonic-gate ibt_get_module_failure(ibt_failure_type_t type, uint64_t ena)
10427c478bd9Sstevel@tonic-gate {
10437c478bd9Sstevel@tonic-gate 	ibt_status_t	ret;
10447c478bd9Sstevel@tonic-gate 
10457c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf, "ibt_get_module_failure(%d, 0x%llX)", type, ena);
10467c478bd9Sstevel@tonic-gate 
10477c478bd9Sstevel@tonic-gate 	switch (type) {
10487c478bd9Sstevel@tonic-gate 	case IBT_FAILURE_CI:
10497c478bd9Sstevel@tonic-gate 	case IBT_FAILURE_IBMF:
10507c478bd9Sstevel@tonic-gate 	case IBT_FAILURE_IBCM:
10517c478bd9Sstevel@tonic-gate 	case IBT_FAILURE_IBDM:
10527c478bd9Sstevel@tonic-gate 	case IBT_FAILURE_IBTL:
105343ed929aSsrust 	case IBT_FAILURE_IBSM:
10547c478bd9Sstevel@tonic-gate 		ret = IBTL_ENA_POSSIBLE | (type << IBTL_TYPE_SHIFT);
10557c478bd9Sstevel@tonic-gate 		break;
10567c478bd9Sstevel@tonic-gate 	default:
10577c478bd9Sstevel@tonic-gate 		ret = IBT_FAILURE;
10587c478bd9Sstevel@tonic-gate 	}
10597c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf, "ibt_get_module_failure: ret = 0x%lX", ret);
10607c478bd9Sstevel@tonic-gate 	return (ret);
10617c478bd9Sstevel@tonic-gate }
10627c478bd9Sstevel@tonic-gate 
10637c478bd9Sstevel@tonic-gate 
10647c478bd9Sstevel@tonic-gate /*
10657c478bd9Sstevel@tonic-gate  * Function:
10667c478bd9Sstevel@tonic-gate  *	ibc_get_ci_failure()
10677c478bd9Sstevel@tonic-gate  *
10687c478bd9Sstevel@tonic-gate  * Input:
10697c478bd9Sstevel@tonic-gate  *	ena			'0' or the data for Fault Management
10707c478bd9Sstevel@tonic-gate  *				Architecture (ENA).
10717c478bd9Sstevel@tonic-gate  *
10727c478bd9Sstevel@tonic-gate  * Returns:
10737c478bd9Sstevel@tonic-gate  *	status			Special CI failure status.
10747c478bd9Sstevel@tonic-gate  *
10757c478bd9Sstevel@tonic-gate  * Description:
10767c478bd9Sstevel@tonic-gate  *	Just use the function above to do the job.
10777c478bd9Sstevel@tonic-gate  */
10787c478bd9Sstevel@tonic-gate ibt_status_t
ibc_get_ci_failure(uint64_t ena)10797c478bd9Sstevel@tonic-gate ibc_get_ci_failure(uint64_t ena)
10807c478bd9Sstevel@tonic-gate {
10817c478bd9Sstevel@tonic-gate 	return (ibt_get_module_failure(IBT_FAILURE_CI, ena));
10827c478bd9Sstevel@tonic-gate }
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate 
10857c478bd9Sstevel@tonic-gate /*
10867c478bd9Sstevel@tonic-gate  * ibt_check_failure()
10877c478bd9Sstevel@tonic-gate  *	Function to test for special case failures.
10887c478bd9Sstevel@tonic-gate  *
10897c478bd9Sstevel@tonic-gate  *	status		An ibt_status_t returned from an IBTF function call.
10907c478bd9Sstevel@tonic-gate  *
10917c478bd9Sstevel@tonic-gate  *	reserved_p	NULL, or a pointer to where we store the data for
10927c478bd9Sstevel@tonic-gate  *			Fault Management Architecture (ENA).
10937c478bd9Sstevel@tonic-gate  *
10947c478bd9Sstevel@tonic-gate  * Description:
10957c478bd9Sstevel@tonic-gate  *	XXX Still need to determine the data for Fault Management Architecture
10967c478bd9Sstevel@tonic-gate  *	(ENA), using 0 for now XXX
10977c478bd9Sstevel@tonic-gate  */
10987c478bd9Sstevel@tonic-gate ibt_failure_type_t
ibt_check_failure(ibt_status_t status,uint64_t * reserved_p)10997c478bd9Sstevel@tonic-gate ibt_check_failure(ibt_status_t status, uint64_t *reserved_p)
11007c478bd9Sstevel@tonic-gate {
11017c478bd9Sstevel@tonic-gate 	ibt_failure_type_t type;
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf, "ibt_check_failure(%X)", status);
11047c478bd9Sstevel@tonic-gate 
11057c478bd9Sstevel@tonic-gate 	if ((status & IBTL_ENA_MASK) == IBTL_ENA_POSSIBLE) {
11067c478bd9Sstevel@tonic-gate 		type = status & ~IBTL_ENA_POSSIBLE >> IBTL_TYPE_SHIFT;
11077c478bd9Sstevel@tonic-gate 
11087c478bd9Sstevel@tonic-gate 		/* XXX Need more work here... */
11097c478bd9Sstevel@tonic-gate 		if (reserved_p != NULL)
11107c478bd9Sstevel@tonic-gate 			*reserved_p = 0;
11117c478bd9Sstevel@tonic-gate 	} else {
11127c478bd9Sstevel@tonic-gate 		type = IBT_FAILURE_STANDARD;
11137c478bd9Sstevel@tonic-gate 		if (reserved_p != NULL)
11147c478bd9Sstevel@tonic-gate 			*reserved_p = 0;	/* No FMA Data Available. */
11157c478bd9Sstevel@tonic-gate 	}
11167c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf, "ibt_check_failure: type = 0x%X", type);
11177c478bd9Sstevel@tonic-gate 	return (type);
11187c478bd9Sstevel@tonic-gate }
1119d1a5c838SRamaswamy Tummala 
1120d1a5c838SRamaswamy Tummala /*
1121d1a5c838SRamaswamy Tummala  * Initialize and create kstats.
1122d1a5c838SRamaswamy Tummala  *
1123d1a5c838SRamaswamy Tummala  * We create the following kstats on all ports of the HCA:
1124d1a5c838SRamaswamy Tummala  *	<hca_driver_name><instance_number>/port<port_num>/stats
1125d1a5c838SRamaswamy Tummala  *	<hca_driver_name><instance_number>/port<port_num>/pkeys
1126d1a5c838SRamaswamy Tummala  */
1127d1a5c838SRamaswamy Tummala static void
ibtl_kstat_init(ibtl_hca_devinfo_t * hca_devp)1128d1a5c838SRamaswamy Tummala ibtl_kstat_init(ibtl_hca_devinfo_t *hca_devp)
1129d1a5c838SRamaswamy Tummala {
1130d1a5c838SRamaswamy Tummala 	uint_t			nports = hca_devp->hd_hca_attr->hca_nports;
1131d1a5c838SRamaswamy Tummala 	ibtl_hca_port_kstat_t	*pks;
1132d1a5c838SRamaswamy Tummala 	int			i;
1133d1a5c838SRamaswamy Tummala 
1134d1a5c838SRamaswamy Tummala 	IBTF_DPRINTF_L3(ibtf, "ibtl_kstat_init(hca_devp = 0x%p)", hca_devp);
1135d1a5c838SRamaswamy Tummala 
1136d1a5c838SRamaswamy Tummala 	hca_devp->hd_hca_port_ks_info_len =
1137d1a5c838SRamaswamy Tummala 	    sizeof (ibtl_hca_port_kstat_t) * nports;
1138d1a5c838SRamaswamy Tummala 	pks = kmem_zalloc(hca_devp->hd_hca_port_ks_info_len, KM_SLEEP);
1139d1a5c838SRamaswamy Tummala 	hca_devp->hd_hca_port_ks_info = pks;
1140d1a5c838SRamaswamy Tummala 
1141d1a5c838SRamaswamy Tummala 	for (i = 0; i < nports; i++, pks++) {
1142d1a5c838SRamaswamy Tummala 		pks->pks_hca_devp = hca_devp;
1143d1a5c838SRamaswamy Tummala 		pks->pks_port_num = i + 1;
1144d1a5c838SRamaswamy Tummala 		ibtl_kstat_stats_create(hca_devp, i + 1);
1145d1a5c838SRamaswamy Tummala 		ibtl_kstat_pkeys_create(hca_devp, i + 1);
1146d1a5c838SRamaswamy Tummala 	}
1147d1a5c838SRamaswamy Tummala }
1148d1a5c838SRamaswamy Tummala 
1149d1a5c838SRamaswamy Tummala /*
1150d1a5c838SRamaswamy Tummala  * Delete kstats on all ports of the HCA.
1151d1a5c838SRamaswamy Tummala  */
1152d1a5c838SRamaswamy Tummala static void
ibtl_kstat_fini(ibtl_hca_devinfo_t * hca_devp)1153d1a5c838SRamaswamy Tummala ibtl_kstat_fini(ibtl_hca_devinfo_t *hca_devp)
1154d1a5c838SRamaswamy Tummala {
1155d1a5c838SRamaswamy Tummala 	ibtl_hca_port_kstat_t	*pks;
1156d1a5c838SRamaswamy Tummala 	int			i;
1157d1a5c838SRamaswamy Tummala 
1158d1a5c838SRamaswamy Tummala 	IBTF_DPRINTF_L3(ibtf, "ibtl_kstat_fini(hca_devp = 0x%p)", hca_devp);
1159d1a5c838SRamaswamy Tummala 
1160d1a5c838SRamaswamy Tummala 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*hca_devp))
1161d1a5c838SRamaswamy Tummala 
1162d1a5c838SRamaswamy Tummala 	pks = hca_devp->hd_hca_port_ks_info;
1163d1a5c838SRamaswamy Tummala 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*pks))
1164d1a5c838SRamaswamy Tummala 
1165d1a5c838SRamaswamy Tummala 	if (pks == NULL)
1166d1a5c838SRamaswamy Tummala 		return;
1167d1a5c838SRamaswamy Tummala 
1168d1a5c838SRamaswamy Tummala 	for (i = 0; i < hca_devp->hd_hca_attr->hca_nports; i++, pks++) {
1169d1a5c838SRamaswamy Tummala 		if (pks->pks_stats_ksp)
1170d1a5c838SRamaswamy Tummala 			kstat_delete(pks->pks_stats_ksp);
1171d1a5c838SRamaswamy Tummala 
1172d1a5c838SRamaswamy Tummala 		if (pks->pks_pkeys_ksp) {
1173d1a5c838SRamaswamy Tummala 			ASSERT(!MUTEX_HELD(&ibtl_clnt_list_mutex));
1174d1a5c838SRamaswamy Tummala 			kstat_delete(pks->pks_pkeys_ksp);
1175d1a5c838SRamaswamy Tummala 		}
1176d1a5c838SRamaswamy Tummala 	}
1177d1a5c838SRamaswamy Tummala 
1178d1a5c838SRamaswamy Tummala 	kmem_free(hca_devp->hd_hca_port_ks_info,
1179d1a5c838SRamaswamy Tummala 	    hca_devp->hd_hca_port_ks_info_len);
1180d1a5c838SRamaswamy Tummala }
1181d1a5c838SRamaswamy Tummala 
1182d1a5c838SRamaswamy Tummala /*
1183d1a5c838SRamaswamy Tummala  * Update "stats" kstat.
1184d1a5c838SRamaswamy Tummala  * Called by kstat framework.
1185d1a5c838SRamaswamy Tummala  */
1186d1a5c838SRamaswamy Tummala static int
ibtl_kstat_stats_update(kstat_t * ksp,int rw)1187d1a5c838SRamaswamy Tummala ibtl_kstat_stats_update(kstat_t *ksp, int rw)
1188d1a5c838SRamaswamy Tummala {
1189d1a5c838SRamaswamy Tummala 	ibtl_hca_port_kstat_t	*pks;
1190d1a5c838SRamaswamy Tummala 	ibtl_hca_devinfo_t	*hca_devp;
1191d1a5c838SRamaswamy Tummala 	ibt_hca_portinfo_t	*p;
1192d1a5c838SRamaswamy Tummala 	struct kstat_named	*data;
1193d1a5c838SRamaswamy Tummala 
1194d1a5c838SRamaswamy Tummala 	IBTF_DPRINTF_L4(ibtf, "ibtl_kstat_stats_update(ksp = 0x%p, rw = %d)",
1195d1a5c838SRamaswamy Tummala 	    ksp, rw);
1196d1a5c838SRamaswamy Tummala 
1197d1a5c838SRamaswamy Tummala 	if (rw == KSTAT_WRITE)
1198d1a5c838SRamaswamy Tummala 		return (EACCES);
1199d1a5c838SRamaswamy Tummala 
1200d1a5c838SRamaswamy Tummala 	mutex_enter(&ibtl_clnt_list_mutex);
1201d1a5c838SRamaswamy Tummala 
1202d1a5c838SRamaswamy Tummala 	/*
1203d1a5c838SRamaswamy Tummala 	 * Update the link_state kstat using the value from portinfo cache.
1204d1a5c838SRamaswamy Tummala 	 */
1205d1a5c838SRamaswamy Tummala 	pks = ksp->ks_private;
1206d1a5c838SRamaswamy Tummala 	hca_devp = pks->pks_hca_devp;
1207d1a5c838SRamaswamy Tummala 	data = (struct kstat_named *)(ksp->ks_data);
1208d1a5c838SRamaswamy Tummala 	p = hca_devp->hd_portinfop + pks->pks_port_num - 1;
1209d1a5c838SRamaswamy Tummala 	data[0].value.ui32 = (uint32_t)p->p_linkstate;
1210d1a5c838SRamaswamy Tummala 
1211d1a5c838SRamaswamy Tummala 	mutex_exit(&ibtl_clnt_list_mutex);
1212d1a5c838SRamaswamy Tummala 
1213d1a5c838SRamaswamy Tummala 	return (0);
1214d1a5c838SRamaswamy Tummala }
1215d1a5c838SRamaswamy Tummala 
1216d1a5c838SRamaswamy Tummala /*
1217d1a5c838SRamaswamy Tummala  * Create "stats" kstat for the specified HCA port in the form:
1218d1a5c838SRamaswamy Tummala  *	<hca_driver_name><instance_number>/port<port_num>/stats
1219d1a5c838SRamaswamy Tummala  *	At preset it contains only one named data of "link_state"
1220d1a5c838SRamaswamy Tummala  */
1221d1a5c838SRamaswamy Tummala static void
ibtl_kstat_stats_create(ibtl_hca_devinfo_t * hca_devp,uint_t port_num)1222d1a5c838SRamaswamy Tummala ibtl_kstat_stats_create(ibtl_hca_devinfo_t *hca_devp, uint_t port_num)
1223d1a5c838SRamaswamy Tummala {
1224d1a5c838SRamaswamy Tummala 	struct kstat		*ksp;
1225d1a5c838SRamaswamy Tummala 	struct kstat_named	*named_data;
1226d1a5c838SRamaswamy Tummala 	char			*drv_name;
1227d1a5c838SRamaswamy Tummala 	int			drv_instance;
1228d1a5c838SRamaswamy Tummala 	ibtl_hca_port_kstat_t	*pks;
1229d1a5c838SRamaswamy Tummala 	char			kname[40];
1230d1a5c838SRamaswamy Tummala 
1231d1a5c838SRamaswamy Tummala 	IBTF_DPRINTF_L3(ibtf, "ibtl_kstat_stats_create(hca_devp = 0x%p, "
1232d1a5c838SRamaswamy Tummala 	    "port_num = 0x%u)", hca_devp, port_num);
1233d1a5c838SRamaswamy Tummala 
1234d1a5c838SRamaswamy Tummala 	drv_name = (char *)ddi_driver_name(hca_devp->hd_hca_dip);
1235d1a5c838SRamaswamy Tummala 	drv_instance = ddi_get_instance(hca_devp->hd_hca_dip);
1236d1a5c838SRamaswamy Tummala 	(void) snprintf(kname, sizeof (kname), "%s%d/port%d/stats",
1237d1a5c838SRamaswamy Tummala 	    drv_name, drv_instance, port_num);
1238d1a5c838SRamaswamy Tummala 
1239d1a5c838SRamaswamy Tummala 	ksp = kstat_create("ibtf", 0, kname, "ib", KSTAT_TYPE_NAMED, 1, 0);
1240d1a5c838SRamaswamy Tummala 	if (ksp == NULL) {
1241d1a5c838SRamaswamy Tummala 		IBTF_DPRINTF_L2(ibtf,
1242d1a5c838SRamaswamy Tummala 		    "ibtl_kstat_stats_create: kstat_create() failed");
1243d1a5c838SRamaswamy Tummala 		return;
1244d1a5c838SRamaswamy Tummala 	}
1245d1a5c838SRamaswamy Tummala 
1246d1a5c838SRamaswamy Tummala 	named_data = (struct kstat_named *)(ksp->ks_data);
1247d1a5c838SRamaswamy Tummala 	kstat_named_init(&named_data[0], "link_state", KSTAT_DATA_UINT32);
1248d1a5c838SRamaswamy Tummala 
1249d1a5c838SRamaswamy Tummala 	pks = hca_devp->hd_hca_port_ks_info + port_num - 1;
1250d1a5c838SRamaswamy Tummala 	pks->pks_stats_ksp = ksp;
1251d1a5c838SRamaswamy Tummala 
1252d1a5c838SRamaswamy Tummala 	ksp->ks_private = pks;
1253d1a5c838SRamaswamy Tummala 	ksp->ks_update = ibtl_kstat_stats_update;
1254d1a5c838SRamaswamy Tummala 
1255d1a5c838SRamaswamy Tummala 	/* Install the kstat */
1256d1a5c838SRamaswamy Tummala 	kstat_install(ksp);
1257d1a5c838SRamaswamy Tummala }
1258d1a5c838SRamaswamy Tummala 
1259d1a5c838SRamaswamy Tummala /*
1260d1a5c838SRamaswamy Tummala  * Update "pkeys" kstat.
1261d1a5c838SRamaswamy Tummala  *
1262d1a5c838SRamaswamy Tummala  * Called by kstat framework. Since ks_lock was set to ibtl_clnt_list_mutex
1263d1a5c838SRamaswamy Tummala  * at the time of the kstat creation, kstat framework will hold this lock
1264d1a5c838SRamaswamy Tummala  * while calling this function.
1265d1a5c838SRamaswamy Tummala  */
1266d1a5c838SRamaswamy Tummala static int
ibtl_kstat_pkeys_update(kstat_t * ksp,int rw)1267d1a5c838SRamaswamy Tummala ibtl_kstat_pkeys_update(kstat_t *ksp, int rw)
1268d1a5c838SRamaswamy Tummala {
1269d1a5c838SRamaswamy Tummala 	ibtl_hca_port_kstat_t	*pks;
1270d1a5c838SRamaswamy Tummala 	ibtl_hca_devinfo_t	*hca_devp;
1271d1a5c838SRamaswamy Tummala 	ibt_hca_portinfo_t	*p;
1272d1a5c838SRamaswamy Tummala 
1273d1a5c838SRamaswamy Tummala 	IBTF_DPRINTF_L4(ibtf, "ibtl_kstat_pkeys_update(ksp = 0x%p, rw = %d)",
1274d1a5c838SRamaswamy Tummala 	    ksp, rw);
1275d1a5c838SRamaswamy Tummala 
1276d1a5c838SRamaswamy Tummala #ifndef	__lock_lint
1277d1a5c838SRamaswamy Tummala 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
1278d1a5c838SRamaswamy Tummala #endif
1279d1a5c838SRamaswamy Tummala 
1280d1a5c838SRamaswamy Tummala 	if (rw == KSTAT_WRITE)
1281d1a5c838SRamaswamy Tummala 		return (EACCES);
1282d1a5c838SRamaswamy Tummala 
1283d1a5c838SRamaswamy Tummala 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ksp))
1284d1a5c838SRamaswamy Tummala 
1285d1a5c838SRamaswamy Tummala 	pks = ksp->ks_private;
1286d1a5c838SRamaswamy Tummala 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*pks))
1287d1a5c838SRamaswamy Tummala 
1288d1a5c838SRamaswamy Tummala 	hca_devp = pks->pks_hca_devp;
1289d1a5c838SRamaswamy Tummala 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*hca_devp))
1290d1a5c838SRamaswamy Tummala 
1291d1a5c838SRamaswamy Tummala 	/*
1292d1a5c838SRamaswamy Tummala 	 * Point kstat data to the pkey table in the portinfo cache.
1293d1a5c838SRamaswamy Tummala 	 */
1294d1a5c838SRamaswamy Tummala 
1295d1a5c838SRamaswamy Tummala 	p = hca_devp->hd_portinfop + pks->pks_port_num - 1;
1296d1a5c838SRamaswamy Tummala 
1297d1a5c838SRamaswamy Tummala 	ksp->ks_data = p->p_pkey_tbl;
1298d1a5c838SRamaswamy Tummala 	ksp->ks_ndata = p->p_pkey_tbl_sz;
1299d1a5c838SRamaswamy Tummala 	ksp->ks_data_size = p->p_pkey_tbl_sz * sizeof (ib_pkey_t);
1300d1a5c838SRamaswamy Tummala 
1301d1a5c838SRamaswamy Tummala 	return (0);
1302d1a5c838SRamaswamy Tummala }
1303d1a5c838SRamaswamy Tummala 
1304d1a5c838SRamaswamy Tummala /*
1305d1a5c838SRamaswamy Tummala  * Create "pkeys" kstat for the specified HCA port in the form:
1306d1a5c838SRamaswamy Tummala  *	<hca_driver_name><instance_number>/port<port_num>/pkeys
1307d1a5c838SRamaswamy Tummala  *
1308d1a5c838SRamaswamy Tummala  * Currently kstat framework allows only some fixed data types as named
1309d1a5c838SRamaswamy Tummala  * data components under a named kstat. Due to this limitation it is not
1310d1a5c838SRamaswamy Tummala  * possible to add "pkeys" as a named data under the "stats" kstat.
1311d1a5c838SRamaswamy Tummala  */
1312d1a5c838SRamaswamy Tummala static void
ibtl_kstat_pkeys_create(ibtl_hca_devinfo_t * hca_devp,uint_t port_num)1313d1a5c838SRamaswamy Tummala ibtl_kstat_pkeys_create(ibtl_hca_devinfo_t *hca_devp, uint_t port_num)
1314d1a5c838SRamaswamy Tummala {
1315d1a5c838SRamaswamy Tummala 	struct kstat		*ksp;
1316d1a5c838SRamaswamy Tummala 	char			*drv_name;
1317d1a5c838SRamaswamy Tummala 	int			drv_instance;
1318d1a5c838SRamaswamy Tummala 	char			kname[40];
1319d1a5c838SRamaswamy Tummala 	ibtl_hca_port_kstat_t	*pks;
1320d1a5c838SRamaswamy Tummala 
1321d1a5c838SRamaswamy Tummala 	IBTF_DPRINTF_L3(ibtf, "ibtl_kstat_stats_create(hca_devp = 0x%p, "
1322d1a5c838SRamaswamy Tummala 	    "port_num = 0x%u)", hca_devp, port_num);
1323d1a5c838SRamaswamy Tummala 
1324d1a5c838SRamaswamy Tummala 	drv_name = (char *)ddi_driver_name(hca_devp->hd_hca_dip);
1325d1a5c838SRamaswamy Tummala 	drv_instance = ddi_get_instance(hca_devp->hd_hca_dip);
1326d1a5c838SRamaswamy Tummala 	(void) snprintf(kname, sizeof (kname), "%s%d/port%d/pkeys",
1327d1a5c838SRamaswamy Tummala 	    drv_name, drv_instance, port_num);
1328d1a5c838SRamaswamy Tummala 
1329d1a5c838SRamaswamy Tummala 	ksp = kstat_create("ibtf", 0, kname, "ib", KSTAT_TYPE_RAW, 0,
1330d1a5c838SRamaswamy Tummala 	    KSTAT_FLAG_VAR_SIZE | KSTAT_FLAG_VIRTUAL);
1331d1a5c838SRamaswamy Tummala 	if (ksp == NULL) {
1332d1a5c838SRamaswamy Tummala 		IBTF_DPRINTF_L2(ibtf,
1333d1a5c838SRamaswamy Tummala 		    "ibtl_kstat_pkeys_create: kstat_create() failed");
1334d1a5c838SRamaswamy Tummala 		return;
1335d1a5c838SRamaswamy Tummala 	}
1336d1a5c838SRamaswamy Tummala 
1337d1a5c838SRamaswamy Tummala 	pks = hca_devp->hd_hca_port_ks_info + port_num - 1;
1338d1a5c838SRamaswamy Tummala 	pks->pks_pkeys_ksp = ksp;
1339d1a5c838SRamaswamy Tummala 
1340d1a5c838SRamaswamy Tummala 	ksp->ks_private = pks;
1341d1a5c838SRamaswamy Tummala 	ksp->ks_update = ibtl_kstat_pkeys_update;
1342d1a5c838SRamaswamy Tummala 	ksp->ks_lock = &ibtl_clnt_list_mutex;
1343d1a5c838SRamaswamy Tummala 
1344d1a5c838SRamaswamy Tummala 	/*
1345d1a5c838SRamaswamy Tummala 	 * We just go with the default_kstat_snapshot().
1346d1a5c838SRamaswamy Tummala 	 * So there is no need to set ks_snapshot field.
1347d1a5c838SRamaswamy Tummala 	 */
1348d1a5c838SRamaswamy Tummala 
1349d1a5c838SRamaswamy Tummala 	/* Install the kstat */
1350d1a5c838SRamaswamy Tummala 	kstat_install(ksp);
1351d1a5c838SRamaswamy Tummala }
1352