xref: /onnv-gate/usr/src/uts/common/io/ib/ibtl/ibtl_ibnex.c (revision 13101:da7b13ec3a28)
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
58082SRamaswamy.Tummala@Sun.COM  * Common Development and Distribution License (the "License").
68082SRamaswamy.Tummala@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  */
21*13101SVenki.Rajagopalan@Sun.COM 
220Sstevel@tonic-gate /*
23*13101SVenki.Rajagopalan@Sun.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <sys/systm.h>
278082SRamaswamy.Tummala@Sun.COM #include <sys/sunndi.h>
288082SRamaswamy.Tummala@Sun.COM #include <sys/sunmdi.h>
290Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl.h>
300Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl_ibnex.h>
310Sstevel@tonic-gate 
320Sstevel@tonic-gate /*
330Sstevel@tonic-gate  * ibtl_ibnex.c
340Sstevel@tonic-gate  *    These routines tie the Device Manager into IBTL.
350Sstevel@tonic-gate  *
360Sstevel@tonic-gate  *    ibt_reprobe_dev which can be called by IBTF clients.
370Sstevel@tonic-gate  *    This results in calls to IBnexus callback.
380Sstevel@tonic-gate  */
390Sstevel@tonic-gate 
400Sstevel@tonic-gate /*
410Sstevel@tonic-gate  * Globals.
420Sstevel@tonic-gate  */
430Sstevel@tonic-gate static char		ibtl_ibnex[] = "ibtl_ibnex";
440Sstevel@tonic-gate ibtl_ibnex_callback_t	ibtl_ibnex_callback_routine = NULL;
450Sstevel@tonic-gate 
460Sstevel@tonic-gate /*
470Sstevel@tonic-gate  * Function:
480Sstevel@tonic-gate  *	ibtl_ibnex_get_hca_info
490Sstevel@tonic-gate  * Input:
500Sstevel@tonic-gate  *	hca_guid	- The HCA's node GUID.
510Sstevel@tonic-gate  *	flag		- Tells what to do
520Sstevel@tonic-gate  *			IBTL_IBNEX_LIST_CLNTS_FLAG - Build a NVLIST containing
530Sstevel@tonic-gate  *						client's names, their AP_IDs and
540Sstevel@tonic-gate  *						alternate_HCA information.
550Sstevel@tonic-gate  *						(-x list_clients option)
560Sstevel@tonic-gate  *			IBTL_IBNEX_UNCFG_CLNTS_FLAG - Build a NVLIST containing
570Sstevel@tonic-gate  *						clients' devpaths and their
580Sstevel@tonic-gate  *						AP_IDs. (-x unconfig_clients)
590Sstevel@tonic-gate  *	callback	- Callback function to get ap_id from ib(7d)
600Sstevel@tonic-gate  * Output:
610Sstevel@tonic-gate  *	buffer		- The information is returned in this buffer
620Sstevel@tonic-gate  *      bufsiz		- The size of the information buffer
630Sstevel@tonic-gate  * Returns:
640Sstevel@tonic-gate  *	IBT_SUCCESS/IBT_HCA_INVALID/IBT_INVALID_PARAM
650Sstevel@tonic-gate  * Description:
660Sstevel@tonic-gate  *      For a given HCA node GUID it figures out the registered clients
670Sstevel@tonic-gate  *	(ie. ones who called ibt_open_hca(9f) on this GUID) and creates
680Sstevel@tonic-gate  *	a NVL packed buffer (of client names/ap_ids or devpaths) and returns
690Sstevel@tonic-gate  *	it. If flag is not specified, then an error is returned.
700Sstevel@tonic-gate  */
710Sstevel@tonic-gate ibt_status_t
ibtl_ibnex_get_hca_info(ib_guid_t hca_guid,int flag,char ** buffer,size_t * bufsiz,void (* callback)(dev_info_t *,char **))720Sstevel@tonic-gate ibtl_ibnex_get_hca_info(ib_guid_t hca_guid, int flag, char **buffer,
730Sstevel@tonic-gate     size_t *bufsiz, void (*callback)(dev_info_t *, char **))
740Sstevel@tonic-gate {
750Sstevel@tonic-gate 	char			*node_name;
760Sstevel@tonic-gate 	char			*ret_apid;
770Sstevel@tonic-gate 	nvlist_t		*nvl;
780Sstevel@tonic-gate 	ibtl_hca_t		*ibt_hca;
790Sstevel@tonic-gate 	ibtl_clnt_t		*clntp;
800Sstevel@tonic-gate 	dev_info_t		*child;
810Sstevel@tonic-gate 	dev_info_t		*parent;
820Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;
830Sstevel@tonic-gate 
840Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_ibnex, "ibtl_ibnex_get_hca_info: "
850Sstevel@tonic-gate 	    "GUID  0x%llX, flag = 0x%x", hca_guid, flag);
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 	*buffer = NULL;
880Sstevel@tonic-gate 	*bufsiz = 0;
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 	/* verify that valid "flag" is passed */
910Sstevel@tonic-gate 	if (flag != IBTL_IBNEX_LIST_CLNTS_FLAG &&
920Sstevel@tonic-gate 	    flag != IBTL_IBNEX_UNCFG_CLNTS_FLAG) {
930Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
940Sstevel@tonic-gate 	}
950Sstevel@tonic-gate 
960Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
970Sstevel@tonic-gate 
980Sstevel@tonic-gate 	if ((hca_devp = ibtl_get_hcadevinfo(hca_guid)) == NULL) {
990Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate 		/*
1020Sstevel@tonic-gate 		 * If we are here, then the requested HCA device is not
1030Sstevel@tonic-gate 		 * present. Return the status as Invalid HCA GUID.
1040Sstevel@tonic-gate 		 */
1050Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_ibnex, "ibtl_ibnex_get_hca_info: "
1060Sstevel@tonic-gate 		    "HCA Not Found, Invalid HCA GUID 0x%llX", hca_guid);
1070Sstevel@tonic-gate 		return (IBT_HCA_INVALID);
1080Sstevel@tonic-gate 	}
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	/* Walk the client list */
1110Sstevel@tonic-gate 	ibt_hca = hca_devp->hd_clnt_list;
1120Sstevel@tonic-gate 	(void) nvlist_alloc(&nvl, 0, KM_SLEEP);
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate 	/* Allocate memory for ret_apid, instead of using stack */
1150Sstevel@tonic-gate 	ret_apid = kmem_alloc(IBTL_IBNEX_APID_LEN, KM_SLEEP);
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 	while (ibt_hca != NULL) {
1180Sstevel@tonic-gate 		clntp = ibt_hca->ha_clnt_devp;
1190Sstevel@tonic-gate 		child = clntp->clnt_dip;
1200Sstevel@tonic-gate 		IBTF_DPRINTF_L4(ibtl_ibnex, "ibtl_ibnex_get_hca_info: "
1210Sstevel@tonic-gate 		    "Client = %s", clntp->clnt_modinfop->mi_clnt_name);
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 		if (flag == IBTL_IBNEX_LIST_CLNTS_FLAG) {
1240Sstevel@tonic-gate 			(void) nvlist_add_string(nvl, "Client",
1250Sstevel@tonic-gate 			    clntp->clnt_modinfop->mi_clnt_name);
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate 			/*
1280Sstevel@tonic-gate 			 * Always check, first, if this client exists
1290Sstevel@tonic-gate 			 * under this HCA anymore? If not, continue.
1300Sstevel@tonic-gate 			 */
1310Sstevel@tonic-gate 			if (clntp->clnt_hca_list == NULL) {
1320Sstevel@tonic-gate 				(void) nvlist_add_string(nvl, "Alt_HCA", "no");
1330Sstevel@tonic-gate 				(void) nvlist_add_string(nvl, "ApID", "-");
1340Sstevel@tonic-gate 				ibt_hca = ibt_hca->ha_clnt_link;
1350Sstevel@tonic-gate 				continue;
1360Sstevel@tonic-gate 			}
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 			/* Check if this client has more than one HCAs */
1390Sstevel@tonic-gate 			if (clntp->clnt_hca_list->ha_hca_link == NULL)
1400Sstevel@tonic-gate 				(void) nvlist_add_string(nvl, "Alt_HCA", "no");
1410Sstevel@tonic-gate 			else
1420Sstevel@tonic-gate 				(void) nvlist_add_string(nvl, "Alt_HCA", "yes");
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate 			if (child == NULL) {
1450Sstevel@tonic-gate 				(void) nvlist_add_string(nvl, "ApID", "-");
1460Sstevel@tonic-gate 				ibt_hca = ibt_hca->ha_clnt_link;
1470Sstevel@tonic-gate 				continue;
1480Sstevel@tonic-gate 			}
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 			/*
1510Sstevel@tonic-gate 			 * All IB clients (IOC, VPPA, Port, Pseudo etc.)
1520Sstevel@tonic-gate 			 * need to be looked at. The parent of IOC nodes
1530Sstevel@tonic-gate 			 * is "ib" nexus and node-name is "ioc". "VPPA/Port"s
1540Sstevel@tonic-gate 			 * should have HCA as parent and node-name is "ibport".
1550Sstevel@tonic-gate 			 * HCA validity is checked by looking at parent's "dip"
1560Sstevel@tonic-gate 			 * and the dip saved in the ibtl_hca_devinfo_t.
1570Sstevel@tonic-gate 			 * NOTE: We only want to list this HCA's IB clients.
1580Sstevel@tonic-gate 			 * All others clients are ignored.
1590Sstevel@tonic-gate 			 */
1600Sstevel@tonic-gate 			parent = ddi_get_parent(child);
1610Sstevel@tonic-gate 			if (parent == NULL || /* No parent? */
1620Sstevel@tonic-gate 			    ddi_get_parent_data(child) == NULL) {
1630Sstevel@tonic-gate 				(void) nvlist_add_string(nvl, "ApID", "-");
1640Sstevel@tonic-gate 				ibt_hca = ibt_hca->ha_clnt_link;
1650Sstevel@tonic-gate 				continue;
1660Sstevel@tonic-gate 			}
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 			node_name = ddi_node_name(child);
1690Sstevel@tonic-gate 			if ((strcmp(ddi_node_name(parent), "ib") == 0) ||
1700Sstevel@tonic-gate 			    ((hca_devp->hd_hca_dip == parent) &&
1710Sstevel@tonic-gate 			    (strncmp(node_name, IBNEX_IBPORT_CNAME, 6) == 0))) {
1720Sstevel@tonic-gate 				ASSERT(callback != NULL);
1730Sstevel@tonic-gate 				/*
1740Sstevel@tonic-gate 				 * Callback is invoked to figure out the
1750Sstevel@tonic-gate 				 * ap_id string.
1760Sstevel@tonic-gate 				 */
1770Sstevel@tonic-gate 				callback(child, &ret_apid);
1780Sstevel@tonic-gate 				(void) nvlist_add_string(nvl, "ApID", ret_apid);
1790Sstevel@tonic-gate 			} else {
1800Sstevel@tonic-gate 				(void) nvlist_add_string(nvl, "ApID", "-");
1810Sstevel@tonic-gate 			}
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate 		} else if (flag == IBTL_IBNEX_UNCFG_CLNTS_FLAG) {
1840Sstevel@tonic-gate 			char		path[MAXPATHLEN];
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate 			if (child == NULL) {
1870Sstevel@tonic-gate 				IBTF_DPRINTF_L4(ibtl_ibnex,
1880Sstevel@tonic-gate 				    "ibtl_ibnex_get_hca_info: No dip exists");
1890Sstevel@tonic-gate 				ibt_hca = ibt_hca->ha_clnt_link;
1900Sstevel@tonic-gate 				continue;
1910Sstevel@tonic-gate 			}
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 			/*
1940Sstevel@tonic-gate 			 * if the child has a alternate HCA then skip it
1950Sstevel@tonic-gate 			 */
1960Sstevel@tonic-gate 			if (clntp->clnt_hca_list->ha_hca_link) {
1970Sstevel@tonic-gate 				IBTF_DPRINTF_L4(ibtl_ibnex,
1980Sstevel@tonic-gate 				    "ibtl_ibnex_get_hca_info: Alt HCA exists");
1990Sstevel@tonic-gate 				ibt_hca = ibt_hca->ha_clnt_link;
2000Sstevel@tonic-gate 				continue;
2010Sstevel@tonic-gate 			}
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 			/*
2040Sstevel@tonic-gate 			 * See earlier comments on how to check if a client
2050Sstevel@tonic-gate 			 * is IOC, VPPA, Port or a Pseudo node.
2060Sstevel@tonic-gate 			 */
2070Sstevel@tonic-gate 			parent = ddi_get_parent(child);
2080Sstevel@tonic-gate 			if (parent == NULL || /* No parent? */
2090Sstevel@tonic-gate 			    ddi_get_parent_data(child) == NULL) {
2100Sstevel@tonic-gate 				IBTF_DPRINTF_L4(ibtl_ibnex,
2110Sstevel@tonic-gate 				    "ibtl_ibnex_get_hca_info: no parent");
2120Sstevel@tonic-gate 				ibt_hca = ibt_hca->ha_clnt_link;
2130Sstevel@tonic-gate 				continue;
2140Sstevel@tonic-gate 			}
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate 			node_name = ddi_node_name(child);
2170Sstevel@tonic-gate 			if ((strcmp(ddi_node_name(parent), "ib") == 0) ||
2180Sstevel@tonic-gate 			    ((hca_devp->hd_hca_dip == parent) &&
2190Sstevel@tonic-gate 			    (strncmp(node_name, IBNEX_IBPORT_CNAME, 6) == 0))) {
2200Sstevel@tonic-gate 				ASSERT(callback != NULL);
2210Sstevel@tonic-gate 				/*
2220Sstevel@tonic-gate 				 * Callback is invoked to figure out the
2230Sstevel@tonic-gate 				 * ap_id string.
2240Sstevel@tonic-gate 				 */
2250Sstevel@tonic-gate 				callback(child, &ret_apid);
2260Sstevel@tonic-gate 				(void) nvlist_add_string(nvl, "ApID", ret_apid);
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 				/*
2290Sstevel@tonic-gate 				 * ddi_pathname() doesn't supply /devices,
2300Sstevel@tonic-gate 				 * so we do
2310Sstevel@tonic-gate 				 */
2320Sstevel@tonic-gate 				(void) strcpy(path, "/devices");
2330Sstevel@tonic-gate 				(void) ddi_pathname(child, path + strlen(path));
2340Sstevel@tonic-gate 				IBTF_DPRINTF_L4(ibtl_ibnex,
2350Sstevel@tonic-gate 				    "ibtl_ibnex_get_hca_info: "
2360Sstevel@tonic-gate 				    "device path = %s", path);
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 				if (nvlist_add_string(nvl, "devpath", path)) {
2390Sstevel@tonic-gate 					IBTF_DPRINTF_L2(ibtl_ibnex,
2400Sstevel@tonic-gate 					    "ibtl_ibnex_get_hca_info: "
2410Sstevel@tonic-gate 					    "failed to fill in path %s", path);
2420Sstevel@tonic-gate 					mutex_exit(&ibtl_clnt_list_mutex);
2430Sstevel@tonic-gate 					nvlist_free(nvl);
2440Sstevel@tonic-gate 					kmem_free(ret_apid,
2450Sstevel@tonic-gate 					    IBTL_IBNEX_APID_LEN);
2460Sstevel@tonic-gate 					return (ibt_get_module_failure(
2470Sstevel@tonic-gate 					    IBT_FAILURE_IBTL, 0));
2480Sstevel@tonic-gate 				}
2490Sstevel@tonic-gate 			} /* end of if */
2500Sstevel@tonic-gate 		} /* end of while */
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 		ibt_hca = ibt_hca->ha_clnt_link;
2530Sstevel@tonic-gate 	} /* End of while */
2540Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 	kmem_free(ret_apid, IBTL_IBNEX_APID_LEN);
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	/* Pack all data into "buffer" */
2590Sstevel@tonic-gate 	if (nvlist_pack(nvl, buffer, bufsiz, NV_ENCODE_NATIVE, KM_SLEEP)) {
2600Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_ibnex, "ibtl_ibnex_get_hca_info: "
2610Sstevel@tonic-gate 		    "nvlist_pack failed");
2620Sstevel@tonic-gate 		nvlist_free(nvl);
2630Sstevel@tonic-gate 		return (ibt_get_module_failure(IBT_FAILURE_IBTL, 0));
2640Sstevel@tonic-gate 	}
2650Sstevel@tonic-gate 
2668082SRamaswamy.Tummala@Sun.COM 	IBTF_DPRINTF_L4(ibtl_ibnex, "ibtl_ibnex_get_hca_info: size = %x",
2678082SRamaswamy.Tummala@Sun.COM 	    *bufsiz);
2680Sstevel@tonic-gate 	nvlist_free(nvl);
2690Sstevel@tonic-gate 	return (IBT_SUCCESS);
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate /*
2740Sstevel@tonic-gate  * Function:
2750Sstevel@tonic-gate  *      ibtl_ibnex_register_callback()
2760Sstevel@tonic-gate  * Input:
2770Sstevel@tonic-gate  *	ibnex_cb	- IB nexus driver callback routine
2780Sstevel@tonic-gate  * Output:
2790Sstevel@tonic-gate  *      none
2800Sstevel@tonic-gate  * Returns:
2810Sstevel@tonic-gate  *      none
2820Sstevel@tonic-gate  * Description:
2830Sstevel@tonic-gate  *     	Register a callback routine for IB nexus driver
2840Sstevel@tonic-gate  */
2850Sstevel@tonic-gate void
ibtl_ibnex_register_callback(ibtl_ibnex_callback_t ibnex_cb)2860Sstevel@tonic-gate ibtl_ibnex_register_callback(ibtl_ibnex_callback_t ibnex_cb)
2870Sstevel@tonic-gate {
2880Sstevel@tonic-gate 	IBTF_DPRINTF_L5(ibtl_ibnex, "ibtl_ibnex_register_callback:");
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
2910Sstevel@tonic-gate 	ibtl_ibnex_callback_routine = ibnex_cb;
2920Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
2930Sstevel@tonic-gate }
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate /*
2960Sstevel@tonic-gate  * Function:
2970Sstevel@tonic-gate  *      ibtl_ibnex_unregister_callback()
2980Sstevel@tonic-gate  * Input:
2990Sstevel@tonic-gate  *      none
3000Sstevel@tonic-gate  * Output:
3010Sstevel@tonic-gate  *      none
3020Sstevel@tonic-gate  * Returns:
3030Sstevel@tonic-gate  *      none
3040Sstevel@tonic-gate  * Description:
3050Sstevel@tonic-gate  *     	Un-register a callback routine for IB nexus driver
3060Sstevel@tonic-gate  */
3070Sstevel@tonic-gate void
ibtl_ibnex_unregister_callback()3080Sstevel@tonic-gate ibtl_ibnex_unregister_callback()
3090Sstevel@tonic-gate {
3100Sstevel@tonic-gate 	IBTF_DPRINTF_L5(ibtl_ibnex, "ibtl_ibnex_unregister_callback: ibnex cb");
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
3130Sstevel@tonic-gate 	ibtl_ibnex_callback_routine = NULL;
3140Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate /*
3190Sstevel@tonic-gate  * Function:
3200Sstevel@tonic-gate  *	ibtl_ibnex_hcadip2guid
3210Sstevel@tonic-gate  * Input:
3220Sstevel@tonic-gate  *	dev_info_t	- The "dip" of this HCA
3230Sstevel@tonic-gate  * Output:
3240Sstevel@tonic-gate  *	hca_guid	- The HCA's node GUID.
3250Sstevel@tonic-gate  * Returns:
3260Sstevel@tonic-gate  *	"HCA GUID" on SUCCESS, NULL on FAILURE
3270Sstevel@tonic-gate  * Description:
3280Sstevel@tonic-gate  *      For a given HCA node GUID it figures out the HCA GUID
3290Sstevel@tonic-gate  *	and returns it. If not found, NULL is returned.
3300Sstevel@tonic-gate  */
3310Sstevel@tonic-gate ib_guid_t
ibtl_ibnex_hcadip2guid(dev_info_t * hca_dip)3320Sstevel@tonic-gate ibtl_ibnex_hcadip2guid(dev_info_t *hca_dip)
3330Sstevel@tonic-gate {
3340Sstevel@tonic-gate 	ib_guid_t		hca_guid = 0LL;
3350Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
3380Sstevel@tonic-gate 	hca_devp = ibtl_hca_list;
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 	while (hca_devp) {
3410Sstevel@tonic-gate 		if (hca_devp->hd_hca_dip == hca_dip) {
3420Sstevel@tonic-gate 			hca_guid = hca_devp->hd_hca_attr->hca_node_guid;
3430Sstevel@tonic-gate 			break;
3440Sstevel@tonic-gate 		}
3450Sstevel@tonic-gate 		hca_devp = hca_devp->hd_hca_dev_link;
3460Sstevel@tonic-gate 	}
3470Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
3480Sstevel@tonic-gate 	IBTF_DPRINTF_L4(ibtl_ibnex, "ibtl_ibnex_hcadip_guid: hca_guid 0x%llX",
3490Sstevel@tonic-gate 	    hca_guid);
3500Sstevel@tonic-gate 	return (hca_guid);
3510Sstevel@tonic-gate }
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate /*
3550Sstevel@tonic-gate  * Function:
3560Sstevel@tonic-gate  *	ibtl_ibnex_hcaguid2dip
3570Sstevel@tonic-gate  * Input:
3580Sstevel@tonic-gate  *	hca_guid	- The HCA's node GUID.
3590Sstevel@tonic-gate  * Output:
3600Sstevel@tonic-gate  *	dev_info_t	- The "dip" of this HCA
3610Sstevel@tonic-gate  * Returns:
3620Sstevel@tonic-gate  *	"dip" on SUCCESS, NULL on FAILURE
3630Sstevel@tonic-gate  * Description:
3640Sstevel@tonic-gate  *      For a given HCA node GUID it figures out the "dip"
3650Sstevel@tonic-gate  *	and returns it. If not found, NULL is returned.
3660Sstevel@tonic-gate  */
3670Sstevel@tonic-gate dev_info_t *
ibtl_ibnex_hcaguid2dip(ib_guid_t hca_guid)3680Sstevel@tonic-gate ibtl_ibnex_hcaguid2dip(ib_guid_t hca_guid)
3690Sstevel@tonic-gate {
3700Sstevel@tonic-gate 	dev_info_t		*dip = NULL;
3710Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;
3720Sstevel@tonic-gate 
3730Sstevel@tonic-gate 	IBTF_DPRINTF_L4(ibtl_ibnex, "ibtl_ibnex_hcaguid2dip:");
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
3760Sstevel@tonic-gate 	hca_devp = ibtl_hca_list;
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	while (hca_devp) {
3790Sstevel@tonic-gate 		if (hca_devp->hd_hca_attr->hca_node_guid == hca_guid) {
3800Sstevel@tonic-gate 			dip = hca_devp->hd_hca_dip;
3810Sstevel@tonic-gate 			break;
3820Sstevel@tonic-gate 		}
3830Sstevel@tonic-gate 		hca_devp = hca_devp->hd_hca_dev_link;
3840Sstevel@tonic-gate 	}
3850Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
3860Sstevel@tonic-gate 	return (dip);
3870Sstevel@tonic-gate }
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate /*
3910Sstevel@tonic-gate  * Function:
3920Sstevel@tonic-gate  *	ibtl_ibnex_get_hca_verbose_data
3930Sstevel@tonic-gate  * Input:
3940Sstevel@tonic-gate  *	hca_guid	- The HCA's node GUID.
3950Sstevel@tonic-gate  * Output:
3960Sstevel@tonic-gate  *	buffer		- The information is returned in this buffer
3970Sstevel@tonic-gate  *      bufsiz		- The size of the information buffer
3980Sstevel@tonic-gate  * Returns:
3990Sstevel@tonic-gate  *	IBT_SUCCESS/IBT_HCA_INVALID
4000Sstevel@tonic-gate  * Description:
4010Sstevel@tonic-gate  *      For a given HCA node GUID it figures out the verbose listing display.
4020Sstevel@tonic-gate  */
4030Sstevel@tonic-gate ibt_status_t
ibtl_ibnex_get_hca_verbose_data(ib_guid_t hca_guid,char ** buffer,size_t * bufsiz)4040Sstevel@tonic-gate ibtl_ibnex_get_hca_verbose_data(ib_guid_t hca_guid, char **buffer,
4050Sstevel@tonic-gate     size_t *bufsiz)
4060Sstevel@tonic-gate {
4070Sstevel@tonic-gate 	char			path[IBTL_IBNEX_STR_LEN];
4080Sstevel@tonic-gate 	char			tmp[MAXPATHLEN];
4090Sstevel@tonic-gate 	uint_t			ii;
4100Sstevel@tonic-gate 	ibt_hca_portinfo_t	*pinfop;
4110Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_ibnex, "ibtl_ibnex_get_hca_verbose_data: "
4140Sstevel@tonic-gate 	    "HCA GUID 0x%llX", hca_guid);
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 	*buffer = NULL;
4170Sstevel@tonic-gate 	*bufsiz = 0;
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
4200Sstevel@tonic-gate 	if ((hca_devp = ibtl_get_hcadevinfo(hca_guid)) == NULL) {
4210Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 		/*
4240Sstevel@tonic-gate 		 * If we are here, then the requested HCA device is not
4250Sstevel@tonic-gate 		 * present. Return the status as Invalid HCA GUID.
4260Sstevel@tonic-gate 		 */
4270Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_ibnex, "ibtl_ibnex_get_hca_verbose_data: "
4280Sstevel@tonic-gate 		    "HCA Not Found, Invalid HCA GUID");
4290Sstevel@tonic-gate 		return (IBT_HCA_INVALID);
4300Sstevel@tonic-gate 	}
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 	(void) snprintf(tmp, MAXPATHLEN, "VID: 0x%x, PID: 0x%x, #ports: 0x%x",
4330Sstevel@tonic-gate 	    hca_devp->hd_hca_attr->hca_vendor_id,
4340Sstevel@tonic-gate 	    hca_devp->hd_hca_attr->hca_device_id,
4350Sstevel@tonic-gate 	    hca_devp->hd_hca_attr->hca_nports);
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate 	pinfop = hca_devp->hd_portinfop;
4380Sstevel@tonic-gate 	for (ii = 0; ii < hca_devp->hd_hca_attr->hca_nports; ii++) {
4390Sstevel@tonic-gate 		(void) snprintf(path, IBTL_IBNEX_STR_LEN,
4400Sstevel@tonic-gate 		    ", port%d GUID: 0x%llX", ii + 1,
4410Sstevel@tonic-gate 		    (longlong_t)pinfop[ii].p_sgid_tbl->gid_guid);
4420Sstevel@tonic-gate 		(void) strcat(tmp, path);
4430Sstevel@tonic-gate 	}
4440Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate 	*bufsiz =  strlen(tmp);
4470Sstevel@tonic-gate 	*buffer = kmem_alloc(*bufsiz, KM_SLEEP);
4480Sstevel@tonic-gate 	(void) strncpy(*buffer, tmp, *bufsiz);
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	IBTF_DPRINTF_L4(ibtl_ibnex, "ibtl_ibnex_get_hca_verbose_data: "
4510Sstevel@tonic-gate 	    "data = %s, size = 0x%x", *buffer, *bufsiz);
4520Sstevel@tonic-gate 	return (IBT_SUCCESS);
4530Sstevel@tonic-gate }
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate /*
4560Sstevel@tonic-gate  * Function:
4570Sstevel@tonic-gate  *      ibt_reprobe_dev()
4580Sstevel@tonic-gate  * Input:
4590Sstevel@tonic-gate  *      dev_info_t	*dip
4600Sstevel@tonic-gate  * Output:
4610Sstevel@tonic-gate  *      none
4620Sstevel@tonic-gate  * Returns:
4630Sstevel@tonic-gate  *      Return value from IBnexus callback handler
4640Sstevel@tonic-gate  *		IBT_ILLEGAL_OP if IBnexus callback is not installed.
4650Sstevel@tonic-gate  * Description:
4660Sstevel@tonic-gate  *     	This function passes the IBTF client's "reprobe device
4670Sstevel@tonic-gate  *		properties" request to IBnexus. See ibt_reprobe_dev(9f)
4680Sstevel@tonic-gate  *		for details.
4690Sstevel@tonic-gate  */
4700Sstevel@tonic-gate ibt_status_t
ibt_reprobe_dev(dev_info_t * dip)4710Sstevel@tonic-gate ibt_reprobe_dev(dev_info_t *dip)
4720Sstevel@tonic-gate {
4730Sstevel@tonic-gate 	ibt_status_t		rv;
4740Sstevel@tonic-gate 	ibtl_ibnex_cb_args_t	cb_args;
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate 	if (dip == NULL)
4770Sstevel@tonic-gate 		return (IBT_NOT_SUPPORTED);
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate 	/*
4800Sstevel@tonic-gate 	 * Restricting the reprobe request to the children of
4810Sstevel@tonic-gate 	 * ibnexus. Note the IB_CONF_UPDATE_EVENT DDI event can
4820Sstevel@tonic-gate 	 * be subscribed by any device on the IBnexus device tree.
4830Sstevel@tonic-gate 	 */
4840Sstevel@tonic-gate 	if (strcmp(ddi_node_name(ddi_get_parent(dip)), "ib") != 0)
4850Sstevel@tonic-gate 		return (IBT_NOT_SUPPORTED);
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate 	/* Reprobe for IOC nodes only */
4880Sstevel@tonic-gate 	if (strncmp(ddi_node_name(dip), IBNEX_IBPORT_CNAME, 6) == 0)
4890Sstevel@tonic-gate 		return (IBT_NOT_SUPPORTED);
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 	cb_args.cb_flag = IBTL_IBNEX_REPROBE_DEV_REQ;
4920Sstevel@tonic-gate 	cb_args.cb_dip = dip;
4930Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
4940Sstevel@tonic-gate 	if (ibtl_ibnex_callback_routine) {
4950Sstevel@tonic-gate 		rv = (*ibtl_ibnex_callback_routine)(&cb_args);
4960Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
4970Sstevel@tonic-gate 		return (rv);
4980Sstevel@tonic-gate 	}
4990Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 	/* Should -not- come here */
5020Sstevel@tonic-gate 	IBTF_DPRINTF_L2("ibtl", "ibt_reprobe_dev: ibnex not registered!!");
5030Sstevel@tonic-gate 	return (IBT_ILLEGAL_OP);
5040Sstevel@tonic-gate }
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate /*
5080Sstevel@tonic-gate  * Function:
5090Sstevel@tonic-gate  *	ibtl_ibnex_valid_hca_parent
5100Sstevel@tonic-gate  * Input:
5110Sstevel@tonic-gate  *	pdip		- The parent dip from client's child dev_info_t
5120Sstevel@tonic-gate  * Output:
5130Sstevel@tonic-gate  *	NONE
5140Sstevel@tonic-gate  * Returns:
5150Sstevel@tonic-gate  *	IBT_SUCCESS/IBT_NO_HCAS_AVAILABLE
5160Sstevel@tonic-gate  * Description:
5170Sstevel@tonic-gate  *	For a given pdip, of Port/VPPA devices, match it against all the
5180Sstevel@tonic-gate  *	registered HCAs's dip.  If match found return IBT_SUCCESS,
5190Sstevel@tonic-gate  *	else IBT_NO_HCAS_AVAILABLE.
520*13101SVenki.Rajagopalan@Sun.COM  *
5210Sstevel@tonic-gate  *	For IOC/Pseudo devices check if the given pdip is that of
522*13101SVenki.Rajagopalan@Sun.COM  *	the ib(7d) nexus or that of the eoib(7d) nexus. If yes
523*13101SVenki.Rajagopalan@Sun.COM  *	return IBT_SUCCESS, else IBT_NO_HCAS_AVAILABLE.
5240Sstevel@tonic-gate  */
5250Sstevel@tonic-gate ibt_status_t
ibtl_ibnex_valid_hca_parent(dev_info_t * pdip)5260Sstevel@tonic-gate ibtl_ibnex_valid_hca_parent(dev_info_t *pdip)
5270Sstevel@tonic-gate {
5280Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate 	IBTF_DPRINTF_L4(ibtl_ibnex, "ibtl_ibnex_valid_hca_parent: pdip %p",
5310Sstevel@tonic-gate 	    pdip);
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate 	/* For Pseudo devices and IOCs */
534*13101SVenki.Rajagopalan@Sun.COM 	if (strncmp(ddi_node_name(pdip), "ib", 2) == 0 ||
535*13101SVenki.Rajagopalan@Sun.COM 	    strncmp(ddi_node_name(pdip), "eibnx", 5) == 0) {
5360Sstevel@tonic-gate 		return (IBT_SUCCESS);
537*13101SVenki.Rajagopalan@Sun.COM 	} else {
5380Sstevel@tonic-gate 		/* For Port devices and VPPAs */
5390Sstevel@tonic-gate 		mutex_enter(&ibtl_clnt_list_mutex);
5400Sstevel@tonic-gate 		hca_devp = ibtl_hca_list;
5410Sstevel@tonic-gate 		while (hca_devp) {
5420Sstevel@tonic-gate 			if (hca_devp->hd_hca_dip == pdip) {
5430Sstevel@tonic-gate 				mutex_exit(&ibtl_clnt_list_mutex);
5440Sstevel@tonic-gate 				return (IBT_SUCCESS);
5450Sstevel@tonic-gate 			}
5460Sstevel@tonic-gate 			hca_devp = hca_devp->hd_hca_dev_link;
5470Sstevel@tonic-gate 		}
5480Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
5490Sstevel@tonic-gate 		return (IBT_NO_HCAS_AVAILABLE);
5500Sstevel@tonic-gate 	}
5510Sstevel@tonic-gate }
5528082SRamaswamy.Tummala@Sun.COM 
5538082SRamaswamy.Tummala@Sun.COM /*
5548082SRamaswamy.Tummala@Sun.COM  * Function:
5558082SRamaswamy.Tummala@Sun.COM  *	ibtl_ibnex_phci_register
5568082SRamaswamy.Tummala@Sun.COM  * Input:
5578082SRamaswamy.Tummala@Sun.COM  *	hca_dip		- The HCA dip
5588082SRamaswamy.Tummala@Sun.COM  * Output:
5598082SRamaswamy.Tummala@Sun.COM  *	NONE
5608082SRamaswamy.Tummala@Sun.COM  * Returns:
5618082SRamaswamy.Tummala@Sun.COM  *	IBT_SUCCESS/IBT_FAILURE
5628082SRamaswamy.Tummala@Sun.COM  * Description:
5638082SRamaswamy.Tummala@Sun.COM  * 	Register the HCA dip as the MPxIO PCHI.
5648082SRamaswamy.Tummala@Sun.COM  */
5658082SRamaswamy.Tummala@Sun.COM ibt_status_t
ibtl_ibnex_phci_register(dev_info_t * hca_dip)5668082SRamaswamy.Tummala@Sun.COM ibtl_ibnex_phci_register(dev_info_t *hca_dip)
5678082SRamaswamy.Tummala@Sun.COM {
5688082SRamaswamy.Tummala@Sun.COM 	/* Register the with MPxIO as PHCI */
5698082SRamaswamy.Tummala@Sun.COM 	if (mdi_phci_register(MDI_HCI_CLASS_IB, hca_dip, 0) !=
5708082SRamaswamy.Tummala@Sun.COM 	    MDI_SUCCESS) {
5718082SRamaswamy.Tummala@Sun.COM 		return (IBT_FAILURE);
5728082SRamaswamy.Tummala@Sun.COM 	}
5738082SRamaswamy.Tummala@Sun.COM 	return (IBT_SUCCESS);
5748082SRamaswamy.Tummala@Sun.COM }
5758082SRamaswamy.Tummala@Sun.COM 
5768082SRamaswamy.Tummala@Sun.COM /*
5778082SRamaswamy.Tummala@Sun.COM  * Function:
5788082SRamaswamy.Tummala@Sun.COM  *	ibtl_ibnex_phci_unregister
5798082SRamaswamy.Tummala@Sun.COM  * Input:
5808082SRamaswamy.Tummala@Sun.COM  *	hca_dip		- The HCA dip
5818082SRamaswamy.Tummala@Sun.COM  * Output:
5828082SRamaswamy.Tummala@Sun.COM  *	NONE
5838082SRamaswamy.Tummala@Sun.COM  * Returns:
5848082SRamaswamy.Tummala@Sun.COM  *	IBT_SUCCESS/IBT_FAILURE
5858082SRamaswamy.Tummala@Sun.COM  * Description:
5868082SRamaswamy.Tummala@Sun.COM  * 	Free up any pending MPxIO Pathinfos and unregister the HCA dip as the
5878082SRamaswamy.Tummala@Sun.COM  * 	MPxIO PCHI.
5888082SRamaswamy.Tummala@Sun.COM  */
5898082SRamaswamy.Tummala@Sun.COM ibt_status_t
ibtl_ibnex_phci_unregister(dev_info_t * hca_dip)5908082SRamaswamy.Tummala@Sun.COM ibtl_ibnex_phci_unregister(dev_info_t *hca_dip)
5918082SRamaswamy.Tummala@Sun.COM {
5928082SRamaswamy.Tummala@Sun.COM 	mdi_pathinfo_t *pip = NULL;
5938082SRamaswamy.Tummala@Sun.COM 	dev_info_t *vdip = 0;
5948082SRamaswamy.Tummala@Sun.COM 	int circ = 0, circ1 = 0;
5958082SRamaswamy.Tummala@Sun.COM 
5968082SRamaswamy.Tummala@Sun.COM 	/*
5978082SRamaswamy.Tummala@Sun.COM 	 * Should free all the Pathinfos associated with the HCA pdip before
5988082SRamaswamy.Tummala@Sun.COM 	 * unregistering the PHCI.
5998082SRamaswamy.Tummala@Sun.COM 	 *
6008082SRamaswamy.Tummala@Sun.COM 	 * mdi_pi_free will call ib_vhci_pi_uninit() callbackfor each PI where
6018082SRamaswamy.Tummala@Sun.COM 	 * the ibnex internal datastructures (ibnex_node_data) will have to be
6028082SRamaswamy.Tummala@Sun.COM 	 * cleaned up if needed.
6038082SRamaswamy.Tummala@Sun.COM 	 */
6048082SRamaswamy.Tummala@Sun.COM 	vdip = mdi_devi_get_vdip(hca_dip);
6058082SRamaswamy.Tummala@Sun.COM 	ndi_devi_enter(vdip, &circ1);
6068082SRamaswamy.Tummala@Sun.COM 	ndi_devi_enter(hca_dip, &circ);
6078082SRamaswamy.Tummala@Sun.COM 	while (pip = mdi_get_next_client_path(hca_dip, NULL)) {
6088082SRamaswamy.Tummala@Sun.COM 		if (mdi_pi_free(pip, 0) == MDI_SUCCESS) {
6098082SRamaswamy.Tummala@Sun.COM 			continue;
6108082SRamaswamy.Tummala@Sun.COM 		}
6118082SRamaswamy.Tummala@Sun.COM 		ndi_devi_exit(hca_dip, circ);
6128082SRamaswamy.Tummala@Sun.COM 		ndi_devi_exit(vdip, circ1);
6138082SRamaswamy.Tummala@Sun.COM 		IBTF_DPRINTF_L1(ibtl_ibnex, "ibtl_ibnex_phci_unregister: "
6148082SRamaswamy.Tummala@Sun.COM 		    "mdi_pi_free failed");
6158082SRamaswamy.Tummala@Sun.COM 		return (IBT_FAILURE);
6168082SRamaswamy.Tummala@Sun.COM 	}
6178082SRamaswamy.Tummala@Sun.COM 	ndi_devi_exit(hca_dip, circ);
6188082SRamaswamy.Tummala@Sun.COM 	ndi_devi_exit(vdip, circ1);
6198082SRamaswamy.Tummala@Sun.COM 
6208082SRamaswamy.Tummala@Sun.COM 	if (mdi_phci_unregister(hca_dip, 0) != MDI_SUCCESS) {
6218082SRamaswamy.Tummala@Sun.COM 		IBTF_DPRINTF_L1(ibtl_ibnex, "ibtl_ibnex_phci_unregister: PHCI "
6228082SRamaswamy.Tummala@Sun.COM 		    "unregister failed");
6238082SRamaswamy.Tummala@Sun.COM 		return (IBT_FAILURE);
6248082SRamaswamy.Tummala@Sun.COM 	}
6258082SRamaswamy.Tummala@Sun.COM 	return (IBT_SUCCESS);
6268082SRamaswamy.Tummala@Sun.COM }
6279879SRamaswamy.Tummala@Sun.COM 
6289879SRamaswamy.Tummala@Sun.COM /*
6299879SRamaswamy.Tummala@Sun.COM  * Function:
6309879SRamaswamy.Tummala@Sun.COM  *	ibtl_ibnex_query_hca_byguid
6319879SRamaswamy.Tummala@Sun.COM  * Input:
6329879SRamaswamy.Tummala@Sun.COM  *	hca_guid	- The HCA's node GUID.
6339879SRamaswamy.Tummala@Sun.COM  *	driver_name_size- size of the caller allocated driver_name buffer
6349879SRamaswamy.Tummala@Sun.COM  * Output:
6359879SRamaswamy.Tummala@Sun.COM  *	hca_attrs	- caller allocated buffer which will contain
6369879SRamaswamy.Tummala@Sun.COM  *			  HCA attributes upon success
6379879SRamaswamy.Tummala@Sun.COM  *	driver_name	- caller allocated buffer which will contain
6389879SRamaswamy.Tummala@Sun.COM  *			  HCA driver name upon success
6399879SRamaswamy.Tummala@Sun.COM  *	driver_instance - HCA driver instance
64010094SRamaswamy.Tummala@Sun.COM  *	hca_device_path	- caller allocated buffer of size MAXPATHLEN which
64110094SRamaswamy.Tummala@Sun.COM  *			  will contain hca device path upon success.
6429879SRamaswamy.Tummala@Sun.COM  * Returns:
6439879SRamaswamy.Tummala@Sun.COM  *	IBT_SUCCESS/IBT_FAILURE
6449879SRamaswamy.Tummala@Sun.COM  * Description:
6459879SRamaswamy.Tummala@Sun.COM  *	Get the HCA attributes, driver name and instance number of the
6469879SRamaswamy.Tummala@Sun.COM  *	specified HCA.
6479879SRamaswamy.Tummala@Sun.COM  */
6489879SRamaswamy.Tummala@Sun.COM ibt_status_t
ibtl_ibnex_query_hca_byguid(ib_guid_t hca_guid,ibt_hca_attr_t * hca_attrs,char * driver_name,size_t driver_name_size,int * driver_instance,char * hca_device_path)6499879SRamaswamy.Tummala@Sun.COM ibtl_ibnex_query_hca_byguid(ib_guid_t hca_guid, ibt_hca_attr_t *hca_attrs,
65010094SRamaswamy.Tummala@Sun.COM     char *driver_name, size_t driver_name_size, int *driver_instance,
65110094SRamaswamy.Tummala@Sun.COM     char *hca_device_path)
6529879SRamaswamy.Tummala@Sun.COM {
6539879SRamaswamy.Tummala@Sun.COM 	ibtl_hca_devinfo_t	*hca_devp;
6549879SRamaswamy.Tummala@Sun.COM 
6559879SRamaswamy.Tummala@Sun.COM 	IBTF_DPRINTF_L4(ibtl_ibnex, "ibtl_ibnex_query_hca_byguid("
6569879SRamaswamy.Tummala@Sun.COM 	    "hca_guid = 0x%llx, hca_attrs = 0x%p, driver_name = 0x%p, "
6579879SRamaswamy.Tummala@Sun.COM 	    "driver_name_size = 0x%d, driver_instancep = 0x%p)", hca_guid,
6589879SRamaswamy.Tummala@Sun.COM 	    hca_attrs, driver_name, (int)driver_name_size, driver_instance);
6599879SRamaswamy.Tummala@Sun.COM 
6609879SRamaswamy.Tummala@Sun.COM 	mutex_enter(&ibtl_clnt_list_mutex);
6619879SRamaswamy.Tummala@Sun.COM 
6629879SRamaswamy.Tummala@Sun.COM 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
6639879SRamaswamy.Tummala@Sun.COM 	if (hca_devp == NULL) {
6649879SRamaswamy.Tummala@Sun.COM 		mutex_exit(&ibtl_clnt_list_mutex);
6659879SRamaswamy.Tummala@Sun.COM 		return (IBT_HCA_INVALID);
6669879SRamaswamy.Tummala@Sun.COM 	}
6679879SRamaswamy.Tummala@Sun.COM 
6689879SRamaswamy.Tummala@Sun.COM 	if (strlcpy(driver_name,
6699879SRamaswamy.Tummala@Sun.COM 	    ddi_driver_name(hca_devp->hd_hca_dip), driver_name_size) >=
6709879SRamaswamy.Tummala@Sun.COM 	    driver_name_size) {
6719879SRamaswamy.Tummala@Sun.COM 		mutex_exit(&ibtl_clnt_list_mutex);
6729879SRamaswamy.Tummala@Sun.COM 		return (IBT_INSUFF_KERNEL_RESOURCE);
6739879SRamaswamy.Tummala@Sun.COM 	}
6749879SRamaswamy.Tummala@Sun.COM 
67510094SRamaswamy.Tummala@Sun.COM 	(void) ddi_pathname(hca_devp->hd_hca_dip, hca_device_path);
6769879SRamaswamy.Tummala@Sun.COM 	*driver_instance = ddi_get_instance(hca_devp->hd_hca_dip);
6779879SRamaswamy.Tummala@Sun.COM 	bcopy(hca_devp->hd_hca_attr, hca_attrs, sizeof (ibt_hca_attr_t));
6789879SRamaswamy.Tummala@Sun.COM 
6799879SRamaswamy.Tummala@Sun.COM 	mutex_exit(&ibtl_clnt_list_mutex);
6809879SRamaswamy.Tummala@Sun.COM 	return (IBT_SUCCESS);
6819879SRamaswamy.Tummala@Sun.COM }
682