xref: /onnv-gate/usr/src/uts/common/io/ib/ibtl/ibtl_hca.c (revision 12574:0d8f6d488501)
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
53826Shiremath  * Common Development and Distribution License (the "License").
63826Shiremath  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*12574SWilliam.Taylor@Oracle.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate /*
260Sstevel@tonic-gate  * ibtl_hca.c
270Sstevel@tonic-gate  *
280Sstevel@tonic-gate  * This file contains Transport API functions related to
290Sstevel@tonic-gate  * Host Channel Adapter (HCA) Verbs.
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl.h>
330Sstevel@tonic-gate 
340Sstevel@tonic-gate static char ibtf_hca[] = "ibtl_hca";
350Sstevel@tonic-gate 
360Sstevel@tonic-gate /* Prototype declarations. */
370Sstevel@tonic-gate static ibt_status_t ibtl_query_hca_ports(ibtl_hca_devinfo_t *hca_devp,
380Sstevel@tonic-gate     uint8_t port, ibt_hca_portinfo_t **port_info_p, uint_t *ports_p,
390Sstevel@tonic-gate     uint_t *size_p, int use_cache);
400Sstevel@tonic-gate 
410Sstevel@tonic-gate /*
420Sstevel@tonic-gate  * Function:
430Sstevel@tonic-gate  *      ibt_open_hca
440Sstevel@tonic-gate  * Input:
450Sstevel@tonic-gate  *      ibt_hdl    - IBT Client Handle
460Sstevel@tonic-gate  *      hca_guid   - HCA's node GUID.
470Sstevel@tonic-gate  * Output:
480Sstevel@tonic-gate  *      hca_hdl_p  - IBT HCA Handle.
490Sstevel@tonic-gate  * Returns:
500Sstevel@tonic-gate  *      IBT_SUCCESS
510Sstevel@tonic-gate  *      IBT_HCA_IN_USE
520Sstevel@tonic-gate  *      IBT_HCA_INVALID
530Sstevel@tonic-gate  * Description:
540Sstevel@tonic-gate  *      Open a HCA. HCA can only be opened/closed once. This routine allocates
550Sstevel@tonic-gate  *      and returns a unique IBT Client HCA handle. Clients passes this
560Sstevel@tonic-gate  *      handle on its subsequent references to this device. Once opened by a
570Sstevel@tonic-gate  *      client, a specific HCA cannot be opened again until after it is closed.
580Sstevel@tonic-gate  *      The IBT_HCA_IN_USE error is returned if client tries to open multiple
590Sstevel@tonic-gate  *      times. In this case, previously allocated IBT HCA handle is returned to
600Sstevel@tonic-gate  *      the client. Opening the HCA prepares the HCA for use by the client.
610Sstevel@tonic-gate  */
620Sstevel@tonic-gate ibt_status_t
ibt_open_hca(ibt_clnt_hdl_t ibt_hdl,ib_guid_t hca_guid,ibt_hca_hdl_t * hca_hdl_p)630Sstevel@tonic-gate ibt_open_hca(ibt_clnt_hdl_t ibt_hdl, ib_guid_t hca_guid,
640Sstevel@tonic-gate     ibt_hca_hdl_t *hca_hdl_p)
650Sstevel@tonic-gate {
660Sstevel@tonic-gate 	ibtl_hca_t  		*hca_infop;
670Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;		/* HCA Dev Info */
680Sstevel@tonic-gate 
690Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_open_hca(%p, %llX)", ibt_hdl, hca_guid);
700Sstevel@tonic-gate 
710Sstevel@tonic-gate 
720Sstevel@tonic-gate 	/*
730Sstevel@tonic-gate 	 * Get HCA Device Info Structure, referenced by HCA GUID.
740Sstevel@tonic-gate 	 */
750Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
760Sstevel@tonic-gate 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
770Sstevel@tonic-gate 	if (hca_devp == NULL) {
780Sstevel@tonic-gate 		/*
790Sstevel@tonic-gate 		 * If we are here, then the requested HCA device is not present.
800Sstevel@tonic-gate 		 * Return the status as Invalid HCA GUID.
810Sstevel@tonic-gate 		 */
820Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
830Sstevel@tonic-gate 
840Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_open_hca: "
850Sstevel@tonic-gate 		    "HCA Device Not Found: Invalid HCA GUID");
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 		*hca_hdl_p = NULL;
880Sstevel@tonic-gate 		return (IBT_HCA_INVALID);
890Sstevel@tonic-gate 	}
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	/*
920Sstevel@tonic-gate 	 * Check whether open is allowed for this dip
930Sstevel@tonic-gate 	 */
940Sstevel@tonic-gate 	if (ibt_hdl->clnt_dip) {
950Sstevel@tonic-gate 		if (ddi_get_parent(ibt_hdl->clnt_dip) == hca_devp->hd_hca_dip) {
960Sstevel@tonic-gate 			if (hca_guid != hca_devp->hd_hca_attr->hca_node_guid) {
970Sstevel@tonic-gate 				mutex_exit(&ibtl_clnt_list_mutex);
980Sstevel@tonic-gate 				return (IBT_FAILURE);
990Sstevel@tonic-gate 			}
1000Sstevel@tonic-gate 		}
1010Sstevel@tonic-gate 	}
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate 	if (hca_devp->hd_state != IBTL_HCA_DEV_ATTACHED) {
1040Sstevel@tonic-gate 		/*
1050Sstevel@tonic-gate 		 * If we are here, then the requested HCA device has detached,
1060Sstevel@tonic-gate 		 * or is in the process of detaching.
1070Sstevel@tonic-gate 		 */
1080Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_open_hca: "
1110Sstevel@tonic-gate 		    "HCA is busy trying to detach");
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 		*hca_hdl_p = NULL;
1140Sstevel@tonic-gate 		return (IBT_HCA_BUSY_DETACHING);
1150Sstevel@tonic-gate 	}
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 	/*
1180Sstevel@tonic-gate 	 * Yes, we found a HCA Device registered with IBTF, which matches with
1190Sstevel@tonic-gate 	 * the requested HCA_GUID.
1200Sstevel@tonic-gate 	 *
1210Sstevel@tonic-gate 	 * Check out whether this client has already opened this HCA device,
1220Sstevel@tonic-gate 	 * if yes return the status as IBT_HCA_IN_USE.
1230Sstevel@tonic-gate 	 */
1240Sstevel@tonic-gate 	hca_infop = hca_devp->hd_clnt_list;
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 	while (hca_infop != NULL) {
1270Sstevel@tonic-gate 		if (ibt_hdl == hca_infop->ha_clnt_devp) {
1280Sstevel@tonic-gate 			IBTF_DPRINTF_L3(ibtf_hca,
1290Sstevel@tonic-gate 			    "ibt_open_hca: Already Open");
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate 			if (hca_infop->ha_flags & IBTL_HA_CLOSING) {
1320Sstevel@tonic-gate 				mutex_exit(&ibtl_clnt_list_mutex);
1330Sstevel@tonic-gate 				*hca_hdl_p = NULL;
1340Sstevel@tonic-gate 				return (IBT_HCA_BUSY_CLOSING);
1350Sstevel@tonic-gate 			}
1360Sstevel@tonic-gate 			mutex_exit(&ibtl_clnt_list_mutex);
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 			/* Already Opened. Return back old HCA Handle. */
1390Sstevel@tonic-gate 			*hca_hdl_p = hca_infop;
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 			return (IBT_HCA_IN_USE);
1420Sstevel@tonic-gate 		}
1430Sstevel@tonic-gate 		hca_infop = hca_infop->ha_clnt_link;
1440Sstevel@tonic-gate 	}
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 	/* Create a new HCA Info entity. */
1470Sstevel@tonic-gate 	hca_infop = kmem_zalloc(sizeof (ibtl_hca_t), KM_SLEEP);
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	/* Update the HCA Info entity */
1500Sstevel@tonic-gate 	hca_infop->ha_hca_devp  = hca_devp;	/* HCA Device Info */
1510Sstevel@tonic-gate 	hca_infop->ha_clnt_devp = ibt_hdl;	/* Client Info */
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	/* Update the HCA List, to keep track about the clients using it. */
1540Sstevel@tonic-gate 	hca_infop->ha_clnt_link = hca_devp->hd_clnt_list;
1550Sstevel@tonic-gate 	hca_devp->hd_clnt_list = hca_infop;
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 	/* Update the client's list to depict that it uses this HCA device. */
1590Sstevel@tonic-gate 	hca_infop->ha_hca_link = ibt_hdl->clnt_hca_list;
1600Sstevel@tonic-gate 	ibt_hdl->clnt_hca_list = hca_infop;
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 	/*
1650Sstevel@tonic-gate 	 * Return back the address of ibtl_hca_t structure as an opaque
1660Sstevel@tonic-gate 	 * IBT HCA handle for the clients, to be used in future calls.
1670Sstevel@tonic-gate 	 */
1680Sstevel@tonic-gate 	*hca_hdl_p = hca_infop;
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate 	return (IBT_SUCCESS);
1710Sstevel@tonic-gate }
1720Sstevel@tonic-gate 
173*12574SWilliam.Taylor@Oracle.COM static char *ibtl_close_error_fmt = "IBT CLOSE HCA failed: %d '%s' "
174*12574SWilliam.Taylor@Oracle.COM 	"resources not yet freed by client '%s'\n";
175*12574SWilliam.Taylor@Oracle.COM 
176*12574SWilliam.Taylor@Oracle.COM #define	IBTL_CLOSE_RESOURCE_CHECK(counter, resource_type) \
177*12574SWilliam.Taylor@Oracle.COM 	if ((cntr = atomic_add_32_nv(&(counter), 0)) != 0) {		\
178*12574SWilliam.Taylor@Oracle.COM 		cmn_err(CE_CONT, ibtl_close_error_fmt,			\
179*12574SWilliam.Taylor@Oracle.COM 		    cntr, resource_type,				\
180*12574SWilliam.Taylor@Oracle.COM 		    hca_hdl->ha_clnt_devp->clnt_modinfop->mi_clnt_name); \
181*12574SWilliam.Taylor@Oracle.COM 	}								\
182*12574SWilliam.Taylor@Oracle.COM 	error |= cntr
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate /*
1850Sstevel@tonic-gate  * Function:
1860Sstevel@tonic-gate  *      ibt_close_hca
1870Sstevel@tonic-gate  * Input:
1880Sstevel@tonic-gate  *      hca_hdl  - The HCA handle as returned during its open.
1890Sstevel@tonic-gate  * Output:
1900Sstevel@tonic-gate  *      none
1910Sstevel@tonic-gate  * Returns:
1920Sstevel@tonic-gate  *      IBT_SUCCESS
1930Sstevel@tonic-gate  *      IBT_HCA_HDL_INVALID
1940Sstevel@tonic-gate  *      IBT_HCA_RESOURCES_NOT_FREED
1950Sstevel@tonic-gate  * Description:
1960Sstevel@tonic-gate  *      Close a HCA.
1970Sstevel@tonic-gate  */
1980Sstevel@tonic-gate ibt_status_t
ibt_close_hca(ibt_hca_hdl_t hca_hdl)1990Sstevel@tonic-gate ibt_close_hca(ibt_hca_hdl_t hca_hdl)
2000Sstevel@tonic-gate {
2010Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp, *tmp_devp;
2020Sstevel@tonic-gate 	ibtl_hca_t		**hcapp;
2030Sstevel@tonic-gate 	ibtl_clnt_t		*clntp = hca_hdl->ha_clnt_devp;
204*12574SWilliam.Taylor@Oracle.COM 	uint32_t		cntr, error;
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_close_hca(%p)", hca_hdl);
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 	/*
2090Sstevel@tonic-gate 	 * Verify the Input HCA Handle, if fake return error as
2100Sstevel@tonic-gate 	 * invalid HCA Handle.
2110Sstevel@tonic-gate 	 */
2120Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
2130Sstevel@tonic-gate 	hca_devp = hca_hdl->ha_hca_devp;
2140Sstevel@tonic-gate 	tmp_devp = ibtl_hca_list;
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate 	for (; tmp_devp != NULL; tmp_devp = tmp_devp->hd_hca_dev_link)
2170Sstevel@tonic-gate 		if (tmp_devp == hca_devp)
2180Sstevel@tonic-gate 			break;
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	if (tmp_devp == NULL) {
2210Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
2220Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_close_hca: "
2230Sstevel@tonic-gate 		    "Unable to find this on global HCA list");
2240Sstevel@tonic-gate 		return (IBT_HCA_HDL_INVALID);
2250Sstevel@tonic-gate 	}
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 	/* Make sure resources have been freed. */
228*12574SWilliam.Taylor@Oracle.COM 	error = 0;
229*12574SWilliam.Taylor@Oracle.COM 	IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_qp_cnt, "QP/Channel");
230*12574SWilliam.Taylor@Oracle.COM 	IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_eec_cnt, "EEC");
231*12574SWilliam.Taylor@Oracle.COM 	IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_cq_cnt, "CQ");
232*12574SWilliam.Taylor@Oracle.COM 	IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_pd_cnt, "Protection Domain");
233*12574SWilliam.Taylor@Oracle.COM 	IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_ah_cnt, "AH");
234*12574SWilliam.Taylor@Oracle.COM 	IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_mr_cnt, "Memory Region");
235*12574SWilliam.Taylor@Oracle.COM 	IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_mw_cnt, "Memory Window");
236*12574SWilliam.Taylor@Oracle.COM 	IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_qpn_cnt, "QPN");
237*12574SWilliam.Taylor@Oracle.COM 	IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_srq_cnt, "SRQ");
238*12574SWilliam.Taylor@Oracle.COM 	IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_fmr_pool_cnt, "FMR Pool");
239*12574SWilliam.Taylor@Oracle.COM 	if (error) {
2400Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
2410Sstevel@tonic-gate 		return (IBT_HCA_RESOURCES_NOT_FREED);
2420Sstevel@tonic-gate 	}
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	/* we are now committed to closing the HCA */
2450Sstevel@tonic-gate 	hca_hdl->ha_flags |= IBTL_HA_CLOSING;
2460Sstevel@tonic-gate 	while (hca_hdl->ha_qpn_cnt > 0)
2470Sstevel@tonic-gate 		cv_wait(&ibtl_close_hca_cv, &ibtl_clnt_list_mutex);
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	/*
2500Sstevel@tonic-gate 	 * Remove this HCA Device entry form Client's current list of HCA
2510Sstevel@tonic-gate 	 * Device Instances being used by it.
2520Sstevel@tonic-gate 	 */
2530Sstevel@tonic-gate 	hcapp = &clntp->clnt_hca_list;
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 	for (; *hcapp != NULL; hcapp = &(*hcapp)->ha_hca_link)
2560Sstevel@tonic-gate 		if (*hcapp == hca_hdl)
2570Sstevel@tonic-gate 			break;
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate 	if (*hcapp == NULL) {
2600Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_close_hca: "
2610Sstevel@tonic-gate 		    "Unable to find this HCA on client list");
2620Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
2630Sstevel@tonic-gate 		return (IBT_HCA_HDL_INVALID);
2640Sstevel@tonic-gate 	}
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	/* hcapp now points to a link that points to us */
2670Sstevel@tonic-gate 	*hcapp = hca_hdl->ha_hca_link;		/* remove us */
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	/*
2700Sstevel@tonic-gate 	 * Remove this Client's entry from this HCA Device's Clients list.
2710Sstevel@tonic-gate 	 */
2720Sstevel@tonic-gate 	hcapp = &hca_devp->hd_clnt_list;
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	for (; *hcapp != NULL; hcapp = &(*hcapp)->ha_clnt_link)
2750Sstevel@tonic-gate 		if (*hcapp == hca_hdl)
2760Sstevel@tonic-gate 			break;
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 	if (*hcapp == NULL) {
2790Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
2800Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_close_hca: "
2810Sstevel@tonic-gate 		    "Unable to find this HCA on the client's HCA list");
2820Sstevel@tonic-gate 		return (IBT_HCA_HDL_INVALID);
2830Sstevel@tonic-gate 	}
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 	/* hcapp now points to a link that points to us */
2860Sstevel@tonic-gate 	*hcapp = hca_hdl->ha_clnt_link;		/* remove us */
2870Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 	/* Free memory for this HCA Handle */
2900Sstevel@tonic-gate 	ibtl_free_hca_async_check(hca_hdl);
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	return (IBT_SUCCESS);
2930Sstevel@tonic-gate }
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate void
ibtl_close_hca_check(ibt_hca_hdl_t hca_hdl)2960Sstevel@tonic-gate ibtl_close_hca_check(ibt_hca_hdl_t hca_hdl)
2970Sstevel@tonic-gate {
2980Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibtl_close_hca_check(%p)", hca_hdl);
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
3010Sstevel@tonic-gate 	if ((--hca_hdl->ha_qpn_cnt == 0) &&
3020Sstevel@tonic-gate 	    (hca_hdl->ha_flags & IBTL_HA_CLOSING)) {
3030Sstevel@tonic-gate 		cv_signal(&ibtl_close_hca_cv);
3040Sstevel@tonic-gate 	}
3050Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
3060Sstevel@tonic-gate }
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate /*
3090Sstevel@tonic-gate  * Function:
3100Sstevel@tonic-gate  *      ibt_get_hca_list
3110Sstevel@tonic-gate  * Input:
3120Sstevel@tonic-gate  *      hca_list_p -  Address of pointer updated here.
3130Sstevel@tonic-gate  * Output:
3140Sstevel@tonic-gate  *      hca_list_p -  Points to an array of ib_guid_t's allocated here.
3150Sstevel@tonic-gate  * Returns:
3160Sstevel@tonic-gate  *      The actual number of valid ib_guid_t's returned.
3170Sstevel@tonic-gate  * Description:
3180Sstevel@tonic-gate  *	If hca_list_p is not NULL then the memory for the array of GUIDs is
3190Sstevel@tonic-gate  *	allocated here and should be freed by the caller using
3200Sstevel@tonic-gate  *	ibt_free_hca_list(). If hca_list_p is NULL then no memory is allocated
3210Sstevel@tonic-gate  *	by ibt_get_hca_list and only the number of HCAs in a system is returned.
3220Sstevel@tonic-gate  */
3230Sstevel@tonic-gate uint_t
ibt_get_hca_list(ib_guid_t ** hca_list_p)3240Sstevel@tonic-gate ibt_get_hca_list(ib_guid_t **hca_list_p)
3250Sstevel@tonic-gate {
3260Sstevel@tonic-gate 	uint_t			hca_count = 0;
3270Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;
3280Sstevel@tonic-gate 	ib_guid_t		*hca_listp;
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_get_hca_list(%p)", hca_list_p);
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	hca_devp = ibtl_hca_list;
3350Sstevel@tonic-gate 	while (hca_devp != NULL) {
3360Sstevel@tonic-gate 		hca_count++;
3370Sstevel@tonic-gate 		hca_devp = hca_devp->hd_hca_dev_link;
3380Sstevel@tonic-gate 	}
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 	if (hca_count == 0)
3410Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_get_hca_list: "
3420Sstevel@tonic-gate 		    "HCA device not found");
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 	if ((hca_count == 0) || (hca_list_p == NULL)) {
3450Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
3460Sstevel@tonic-gate 		return (hca_count);
3470Sstevel@tonic-gate 	}
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 	hca_listp = kmem_alloc(hca_count * sizeof (ib_guid_t), KM_SLEEP);
3500Sstevel@tonic-gate 	*hca_list_p = hca_listp;
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 	hca_devp = ibtl_hca_list;
3530Sstevel@tonic-gate 	while (hca_devp != NULL) {
3540Sstevel@tonic-gate 		/* Traverse Global HCA List & retrieve HCA Node GUIDs. */
3550Sstevel@tonic-gate 		*hca_listp++ = hca_devp->hd_hca_attr->hca_node_guid;
3560Sstevel@tonic-gate 		hca_devp = hca_devp->hd_hca_dev_link;
3570Sstevel@tonic-gate 	}
3580Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_get_hca_list: "
3610Sstevel@tonic-gate 	    "Returned <%d> entries @0x%p", hca_count, *hca_list_p);
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 	return (hca_count);
3640Sstevel@tonic-gate }
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate /*
3670Sstevel@tonic-gate  * Function:
3680Sstevel@tonic-gate  *      ibt_free_hca_list
3690Sstevel@tonic-gate  * Input:
3700Sstevel@tonic-gate  *      hca_list  - The address of an ib_guid_t pointer.
3710Sstevel@tonic-gate  *      entries   - The number of ib_guid_t entries to be freed.
3720Sstevel@tonic-gate  * Output:
3730Sstevel@tonic-gate  *      none.
3740Sstevel@tonic-gate  * Returns:
3750Sstevel@tonic-gate  *      none.
3760Sstevel@tonic-gate  * Description:
3770Sstevel@tonic-gate  *      The memory allocated in ibt_get_hca_list() is freed in this function.
3780Sstevel@tonic-gate  */
3790Sstevel@tonic-gate void
ibt_free_hca_list(ib_guid_t * hca_list,uint_t entries)3800Sstevel@tonic-gate ibt_free_hca_list(ib_guid_t *hca_list, uint_t entries)
3810Sstevel@tonic-gate {
3820Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_free_hca_list: "
3830Sstevel@tonic-gate 	    "Free <%d> entries from 0x%p", entries, hca_list);
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 	if ((hca_list != NULL) && (entries > 0))
3860Sstevel@tonic-gate 		kmem_free(hca_list, entries * sizeof (ib_guid_t));
3870Sstevel@tonic-gate }
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate /*
3900Sstevel@tonic-gate  * ibtl_portinfo_locked() is called when the portinfo cache is being
3910Sstevel@tonic-gate  * updated.  If this port's info update is in progress, we return 0
3920Sstevel@tonic-gate  * immediately and have the c
3930Sstevel@tonic-gate  * unless it's already in progress (distinguished by return value).
3940Sstevel@tonic-gate  * When done updating the portinfo, they call ibtl_portinfo_unlock().
3950Sstevel@tonic-gate  */
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate static int
ibtl_portinfo_locked(ibtl_hca_devinfo_t * hca_devp,uint8_t port)3980Sstevel@tonic-gate ibtl_portinfo_locked(ibtl_hca_devinfo_t *hca_devp, uint8_t port)
3990Sstevel@tonic-gate {
4000Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 	for (;;) {
4030Sstevel@tonic-gate 		if (hca_devp->hd_portinfo_locked_port == 0) {
4040Sstevel@tonic-gate 			hca_devp->hd_portinfo_locked_port = port;
4050Sstevel@tonic-gate 			return (1); /* not busy, so OK to initiate update */
4060Sstevel@tonic-gate 		} else if (hca_devp->hd_portinfo_locked_port == port) {
4070Sstevel@tonic-gate 			IBTF_DPRINTF_L3(ibtf_hca, "ibtl_portinfo_locked: "
4080Sstevel@tonic-gate 			    "HCA %p port %d is already locked",
4090Sstevel@tonic-gate 			    hca_devp, port);
4100Sstevel@tonic-gate 			hca_devp->hd_portinfo_waiters = 1;
4110Sstevel@tonic-gate 			cv_wait(&hca_devp->hd_portinfo_cv,
4120Sstevel@tonic-gate 			    &ibtl_clnt_list_mutex);
4130Sstevel@tonic-gate 			return (0); /* it's now done, so no need to initiate */
4140Sstevel@tonic-gate 		} else {
4150Sstevel@tonic-gate 			/* need to wait for other port before we try again */
4160Sstevel@tonic-gate 			hca_devp->hd_portinfo_waiters = 1;
4170Sstevel@tonic-gate 			cv_wait(&hca_devp->hd_portinfo_cv,
4180Sstevel@tonic-gate 			    &ibtl_clnt_list_mutex);
4190Sstevel@tonic-gate 		}
4200Sstevel@tonic-gate 	}
4210Sstevel@tonic-gate }
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate static void
ibtl_portinfo_unlock(ibtl_hca_devinfo_t * hca_devp,uint8_t port)4240Sstevel@tonic-gate ibtl_portinfo_unlock(ibtl_hca_devinfo_t *hca_devp, uint8_t port)
4250Sstevel@tonic-gate {
4260Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
4270Sstevel@tonic-gate 	ASSERT(hca_devp->hd_portinfo_locked_port == port);
4280Sstevel@tonic-gate 	hca_devp->hd_portinfo_locked_port = 0;
4290Sstevel@tonic-gate 	if (hca_devp->hd_portinfo_waiters) {
4300Sstevel@tonic-gate 		hca_devp->hd_portinfo_waiters = 0;
4310Sstevel@tonic-gate 		cv_broadcast(&hca_devp->hd_portinfo_cv);
4320Sstevel@tonic-gate 		IBTF_DPRINTF_L3(ibtf_hca, "ibtl_portinfo_unlock: "
4330Sstevel@tonic-gate 		    "waking up waiters for port %d info on HCA %p",
4340Sstevel@tonic-gate 		    port, hca_devp);
4350Sstevel@tonic-gate 	}
4360Sstevel@tonic-gate }
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate /*
4390Sstevel@tonic-gate  * Function:
4400Sstevel@tonic-gate  *      ibt_get_port_state
4410Sstevel@tonic-gate  * Input:
4420Sstevel@tonic-gate  *      hca_devp    - The HCA Dev Info pointer.
4430Sstevel@tonic-gate  *	port        - Port number to query.
4440Sstevel@tonic-gate  * Output:
4450Sstevel@tonic-gate  *      sgid_p	    - Returned sgid[0], NULL implies no return value.
4460Sstevel@tonic-gate  *      base_lid_p  - Returned base_lid, NULL implies no return value.
4470Sstevel@tonic-gate  * Returns:
4480Sstevel@tonic-gate  *      IBT_SUCCESS
4490Sstevel@tonic-gate  *	IBT_HCA_PORT_INVALID
4500Sstevel@tonic-gate  * Description:
4510Sstevel@tonic-gate  *      Returns HCA port attributes for one of the HCA ports.
4520Sstevel@tonic-gate  */
4530Sstevel@tonic-gate static ibt_status_t
ibtl_get_port_state(ibtl_hca_devinfo_t * hca_devp,uint8_t port,ib_gid_t * sgid_p,ib_lid_t * base_lid_p)4540Sstevel@tonic-gate ibtl_get_port_state(ibtl_hca_devinfo_t *hca_devp, uint8_t port,
4550Sstevel@tonic-gate     ib_gid_t *sgid_p, ib_lid_t *base_lid_p)
4560Sstevel@tonic-gate {
4570Sstevel@tonic-gate 	ibt_hca_portinfo_t *portinfop;
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate 	if ((port < 1) || (port > hca_devp->hd_hca_attr->hca_nports)) {
4620Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibtl_get_port_state: "
4630Sstevel@tonic-gate 		    "invalid port %d, nports = %d", port,
4640Sstevel@tonic-gate 		    hca_devp->hd_hca_attr->hca_nports);
4650Sstevel@tonic-gate 		return (IBT_HCA_PORT_INVALID);
4660Sstevel@tonic-gate 	}
4670Sstevel@tonic-gate 	portinfop = hca_devp->hd_portinfop + port - 1;
4683826Shiremath 	if (portinfop->p_linkstate != IBT_PORT_ACTIVE)
4693826Shiremath 		ibtl_reinit_hca_portinfo(hca_devp, port);
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate 	if (sgid_p)
4720Sstevel@tonic-gate 		*sgid_p = portinfop->p_sgid_tbl[0];
4730Sstevel@tonic-gate 	if (base_lid_p)
4740Sstevel@tonic-gate 		*base_lid_p = portinfop->p_base_lid;
4750Sstevel@tonic-gate 	if (portinfop->p_linkstate != IBT_PORT_ACTIVE) {
4760Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibtl_get_port_state: "
4770Sstevel@tonic-gate 		    "port %d, port_state %d, base_lid %d",
4780Sstevel@tonic-gate 		    port, portinfop->p_linkstate, portinfop->p_base_lid);
4790Sstevel@tonic-gate 		return (IBT_HCA_PORT_NOT_ACTIVE);
4800Sstevel@tonic-gate 	}
4810Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibtl_get_port_state: "
4820Sstevel@tonic-gate 	    "port %d, port_state %d, base_lid %d",
4830Sstevel@tonic-gate 	    port, portinfop->p_linkstate, portinfop->p_base_lid);
4840Sstevel@tonic-gate 	return (IBT_SUCCESS);
4850Sstevel@tonic-gate }
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate /*
4880Sstevel@tonic-gate  * Function:
4890Sstevel@tonic-gate  *      ibt_get_port_state
4900Sstevel@tonic-gate  * Input:
4910Sstevel@tonic-gate  *      hca_hdl	    - The HCA handle.
4920Sstevel@tonic-gate  *	port        - Port number to query.
4930Sstevel@tonic-gate  * Output:
4940Sstevel@tonic-gate  *      sgid_p	    - Returned sgid[0], NULL implies no return value.
4950Sstevel@tonic-gate  *      base_lid_p  - Returned base_lid, NULL implies no return value.
4960Sstevel@tonic-gate  * Returns:
4970Sstevel@tonic-gate  *      IBT_SUCCESS
4980Sstevel@tonic-gate  *	IBT_HCA_PORT_INVALID
4990Sstevel@tonic-gate  * Description:
5000Sstevel@tonic-gate  *      Returns HCA port attributes for one of the HCA ports.
5010Sstevel@tonic-gate  */
5020Sstevel@tonic-gate ibt_status_t
ibt_get_port_state(ibt_hca_hdl_t hca_hdl,uint8_t port,ib_gid_t * sgid_p,ib_lid_t * base_lid_p)5030Sstevel@tonic-gate ibt_get_port_state(ibt_hca_hdl_t hca_hdl, uint8_t port,
5040Sstevel@tonic-gate     ib_gid_t *sgid_p, ib_lid_t *base_lid_p)
5050Sstevel@tonic-gate {
5060Sstevel@tonic-gate 	ibt_status_t		retval;
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_get_port_state(%p, %d, %p, %p)",
5090Sstevel@tonic-gate 	    hca_hdl, port, sgid_p, base_lid_p);
5100Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
5110Sstevel@tonic-gate 	retval = ibtl_get_port_state(hca_hdl->ha_hca_devp, port, sgid_p,
5120Sstevel@tonic-gate 	    base_lid_p);
5130Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
5140Sstevel@tonic-gate 	return (retval);
5150Sstevel@tonic-gate }
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate /*
5190Sstevel@tonic-gate  * Function:
5200Sstevel@tonic-gate  *      ibt_get_port_state_byguid
5210Sstevel@tonic-gate  * Input:
5220Sstevel@tonic-gate  *      hca_guid    - The HCA node GUID.
5230Sstevel@tonic-gate  *	port        - Port number to query.
5240Sstevel@tonic-gate  * Output:
5250Sstevel@tonic-gate  *      sgid_p	    - Returned sgid[0], NULL implies no return value.
5260Sstevel@tonic-gate  *      base_lid_p  - Returned base_lid, NULL implies no return value.
5270Sstevel@tonic-gate  * Returns:
5280Sstevel@tonic-gate  *      IBT_SUCCESS
5290Sstevel@tonic-gate  *	IBT_HCA_PORT_INVALID
5300Sstevel@tonic-gate  *      IBT_HCA_INVALID
5310Sstevel@tonic-gate  * Description:
5320Sstevel@tonic-gate  *      Returns HCA port attributes for one of the HCA ports.
5330Sstevel@tonic-gate  */
5340Sstevel@tonic-gate ibt_status_t
ibt_get_port_state_byguid(ib_guid_t hca_guid,uint8_t port,ib_gid_t * sgid_p,ib_lid_t * base_lid_p)5350Sstevel@tonic-gate ibt_get_port_state_byguid(ib_guid_t hca_guid, uint8_t port,
5360Sstevel@tonic-gate     ib_gid_t *sgid_p, ib_lid_t *base_lid_p)
5370Sstevel@tonic-gate {
5380Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;		/* HCA Dev Info */
5390Sstevel@tonic-gate 	ibt_status_t		retval;
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_get_port_state_byguid(%llx, %d, %p, "
5420Sstevel@tonic-gate 	    "%p)", (longlong_t)hca_guid, port, sgid_p, base_lid_p);
5430Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
5440Sstevel@tonic-gate 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
5450Sstevel@tonic-gate 	if (hca_devp == NULL)
5460Sstevel@tonic-gate 		retval = IBT_HCA_INVALID;
5470Sstevel@tonic-gate 	else
5480Sstevel@tonic-gate 		retval = ibtl_get_port_state(hca_devp, port, sgid_p,
5490Sstevel@tonic-gate 		    base_lid_p);
5500Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
5510Sstevel@tonic-gate 	return (retval);
5520Sstevel@tonic-gate }
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate /*
5560Sstevel@tonic-gate  * Function:
5570Sstevel@tonic-gate  *      ibt_query_hca_byguid
5580Sstevel@tonic-gate  * Input:
5590Sstevel@tonic-gate  *      hca_guid  - The HCA node GUID.
5600Sstevel@tonic-gate  * Output:
5610Sstevel@tonic-gate  *      hca_attrs - A pointer to a ibt_hca_attr_t allocated by the caller,
5620Sstevel@tonic-gate  *                  into which the HCA Attributes are copied.
5630Sstevel@tonic-gate  * Returns:
5640Sstevel@tonic-gate  *      IBT_SUCCESS
5650Sstevel@tonic-gate  *      IBT_INVALID_PARAM
5660Sstevel@tonic-gate  *      IBT_HCA_INVALID
5670Sstevel@tonic-gate  * Description:
5680Sstevel@tonic-gate  *      Returns the static attributes of the specified HCA.
5690Sstevel@tonic-gate  */
5700Sstevel@tonic-gate ibt_status_t
ibt_query_hca_byguid(ib_guid_t hca_guid,ibt_hca_attr_t * hca_attrs)5710Sstevel@tonic-gate ibt_query_hca_byguid(ib_guid_t hca_guid, ibt_hca_attr_t *hca_attrs)
5720Sstevel@tonic-gate {
5730Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;	/* HCA Dev Info. */
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_query_hca_byguid(%llX)", hca_guid);
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
5780Sstevel@tonic-gate 	/* Get HCA Dev Info Structure, referenced by HCA GUID. */
5790Sstevel@tonic-gate 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
5800Sstevel@tonic-gate 	if (hca_devp == NULL) {
5810Sstevel@tonic-gate 		/*
5820Sstevel@tonic-gate 		 * If we are here, then the requested HCA device is not present.
5830Sstevel@tonic-gate 		 */
5840Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
5850Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_query_hca_byguid: "
5860Sstevel@tonic-gate 		    "Device Not Found");
5870Sstevel@tonic-gate 		return (IBT_HCA_INVALID);
5880Sstevel@tonic-gate 	}
5890Sstevel@tonic-gate 
5900Sstevel@tonic-gate 	/* Return back the static HCA attributes */
5910Sstevel@tonic-gate 	bcopy(hca_devp->hd_hca_attr, hca_attrs, sizeof (ibt_hca_attr_t));
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
5940Sstevel@tonic-gate 
5950Sstevel@tonic-gate 	return (IBT_SUCCESS);
5960Sstevel@tonic-gate }
5970Sstevel@tonic-gate 
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate /*
6000Sstevel@tonic-gate  * Function:
6010Sstevel@tonic-gate  *      ibt_query_hca
6020Sstevel@tonic-gate  * Input:
6030Sstevel@tonic-gate  *      hca_hdl   - The HCA handle.
6040Sstevel@tonic-gate  * Output:
6050Sstevel@tonic-gate  *      hca_attrs - A pointer to a ibt_hca_attr_t allocated by the caller,
6060Sstevel@tonic-gate  *                  into which the HCA Attributes are copied.
6070Sstevel@tonic-gate  * Returns:
6080Sstevel@tonic-gate  *      IBT_SUCCESS
6090Sstevel@tonic-gate  *
6100Sstevel@tonic-gate  * Description:
6110Sstevel@tonic-gate  *      Returns the static attributes of the specified HCA.
6120Sstevel@tonic-gate  */
6130Sstevel@tonic-gate ibt_status_t
ibt_query_hca(ibt_hca_hdl_t hca_hdl,ibt_hca_attr_t * hca_attrs)6140Sstevel@tonic-gate ibt_query_hca(ibt_hca_hdl_t hca_hdl, ibt_hca_attr_t *hca_attrs)
6150Sstevel@tonic-gate {
6160Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_query_hca(%p)", hca_hdl);
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate 	/* Return back the static HCA attributes */
6190Sstevel@tonic-gate 	bcopy(hca_hdl->ha_hca_devp->hd_hca_attr, hca_attrs,
6200Sstevel@tonic-gate 	    sizeof (ibt_hca_attr_t));
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 	return (IBT_SUCCESS);
6230Sstevel@tonic-gate }
6240Sstevel@tonic-gate 
6250Sstevel@tonic-gate #define	ROUNDUP(x, y)	((((x)+((y)-1))/(y))*(y))
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate /*
6280Sstevel@tonic-gate  * Function:
6290Sstevel@tonic-gate  *      ibt_query_hca_ports
6300Sstevel@tonic-gate  * Input:
6310Sstevel@tonic-gate  *      hca_hdl	    - The HCA handle.
6320Sstevel@tonic-gate  *	port        - Port number.  If "0", then query ALL Ports.
6330Sstevel@tonic-gate  * Output:
6340Sstevel@tonic-gate  *      port_info_p - The address of a pointer to a ibt_hca_portinfo_t struct.
6350Sstevel@tonic-gate  *      ports_p     - The number of hca ports on the specified HCA.
6360Sstevel@tonic-gate  *      size_p      - Size of the memory allocated by IBTL to get portinfo,
6370Sstevel@tonic-gate  *                   to be freed by calling ibt_free_portinfo().
6380Sstevel@tonic-gate  * Returns:
6390Sstevel@tonic-gate  *      IBT_SUCCESS
6400Sstevel@tonic-gate  *      IBT_HCA_HDL_INVALID
6410Sstevel@tonic-gate  *      IBT_HCA_INVALID
6420Sstevel@tonic-gate  * Description:
6430Sstevel@tonic-gate  *      Returns HCA port attributes for either "one", or "all" of the HCA ports.
6440Sstevel@tonic-gate  */
6450Sstevel@tonic-gate ibt_status_t
ibt_query_hca_ports(ibt_hca_hdl_t hca_hdl,uint8_t port,ibt_hca_portinfo_t ** port_info_p,uint_t * ports_p,uint_t * size_p)6460Sstevel@tonic-gate ibt_query_hca_ports(ibt_hca_hdl_t hca_hdl, uint8_t port,
6470Sstevel@tonic-gate     ibt_hca_portinfo_t **port_info_p, uint_t *ports_p, uint_t *size_p)
6480Sstevel@tonic-gate {
6490Sstevel@tonic-gate 	ibt_status_t	retval;
6500Sstevel@tonic-gate 
6510Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_query_hca_ports(%p, %d)",
6520Sstevel@tonic-gate 	    hca_hdl, port);
6530Sstevel@tonic-gate 
6540Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate 	retval = ibtl_query_hca_ports(hca_hdl->ha_hca_devp, port, port_info_p,
6570Sstevel@tonic-gate 	    ports_p, size_p, 0);
6580Sstevel@tonic-gate 
6590Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
6600Sstevel@tonic-gate 
6610Sstevel@tonic-gate 	return (retval);
6620Sstevel@tonic-gate }
6630Sstevel@tonic-gate 
6640Sstevel@tonic-gate /*
6650Sstevel@tonic-gate  * Function:
6660Sstevel@tonic-gate  *      ibt_query_hca_ports_byguid
6670Sstevel@tonic-gate  * Input:
6680Sstevel@tonic-gate  *      hca_guid    - The HCA node GUID.
6690Sstevel@tonic-gate  *	port        - Port number.  If "0", then query ALL Ports.
6700Sstevel@tonic-gate  * Output:
6710Sstevel@tonic-gate  *      port_info_p - The address of a pointer to a ibt_hca_portinfo_t struct.
6720Sstevel@tonic-gate  *      ports_p     - The number of hca ports on the specified HCA.
6730Sstevel@tonic-gate  *      size_p      - Size of the memory allocated by IBTL to get portinfo,
6740Sstevel@tonic-gate  *                   to be freed by calling ibt_free_portinfo().
6750Sstevel@tonic-gate  * Returns:
6760Sstevel@tonic-gate  *      IBT_SUCCESS
6770Sstevel@tonic-gate  *      IBT_HCA_HDL_INVALID
6780Sstevel@tonic-gate  *      IBT_HCA_INVALID
6790Sstevel@tonic-gate  * Description:
6800Sstevel@tonic-gate  *      Returns HCA port attributes for either "one", or "all" of the HCA ports.
6810Sstevel@tonic-gate  */
6820Sstevel@tonic-gate ibt_status_t
ibt_query_hca_ports_byguid(ib_guid_t hca_guid,uint8_t port,ibt_hca_portinfo_t ** port_info_p,uint_t * ports_p,uint_t * size_p)6830Sstevel@tonic-gate ibt_query_hca_ports_byguid(ib_guid_t hca_guid, uint8_t port,
6840Sstevel@tonic-gate     ibt_hca_portinfo_t **port_info_p, uint_t *ports_p, uint_t *size_p)
6850Sstevel@tonic-gate {
6860Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;	/* HCA Dev Info */
6870Sstevel@tonic-gate 	ibt_status_t		retval;
6880Sstevel@tonic-gate 
6890Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
6900Sstevel@tonic-gate 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
6910Sstevel@tonic-gate 	if (hca_devp == NULL) {
6920Sstevel@tonic-gate 		/*
6930Sstevel@tonic-gate 		 * If we are here, then the requested HCA device is not present.
6940Sstevel@tonic-gate 		 * Return the status as Invalid HCA GUID.
6950Sstevel@tonic-gate 		 */
6960Sstevel@tonic-gate 		*ports_p = *size_p = 0;
6970Sstevel@tonic-gate 		*port_info_p = NULL;
6980Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
6990Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_query_hca_ports_byguid: "
7000Sstevel@tonic-gate 		    "HCA Device Not Found. ");
7010Sstevel@tonic-gate 		return (IBT_HCA_INVALID);
7020Sstevel@tonic-gate 	}
7030Sstevel@tonic-gate 
7040Sstevel@tonic-gate 	retval = ibtl_query_hca_ports(hca_devp, port, port_info_p, ports_p,
7050Sstevel@tonic-gate 	    size_p, 0);
7060Sstevel@tonic-gate 
7070Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
7080Sstevel@tonic-gate 
7090Sstevel@tonic-gate 	return (retval);
7100Sstevel@tonic-gate }
7110Sstevel@tonic-gate 
7120Sstevel@tonic-gate /*
7130Sstevel@tonic-gate  * Define the above function for CM's use that uses the cached copy.
7140Sstevel@tonic-gate  */
7150Sstevel@tonic-gate ibt_status_t
ibtl_cm_query_hca_ports_byguid(ib_guid_t hca_guid,uint8_t port,ibt_hca_portinfo_t ** port_info_p,uint_t * ports_p,uint_t * size_p)7160Sstevel@tonic-gate ibtl_cm_query_hca_ports_byguid(ib_guid_t hca_guid, uint8_t port,
7170Sstevel@tonic-gate     ibt_hca_portinfo_t **port_info_p, uint_t *ports_p, uint_t *size_p)
7180Sstevel@tonic-gate {
7190Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;	/* HCA Dev Info */
7200Sstevel@tonic-gate 	ibt_status_t		retval;
7210Sstevel@tonic-gate 
7220Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
7230Sstevel@tonic-gate 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
7240Sstevel@tonic-gate 	if (hca_devp == NULL) {
7250Sstevel@tonic-gate 		/*
7260Sstevel@tonic-gate 		 * If we are here, then the requested HCA device is not present.
7270Sstevel@tonic-gate 		 * Return the status as Invalid HCA GUID.
7280Sstevel@tonic-gate 		 */
7290Sstevel@tonic-gate 		*ports_p = *size_p = 0;
7300Sstevel@tonic-gate 		*port_info_p = NULL;
7310Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
7320Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_query_hca_ports_byguid: "
7330Sstevel@tonic-gate 		    "HCA Device Not Found. ");
7340Sstevel@tonic-gate 		return (IBT_HCA_INVALID);
7350Sstevel@tonic-gate 	}
7360Sstevel@tonic-gate 
7370Sstevel@tonic-gate 	retval = ibtl_query_hca_ports(hca_devp, port, port_info_p, ports_p,
7380Sstevel@tonic-gate 	    size_p, 1);
7390Sstevel@tonic-gate 
7400Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
7410Sstevel@tonic-gate 
7420Sstevel@tonic-gate 	return (retval);
7430Sstevel@tonic-gate }
7440Sstevel@tonic-gate 
7450Sstevel@tonic-gate 
7460Sstevel@tonic-gate /*
7470Sstevel@tonic-gate  * ibtl_query_one_port - fill in portinfo for one port.
7480Sstevel@tonic-gate  */
7490Sstevel@tonic-gate static ibt_status_t
ibtl_query_one_port(ibtl_hca_devinfo_t * hca_devp,uint8_t port,ibt_hca_portinfo_t ** port_info_p,uint_t * ports_p,uint_t * size_p,int use_cache)7500Sstevel@tonic-gate ibtl_query_one_port(ibtl_hca_devinfo_t *hca_devp, uint8_t port,
7510Sstevel@tonic-gate     ibt_hca_portinfo_t **port_info_p, uint_t *ports_p, uint_t *size_p,
7520Sstevel@tonic-gate     int use_cache)
7530Sstevel@tonic-gate {
7540Sstevel@tonic-gate 	ibt_hca_portinfo_t	*sp1;	/* src */
7550Sstevel@tonic-gate 	ibt_hca_portinfo_t	*p1;	/* dst */
7560Sstevel@tonic-gate 	caddr_t			p2;
7570Sstevel@tonic-gate 	uint_t			len;
7580Sstevel@tonic-gate 	uint_t			sgid_tbl_len, pkey_tbl_len;
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
7610Sstevel@tonic-gate 
7620Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibtl_query_one_port(%p, %d)",
7630Sstevel@tonic-gate 	    hca_devp, port);
7640Sstevel@tonic-gate 
7650Sstevel@tonic-gate 	if (port > hca_devp->hd_hca_attr->hca_nports) {
7660Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibtl_query_one_port: "
7670Sstevel@tonic-gate 		    "invalid port %d", port);
7680Sstevel@tonic-gate 		return (IBT_HCA_PORT_INVALID);
7690Sstevel@tonic-gate 	}
7700Sstevel@tonic-gate 
7710Sstevel@tonic-gate 	/* If the PORT_UP event is not supported, we need to query */
7720Sstevel@tonic-gate 	sp1 = hca_devp->hd_portinfop + port - 1;
7730Sstevel@tonic-gate 	if (use_cache == 0)
7740Sstevel@tonic-gate 		ibtl_reinit_hca_portinfo(hca_devp, port);
7750Sstevel@tonic-gate 
7760Sstevel@tonic-gate 	*ports_p = 1;
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate 	/*
7790Sstevel@tonic-gate 	 * Calculate how much memory we need for one port, and allocate it.
7800Sstevel@tonic-gate 	 */
7810Sstevel@tonic-gate 	sgid_tbl_len = ROUNDUP(sp1->p_sgid_tbl_sz * sizeof (ib_gid_t),
7820Sstevel@tonic-gate 	    _LONG_LONG_ALIGNMENT);
7830Sstevel@tonic-gate 	pkey_tbl_len = ROUNDUP(sp1->p_pkey_tbl_sz * sizeof (ib_pkey_t),
7840Sstevel@tonic-gate 	    _LONG_LONG_ALIGNMENT);
7850Sstevel@tonic-gate 
7860Sstevel@tonic-gate 	len = sizeof (ibt_hca_portinfo_t) + sgid_tbl_len + pkey_tbl_len;
7870Sstevel@tonic-gate 	*size_p = len;
7880Sstevel@tonic-gate 
7890Sstevel@tonic-gate 	p1 = kmem_zalloc(len, KM_SLEEP);
7900Sstevel@tonic-gate 	*port_info_p = p1;
7910Sstevel@tonic-gate 	bcopy(sp1, p1, sizeof (ibt_hca_portinfo_t));
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 	/* initialize the p_pkey_tbl & p_sgid_tbl pointers. */
7940Sstevel@tonic-gate 	p2 = (caddr_t)(p1 + 1);	/* pkeys follow the struct ibt_hca_portinfo_s */
7950Sstevel@tonic-gate 	bcopy(sp1->p_pkey_tbl, p2, pkey_tbl_len);
7960Sstevel@tonic-gate 	p1->p_pkey_tbl = (ib_pkey_t *)p2;
7970Sstevel@tonic-gate 
7980Sstevel@tonic-gate 	p2 += pkey_tbl_len;	/* sgids follow the pkeys */
7990Sstevel@tonic-gate 	bcopy(sp1->p_sgid_tbl, p2, sgid_tbl_len);
8000Sstevel@tonic-gate 	p1->p_sgid_tbl = (ib_gid_t *)p2;
8010Sstevel@tonic-gate 
8020Sstevel@tonic-gate 	return (IBT_SUCCESS);
8030Sstevel@tonic-gate }
8040Sstevel@tonic-gate 
8050Sstevel@tonic-gate /*
8060Sstevel@tonic-gate  * ibtl_query_hca_ports - worker routine to get port_info for clients.
8070Sstevel@tonic-gate  */
8080Sstevel@tonic-gate static ibt_status_t
ibtl_query_hca_ports(ibtl_hca_devinfo_t * hca_devp,uint8_t port,ibt_hca_portinfo_t ** port_info_p,uint_t * ports_p,uint_t * size_p,int use_cache)8090Sstevel@tonic-gate ibtl_query_hca_ports(ibtl_hca_devinfo_t *hca_devp, uint8_t port,
8100Sstevel@tonic-gate     ibt_hca_portinfo_t **port_info_p, uint_t *ports_p, uint_t *size_p,
8110Sstevel@tonic-gate     int use_cache)
8120Sstevel@tonic-gate {
8130Sstevel@tonic-gate 	ibt_hca_portinfo_t	*sp1;	/* src */
8140Sstevel@tonic-gate 	ibt_hca_portinfo_t	*p1;	/* dst */
8150Sstevel@tonic-gate 	uint_t			i, nports;
8160Sstevel@tonic-gate 	caddr_t			p2;
8170Sstevel@tonic-gate 	uint_t			len;
8180Sstevel@tonic-gate 	uint_t			sgid_tbl_len, pkey_tbl_len;
8190Sstevel@tonic-gate 
8200Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
8210Sstevel@tonic-gate 
8220Sstevel@tonic-gate 	/*
8230Sstevel@tonic-gate 	 * If user has specified the port num, then query only that port,
8240Sstevel@tonic-gate 	 * else query all ports.
8250Sstevel@tonic-gate 	 */
8260Sstevel@tonic-gate 	if (port)
8270Sstevel@tonic-gate 		return (ibtl_query_one_port(hca_devp, port, port_info_p,
8280Sstevel@tonic-gate 		    ports_p, size_p, use_cache));
8290Sstevel@tonic-gate 
8300Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibtl_query_hca_ports(%p, ALL)", hca_devp);
8310Sstevel@tonic-gate 
8320Sstevel@tonic-gate 	nports = hca_devp->hd_hca_attr->hca_nports;
8330Sstevel@tonic-gate 	*ports_p = nports;
8340Sstevel@tonic-gate 
8350Sstevel@tonic-gate 	/* If the PORT_UP event is not supported, we need to query */
8360Sstevel@tonic-gate 	if (use_cache == 0)
8370Sstevel@tonic-gate 		for (i = 0; i < nports; i++)
8380Sstevel@tonic-gate 			ibtl_reinit_hca_portinfo(hca_devp, i + 1);
8390Sstevel@tonic-gate 
8400Sstevel@tonic-gate 	sp1 = hca_devp->hd_portinfop;
8410Sstevel@tonic-gate 
8420Sstevel@tonic-gate 	/*
8430Sstevel@tonic-gate 	 * Calculate how much memory we need for all ports, and allocate it.
8440Sstevel@tonic-gate 	 */
8450Sstevel@tonic-gate 	sgid_tbl_len = ROUNDUP(sp1->p_sgid_tbl_sz * sizeof (ib_gid_t),
8460Sstevel@tonic-gate 	    _LONG_LONG_ALIGNMENT);
8470Sstevel@tonic-gate 	pkey_tbl_len = ROUNDUP(sp1->p_pkey_tbl_sz * sizeof (ib_pkey_t),
8480Sstevel@tonic-gate 	    _LONG_LONG_ALIGNMENT);
8490Sstevel@tonic-gate 
8500Sstevel@tonic-gate 	len = (sizeof (ibt_hca_portinfo_t) + sgid_tbl_len + pkey_tbl_len) *
8510Sstevel@tonic-gate 	    nports;
8520Sstevel@tonic-gate 	*size_p = len;
8530Sstevel@tonic-gate 
8540Sstevel@tonic-gate 	ASSERT(len == hca_devp->hd_portinfo_len);
8550Sstevel@tonic-gate 
8560Sstevel@tonic-gate 	p1 = kmem_zalloc(len, KM_SLEEP);
8570Sstevel@tonic-gate 	*port_info_p = p1;
8580Sstevel@tonic-gate 	bcopy(sp1, p1, len);	/* start with an exact copy of our cache */
8590Sstevel@tonic-gate 
8600Sstevel@tonic-gate 	p2 = (caddr_t)(p1 + nports);
8610Sstevel@tonic-gate 
8620Sstevel@tonic-gate 	/* For each port, update the p_pkey_tbl & p_sgid_tbl ptrs. */
8630Sstevel@tonic-gate 	for (i = 0; i < nports; i++) {
8640Sstevel@tonic-gate 		p1->p_pkey_tbl = (ib_pkey_t *)p2;
8650Sstevel@tonic-gate 		p2 += pkey_tbl_len;
8660Sstevel@tonic-gate 		p1->p_sgid_tbl = (ib_gid_t *)p2;
8670Sstevel@tonic-gate 		p2 += sgid_tbl_len;
8680Sstevel@tonic-gate 		p1++;
8690Sstevel@tonic-gate 	}
8700Sstevel@tonic-gate 	return (IBT_SUCCESS);
8710Sstevel@tonic-gate }
8720Sstevel@tonic-gate 
8730Sstevel@tonic-gate /*
8740Sstevel@tonic-gate  *	Search for a Full pkey.  Use the pkey at index 0 if not found.
8750Sstevel@tonic-gate  */
8760Sstevel@tonic-gate static void
ibtl_set_default_pkey_ix(ibt_hca_portinfo_t * p1)8770Sstevel@tonic-gate ibtl_set_default_pkey_ix(ibt_hca_portinfo_t *p1)
8780Sstevel@tonic-gate {
8790Sstevel@tonic-gate 	uint16_t	pkey_ix;
8800Sstevel@tonic-gate 
8810Sstevel@tonic-gate 	for (pkey_ix = 0; pkey_ix < p1->p_pkey_tbl_sz; pkey_ix++) {
8820Sstevel@tonic-gate 		if ((p1->p_pkey_tbl[pkey_ix] & 0x8000) &&
8830Sstevel@tonic-gate 		    (p1->p_pkey_tbl[pkey_ix] != IB_PKEY_INVALID_FULL)) {
8840Sstevel@tonic-gate 			p1->p_def_pkey_ix = pkey_ix;
8850Sstevel@tonic-gate 			IBTF_DPRINTF_L3(ibtf_hca,
8860Sstevel@tonic-gate 			    "ibtl_set_default_pkey_ix: portinfop %p, "
8870Sstevel@tonic-gate 			    "FULL PKEY 0x%x found, pkey_ix is %d",
8880Sstevel@tonic-gate 			    p1, p1->p_pkey_tbl[pkey_ix], pkey_ix);
8890Sstevel@tonic-gate 			return;
8900Sstevel@tonic-gate 		}
8910Sstevel@tonic-gate 	}
8920Sstevel@tonic-gate 	IBTF_DPRINTF_L2(ibtf_hca,
8930Sstevel@tonic-gate 	    "ibtl_set_default_pkey_ix: portinfop %p: failed "
8940Sstevel@tonic-gate 	    "to find a default PKEY in the table, using PKey 0x%x",
8950Sstevel@tonic-gate 	    p1, p1->p_pkey_tbl[0]);
8960Sstevel@tonic-gate 	p1->p_def_pkey_ix = 0;
8970Sstevel@tonic-gate }
8980Sstevel@tonic-gate 
8990Sstevel@tonic-gate /*
9000Sstevel@tonic-gate  * ibtl_reinit_hca_portinfo - update the portinfo cache for use by IBTL.
9010Sstevel@tonic-gate  *
9020Sstevel@tonic-gate  * We have the HCA driver fill in a temporary portinfo, then we bcopy
9030Sstevel@tonic-gate  * it into our cache while holding the appropriate lock.
9040Sstevel@tonic-gate  */
9050Sstevel@tonic-gate void
ibtl_reinit_hca_portinfo(ibtl_hca_devinfo_t * hca_devp,uint8_t port)9060Sstevel@tonic-gate ibtl_reinit_hca_portinfo(ibtl_hca_devinfo_t *hca_devp, uint8_t port)
9070Sstevel@tonic-gate {
9080Sstevel@tonic-gate 	ibt_status_t		status;
9090Sstevel@tonic-gate 	ibt_hca_portinfo_t	*p1, *sp1;
9100Sstevel@tonic-gate 	ibt_port_state_t	old_linkstate;
9110Sstevel@tonic-gate 	uint_t			len, sgid_tbl_len, pkey_tbl_len;
9120Sstevel@tonic-gate 	ib_pkey_t		*saved_pkey_tbl;
9130Sstevel@tonic-gate 	ib_gid_t		*saved_sgid_tbl;
9140Sstevel@tonic-gate 	ib_sn_prefix_t		sn_pfx = 0;
9150Sstevel@tonic-gate 	uint_t			multiSM;
9160Sstevel@tonic-gate 	int			i;
9170Sstevel@tonic-gate 
9180Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibtl_reinit_hca_portinfo(%p, %d)",
9190Sstevel@tonic-gate 	    hca_devp, port);
9200Sstevel@tonic-gate 
9210Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
9220Sstevel@tonic-gate 	ASSERT(port != 0);
9230Sstevel@tonic-gate 
9240Sstevel@tonic-gate 	if (ibtl_portinfo_locked(hca_devp, port)) {
9250Sstevel@tonic-gate 		/* we got the lock, so we need to do the portinfo update */
9260Sstevel@tonic-gate 
9270Sstevel@tonic-gate 		/* invalidate fast_gid_cache */
9280Sstevel@tonic-gate 		ibtl_fast_gid_cache_valid = B_FALSE;
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate 		p1 = hca_devp->hd_portinfop + port - 1;
9310Sstevel@tonic-gate 		sgid_tbl_len = ROUNDUP(p1->p_sgid_tbl_sz * sizeof (ib_gid_t),
9320Sstevel@tonic-gate 		    _LONG_LONG_ALIGNMENT);
9330Sstevel@tonic-gate 		pkey_tbl_len = ROUNDUP(p1->p_pkey_tbl_sz * sizeof (ib_pkey_t),
9340Sstevel@tonic-gate 		    _LONG_LONG_ALIGNMENT);
9350Sstevel@tonic-gate 		len = sizeof (ibt_hca_portinfo_t) + sgid_tbl_len + pkey_tbl_len;
9360Sstevel@tonic-gate 
9370Sstevel@tonic-gate 		/* update was NOT in progress, so we do it here */
9380Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
9390Sstevel@tonic-gate 
9400Sstevel@tonic-gate 		IBTF_DPRINTF_L3(ibtf_hca, "ibtl_reinit_hca_portinfo(%p, %d): "
9410Sstevel@tonic-gate 		    "calling ibc_query_hca_ports", hca_devp, port);
9420Sstevel@tonic-gate 
9430Sstevel@tonic-gate 		sp1 = kmem_zalloc(len, KM_SLEEP);
9440Sstevel@tonic-gate 		sp1->p_pkey_tbl = (ib_pkey_t *)(sp1 + 1);
9450Sstevel@tonic-gate 		sp1->p_sgid_tbl =
9460Sstevel@tonic-gate 		    (ib_gid_t *)((caddr_t)sp1->p_pkey_tbl + pkey_tbl_len);
9470Sstevel@tonic-gate 		status = IBTL_HDIP2CIHCAOPS_P(hca_devp)->ibc_query_hca_ports(
9480Sstevel@tonic-gate 		    IBTL_HDIP2CIHCA(hca_devp), port, sp1);
9490Sstevel@tonic-gate 
9500Sstevel@tonic-gate 		mutex_enter(&ibtl_clnt_list_mutex);
9510Sstevel@tonic-gate 		if (status != IBT_SUCCESS) {
9520Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtf_hca,
9530Sstevel@tonic-gate 			    "ibtl_reinit_hca_portinfo(%p, %d): "
9540Sstevel@tonic-gate 			    "ibc_query_hca_ports() failed: status = %d",
9550Sstevel@tonic-gate 			    hca_devp, port, status);
9560Sstevel@tonic-gate 		} else {
9570Sstevel@tonic-gate 			old_linkstate = p1->p_linkstate;
9580Sstevel@tonic-gate 			bcopy(sp1->p_pkey_tbl, p1->p_pkey_tbl, pkey_tbl_len);
9590Sstevel@tonic-gate 			bcopy(sp1->p_sgid_tbl, p1->p_sgid_tbl, sgid_tbl_len);
9600Sstevel@tonic-gate 			saved_pkey_tbl = p1->p_pkey_tbl;
9610Sstevel@tonic-gate 			saved_sgid_tbl = p1->p_sgid_tbl;
9620Sstevel@tonic-gate 			bcopy(sp1, p1, sizeof (ibt_hca_portinfo_t));
9630Sstevel@tonic-gate 			p1->p_pkey_tbl = saved_pkey_tbl;
9640Sstevel@tonic-gate 			p1->p_sgid_tbl = saved_sgid_tbl;
9650Sstevel@tonic-gate 			if (p1->p_linkstate == IBT_PORT_ACTIVE) {
9660Sstevel@tonic-gate 				ibtl_set_default_pkey_ix(p1);
9670Sstevel@tonic-gate 				if (p1->p_linkstate != old_linkstate)
9680Sstevel@tonic-gate 					IBTF_DPRINTF_L2(ibtf_hca,
9690Sstevel@tonic-gate 					    "ibtl_reinit_hca_portinfo(%p, %d): "
9700Sstevel@tonic-gate 					    "PORT UP", hca_devp, port);
9710Sstevel@tonic-gate 			} else {
9723826Shiremath 				if (p1->p_linkstate != IBT_PORT_ARM)
9733826Shiremath 					p1->p_base_lid = 0;
9740Sstevel@tonic-gate 				if (p1->p_linkstate != old_linkstate)
9750Sstevel@tonic-gate 					IBTF_DPRINTF_L2(ibtf_hca,
9760Sstevel@tonic-gate 					    "ibtl_reinit_hca_portinfo(%p, %d): "
9770Sstevel@tonic-gate 					    "PORT DOWN", hca_devp, port);
9780Sstevel@tonic-gate 			}
9790Sstevel@tonic-gate 		}
9800Sstevel@tonic-gate 		kmem_free(sp1, len);
9810Sstevel@tonic-gate 
9820Sstevel@tonic-gate 		/* Set multism bit accordingly. */
9830Sstevel@tonic-gate 		multiSM = 0;
9840Sstevel@tonic-gate 		p1 = hca_devp->hd_portinfop;
9850Sstevel@tonic-gate 		for (i = 0; i < hca_devp->hd_hca_attr->hca_nports; i++) {
9860Sstevel@tonic-gate 			if (p1->p_linkstate == IBT_PORT_ACTIVE) {
9870Sstevel@tonic-gate 				if (sn_pfx == 0) {
9880Sstevel@tonic-gate 					sn_pfx = p1->p_sgid_tbl[0].gid_prefix;
9890Sstevel@tonic-gate 				} else if (sn_pfx !=
9900Sstevel@tonic-gate 				    p1->p_sgid_tbl[0].gid_prefix) {
9910Sstevel@tonic-gate 					multiSM = 1;
9920Sstevel@tonic-gate 					IBTF_DPRINTF_L3(ibtf_hca,
9930Sstevel@tonic-gate 					    "ibtl_reinit_hca_portinfo: "
9940Sstevel@tonic-gate 					    "MULTI SM, Port1 SnPfx=0x%llX, "
9950Sstevel@tonic-gate 					    "Port2 SnPfx=0x%llX", sn_pfx,
9960Sstevel@tonic-gate 					    p1->p_sgid_tbl[0].gid_prefix);
9970Sstevel@tonic-gate 				}
9980Sstevel@tonic-gate 			}
9990Sstevel@tonic-gate 			p1++;
10000Sstevel@tonic-gate 		}
10010Sstevel@tonic-gate 		hca_devp->hd_multism = multiSM;
10020Sstevel@tonic-gate 
10030Sstevel@tonic-gate 		ibtl_portinfo_unlock(hca_devp, port);
10040Sstevel@tonic-gate 	}
10050Sstevel@tonic-gate }
10060Sstevel@tonic-gate 
10070Sstevel@tonic-gate /*
10080Sstevel@tonic-gate  * ibtl_init_hca_portinfo - fill in the portinfo cache for use by IBTL.
10090Sstevel@tonic-gate  */
10100Sstevel@tonic-gate ibt_status_t
ibtl_init_hca_portinfo(ibtl_hca_devinfo_t * hca_devp)10110Sstevel@tonic-gate ibtl_init_hca_portinfo(ibtl_hca_devinfo_t *hca_devp)
10120Sstevel@tonic-gate {
10130Sstevel@tonic-gate 	ibt_hca_portinfo_t	*p1;
10140Sstevel@tonic-gate 	ibt_status_t		retval;
10150Sstevel@tonic-gate 	uint_t			i, nports;
10160Sstevel@tonic-gate 	caddr_t			p2;
10170Sstevel@tonic-gate 	uint_t			len;
10180Sstevel@tonic-gate 	uint_t			sgid_tbl_len, pkey_tbl_len;
10190Sstevel@tonic-gate 	uint_t			sgid_tbl_sz, pkey_tbl_sz;
10200Sstevel@tonic-gate 	ib_sn_prefix_t		sn_pfx = 0;
10210Sstevel@tonic-gate 	uint_t			multiSM;
10220Sstevel@tonic-gate 
10230Sstevel@tonic-gate 	IBTF_DPRINTF_L2(ibtf_hca, "ibtl_init_hca_portinfo(%p)", hca_devp);
10240Sstevel@tonic-gate 
10250Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
10260Sstevel@tonic-gate 
10270Sstevel@tonic-gate 	nports = hca_devp->hd_hca_attr->hca_nports;
10280Sstevel@tonic-gate 
10290Sstevel@tonic-gate 	/*
10300Sstevel@tonic-gate 	 * Calculate how much memory we need for all ports, and allocate it.
10310Sstevel@tonic-gate 	 */
10320Sstevel@tonic-gate 	pkey_tbl_sz = IBTL_HDIP2PKEYTBLSZ(hca_devp);
10330Sstevel@tonic-gate 	sgid_tbl_sz = IBTL_HDIP2SGIDTBLSZ(hca_devp);
10340Sstevel@tonic-gate 	pkey_tbl_len = ROUNDUP(pkey_tbl_sz * sizeof (ib_pkey_t),
10350Sstevel@tonic-gate 	    _LONG_LONG_ALIGNMENT);
10360Sstevel@tonic-gate 	sgid_tbl_len = ROUNDUP(sgid_tbl_sz * sizeof (ib_gid_t),
10370Sstevel@tonic-gate 	    _LONG_LONG_ALIGNMENT);
10380Sstevel@tonic-gate 
10390Sstevel@tonic-gate 	len = (sizeof (ibt_hca_portinfo_t) + sgid_tbl_len + pkey_tbl_len) *
10400Sstevel@tonic-gate 	    nports;
10410Sstevel@tonic-gate 
10420Sstevel@tonic-gate 	p1 = kmem_zalloc(len, KM_SLEEP);
10430Sstevel@tonic-gate 	p2 = (caddr_t)(p1 + nports);
10440Sstevel@tonic-gate 
10450Sstevel@tonic-gate 	hca_devp->hd_portinfop = p1;
10460Sstevel@tonic-gate 	hca_devp->hd_portinfo_len = len;
10470Sstevel@tonic-gate 
10480Sstevel@tonic-gate 	/* For each port initialize the p_pkey_tbl & p_sgid_tbl ptrs. */
10490Sstevel@tonic-gate 	for (i = 0; i < nports; i++) {
10500Sstevel@tonic-gate 		p1->p_pkey_tbl_sz = pkey_tbl_sz;
10510Sstevel@tonic-gate 		p1->p_sgid_tbl_sz = sgid_tbl_sz;
10520Sstevel@tonic-gate 		p1->p_pkey_tbl = (ib_pkey_t *)p2;
10530Sstevel@tonic-gate 		p2 += pkey_tbl_len;
10540Sstevel@tonic-gate 		p1->p_sgid_tbl = (ib_gid_t *)p2;
10550Sstevel@tonic-gate 		p2 += sgid_tbl_len;
10560Sstevel@tonic-gate 		p1++;
10570Sstevel@tonic-gate 	}
10580Sstevel@tonic-gate 	p1 = hca_devp->hd_portinfop;
10590Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
10600Sstevel@tonic-gate 
10610Sstevel@tonic-gate 	/* re-direct the call to CI's call */
10620Sstevel@tonic-gate 	retval = IBTL_HDIP2CIHCAOPS_P(hca_devp)->ibc_query_hca_ports(
10630Sstevel@tonic-gate 	    IBTL_HDIP2CIHCA(hca_devp), 0, p1);
10640Sstevel@tonic-gate 
10650Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
10660Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
10670Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibtl_init_hca_portinfo(%p): "
10680Sstevel@tonic-gate 		    "ibc_query_hca_ports() failed: status = %d",
10690Sstevel@tonic-gate 		    hca_devp, retval);
10700Sstevel@tonic-gate 		kmem_free(hca_devp->hd_portinfop, len);
10710Sstevel@tonic-gate 		hca_devp->hd_portinfop = NULL;
10720Sstevel@tonic-gate 		hca_devp->hd_portinfo_len = 0;
10730Sstevel@tonic-gate 		return (retval);
10740Sstevel@tonic-gate 	}
10750Sstevel@tonic-gate 
10760Sstevel@tonic-gate 	p1 = hca_devp->hd_portinfop;
10770Sstevel@tonic-gate 	multiSM = 0;
10780Sstevel@tonic-gate 	for (i = 0; i < nports; i++) {
10790Sstevel@tonic-gate 		if (p1->p_linkstate == IBT_PORT_ACTIVE) {
10800Sstevel@tonic-gate 			ibtl_set_default_pkey_ix(p1);
10810Sstevel@tonic-gate 			if (sn_pfx == 0) {
10820Sstevel@tonic-gate 				sn_pfx = p1->p_sgid_tbl[0].gid_prefix;
10830Sstevel@tonic-gate 			} else if (p1->p_sgid_tbl[0].gid_prefix != sn_pfx) {
10840Sstevel@tonic-gate 				multiSM = 1;
10850Sstevel@tonic-gate 				IBTF_DPRINTF_L3(ibtf_hca,
10860Sstevel@tonic-gate 				    "ibtl_init_hca_portinfo: MULTI SM, "
10870Sstevel@tonic-gate 				    "Port1 SnPfx=0x%llX, Port2 SnPfx=0x%llX",
10880Sstevel@tonic-gate 				    sn_pfx, p1->p_sgid_tbl[0].gid_prefix);
10890Sstevel@tonic-gate 			}
10900Sstevel@tonic-gate 		} else {
10913826Shiremath 			if (p1->p_linkstate != IBT_PORT_ARM)
10923826Shiremath 				p1->p_base_lid = 0;
10930Sstevel@tonic-gate 		}
10940Sstevel@tonic-gate 		p1++;
10950Sstevel@tonic-gate 	}
10960Sstevel@tonic-gate 	hca_devp->hd_multism = multiSM;
10970Sstevel@tonic-gate 
10980Sstevel@tonic-gate 	return (IBT_SUCCESS);
10990Sstevel@tonic-gate }
11000Sstevel@tonic-gate 
11010Sstevel@tonic-gate /*
11020Sstevel@tonic-gate  * Function:
11030Sstevel@tonic-gate  *	ibt_modify_system_image
11040Sstevel@tonic-gate  * Input:
11050Sstevel@tonic-gate  *	hca_hdl	 - The HCA handle.
11060Sstevel@tonic-gate  *	sys_guid - The New system image GUID.
11070Sstevel@tonic-gate  * Description:
11080Sstevel@tonic-gate  *	Modify specified HCA's system image GUID.
11090Sstevel@tonic-gate  */
11100Sstevel@tonic-gate ibt_status_t
ibt_modify_system_image(ibt_hca_hdl_t hca_hdl,ib_guid_t sys_guid)11110Sstevel@tonic-gate ibt_modify_system_image(ibt_hca_hdl_t hca_hdl, ib_guid_t sys_guid)
11120Sstevel@tonic-gate {
11130Sstevel@tonic-gate 	ibt_status_t		retval;
11140Sstevel@tonic-gate 
11150Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_modify_system_image(%p, %llX)",
11160Sstevel@tonic-gate 	    hca_hdl, sys_guid);
11170Sstevel@tonic-gate 
11180Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
11190Sstevel@tonic-gate 	/* Get HCA Dev Info Structure, referenced by HCA GUID. */
11200Sstevel@tonic-gate 
11210Sstevel@tonic-gate 	/* re-direct the call to CI's call */
11220Sstevel@tonic-gate 	retval = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_modify_system_image(
11230Sstevel@tonic-gate 	    IBTL_HCA2CIHCA(hca_hdl), sys_guid);
11240Sstevel@tonic-gate 
11250Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
11260Sstevel@tonic-gate 	return (retval);
11270Sstevel@tonic-gate }
11280Sstevel@tonic-gate 
11290Sstevel@tonic-gate /*
11300Sstevel@tonic-gate  * Function:
11310Sstevel@tonic-gate  *	ibt_modify_system_image_byguid
11320Sstevel@tonic-gate  *
11330Sstevel@tonic-gate  * Input:
11340Sstevel@tonic-gate  *	hca_guid - The HCA Node GUID.
11350Sstevel@tonic-gate  *	sys_guid - The New system image GUID.
11360Sstevel@tonic-gate  * Description:
11370Sstevel@tonic-gate  *	Modify specified HCA's system image GUID.
11380Sstevel@tonic-gate  */
11390Sstevel@tonic-gate ibt_status_t
ibt_modify_system_image_byguid(ib_guid_t hca_guid,ib_guid_t sys_guid)11400Sstevel@tonic-gate ibt_modify_system_image_byguid(ib_guid_t hca_guid, ib_guid_t sys_guid)
11410Sstevel@tonic-gate {
11420Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;	/* HCA Dev Info. */
11430Sstevel@tonic-gate 	ibt_status_t		retval;
11440Sstevel@tonic-gate 
11450Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_modify_system_image_byguid(%llX, %llX)",
11460Sstevel@tonic-gate 	    hca_guid, sys_guid);
11470Sstevel@tonic-gate 
11480Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
11490Sstevel@tonic-gate 	/* Get HCA Dev Info Structure, referenced by HCA GUID. */
11500Sstevel@tonic-gate 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
11510Sstevel@tonic-gate 	if (hca_devp == NULL) {
11520Sstevel@tonic-gate 		/*
11530Sstevel@tonic-gate 		 * If we are here, then the requested HCA device is not present.
11540Sstevel@tonic-gate 		 */
11550Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
11560Sstevel@tonic-gate 		return (IBT_HCA_INVALID);
11570Sstevel@tonic-gate 	}
11580Sstevel@tonic-gate 
11590Sstevel@tonic-gate 	/* re-direct the call to CI's call */
11600Sstevel@tonic-gate 	retval = IBTL_HDIP2CIHCAOPS_P(hca_devp)->ibc_modify_system_image(
11610Sstevel@tonic-gate 	    IBTL_HDIP2CIHCA(hca_devp), sys_guid);
11620Sstevel@tonic-gate 
11630Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
11640Sstevel@tonic-gate 	return (retval);
11650Sstevel@tonic-gate }
11660Sstevel@tonic-gate 
11670Sstevel@tonic-gate /*
11680Sstevel@tonic-gate  * Function:
11690Sstevel@tonic-gate  *      ibt_modify_port_byguid
11700Sstevel@tonic-gate  * Input:
11710Sstevel@tonic-gate  *      hca_guid - The HCA Guid.
11720Sstevel@tonic-gate  *      cmds     - A pointer to an array of ibt_port_modify_t cmds. The
11730Sstevel@tonic-gate  *                 pmod_port field specifies the port to modify (all ports if 0)
11740Sstevel@tonic-gate  *                 and the pmod_flags field specifies which attribute to reset.
11750Sstevel@tonic-gate  *      num_cmds - The number of commands in the cmds array.
11760Sstevel@tonic-gate  * Output:
11770Sstevel@tonic-gate  *      none.
11780Sstevel@tonic-gate  * Returns:
11790Sstevel@tonic-gate  *      IBT_SUCCESS
11800Sstevel@tonic-gate  *      IBT_HCA_HDL_INVALID
11810Sstevel@tonic-gate  *      IBT_HCA_CNTR_INVALID
11820Sstevel@tonic-gate  *      IBT_HCA_CNTR_VAL_INVALID
11830Sstevel@tonic-gate  * Description:
11840Sstevel@tonic-gate  *      Reset the specified port, or all ports attribute(s).
11850Sstevel@tonic-gate  */
11860Sstevel@tonic-gate ibt_status_t
ibt_modify_port_byguid(ib_guid_t hca_guid,uint8_t port,ibt_port_modify_flags_t flags,uint8_t init_type)11870Sstevel@tonic-gate ibt_modify_port_byguid(ib_guid_t hca_guid,  uint8_t port,
11880Sstevel@tonic-gate     ibt_port_modify_flags_t flags, uint8_t init_type)
11890Sstevel@tonic-gate {
11900Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;	/* HCA Dev Info. */
11910Sstevel@tonic-gate 	ibt_status_t		retval;
11920Sstevel@tonic-gate 
11930Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_modify_port_byguid(%llX, %d, %X, %X)",
11940Sstevel@tonic-gate 	    hca_guid, port, flags, init_type);
11950Sstevel@tonic-gate 
11960Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
11970Sstevel@tonic-gate 	/* Get HCA Dev Info Structure, referenced by HCA GUID. */
11980Sstevel@tonic-gate 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
11990Sstevel@tonic-gate 	if (hca_devp == NULL) {
12000Sstevel@tonic-gate 		/*
12010Sstevel@tonic-gate 		 * If we are here, then the requested HCA device is not present.
12020Sstevel@tonic-gate 		 */
12030Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
12040Sstevel@tonic-gate 		return (IBT_HCA_INVALID);
12050Sstevel@tonic-gate 	}
12060Sstevel@tonic-gate 
12070Sstevel@tonic-gate 	/* re-direct the call to CI's call */
12080Sstevel@tonic-gate 	retval = IBTL_HDIP2CIHCAOPS_P(hca_devp)->ibc_modify_ports(
12090Sstevel@tonic-gate 	    IBTL_HDIP2CIHCA(hca_devp), port, flags, init_type);
12100Sstevel@tonic-gate 
12110Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
12120Sstevel@tonic-gate 	return (retval);
12130Sstevel@tonic-gate }
12140Sstevel@tonic-gate 
12150Sstevel@tonic-gate /*
12160Sstevel@tonic-gate  * Function:
12170Sstevel@tonic-gate  *      ibt_modify_port
12180Sstevel@tonic-gate  * Input:
12190Sstevel@tonic-gate  *      hca_hdl  - The HCA handle.
12200Sstevel@tonic-gate  *      cmds     - A pointer to an array of ibt_port_modify_t cmds. The
12210Sstevel@tonic-gate  *                 pmod_port field specifies the port to modify (all ports if 0)
12220Sstevel@tonic-gate  *                 and the pmod_flags field specifies which attribute to reset.
12230Sstevel@tonic-gate  *      num_cmds - The number of commands in the cmds array.
12240Sstevel@tonic-gate  * Output:
12250Sstevel@tonic-gate  *      none.
12260Sstevel@tonic-gate  * Returns:
12270Sstevel@tonic-gate  *      IBT_SUCCESS
12280Sstevel@tonic-gate  *      IBT_HCA_HDL_INVALID
12290Sstevel@tonic-gate  *      IBT_HCA_CNTR_INVALID
12300Sstevel@tonic-gate  *      IBT_HCA_CNTR_VAL_INVALID
12310Sstevel@tonic-gate  * Description:
12320Sstevel@tonic-gate  *      Reset the specified port, or all ports attribute(s).
12330Sstevel@tonic-gate  */
12340Sstevel@tonic-gate ibt_status_t
ibt_modify_port(ibt_hca_hdl_t hca_hdl,uint8_t port,ibt_port_modify_flags_t flags,uint8_t init_type)12350Sstevel@tonic-gate ibt_modify_port(ibt_hca_hdl_t hca_hdl, uint8_t port,
12360Sstevel@tonic-gate     ibt_port_modify_flags_t flags, uint8_t init_type)
12370Sstevel@tonic-gate 
12380Sstevel@tonic-gate {
12390Sstevel@tonic-gate 	ibt_status_t		retval;
12400Sstevel@tonic-gate 
12410Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_modify_port(%p, %d, %X, %X)",
12420Sstevel@tonic-gate 	    hca_hdl, port, flags, init_type);
12430Sstevel@tonic-gate 
12440Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
12450Sstevel@tonic-gate 
12460Sstevel@tonic-gate 	/* re-direct the call to CI's call */
12470Sstevel@tonic-gate 	retval = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_modify_ports(
12480Sstevel@tonic-gate 	    IBTL_HCA2CIHCA(hca_hdl), port, flags, init_type);
12490Sstevel@tonic-gate 
12500Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
12510Sstevel@tonic-gate 	return (retval);
12520Sstevel@tonic-gate }
12530Sstevel@tonic-gate 
12540Sstevel@tonic-gate /*
12550Sstevel@tonic-gate  * Function:
12560Sstevel@tonic-gate  *      ibt_free_portinfo
12570Sstevel@tonic-gate  * Input:
12580Sstevel@tonic-gate  *      port_info  - The address of an array to a ibt_hca_portinfo_t struct.
12590Sstevel@tonic-gate  *	size	   - Memory Size as returned from ibt_query_hca_ports().
12600Sstevel@tonic-gate  * Output:
12610Sstevel@tonic-gate  *      none
12620Sstevel@tonic-gate  * Returns:
12630Sstevel@tonic-gate  *      none
12640Sstevel@tonic-gate  * Description:
12650Sstevel@tonic-gate  *      Frees the memory allocated for a specified ibt_hca_portinfo_t struct.
12660Sstevel@tonic-gate  */
12670Sstevel@tonic-gate void
ibt_free_portinfo(ibt_hca_portinfo_t * port_info,uint_t size)12680Sstevel@tonic-gate ibt_free_portinfo(ibt_hca_portinfo_t *port_info, uint_t size)
12690Sstevel@tonic-gate {
12700Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_free_portinfo(%p, %d)",
12710Sstevel@tonic-gate 	    port_info, size);
12720Sstevel@tonic-gate 
12730Sstevel@tonic-gate 	if ((port_info == NULL) || (size == 0)) {
12740Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_free_portinfo: NULL Pointer");
12750Sstevel@tonic-gate 	} else {
12760Sstevel@tonic-gate 		kmem_free(port_info, size);
12770Sstevel@tonic-gate 	}
12780Sstevel@tonic-gate }
12790Sstevel@tonic-gate 
12800Sstevel@tonic-gate 
12810Sstevel@tonic-gate /*
12820Sstevel@tonic-gate  * Function:
12830Sstevel@tonic-gate  *      ibt_get_hcadevinfo
12840Sstevel@tonic-gate  * Input:
12850Sstevel@tonic-gate  *      hca_guid - The HCA's node GUID.
12860Sstevel@tonic-gate  * Output:
12870Sstevel@tonic-gate  *      none.
12880Sstevel@tonic-gate  * Returns:
12890Sstevel@tonic-gate  *      Pointer to HCA Device Info structure whose HCA GUID is requested or NULL
12900Sstevel@tonic-gate  * Description:
12910Sstevel@tonic-gate  *      Get a pointer to HCA Device Info Structure for the requested HCA GUID.
12920Sstevel@tonic-gate  *      If no matching HCA GUID Device info is found, NULL is returned.
12930Sstevel@tonic-gate  */
12940Sstevel@tonic-gate ibtl_hca_devinfo_t *
ibtl_get_hcadevinfo(ib_guid_t hca_guid)12950Sstevel@tonic-gate ibtl_get_hcadevinfo(ib_guid_t hca_guid)
12960Sstevel@tonic-gate {
12970Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;	/* HCA Dev Info */
12980Sstevel@tonic-gate 
12990Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibtl_get_hcadevinfo(%llX)", hca_guid);
13000Sstevel@tonic-gate 
13010Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
13020Sstevel@tonic-gate 
13030Sstevel@tonic-gate 	hca_devp = ibtl_hca_list;
13040Sstevel@tonic-gate 
13050Sstevel@tonic-gate 	/*
13060Sstevel@tonic-gate 	 * Check whether a HCA device with requested Node GUID is available.
13070Sstevel@tonic-gate 	 * This is done, by searching the global HCA devinfo list and
13080Sstevel@tonic-gate 	 * comparing the Node GUID from the device attribute info.
13090Sstevel@tonic-gate 	 */
13100Sstevel@tonic-gate 	while (hca_devp != NULL) {
13110Sstevel@tonic-gate 		if (hca_devp->hd_hca_attr->hca_node_guid == hca_guid) {
13120Sstevel@tonic-gate 			/* Match Found. */
13130Sstevel@tonic-gate 			break;
13140Sstevel@tonic-gate 		}
13150Sstevel@tonic-gate 		hca_devp = hca_devp->hd_hca_dev_link;
13160Sstevel@tonic-gate 	}
13170Sstevel@tonic-gate 	return (hca_devp);
13180Sstevel@tonic-gate }
13190Sstevel@tonic-gate 
13200Sstevel@tonic-gate 
13210Sstevel@tonic-gate /*
13220Sstevel@tonic-gate  * Function:
13230Sstevel@tonic-gate  *      ibtl_pkey2index
13240Sstevel@tonic-gate  * Input:
13250Sstevel@tonic-gate  *      hca_devp     - The IBTL HCA Device Info.
13260Sstevel@tonic-gate  *      port_num     - The HCA port number.
13270Sstevel@tonic-gate  *      pkey         - The input PKey value, whose index we are interested in.
13280Sstevel@tonic-gate  * Output:
13290Sstevel@tonic-gate  *      pkey_ix      - The PKey index returned for the specified PKey.
13300Sstevel@tonic-gate  * Returns:
13310Sstevel@tonic-gate  *      IBT_SUCCESS/IBT_HCA_PORT_INVALID/IBT_INVALID_PARAM
13320Sstevel@tonic-gate  * Description:
13330Sstevel@tonic-gate  *      Returns the PKey Index for the specified PKey, the device as specified
13340Sstevel@tonic-gate  *      by IBT HCA Handle.
13350Sstevel@tonic-gate  */
13360Sstevel@tonic-gate static ibt_status_t
ibtl_pkey2index(ibtl_hca_devinfo_t * hca_devp,uint8_t port_num,ib_pkey_t pkey,uint16_t * pkey_ix)13370Sstevel@tonic-gate ibtl_pkey2index(ibtl_hca_devinfo_t *hca_devp, uint8_t port_num,
13380Sstevel@tonic-gate     ib_pkey_t pkey, uint16_t *pkey_ix)
13390Sstevel@tonic-gate {
13400Sstevel@tonic-gate 	ibt_hca_portinfo_t 	*port_infop;
13410Sstevel@tonic-gate 	uint_t			ports;
13420Sstevel@tonic-gate 	uint_t			i;
13430Sstevel@tonic-gate 
13440Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibtl_pkey2index(%p, %d, %d)",
13450Sstevel@tonic-gate 	    hca_devp, port_num, pkey);
13460Sstevel@tonic-gate 
13470Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
13480Sstevel@tonic-gate 
13490Sstevel@tonic-gate 	if ((pkey == IB_PKEY_INVALID_FULL) ||
13500Sstevel@tonic-gate 	    (pkey == IB_PKEY_INVALID_LIMITED))
13510Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
13520Sstevel@tonic-gate 
13530Sstevel@tonic-gate 	ports = hca_devp->hd_hca_attr->hca_nports;
13540Sstevel@tonic-gate 	if ((port_num == 0) || (port_num > ports)) {
13550Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibtl_pkey2index: "
13560Sstevel@tonic-gate 		    "Invalid port_num %d, range is (1 to %d)", port_num, ports);
13570Sstevel@tonic-gate 		return (IBT_HCA_PORT_INVALID);
13580Sstevel@tonic-gate 	}
13590Sstevel@tonic-gate 
13600Sstevel@tonic-gate 	port_infop = hca_devp->hd_portinfop + port_num - 1;
13610Sstevel@tonic-gate 	for (i = 0; i < port_infop->p_pkey_tbl_sz; i++) {
13620Sstevel@tonic-gate 		if (pkey == port_infop->p_pkey_tbl[i]) {
13630Sstevel@tonic-gate 			*pkey_ix = i;
13640Sstevel@tonic-gate 			return (IBT_SUCCESS);
13650Sstevel@tonic-gate 		}
13660Sstevel@tonic-gate 	}
13670Sstevel@tonic-gate 	return (IBT_INVALID_PARAM);
13680Sstevel@tonic-gate }
13690Sstevel@tonic-gate 
13700Sstevel@tonic-gate /*
13710Sstevel@tonic-gate  * Function:
13720Sstevel@tonic-gate  *      ibtl_index2pkey
13730Sstevel@tonic-gate  * Input:
13740Sstevel@tonic-gate  *      hca_devp     - The IBTL HCA Device Info.
13750Sstevel@tonic-gate  *      port_num     - The HCA port
13760Sstevel@tonic-gate  *      pkey_ix      - The input PKey index, whose PKey we are interested in.
13770Sstevel@tonic-gate  * Output:
13780Sstevel@tonic-gate  *      pkey         - The returned PKey value.
13790Sstevel@tonic-gate  * Returns:
13800Sstevel@tonic-gate  *      IBT_SUCCESS/IBT_PKEY_IX_ILLEGAL/IBT_PKEY_IX_INVALID/IBT_HCA_PORT_INVALID
13810Sstevel@tonic-gate  * Description:
13820Sstevel@tonic-gate  *      Returns the PKey value for the specified PKey index, the device as
13830Sstevel@tonic-gate  *      specified by IBT HCA Handle.
13840Sstevel@tonic-gate  */
13850Sstevel@tonic-gate static ibt_status_t
ibtl_index2pkey(ibtl_hca_devinfo_t * hca_devp,uint8_t port_num,uint16_t pkey_ix,ib_pkey_t * pkey)13860Sstevel@tonic-gate ibtl_index2pkey(ibtl_hca_devinfo_t *hca_devp, uint8_t port_num,
13870Sstevel@tonic-gate     uint16_t pkey_ix, ib_pkey_t *pkey)
13880Sstevel@tonic-gate {
13890Sstevel@tonic-gate 	ibt_hca_portinfo_t 	*port_infop;
13900Sstevel@tonic-gate 	uint_t			ports;
13910Sstevel@tonic-gate 
13920Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibtl_index2pkey(%p, %d, %d)",
13930Sstevel@tonic-gate 	    hca_devp, port_num, pkey_ix);
13940Sstevel@tonic-gate 
13950Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
13960Sstevel@tonic-gate 
13970Sstevel@tonic-gate 	ports = hca_devp->hd_hca_attr->hca_nports;
13980Sstevel@tonic-gate 	if ((port_num == 0) || (port_num > ports)) {
13990Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibtl_index2pkey: "
14000Sstevel@tonic-gate 		    "Invalid port_num %d, range is (1 to %d)", port_num, ports);
14010Sstevel@tonic-gate 		return (IBT_HCA_PORT_INVALID);
14020Sstevel@tonic-gate 	}
14030Sstevel@tonic-gate 
14040Sstevel@tonic-gate 	port_infop = hca_devp->hd_portinfop + port_num - 1;
14050Sstevel@tonic-gate 	if (pkey_ix >= port_infop->p_pkey_tbl_sz) {
14060Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibtl_index2pkey: "
14070Sstevel@tonic-gate 		    "pkey index %d out of range (0, %d)",
14080Sstevel@tonic-gate 		    pkey_ix, port_infop->p_pkey_tbl_sz - 1);
14090Sstevel@tonic-gate 		return (IBT_PKEY_IX_ILLEGAL);
14100Sstevel@tonic-gate 	}
14110Sstevel@tonic-gate 
14120Sstevel@tonic-gate 	*pkey = port_infop->p_pkey_tbl[pkey_ix];
14130Sstevel@tonic-gate 	if ((*pkey == IB_PKEY_INVALID_FULL) ||
14140Sstevel@tonic-gate 	    (*pkey == IB_PKEY_INVALID_LIMITED))
14150Sstevel@tonic-gate 		return (IBT_PKEY_IX_INVALID);
14160Sstevel@tonic-gate 	return (IBT_SUCCESS);
14170Sstevel@tonic-gate }
14180Sstevel@tonic-gate 
14190Sstevel@tonic-gate /*
14200Sstevel@tonic-gate  * Function:
14210Sstevel@tonic-gate  *      ibt_pkey2index
14220Sstevel@tonic-gate  * Input:
14230Sstevel@tonic-gate  *      hca_hdl      - The IBT HCA handle.
14240Sstevel@tonic-gate  *      port_num     - The HCA port number.
14250Sstevel@tonic-gate  *      pkey         - The input PKey value, whose index we are interested in.
14260Sstevel@tonic-gate  * Output:
14270Sstevel@tonic-gate  *      pkey_ix      - The PKey index returned for the specified PKey.
14280Sstevel@tonic-gate  * Returns:
14290Sstevel@tonic-gate  *      IBT_SUCCESS/IBT_HCA_PORT_INVALID/IBT_INVALID_PARAM
14300Sstevel@tonic-gate  * Description:
14310Sstevel@tonic-gate  *      Returns the PKey Index for the specified PKey, the device as specified
14320Sstevel@tonic-gate  *      by IBT HCA Handle.
14330Sstevel@tonic-gate  */
14340Sstevel@tonic-gate ibt_status_t
ibt_pkey2index(ibt_hca_hdl_t hca_hdl,uint8_t port_num,ib_pkey_t pkey,uint16_t * pkey_ix)14350Sstevel@tonic-gate ibt_pkey2index(ibt_hca_hdl_t hca_hdl, uint8_t port_num, ib_pkey_t pkey,
14360Sstevel@tonic-gate     uint16_t *pkey_ix)
14370Sstevel@tonic-gate {
14380Sstevel@tonic-gate 	ibt_status_t		retval;
14390Sstevel@tonic-gate 
14400Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_pkey2index(%p, %d, %d)",
14410Sstevel@tonic-gate 	    hca_hdl, port_num, pkey);
14420Sstevel@tonic-gate 
14430Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
14440Sstevel@tonic-gate 	retval = ibtl_pkey2index(hca_hdl->ha_hca_devp, port_num, pkey, pkey_ix);
14450Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
14460Sstevel@tonic-gate 
14470Sstevel@tonic-gate 	return (retval);
14480Sstevel@tonic-gate }
14490Sstevel@tonic-gate 
14500Sstevel@tonic-gate /*
14510Sstevel@tonic-gate  * Function:
14520Sstevel@tonic-gate  *      ibt_pkey2index_byguid
14530Sstevel@tonic-gate  * Input:
14540Sstevel@tonic-gate  *      hca_guid     - The HCA's node GUID.
14550Sstevel@tonic-gate  *      port_num     - The HCA port number.
14560Sstevel@tonic-gate  *      pkey         - The input PKey value, whose index we are interested in.
14570Sstevel@tonic-gate  * Output:
14580Sstevel@tonic-gate  *      pkey_ix      - The PKey Index returned for the specified PKey.
14590Sstevel@tonic-gate  * Returns:
14600Sstevel@tonic-gate  *      IBT_SUCCESS/IBT_HCA_PORT_INVALID/IBT_INVALID_PARAM/IBT_HCA_INVALID
14610Sstevel@tonic-gate  * Description:
14620Sstevel@tonic-gate  *      Returns the PKey Index for the specified PKey, the device as specified
14630Sstevel@tonic-gate  *      by HCA GUID Info.
14640Sstevel@tonic-gate  */
14650Sstevel@tonic-gate ibt_status_t
ibt_pkey2index_byguid(ib_guid_t hca_guid,uint8_t port_num,ib_pkey_t pkey,uint16_t * pkey_ix)14660Sstevel@tonic-gate ibt_pkey2index_byguid(ib_guid_t hca_guid, uint8_t port_num, ib_pkey_t pkey,
14670Sstevel@tonic-gate     uint16_t *pkey_ix)
14680Sstevel@tonic-gate {
14690Sstevel@tonic-gate 	ibt_status_t		retval;
14700Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;	/* HCA Dev Info */
14710Sstevel@tonic-gate 
14720Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_pkey2index_byguid(%llX, %d, %d)",
14730Sstevel@tonic-gate 	    hca_guid, port_num, pkey);
14740Sstevel@tonic-gate 
14750Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
14760Sstevel@tonic-gate 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
14770Sstevel@tonic-gate 	if (hca_devp == NULL) {
14780Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_pkey2index_byguid: "
14790Sstevel@tonic-gate 		    "Invalid HCA GUID 0x%llx", hca_guid);
14800Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
14810Sstevel@tonic-gate 		return (IBT_HCA_INVALID);
14820Sstevel@tonic-gate 	}
14830Sstevel@tonic-gate 	retval = ibtl_pkey2index(hca_devp, port_num, pkey, pkey_ix);
14840Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
14850Sstevel@tonic-gate 
14860Sstevel@tonic-gate 	return (retval);
14870Sstevel@tonic-gate }
14880Sstevel@tonic-gate 
14890Sstevel@tonic-gate 
14900Sstevel@tonic-gate /*
14910Sstevel@tonic-gate  * Function:
14920Sstevel@tonic-gate  *      ibt_index2pkey
14930Sstevel@tonic-gate  * Input:
14940Sstevel@tonic-gate  *      hca_hdl      - The IBT HCA handle.
14950Sstevel@tonic-gate  *      port_num     - The HCA port
14960Sstevel@tonic-gate  *      pkey_ix      - The input PKey index, whose PKey we are interested in.
14970Sstevel@tonic-gate  * Output:
14980Sstevel@tonic-gate  *      pkey         - The returned PKey value.
14990Sstevel@tonic-gate  * Returns:
15000Sstevel@tonic-gate  *      IBT_SUCCESS/IBT_PKEY_IX_ILLEGAL/IBT_PKEY_IX_INVALID/IBT_HCA_PORT_INVALID
15010Sstevel@tonic-gate  * Description:
15020Sstevel@tonic-gate  *      Returns the PKey value for the specified PKey index, the device as
15030Sstevel@tonic-gate  *      specified by IBT HCA Handle.
15040Sstevel@tonic-gate  */
15050Sstevel@tonic-gate ibt_status_t
ibt_index2pkey(ibt_hca_hdl_t hca_hdl,uint8_t port_num,uint16_t pkey_ix,ib_pkey_t * pkey)15060Sstevel@tonic-gate ibt_index2pkey(ibt_hca_hdl_t hca_hdl, uint8_t port_num, uint16_t pkey_ix,
15070Sstevel@tonic-gate     ib_pkey_t *pkey)
15080Sstevel@tonic-gate {
15090Sstevel@tonic-gate 	ibt_status_t		retval;
15100Sstevel@tonic-gate 
15110Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_index2pkey(%p, %d, %d)",
15120Sstevel@tonic-gate 	    hca_hdl, port_num, pkey_ix);
15130Sstevel@tonic-gate 
15140Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
15150Sstevel@tonic-gate 	retval = ibtl_index2pkey(hca_hdl->ha_hca_devp, port_num, pkey_ix, pkey);
15160Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
15170Sstevel@tonic-gate 
15180Sstevel@tonic-gate 	return (retval);
15190Sstevel@tonic-gate }
15200Sstevel@tonic-gate 
15210Sstevel@tonic-gate /*
15220Sstevel@tonic-gate  * Function:
15230Sstevel@tonic-gate  *      ibt_index2pkey_byguid
15240Sstevel@tonic-gate  * Input:
15250Sstevel@tonic-gate  *      hca_guid     - The HCA's node GUID.
15260Sstevel@tonic-gate  *      port_num     - The HCA port
15270Sstevel@tonic-gate  *      pkey_ix      - The input PKey index, whose PKey we are interested in.
15280Sstevel@tonic-gate  * Output:
15290Sstevel@tonic-gate  *      pkey         - The returned PKey value, for the specified index.
15300Sstevel@tonic-gate  * Returns:
15310Sstevel@tonic-gate  *      IBT_SUCCESS/IBT_PKEY_IX_ILLEGAL/IBT_PKEY_IX_INVALID/
15320Sstevel@tonic-gate  *	IBT_HCA_PORT_INVALID/IBT_HCA_INVALID
15330Sstevel@tonic-gate  * Description:
15340Sstevel@tonic-gate  *      Returns the PKey Index for the specified PKey, the device as specified
15350Sstevel@tonic-gate  *      by HCA GUID Info.
15360Sstevel@tonic-gate  */
15370Sstevel@tonic-gate ibt_status_t
ibt_index2pkey_byguid(ib_guid_t hca_guid,uint8_t port_num,uint16_t pkey_ix,ib_pkey_t * pkey)15380Sstevel@tonic-gate ibt_index2pkey_byguid(ib_guid_t hca_guid, uint8_t port_num, uint16_t pkey_ix,
15390Sstevel@tonic-gate     ib_pkey_t *pkey)
15400Sstevel@tonic-gate {
15410Sstevel@tonic-gate 	ibt_status_t		retval;
15420Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;	/* HCA Dev Info */
15430Sstevel@tonic-gate 
15440Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_index2pkey_byguid(%llX, %d, %d)",
15450Sstevel@tonic-gate 	    hca_guid, port_num, pkey_ix);
15460Sstevel@tonic-gate 
15470Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
15480Sstevel@tonic-gate 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
15490Sstevel@tonic-gate 	if (hca_devp == NULL) {
15500Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_index2pkey_byguid: "
15510Sstevel@tonic-gate 		    "Invalid HCA GUID 0x%llx", hca_guid);
15520Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
15530Sstevel@tonic-gate 		return (IBT_HCA_INVALID);
15540Sstevel@tonic-gate 	}
15550Sstevel@tonic-gate 	retval = ibtl_index2pkey(hca_devp, port_num, pkey_ix, pkey);
15560Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
15570Sstevel@tonic-gate 
15580Sstevel@tonic-gate 	return (retval);
15590Sstevel@tonic-gate }
15600Sstevel@tonic-gate 
15610Sstevel@tonic-gate 
15620Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("client managed", ibtl_hca_s::ha_clnt_private))
15630Sstevel@tonic-gate 
15640Sstevel@tonic-gate /*
15650Sstevel@tonic-gate  * Function:
15660Sstevel@tonic-gate  *      ibt_set_hca_private
15670Sstevel@tonic-gate  * Input:
15680Sstevel@tonic-gate  *      hca_hdl		The ibt_hca_hdl_t of the opened HCA.
15690Sstevel@tonic-gate  *      clnt_private	The client private data.
15700Sstevel@tonic-gate  * Output:
15710Sstevel@tonic-gate  *	none.
15720Sstevel@tonic-gate  * Returns:
15730Sstevel@tonic-gate  *      none
15740Sstevel@tonic-gate  * Description:
15750Sstevel@tonic-gate  *      Sets the client private data.
15760Sstevel@tonic-gate  */
15770Sstevel@tonic-gate void
ibt_set_hca_private(ibt_hca_hdl_t hca_hdl,void * clnt_private)15780Sstevel@tonic-gate ibt_set_hca_private(ibt_hca_hdl_t hca_hdl, void *clnt_private)
15790Sstevel@tonic-gate {
15800Sstevel@tonic-gate 	hca_hdl->ha_clnt_private = clnt_private;
15810Sstevel@tonic-gate }
15820Sstevel@tonic-gate 
15830Sstevel@tonic-gate 
15840Sstevel@tonic-gate /*
15850Sstevel@tonic-gate  * Function:
15860Sstevel@tonic-gate  *      ibt_get_hca_private
15870Sstevel@tonic-gate  * Input:
15880Sstevel@tonic-gate  *      hca_hdl		The ibt_hca_hdl_t of the opened HCA.
15890Sstevel@tonic-gate  * Output:
15900Sstevel@tonic-gate  *      none
15910Sstevel@tonic-gate  * Returns:
15920Sstevel@tonic-gate  *      The client private data.
15930Sstevel@tonic-gate  * Description:
15940Sstevel@tonic-gate  *      Retrieves the private data from a specified HCA.
15950Sstevel@tonic-gate  */
15960Sstevel@tonic-gate void *
ibt_get_hca_private(ibt_hca_hdl_t hca_hdl)15970Sstevel@tonic-gate ibt_get_hca_private(ibt_hca_hdl_t hca_hdl)
15980Sstevel@tonic-gate {
15990Sstevel@tonic-gate 	return (hca_hdl->ha_clnt_private);
16000Sstevel@tonic-gate }
16010Sstevel@tonic-gate 
16020Sstevel@tonic-gate /*
16030Sstevel@tonic-gate  * Function:
16040Sstevel@tonic-gate  *	ibt_hca_handle_to_guid
16050Sstevel@tonic-gate  * Input:
16060Sstevel@tonic-gate  *	hca		HCA Handle.
16070Sstevel@tonic-gate  * Output:
16080Sstevel@tonic-gate  *	none.
16090Sstevel@tonic-gate  * Returns:
16100Sstevel@tonic-gate  *	hca_guid	Returned HCA GUID on which the specified Channel is
16110Sstevel@tonic-gate  *			allocated. Valid if it is non-NULL on return.
16120Sstevel@tonic-gate  * Description:
16130Sstevel@tonic-gate  *	A helper function to retrieve HCA GUID for the specified handle.
16140Sstevel@tonic-gate  */
16150Sstevel@tonic-gate ib_guid_t
ibt_hca_handle_to_guid(ibt_hca_hdl_t hca)16160Sstevel@tonic-gate ibt_hca_handle_to_guid(ibt_hca_hdl_t hca)
16170Sstevel@tonic-gate {
16180Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_hca_handle_to_guid(%p)", hca);
16190Sstevel@tonic-gate 	return (IBTL_HCA2HCAGUID(hca));
16200Sstevel@tonic-gate }
16210Sstevel@tonic-gate 
16220Sstevel@tonic-gate /*
16230Sstevel@tonic-gate  * Function:
16240Sstevel@tonic-gate  *	ibt_hca_guid_to_handle
16250Sstevel@tonic-gate  * Input:
16260Sstevel@tonic-gate  *	ibt_hdl		The handle returned to the client by the IBTF from
16270Sstevel@tonic-gate  *                      an ibt_attach() call.
16280Sstevel@tonic-gate  *	hca_guid	HCA GUID
16290Sstevel@tonic-gate  * Output:
16300Sstevel@tonic-gate  *	hca_hdl		Returned ibt_hca_hdl_t.
16310Sstevel@tonic-gate  * Returns:
16320Sstevel@tonic-gate  *      IBT_SUCCESS
16330Sstevel@tonic-gate  *      IBT_HCA_INVALID
16340Sstevel@tonic-gate  * Description:
16350Sstevel@tonic-gate  *	A helper function to retrieve a hca handle from a HCA GUID.
16360Sstevel@tonic-gate  */
16370Sstevel@tonic-gate ibt_status_t
ibt_hca_guid_to_handle(ibt_clnt_hdl_t ibt_hdl,ib_guid_t hca_guid,ibt_hca_hdl_t * hca_hdl)16380Sstevel@tonic-gate ibt_hca_guid_to_handle(ibt_clnt_hdl_t ibt_hdl, ib_guid_t hca_guid,
16390Sstevel@tonic-gate     ibt_hca_hdl_t *hca_hdl)
16400Sstevel@tonic-gate {
16410Sstevel@tonic-gate 	ibtl_hca_t  		*hca_infop;
16420Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;		/* HCA Dev Info */
16430Sstevel@tonic-gate 	ibt_status_t		rval = IBT_HCA_INVALID;
16440Sstevel@tonic-gate 
16450Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_hca_guid_to_handle(%p, %llX)",
16460Sstevel@tonic-gate 	    ibt_hdl, hca_guid);
16470Sstevel@tonic-gate 
16480Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
16490Sstevel@tonic-gate 
16500Sstevel@tonic-gate 	/*
16510Sstevel@tonic-gate 	 * Get HCA Device Info Structure, referenced by HCA GUID.
16520Sstevel@tonic-gate 	 */
16530Sstevel@tonic-gate 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
16540Sstevel@tonic-gate 	if (hca_devp == NULL) {
16550Sstevel@tonic-gate 		/*
16560Sstevel@tonic-gate 		 * If we are here, then the requested HCA device is not present.
16570Sstevel@tonic-gate 		 * Return the status as Invalid HCA GUID.
16580Sstevel@tonic-gate 		 */
16590Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
16600Sstevel@tonic-gate 
16610Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_hca_guid_to_handle: "
16620Sstevel@tonic-gate 		    "HCA Device Not Found: Invalid HCA GUID");
16630Sstevel@tonic-gate 
16640Sstevel@tonic-gate 		*hca_hdl = NULL;
16650Sstevel@tonic-gate 		return (rval);
16660Sstevel@tonic-gate 	}
16670Sstevel@tonic-gate 
16680Sstevel@tonic-gate 	/*
16690Sstevel@tonic-gate 	 * Yes, we found a HCA Device registered with IBTF, which matches with
16700Sstevel@tonic-gate 	 * the requested HCA_GUID.
16710Sstevel@tonic-gate 	 */
16720Sstevel@tonic-gate 	hca_infop = hca_devp->hd_clnt_list;
16730Sstevel@tonic-gate 
16740Sstevel@tonic-gate 	while (hca_infop != NULL) {
16750Sstevel@tonic-gate 		if (ibt_hdl == hca_infop->ha_clnt_devp) {
16760Sstevel@tonic-gate 			rval = IBT_SUCCESS;
16770Sstevel@tonic-gate 			break;
16780Sstevel@tonic-gate 		}
16790Sstevel@tonic-gate 		hca_infop = hca_infop->ha_clnt_link;
16800Sstevel@tonic-gate 	}
16810Sstevel@tonic-gate 
16820Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
16830Sstevel@tonic-gate 	*hca_hdl = hca_infop;
16840Sstevel@tonic-gate 	return (rval);
16850Sstevel@tonic-gate }
1686