xref: /onnv-gate/usr/src/uts/common/io/ib/ibnex/ibnex_ioctl.c (revision 12163:f0cf0084e756)
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
54411Svikram  * Common Development and Distribution License (the "License").
64411Svikram  * 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*12163SRamaswamy.Tummala@Sun.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate /*
260Sstevel@tonic-gate  * This file contains support required for IB cfgadm plugin.
270Sstevel@tonic-gate  */
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <sys/conf.h>
300Sstevel@tonic-gate #include <sys/stat.h>
310Sstevel@tonic-gate #include <sys/modctl.h>
320Sstevel@tonic-gate #include <sys/ib/mgt/ibdm/ibdm_impl.h>
330Sstevel@tonic-gate #include <sys/ib/ibnex/ibnex.h>
340Sstevel@tonic-gate #include <sys/ib/ibnex/ibnex_devctl.h>
350Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl_ibnex.h>
369879SRamaswamy.Tummala@Sun.COM #include <sys/ib/ibtl/impl/ibtl.h>
370Sstevel@tonic-gate #include <sys/file.h>
380Sstevel@tonic-gate #include <sys/sunndi.h>
390Sstevel@tonic-gate #include <sys/fs/dv_node.h>
400Sstevel@tonic-gate #include <sys/mdi_impldefs.h>
410Sstevel@tonic-gate #include <sys/sunmdi.h>
420Sstevel@tonic-gate 
439879SRamaswamy.Tummala@Sun.COM /* return the minimum value of (x) and (y) */
449879SRamaswamy.Tummala@Sun.COM #define	MIN(x, y)	((x) < (y) ? (x) : (y))
459879SRamaswamy.Tummala@Sun.COM 
460Sstevel@tonic-gate /*
470Sstevel@tonic-gate  * function prototypes
480Sstevel@tonic-gate  */
490Sstevel@tonic-gate int			ibnex_open(dev_t *, int, int, cred_t *);
500Sstevel@tonic-gate int			ibnex_close(dev_t, int, int, cred_t *);
510Sstevel@tonic-gate int			ibnex_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
520Sstevel@tonic-gate int			ibnex_offline_childdip(dev_info_t *);
530Sstevel@tonic-gate static int		ibnex_get_num_devices(void);
540Sstevel@tonic-gate static int		ibnex_get_snapshot(char **, size_t *, int);
550Sstevel@tonic-gate static int		ibnex_get_commsvcnode_snapshot(nvlist_t **, ib_guid_t,
560Sstevel@tonic-gate 			    ib_guid_t, int, ib_pkey_t, ibnex_node_type_t);
570Sstevel@tonic-gate static int		ibnex_fill_ioc_tmp(nvlist_t **, ibdm_ioc_info_t *);
580Sstevel@tonic-gate static int		ibnex_fill_nodeinfo(nvlist_t **, ibnex_node_data_t *,
590Sstevel@tonic-gate 			    void *);
60*12163SRamaswamy.Tummala@Sun.COM static void		ibnex_figure_ap_devstate(ibnex_node_data_t *,
610Sstevel@tonic-gate 			    devctl_ap_state_t *);
620Sstevel@tonic-gate static void		ibnex_figure_ib_apid_devstate(devctl_ap_state_t *);
630Sstevel@tonic-gate static	char 		*ibnex_get_apid(struct devctl_iocdata *);
640Sstevel@tonic-gate static int		ibnex_get_dip_from_apid(char *, dev_info_t **,
650Sstevel@tonic-gate 			    ibnex_node_data_t **);
66*12163SRamaswamy.Tummala@Sun.COM extern int		ibnex_get_node_and_dip_from_guid(ib_guid_t, int,
67*12163SRamaswamy.Tummala@Sun.COM 			    ib_pkey_t, ibnex_node_data_t **, dev_info_t **);
680Sstevel@tonic-gate static ibnex_rval_t	ibnex_handle_pseudo_configure(char *);
690Sstevel@tonic-gate static ibnex_rval_t	ibnex_handle_ioc_configure(char *);
700Sstevel@tonic-gate static ibnex_rval_t	ibnex_handle_commsvcnode_configure(char *);
710Sstevel@tonic-gate static void		ibnex_return_apid(dev_info_t *, char **);
720Sstevel@tonic-gate static void		ibnex_port_conf_entry_add(char *);
730Sstevel@tonic-gate static void		ibnex_vppa_conf_entry_add(char *);
740Sstevel@tonic-gate static void		ibnex_hcasvc_conf_entry_add(char *);
750Sstevel@tonic-gate static int		ibnex_port_conf_entry_delete(char *, char *);
760Sstevel@tonic-gate static int		ibnex_vppa_conf_entry_delete(char *, char *);
770Sstevel@tonic-gate static int		ibnex_hcasvc_conf_entry_delete(char *, char *);
780Sstevel@tonic-gate 
790Sstevel@tonic-gate static ibnex_rval_t	ibnex_ioc_fininode(dev_info_t *, ibnex_ioc_node_t *);
800Sstevel@tonic-gate static ibnex_rval_t	ibnex_commsvc_fininode(dev_info_t *);
810Sstevel@tonic-gate static ibnex_rval_t	ibnex_pseudo_fininode(dev_info_t *);
820Sstevel@tonic-gate 
839879SRamaswamy.Tummala@Sun.COM static int		ibnex_devctl(dev_t, int, intptr_t, int,
849879SRamaswamy.Tummala@Sun.COM 			    cred_t *, int *);
859879SRamaswamy.Tummala@Sun.COM static int		ibnex_ctl_get_api_ver(dev_t, int, intptr_t, int,
869879SRamaswamy.Tummala@Sun.COM 			    cred_t *, int *);
879879SRamaswamy.Tummala@Sun.COM static int		ibnex_ctl_get_hca_list(dev_t, int, intptr_t, int,
889879SRamaswamy.Tummala@Sun.COM 			    cred_t *, int *);
899879SRamaswamy.Tummala@Sun.COM static int		ibnex_ctl_query_hca(dev_t, int, intptr_t, int,
909879SRamaswamy.Tummala@Sun.COM 			    cred_t *, int *);
919879SRamaswamy.Tummala@Sun.COM static int		ibnex_ctl_query_hca_port(dev_t, int, intptr_t, int,
929879SRamaswamy.Tummala@Sun.COM 			    cred_t *, int *);
939879SRamaswamy.Tummala@Sun.COM 
940Sstevel@tonic-gate extern uint64_t		ibnex_str2hex(char *, int, int *);
958082SRamaswamy.Tummala@Sun.COM extern int		ibnex_ioc_initnode_all_pi(ibdm_ioc_info_t *);
960Sstevel@tonic-gate extern dev_info_t	*ibnex_commsvc_initnode(dev_info_t *,
970Sstevel@tonic-gate 			    ibdm_port_attr_t *, int, int, ib_pkey_t, int *,
980Sstevel@tonic-gate 			    int);
990Sstevel@tonic-gate extern int		ibnex_get_dip_from_guid(ib_guid_t, int,
1000Sstevel@tonic-gate 			    ib_pkey_t, dev_info_t **);
1010Sstevel@tonic-gate extern void		ibnex_reprobe_ioc_dev(void *arg);
1020Sstevel@tonic-gate extern void		ibnex_reprobe_ioc_all();
1038082SRamaswamy.Tummala@Sun.COM extern int		ibnex_pseudo_create_all_pi(ibnex_node_data_t *);
1040Sstevel@tonic-gate extern void		ibnex_pseudo_initnodes(void);
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate extern ibnex_t	ibnex;
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate /*
1090Sstevel@tonic-gate  * ibnex_open()
1100Sstevel@tonic-gate  */
1110Sstevel@tonic-gate /* ARGSUSED */
1120Sstevel@tonic-gate int
ibnex_open(dev_t * dev,int flag,int otyp,cred_t * credp)1130Sstevel@tonic-gate ibnex_open(dev_t *dev, int flag, int otyp, cred_t *credp)
1140Sstevel@tonic-gate {
1150Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\topen");
1160Sstevel@tonic-gate 	return (0);
1170Sstevel@tonic-gate }
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate /*
1210Sstevel@tonic-gate  * ibnex_close()
1220Sstevel@tonic-gate  */
1230Sstevel@tonic-gate /* ARGSUSED */
1240Sstevel@tonic-gate int
ibnex_close(dev_t dev,int flag,int otyp,cred_t * credp)1250Sstevel@tonic-gate ibnex_close(dev_t dev, int flag, int otyp, cred_t *credp)
1260Sstevel@tonic-gate {
1270Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tclose");
1280Sstevel@tonic-gate 	return (0);
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate 
1319879SRamaswamy.Tummala@Sun.COM int
ibnex_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)1329879SRamaswamy.Tummala@Sun.COM ibnex_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
1339879SRamaswamy.Tummala@Sun.COM     int *rvalp)
1349879SRamaswamy.Tummala@Sun.COM {
1359879SRamaswamy.Tummala@Sun.COM 	/*
1369879SRamaswamy.Tummala@Sun.COM 	 * For all generic devctl ioctls (such as DEVCTL_AP_CONFIGURE),
1379879SRamaswamy.Tummala@Sun.COM 	 * call ibnex_devctl().
1389879SRamaswamy.Tummala@Sun.COM 	 */
1399879SRamaswamy.Tummala@Sun.COM 	if (IS_DEVCTL(cmd))
1409879SRamaswamy.Tummala@Sun.COM 		return (ibnex_devctl(dev, cmd, arg, mode, credp, rvalp));
1419879SRamaswamy.Tummala@Sun.COM 
1429879SRamaswamy.Tummala@Sun.COM 	/*
1439879SRamaswamy.Tummala@Sun.COM 	 * The rest are ibnex specific ioctls.
1449879SRamaswamy.Tummala@Sun.COM 	 */
1459879SRamaswamy.Tummala@Sun.COM 
1469879SRamaswamy.Tummala@Sun.COM 	switch (cmd) {
1479879SRamaswamy.Tummala@Sun.COM 	case IBNEX_CTL_GET_API_VER:
1489879SRamaswamy.Tummala@Sun.COM 		return (ibnex_ctl_get_api_ver(dev, cmd, arg, mode,
1499879SRamaswamy.Tummala@Sun.COM 		    credp, rvalp));
1509879SRamaswamy.Tummala@Sun.COM 
1519879SRamaswamy.Tummala@Sun.COM 	case IBNEX_CTL_GET_HCA_LIST:
1529879SRamaswamy.Tummala@Sun.COM 		return (ibnex_ctl_get_hca_list(dev, cmd, arg, mode,
1539879SRamaswamy.Tummala@Sun.COM 		    credp, rvalp));
1549879SRamaswamy.Tummala@Sun.COM 
1559879SRamaswamy.Tummala@Sun.COM 	case IBNEX_CTL_QUERY_HCA:
1569879SRamaswamy.Tummala@Sun.COM 		return (ibnex_ctl_query_hca(dev, cmd, arg, mode,
1579879SRamaswamy.Tummala@Sun.COM 		    credp, rvalp));
1589879SRamaswamy.Tummala@Sun.COM 
1599879SRamaswamy.Tummala@Sun.COM 	case IBNEX_CTL_QUERY_HCA_PORT:
1609879SRamaswamy.Tummala@Sun.COM 		return (ibnex_ctl_query_hca_port(dev, cmd, arg, mode,
1619879SRamaswamy.Tummala@Sun.COM 		    credp, rvalp));
1629879SRamaswamy.Tummala@Sun.COM 
1639879SRamaswamy.Tummala@Sun.COM 	default:
1649879SRamaswamy.Tummala@Sun.COM 		return (EINVAL);
1659879SRamaswamy.Tummala@Sun.COM 	}
1669879SRamaswamy.Tummala@Sun.COM }
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate /*
1690Sstevel@tonic-gate  * ibnex_ioctl()
1700Sstevel@tonic-gate  *	Ioctl routine for cfgadm controls
1710Sstevel@tonic-gate  *	DEVCTL_AP_GETSTATE:	returns attachment point state
1720Sstevel@tonic-gate  *	DEVCTL_AP_CONTROL:	Does "ibnex" specific ioctls listed below
1730Sstevel@tonic-gate  *		IBNEX_NUM_DEVICE_NODES	Gives how many device nodes exist?
1740Sstevel@tonic-gate  *		IBNEX_NUM_HCA_NODES	Gives how many HCAs exist in the fabric
1750Sstevel@tonic-gate  *		IBNEX_UPDATE_PKEY_TBLS	"-x update_pkey_tbls"
1760Sstevel@tonic-gate  *		IBNEX_GET_SNAPSHOT	Gets the "snapshot" back to user-land
1770Sstevel@tonic-gate  *		IBNEX_SNAPSHOT_SIZE	What is "snapshot" size
1780Sstevel@tonic-gate  *		IBNEX_DEVICE_PATH_SZ	What is device-path size
1790Sstevel@tonic-gate  *		IBNEX_GET_DEVICE_PATH	Gets the device path for Dynamic ap
1800Sstevel@tonic-gate  *		IBNEX_HCA_LIST_SZ	"-x list" option size for the HCA ap_id
1810Sstevel@tonic-gate  *		IBNEX_HCA_LIST_INFO	"-x list" option info for the HCA ap_id
1820Sstevel@tonic-gate  *		IBNEX_UNCFG_CLNTS_SZ	"-x unconfig_client option size"
1830Sstevel@tonic-gate  *		IBNEX_UNCFG_CLNTS_INFO	"-x unconfig_client data"
1840Sstevel@tonic-gate  *		IBNEX_CONF_ENTRY_ADD:	"-x add_service"
1850Sstevel@tonic-gate  *		IBNEX_CONF_ENTRY_DEL:	"-x delete_service"
1860Sstevel@tonic-gate  *		IBNEX_HCA_VERBOSE_SZ:	"-alv hca_apid data size"
1870Sstevel@tonic-gate  *		IBNEX_HCA_VERBOSE_INFO: "-alv hca_apid actual data"
1880Sstevel@tonic-gate  *		IBNEX_UPDATE_IOC_CONF	"-x update_ioc_conf"
1890Sstevel@tonic-gate  *	DEVCTL_AP_CONFIGURE:	"configure" the attachment point
1900Sstevel@tonic-gate  *	DEVCTL_AP_UNCONFIGURE:	"unconfigure" the attachment point
1910Sstevel@tonic-gate  */
1920Sstevel@tonic-gate /* ARGSUSED */
1939879SRamaswamy.Tummala@Sun.COM static int
ibnex_devctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)1949879SRamaswamy.Tummala@Sun.COM ibnex_devctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
1950Sstevel@tonic-gate     int *rvalp)
1960Sstevel@tonic-gate {
1970Sstevel@tonic-gate 	int			ret, rv = 0, ioc_reprobe_pending = 0;
1980Sstevel@tonic-gate 	int			circ;
1990Sstevel@tonic-gate 	char			*snapshot = NULL;
2000Sstevel@tonic-gate 	char			*apid_n = NULL;
2010Sstevel@tonic-gate 	char			*service = NULL;
2020Sstevel@tonic-gate 	char			*devnm = NULL;
2030Sstevel@tonic-gate 	char			*msg;
2040Sstevel@tonic-gate 	char			*guid_str;
2050Sstevel@tonic-gate 	uint_t			num_hcas = 0;
2060Sstevel@tonic-gate 	size_t			snapshot_sz  = 0;
2070Sstevel@tonic-gate 	uint32_t		ssiz;
2080Sstevel@tonic-gate 	uint32_t		apid_len;
2090Sstevel@tonic-gate 	ib_guid_t		hca_guid;
2100Sstevel@tonic-gate 	boolean_t		apid_alloced = B_FALSE;
2110Sstevel@tonic-gate 	dev_info_t		*apid_dip = NULL;
2120Sstevel@tonic-gate 	dev_info_t		*pdip;
2130Sstevel@tonic-gate 	ibnex_rval_t		ret_val;
2140Sstevel@tonic-gate 	ib_service_type_t	svc_type = IB_NONE;
2150Sstevel@tonic-gate 	devctl_ap_state_t	ap_state;
216*12163SRamaswamy.Tummala@Sun.COM 	ibnex_node_data_t	*nodep = NULL;
217*12163SRamaswamy.Tummala@Sun.COM 	ibnex_node_data_t	*scanp;
2180Sstevel@tonic-gate 	struct devctl_iocdata	*dcp = NULL;
2190Sstevel@tonic-gate 
2209879SRamaswamy.Tummala@Sun.COM 	IBTF_DPRINTF_L4("ibnex", "\tdevctl: cmd=%x, arg=%p, mode=%x, cred=%p, "
2210Sstevel@tonic-gate 	    "\t\trval=%p dev=0x%x", cmd, arg, mode, credp, rvalp, dev);
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 	/* read devctl ioctl data */
2240Sstevel@tonic-gate 	if ((cmd != DEVCTL_AP_CONTROL) &&
2250Sstevel@tonic-gate 	    (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS)) {
2260Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex",
2279879SRamaswamy.Tummala@Sun.COM 		    "\tdevctl: ndi_dc_allochdl failed\n");
2280Sstevel@tonic-gate 		return (EFAULT);
2290Sstevel@tonic-gate 	}
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
2320Sstevel@tonic-gate 	switch (cmd) {
2330Sstevel@tonic-gate 	case DEVCTL_AP_GETSTATE:
2349879SRamaswamy.Tummala@Sun.COM 		msg = "\tdevctl: DEVCTL_AP_GETSTATE";
2350Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "%s:", msg);
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 		apid_n = ibnex_get_apid(dcp);
2380Sstevel@tonic-gate 		if (*apid_n == '\0') {
2390Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
2400Sstevel@tonic-gate 			    "%s: ibnex_get_apid failed", msg);
2410Sstevel@tonic-gate 			rv = EIO;
2420Sstevel@tonic-gate 			break;
2430Sstevel@tonic-gate 		}
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 		if (strncmp(apid_n, IBNEX_FABRIC, strlen(IBNEX_FABRIC)) == 0) {
2460Sstevel@tonic-gate 			ibnex_figure_ib_apid_devstate(&ap_state);
2470Sstevel@tonic-gate 			apid_dip = ibnex.ibnex_dip;
2480Sstevel@tonic-gate 		} else {
2490Sstevel@tonic-gate 			/* if this apid is already seen by IBNEX, get the dip */
2500Sstevel@tonic-gate 			rv = ibnex_get_dip_from_apid(apid_n, &apid_dip, &nodep);
2510Sstevel@tonic-gate 			if (rv != IBNEX_DYN_APID) {
2520Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex",
2530Sstevel@tonic-gate 				    "%s: ibnex_get_dip_from_apid failed", msg);
2540Sstevel@tonic-gate 				rv = EIO;
2550Sstevel@tonic-gate 				break;
2560Sstevel@tonic-gate 			}
2570Sstevel@tonic-gate 			if (apid_dip)
2580Sstevel@tonic-gate 				ndi_rele_devi(apid_dip);
2590Sstevel@tonic-gate 			/* rv could be something undesirable, so reset it */
2600Sstevel@tonic-gate 			rv = 0;
2610Sstevel@tonic-gate 
262*12163SRamaswamy.Tummala@Sun.COM 			ibnex_figure_ap_devstate(nodep, &ap_state);
2630Sstevel@tonic-gate 		}
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 		/* copy the return-AP-state information to the user space */
2660Sstevel@tonic-gate 		if (ndi_dc_return_ap_state(&ap_state, dcp) != NDI_SUCCESS) {
2670Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
2680Sstevel@tonic-gate 			    "%s: ndi_dc_return_ap_state failed", msg);
2690Sstevel@tonic-gate 			rv = EFAULT;
2700Sstevel@tonic-gate 		}
2710Sstevel@tonic-gate 		break;
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 	case DEVCTL_AP_CONTROL:
2740Sstevel@tonic-gate 	{
2750Sstevel@tonic-gate 		int			num_nodes = 0;
2760Sstevel@tonic-gate 		ibnex_ioctl_data_t	ioc;	/* for 64-bit copies only */
2770Sstevel@tonic-gate 
2789879SRamaswamy.Tummala@Sun.COM 		msg = "\tdevctl: DEVCTL_AP_CONTROL";
2790Sstevel@tonic-gate #ifdef	_MULTI_DATAMODEL
2800Sstevel@tonic-gate 		if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
2810Sstevel@tonic-gate 			ibnex_ioctl_data_32_t ioc32;
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &ioc32,
2840Sstevel@tonic-gate 			    sizeof (ioc32), mode) != 0) {
2850Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex",
2860Sstevel@tonic-gate 				    "%s: ddi_copyin err 1", msg);
2870Sstevel@tonic-gate 				rv = EFAULT;
2880Sstevel@tonic-gate 				break;
2890Sstevel@tonic-gate 			}
2900Sstevel@tonic-gate 			ioc.cmd		= (uint_t)ioc32.cmd;
2910Sstevel@tonic-gate 			ioc.buf		= (caddr_t)(uintptr_t)ioc32.buf;
2920Sstevel@tonic-gate 			ioc.bufsiz	= (uint_t)ioc32.bufsiz;
2930Sstevel@tonic-gate 			ioc.ap_id	= (caddr_t)(uintptr_t)ioc32.ap_id;
2940Sstevel@tonic-gate 			ioc.ap_id_len	= (uint_t)ioc32.ap_id_len;
2950Sstevel@tonic-gate 			ioc.misc_arg	= (uint_t)ioc32.misc_arg;
2960Sstevel@tonic-gate 		}
2970Sstevel@tonic-gate #else
2980Sstevel@tonic-gate 		if (ddi_copyin((void *)arg, &ioc, sizeof (ioc),
2990Sstevel@tonic-gate 		    mode) != 0) {
3000Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
3010Sstevel@tonic-gate 			    "%s: ddi_copyin 2 failed", msg);
3020Sstevel@tonic-gate 			rv = EFAULT;
3030Sstevel@tonic-gate 			break;
3040Sstevel@tonic-gate 		}
3050Sstevel@tonic-gate #endif	/* _MULTI_DATAMODEL */
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "%s: \n\tioc: cmd=%x buf=%p, "
3080Sstevel@tonic-gate 		    "bufsiz=%d", msg, ioc.cmd, ioc.buf, ioc.bufsiz);
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate 		/*
3110Sstevel@tonic-gate 		 * figure out ap_id name as passed from user-land
3120Sstevel@tonic-gate 		 * NOTE: We don't need to figure out ap_id for these
3130Sstevel@tonic-gate 		 * two sub-commands:-
3140Sstevel@tonic-gate 		 *	IBNEX_NUM_DEVICE_NODES, IBNEX_NUM_HCA_NODES
3150Sstevel@tonic-gate 		 *
3160Sstevel@tonic-gate 		 * Hence, In user-land, these two ioctls force "ap_id_len" to 0.
3170Sstevel@tonic-gate 		 */
3180Sstevel@tonic-gate 		if (ioc.ap_id_len > 0) {
3190Sstevel@tonic-gate 			apid_alloced = B_TRUE;
3200Sstevel@tonic-gate 			apid_len = ioc.ap_id_len + 1;
3210Sstevel@tonic-gate 			apid_n = kmem_zalloc(apid_len, KM_SLEEP);
3220Sstevel@tonic-gate 			if (ddi_copyin((void *)ioc.ap_id, apid_n,
3230Sstevel@tonic-gate 			    ioc.ap_id_len, mode) != 0) {
3240Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex",
3250Sstevel@tonic-gate 				    "%s: ddi_copyin err 3", msg);
3260Sstevel@tonic-gate 				rv = EFAULT;
3270Sstevel@tonic-gate 				break;
3280Sstevel@tonic-gate 			}
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 			IBTF_DPRINTF_L3("ibnex", "%s: apid_n= %s", msg, apid_n);
3310Sstevel@tonic-gate 		}
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 		/* process sub-commands */
3350Sstevel@tonic-gate 		switch (ioc.cmd) {
3360Sstevel@tonic-gate 		case IBNEX_NUM_DEVICE_NODES:
3379879SRamaswamy.Tummala@Sun.COM 			msg = "\tdevctl: DEVCTL_AP_CONTROL: NUM_DEVICE_NODES";
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate 			/*
3400Sstevel@tonic-gate 			 * figure out how many IOC, VPPA,
3410Sstevel@tonic-gate 			 * Pseudo and Port nodes are present
3420Sstevel@tonic-gate 			 */
3430Sstevel@tonic-gate 			num_nodes = ibnex_get_num_devices();
3440Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s: num_nodes = %d",
3450Sstevel@tonic-gate 			    msg, num_nodes);
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate 			if (ddi_copyout(&num_nodes, ioc.buf,
3480Sstevel@tonic-gate 			    ioc.bufsiz, mode) != 0) {
3490Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: copyout", msg);
3500Sstevel@tonic-gate 				rv = EIO;
3510Sstevel@tonic-gate 			}
3520Sstevel@tonic-gate 			mutex_exit(&ibnex.ibnex_mutex);
3530Sstevel@tonic-gate 			return (rv);
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate 		case IBNEX_NUM_HCA_NODES:
3569879SRamaswamy.Tummala@Sun.COM 			msg = "\tdevctl: DEVCTL_AP_CONTROL: NUM_HCA_NODES";
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate 			/* figure out how many HCAs are present in the host */
3590Sstevel@tonic-gate 			mutex_exit(&ibnex.ibnex_mutex);
3600Sstevel@tonic-gate 			num_hcas = ibt_get_hca_list(NULL);
3610Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s: num %d", msg, num_hcas);
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 			if (ddi_copyout(&num_hcas, ioc.buf,
3640Sstevel@tonic-gate 			    ioc.bufsiz, mode) != 0) {
3650Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: copyout", msg);
3660Sstevel@tonic-gate 				rv = EIO;
3670Sstevel@tonic-gate 			}
3680Sstevel@tonic-gate 			return (rv);
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 		case IBNEX_UPDATE_PKEY_TBLS:
3719879SRamaswamy.Tummala@Sun.COM 			msg = "\tdevctl: DEVCTL_AP_CONTROL: UPDATE_PKEY_TBLS";
3720Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s", msg);
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate 			/*
3750Sstevel@tonic-gate 			 * update P_Key tables:
3760Sstevel@tonic-gate 			 *	ibdm_ibnex_update_pkey_tbls() calls
3770Sstevel@tonic-gate 			 *	ibt_query_hca_ports_byguids() for all the
3780Sstevel@tonic-gate 			 *	HCAs that the IBDM has "seen" in the system.
3790Sstevel@tonic-gate 			 *	This ends up updating the IBTL P_Key database.
3800Sstevel@tonic-gate 			 *	NOTE: Changes in this area will break this
3810Sstevel@tonic-gate 			 *	assumption. Initially the plan was to call
3820Sstevel@tonic-gate 			 *	ibt_query_hca_ports_byguids() in IBTL but
3830Sstevel@tonic-gate 			 *	IBDM needs to call it as well. So, eliminating
3840Sstevel@tonic-gate 			 *	the first invocation.
3850Sstevel@tonic-gate 			 *
3860Sstevel@tonic-gate 			 *	It next updates the DM P_Key database.
3870Sstevel@tonic-gate 			 *	Note that the DM P_Key database updating
3880Sstevel@tonic-gate 			 *	will always be driven through cfgadm.
3890Sstevel@tonic-gate 			 */
3900Sstevel@tonic-gate 			mutex_exit(&ibnex.ibnex_mutex);
3910Sstevel@tonic-gate 			ibdm_ibnex_update_pkey_tbls();
3920Sstevel@tonic-gate 			mutex_enter(&ibnex.ibnex_mutex);
3930Sstevel@tonic-gate 			break;
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate 		case IBNEX_GET_SNAPSHOT:
3960Sstevel@tonic-gate 		case IBNEX_SNAPSHOT_SIZE:
3970Sstevel@tonic-gate 			msg = (ioc.cmd == IBNEX_SNAPSHOT_SIZE) ?
3989879SRamaswamy.Tummala@Sun.COM 			    "\tdevctl: DEVCTL_AP_CONTROL: IBNEX_SNAPSHOT_SIZE" :
3999879SRamaswamy.Tummala@Sun.COM 			    "\tdevctl: DEVCTL_AP_CONTROL: IBNEX_GET_SNAPSHOT";
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s:", msg);
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate 			if (ibnex_get_snapshot(&snapshot, &snapshot_sz,
4040Sstevel@tonic-gate 			    ioc.misc_arg) != 0) {
4050Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex",
4060Sstevel@tonic-gate 				    "%s:\n\tibnex_get_snapshot failed", msg);
4070Sstevel@tonic-gate 				rv = EIO;
4080Sstevel@tonic-gate 				break;
4090Sstevel@tonic-gate 			}
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 			/* ssiz needs to be reinitialized again */
4120Sstevel@tonic-gate 			ssiz = snapshot_sz;
4130Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex",
4140Sstevel@tonic-gate 			    "%s:\n\tsize =%x", msg, snapshot_sz);
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 			if (ioc.cmd == IBNEX_SNAPSHOT_SIZE) {
4170Sstevel@tonic-gate 				if (ddi_copyout(&ssiz, ioc.buf,
4180Sstevel@tonic-gate 				    ioc.bufsiz, mode) != 0) {
4190Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
4200Sstevel@tonic-gate 					    "%s:\n\tddi_copyout 2 failed", msg);
4210Sstevel@tonic-gate 					rv = EFAULT;
4220Sstevel@tonic-gate 				}
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate 			} else {
4250Sstevel@tonic-gate 				if (ioc.bufsiz != snapshot_sz) {
4260Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
4270Sstevel@tonic-gate 					    "%s:\n\tinvalid buffer size (%x %x)"
4280Sstevel@tonic-gate 					    " ", msg, ioc.bufsiz, snapshot_sz);
4290Sstevel@tonic-gate 					rv = EINVAL;
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 				} else if (ddi_copyout(snapshot, ioc.buf,
4320Sstevel@tonic-gate 				    ioc.bufsiz, mode) != 0) {
4330Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
4340Sstevel@tonic-gate 					    "%s:\n\tddi_copyout 3 failed", msg);
4350Sstevel@tonic-gate 					rv = EFAULT;
4360Sstevel@tonic-gate 				}
4370Sstevel@tonic-gate 			}
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate 			kmem_free(snapshot, snapshot_sz);
4400Sstevel@tonic-gate 			break;
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 		case IBNEX_DEVICE_PATH_SZ:
4430Sstevel@tonic-gate 		case IBNEX_GET_DEVICE_PATH:
4440Sstevel@tonic-gate 		{
4450Sstevel@tonic-gate 			char	 path[MAXPATHLEN];
4460Sstevel@tonic-gate 
4470Sstevel@tonic-gate 			msg = (ioc.cmd == IBNEX_DEVICE_PATH_SZ) ?
4489879SRamaswamy.Tummala@Sun.COM 			    "\tdevctl:DEVCTL_AP_CONTROL: IBNEX_DEVICE_PATH_SZ" :
4499879SRamaswamy.Tummala@Sun.COM 			    "\tdevctl:DEVCTL_AP_CONTROL: IBNEX_GET_DEVICE_PATH";
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s: apid = %s", msg, apid_n);
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate 			/* if this apid is already seen by IBNEX, get the dip */
4540Sstevel@tonic-gate 			rv = ibnex_get_dip_from_apid(apid_n, &apid_dip, &nodep);
4550Sstevel@tonic-gate 			if (rv != IBNEX_DYN_APID || apid_dip == NULL) {
4560Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex",
4570Sstevel@tonic-gate 				    "%s:\n\tget_dip_from_apid failed", msg);
4580Sstevel@tonic-gate 				rv = EIO;
4590Sstevel@tonic-gate 				break;
4600Sstevel@tonic-gate 			}
4610Sstevel@tonic-gate 			ndi_rele_devi(apid_dip);
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 			/* ddi_pathname doesn't supply /devices, so we do. */
4640Sstevel@tonic-gate 			(void) strcpy(path, "/devices");
4650Sstevel@tonic-gate 			(void) ddi_pathname(apid_dip, path + strlen(path));
4660Sstevel@tonic-gate 			ssiz = (uint32_t)strlen(path) + 1;
4670Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex",
4680Sstevel@tonic-gate 			    "%s: len = %x\n\tpath = %s", msg, ssiz, path);
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate 			/* rv could be something undesirable, so reset it */
4710Sstevel@tonic-gate 			rv = 0;
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 			if (ioc.cmd == IBNEX_DEVICE_PATH_SZ) {
4740Sstevel@tonic-gate 				if (ddi_copyout(&ssiz, ioc.buf,
4750Sstevel@tonic-gate 				    ioc.bufsiz, mode) != 0) {
4760Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
4770Sstevel@tonic-gate 					    "%s: ddi_copyout 4 failed", msg);
4780Sstevel@tonic-gate 					rv = EFAULT;
4790Sstevel@tonic-gate 				}
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 			} else {
4820Sstevel@tonic-gate 				if (ioc.bufsiz != ssiz) {
4830Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
4840Sstevel@tonic-gate 					    "%s: invalid size (%x, %x)",
4850Sstevel@tonic-gate 					    msg, ioc.bufsiz, ssiz);
4860Sstevel@tonic-gate 					rv = EINVAL;
4870Sstevel@tonic-gate 				} else if (ddi_copyout(&path, ioc.buf,
4880Sstevel@tonic-gate 				    ioc.bufsiz, mode) != 0) {
4890Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex", "%s "
4900Sstevel@tonic-gate 					    "ddi_copyout 5 failed", msg);
4910Sstevel@tonic-gate 					rv = EFAULT;
4920Sstevel@tonic-gate 				}
4930Sstevel@tonic-gate 			}
4940Sstevel@tonic-gate 			break;
4950Sstevel@tonic-gate 		}
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 		case IBNEX_HCA_LIST_SZ:
4980Sstevel@tonic-gate 		case IBNEX_HCA_LIST_INFO:
4990Sstevel@tonic-gate 			msg = (ioc.cmd == IBNEX_HCA_LIST_SZ) ?
5000Sstevel@tonic-gate 			    "DEVCTL_AP_CONTROL: IBNEX_HCA_LIST_SZ" :
5010Sstevel@tonic-gate 			    "DEVCTL_AP_CONTROL: IBNEX_HCA_LIST_INFO";
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate 			guid_str = strrchr(apid_n, ':') + 1;
5040Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s, input apid = %s, "
5050Sstevel@tonic-gate 			    "guid = %s", msg, apid_n, guid_str);
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate 			if (guid_str == NULL) {
5080Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: invalid input "
5090Sstevel@tonic-gate 				    "GUID passed %s", msg, guid_str);
5100Sstevel@tonic-gate 				rv = EFAULT;
5110Sstevel@tonic-gate 				break;
5120Sstevel@tonic-gate 			}
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 			/* Get the GUID(hex value) from apid_n */
5150Sstevel@tonic-gate 			hca_guid = ibnex_str2hex(guid_str, strlen(guid_str),
5160Sstevel@tonic-gate 			    &ret);
5170Sstevel@tonic-gate 			if (ret != IBNEX_SUCCESS) {
5180Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: Invalid HCA "
5190Sstevel@tonic-gate 				    "GUID string", msg);
5200Sstevel@tonic-gate 				rv = EIO;
5210Sstevel@tonic-gate 				break;
5220Sstevel@tonic-gate 			}
5230Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s HCA GUID = %llX",
5240Sstevel@tonic-gate 			    msg, hca_guid);
5250Sstevel@tonic-gate 			if (ibtl_ibnex_get_hca_info(hca_guid,
5260Sstevel@tonic-gate 			    IBTL_IBNEX_LIST_CLNTS_FLAG, &snapshot, &snapshot_sz,
5270Sstevel@tonic-gate 			    ibnex_return_apid) != IBT_SUCCESS) {
5280Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex",
5290Sstevel@tonic-gate 				    "%s: get HCA consumers failed", msg);
5300Sstevel@tonic-gate 				rv = EIO;
5310Sstevel@tonic-gate 				break;
5320Sstevel@tonic-gate 			}
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 			ssiz = snapshot_sz;
5350Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s: size =%x", msg, ssiz);
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate 			if (ioc.cmd == IBNEX_HCA_LIST_SZ) {
5380Sstevel@tonic-gate 				if (ddi_copyout(&ssiz, ioc.buf,
5390Sstevel@tonic-gate 				    ioc.bufsiz, mode) != 0) {
5400Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
5410Sstevel@tonic-gate 					    "%s: ddi_copyout 6 failed", msg);
5420Sstevel@tonic-gate 					rv = EFAULT;
5430Sstevel@tonic-gate 				}
5440Sstevel@tonic-gate 			} else {
5450Sstevel@tonic-gate 				if (ioc.bufsiz != ssiz) {
5460Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex", "%s: invalid "
5470Sstevel@tonic-gate 					    "size (%x, %x)", msg, ioc.bufsiz,
5480Sstevel@tonic-gate 					    ssiz);
5490Sstevel@tonic-gate 					rv = EINVAL;
5500Sstevel@tonic-gate 				} else if (ddi_copyout(snapshot, ioc.buf,
5510Sstevel@tonic-gate 				    ioc.bufsiz, mode) != 0) {
5520Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex", "%s "
5530Sstevel@tonic-gate 					    "ddi_copyout 7 failed", msg);
5540Sstevel@tonic-gate 					rv = EFAULT;
5550Sstevel@tonic-gate 				}
5560Sstevel@tonic-gate 			}
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate 			kmem_free(snapshot, snapshot_sz);
5590Sstevel@tonic-gate 			break;
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate 		case IBNEX_UNCFG_CLNTS_SZ:
5620Sstevel@tonic-gate 		case IBNEX_UNCFG_CLNTS_INFO:
5630Sstevel@tonic-gate 			msg = (ioc.cmd == IBNEX_UNCFG_CLNTS_SZ) ?
5649879SRamaswamy.Tummala@Sun.COM 			    "\tdevctl:DEVCTL_AP_CONTROL: IBNEX_UNCFG_CLNTS_SZ" :
5659879SRamaswamy.Tummala@Sun.COM 			    "\tdevctl:DEVCTL_AP_CONTROL: "
5669879SRamaswamy.Tummala@Sun.COM 			    "IBNEX_UNCFG_CLNTS_INFO";
5670Sstevel@tonic-gate 
5680Sstevel@tonic-gate 			guid_str = strrchr(apid_n, ':') + 1;
5690Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s, apid = %s, guid = %s",
5700Sstevel@tonic-gate 			    msg, apid_n, guid_str);
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 			if (guid_str == NULL) {
5730Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: invalid input "
5740Sstevel@tonic-gate 				    "GUID %s", msg, guid_str);
5750Sstevel@tonic-gate 				rv = EFAULT;
5760Sstevel@tonic-gate 				break;
5770Sstevel@tonic-gate 			}
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate 			/* Get the GUID(hex value) from apid_n */
5800Sstevel@tonic-gate 			hca_guid = ibnex_str2hex(guid_str, strlen(guid_str),
5810Sstevel@tonic-gate 			    &ret);
5820Sstevel@tonic-gate 			if (ret != IBNEX_SUCCESS) {
5830Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: Invalid HCA "
5840Sstevel@tonic-gate 				    "GUID string passed", msg);
5850Sstevel@tonic-gate 				rv = EIO;
5860Sstevel@tonic-gate 				break;
5870Sstevel@tonic-gate 			}
5880Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s G = %llX", msg, hca_guid);
5890Sstevel@tonic-gate 			if (ibtl_ibnex_get_hca_info(hca_guid,
5900Sstevel@tonic-gate 			    IBTL_IBNEX_UNCFG_CLNTS_FLAG, &snapshot,
5910Sstevel@tonic-gate 			    &snapshot_sz, ibnex_return_apid) != IBT_SUCCESS) {
5920Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex",
5930Sstevel@tonic-gate 				    "%s: get HCA consumers failed", msg);
5940Sstevel@tonic-gate 				rv = EIO;
5950Sstevel@tonic-gate 				break;
5960Sstevel@tonic-gate 			}
5970Sstevel@tonic-gate 			/* ssiz needs to be reinitialized again */
5980Sstevel@tonic-gate 			ssiz = snapshot_sz;
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s: size =%x", msg, ssiz);
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 			if (ioc.cmd == IBNEX_UNCFG_CLNTS_SZ) {
6030Sstevel@tonic-gate 				if (ddi_copyout(&ssiz, ioc.buf,
6040Sstevel@tonic-gate 				    ioc.bufsiz, mode) != 0) {
6050Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
6060Sstevel@tonic-gate 					    "%s: ddi_copyout 9 failed", msg);
6070Sstevel@tonic-gate 					rv = EFAULT;
6080Sstevel@tonic-gate 				}
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate 			} else {
6110Sstevel@tonic-gate 				if (ioc.bufsiz != ssiz) {
6120Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
6130Sstevel@tonic-gate 					    "%s: invalid size (%x, %x)",
6140Sstevel@tonic-gate 					    msg, ioc.bufsiz, ssiz);
6150Sstevel@tonic-gate 					rv = EINVAL;
6160Sstevel@tonic-gate 				} else if (ddi_copyout(snapshot, ioc.buf,
6170Sstevel@tonic-gate 				    ioc.bufsiz, mode) != 0) {
6180Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex", "%s "
6190Sstevel@tonic-gate 					    "ddi_copyout 10 failed", msg);
6200Sstevel@tonic-gate 					rv = EFAULT;
6210Sstevel@tonic-gate 				}
6220Sstevel@tonic-gate 			}
6230Sstevel@tonic-gate 
6240Sstevel@tonic-gate 			kmem_free(snapshot, snapshot_sz);
6250Sstevel@tonic-gate 			break;
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate 		case IBNEX_CONF_ENTRY_ADD:
6289879SRamaswamy.Tummala@Sun.COM 			msg = "\tdevctl: IBNEX_CONF_ENTRY_ADD: ";
6290Sstevel@tonic-gate 			service = kmem_zalloc(ioc.bufsiz + 1, KM_SLEEP);
6300Sstevel@tonic-gate 			/* read in the "service" name */
6310Sstevel@tonic-gate 			if (ddi_copyin(ioc.buf, service,
6320Sstevel@tonic-gate 			    ioc.bufsiz, mode) != 0) {
6330Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: ddi_copyin err 6",
6340Sstevel@tonic-gate 				    msg);
6350Sstevel@tonic-gate 				rv = EFAULT;
6360Sstevel@tonic-gate 				break;
6370Sstevel@tonic-gate 			}
6380Sstevel@tonic-gate 
6390Sstevel@tonic-gate 			/* read in the "service type" */
6400Sstevel@tonic-gate 			svc_type = ioc.misc_arg;
6410Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s: service = %s, type = %d",
6420Sstevel@tonic-gate 			    msg, service, svc_type);
6430Sstevel@tonic-gate 
6440Sstevel@tonic-gate 			if (svc_type == IB_PORT_SERVICE) {
6450Sstevel@tonic-gate 				ibnex_port_conf_entry_add(service);
6460Sstevel@tonic-gate 			} else if (svc_type == IB_VPPA_SERVICE) {
6470Sstevel@tonic-gate 				ibnex_vppa_conf_entry_add(service);
6480Sstevel@tonic-gate 			} else if (svc_type == IB_HCASVC_SERVICE) {
6490Sstevel@tonic-gate 				ibnex_hcasvc_conf_entry_add(service);
6500Sstevel@tonic-gate 			}
6510Sstevel@tonic-gate 			kmem_free(service, ioc.bufsiz + 1);
6520Sstevel@tonic-gate 			break;
6530Sstevel@tonic-gate 
6540Sstevel@tonic-gate 		case IBNEX_CONF_ENTRY_DEL:
6559879SRamaswamy.Tummala@Sun.COM 			msg = "\tdevctl:IBNEX_CONF_ENTRY_DEL: ";
6560Sstevel@tonic-gate 			service = kmem_zalloc(ioc.bufsiz + 1, KM_SLEEP);
6570Sstevel@tonic-gate 			/* read in the "service" name */
6580Sstevel@tonic-gate 			if (ddi_copyin(ioc.buf, service,
6590Sstevel@tonic-gate 			    ioc.bufsiz, mode) != 0) {
6600Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: ddi_copyin err 7",
6610Sstevel@tonic-gate 				    msg);
6620Sstevel@tonic-gate 				rv = EFAULT;
6630Sstevel@tonic-gate 				break;
6640Sstevel@tonic-gate 			}
6650Sstevel@tonic-gate 
6660Sstevel@tonic-gate 			/* read in the "service type" */
6670Sstevel@tonic-gate 			svc_type = ioc.misc_arg;
6680Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s: service = %s, type = %d",
6690Sstevel@tonic-gate 			    msg, service, svc_type);
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate 			if (svc_type == IB_PORT_SERVICE) {
6720Sstevel@tonic-gate 				rv = ibnex_port_conf_entry_delete(msg, service);
6730Sstevel@tonic-gate 			} else if (svc_type == IB_VPPA_SERVICE) {
6740Sstevel@tonic-gate 				rv = ibnex_vppa_conf_entry_delete(msg, service);
6750Sstevel@tonic-gate 			} else if (svc_type == IB_HCASVC_SERVICE) {
6760Sstevel@tonic-gate 				rv = ibnex_hcasvc_conf_entry_delete(msg,
6770Sstevel@tonic-gate 				    service);
6780Sstevel@tonic-gate 			}
6790Sstevel@tonic-gate 			kmem_free(service, ioc.bufsiz + 1);
6800Sstevel@tonic-gate 			break;
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate 		case IBNEX_HCA_VERBOSE_SZ:
6830Sstevel@tonic-gate 		case IBNEX_HCA_VERBOSE_INFO:
6840Sstevel@tonic-gate 			msg = (ioc.cmd == IBNEX_HCA_VERBOSE_SZ) ?
6850Sstevel@tonic-gate 			    "DEVCTL_AP_CONTROL: IBNEX_HCA_VERBOSE_SZ" :
6860Sstevel@tonic-gate 			    "DEVCTL_AP_CONTROL: IBNEX_HCA_VERBOSE_INFO";
6870Sstevel@tonic-gate 
6880Sstevel@tonic-gate 			guid_str = strrchr(apid_n, ':') + 1;
6890Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s, apid = %s, guid = %s",
6900Sstevel@tonic-gate 			    msg, apid_n, guid_str);
6910Sstevel@tonic-gate 
6920Sstevel@tonic-gate 			if (guid_str == NULL) {
6930Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: invalid GUID %s",
6940Sstevel@tonic-gate 				    msg, guid_str);
6950Sstevel@tonic-gate 				rv = EFAULT;
6960Sstevel@tonic-gate 				break;
6970Sstevel@tonic-gate 			}
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate 			/* Get the GUID(hex value) from apid_n */
7000Sstevel@tonic-gate 			hca_guid = ibnex_str2hex(guid_str, strlen(guid_str),
7010Sstevel@tonic-gate 			    &ret);
7020Sstevel@tonic-gate 			if (ret != IBNEX_SUCCESS) {
7030Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: Invalid HCA GUID "
7040Sstevel@tonic-gate 				    "string", msg);
7050Sstevel@tonic-gate 				rv = EIO;
7060Sstevel@tonic-gate 				break;
7070Sstevel@tonic-gate 			}
7080Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s HCA GUID = 0x%llX",
7090Sstevel@tonic-gate 			    msg, hca_guid);
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate 			if (ibtl_ibnex_get_hca_verbose_data(hca_guid, &snapshot,
7120Sstevel@tonic-gate 			    &snapshot_sz) != IBT_SUCCESS) {
7130Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: get HCA verbose "
7140Sstevel@tonic-gate 				    "data failed", msg);
7150Sstevel@tonic-gate 				rv = EIO;
7160Sstevel@tonic-gate 				break;
7170Sstevel@tonic-gate 			}
7180Sstevel@tonic-gate 
7190Sstevel@tonic-gate 			ssiz = snapshot_sz;
7200Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s: size =%x", msg, ssiz);
7210Sstevel@tonic-gate 
7220Sstevel@tonic-gate 			if (ioc.cmd == IBNEX_HCA_VERBOSE_SZ) {
7230Sstevel@tonic-gate 				if (ddi_copyout(&ssiz, ioc.buf,
7240Sstevel@tonic-gate 				    ioc.bufsiz, mode) != 0) {
7250Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
7260Sstevel@tonic-gate 					    "%s: ddi_copyout 11 failed", msg);
7270Sstevel@tonic-gate 					rv = EFAULT;
7280Sstevel@tonic-gate 				}
7290Sstevel@tonic-gate 			} else {
7300Sstevel@tonic-gate 				if (ioc.bufsiz != ssiz) {
7310Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
7320Sstevel@tonic-gate 					    "%s: invalid size (%x, %x)",
7330Sstevel@tonic-gate 					    msg, ioc.bufsiz, ssiz);
7340Sstevel@tonic-gate 					rv = EINVAL;
7350Sstevel@tonic-gate 				} else if (ddi_copyout(snapshot,
7360Sstevel@tonic-gate 				    ioc.buf, ioc.bufsiz, mode) != 0) {
7370Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex", "%s "
7380Sstevel@tonic-gate 					    "ddi_copyout 12 failed", msg);
7390Sstevel@tonic-gate 					rv = EFAULT;
7400Sstevel@tonic-gate 				}
7410Sstevel@tonic-gate 			}
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate 			kmem_free(snapshot, snapshot_sz);
7440Sstevel@tonic-gate 			break;
7450Sstevel@tonic-gate 
7460Sstevel@tonic-gate 		case IBNEX_UPDATE_IOC_CONF :
7479879SRamaswamy.Tummala@Sun.COM 			msg = "\tdevctl:IBNEX_UPDATE_IOC_CONF: ";
7480Sstevel@tonic-gate 
7490Sstevel@tonic-gate 			/*
7500Sstevel@tonic-gate 			 * If IB fabric APID, call ibnex_update_all
7510Sstevel@tonic-gate 			 * If IOC APID, get the apid dip and call
7520Sstevel@tonic-gate 			 * ibnex_update_ioc
7530Sstevel@tonic-gate 			 */
7540Sstevel@tonic-gate 			if (ioc.misc_arg == IBNEX_BASE_APID) {
7550Sstevel@tonic-gate 				/*
7560Sstevel@tonic-gate 				 * If reprobe is in progress or another reprobe
7570Sstevel@tonic-gate 				 * is already waiting, wait.
7580Sstevel@tonic-gate 				 */
7590Sstevel@tonic-gate 				if (ibnex.ibnex_reprobe_state != 0) {
7600Sstevel@tonic-gate 					if (ibnex.ibnex_reprobe_state ==
7610Sstevel@tonic-gate 					    IBNEX_REPROBE_ALL_PROGRESS)
7620Sstevel@tonic-gate 						ibnex.ibnex_reprobe_state =
7630Sstevel@tonic-gate 						    IBNEX_REPROBE_ALL_WAIT;
7640Sstevel@tonic-gate 					while (ibnex.ibnex_reprobe_state) {
7650Sstevel@tonic-gate 						cv_wait(&ibnex.ibnex_reprobe_cv,
7660Sstevel@tonic-gate 						    &ibnex.ibnex_mutex);
7670Sstevel@tonic-gate 					}
7680Sstevel@tonic-gate 
7690Sstevel@tonic-gate 					/*
7700Sstevel@tonic-gate 					 * Pending reprobe all completed, return
7710Sstevel@tonic-gate 					 */
7720Sstevel@tonic-gate 					break;
7730Sstevel@tonic-gate 				}
7740Sstevel@tonic-gate 
7750Sstevel@tonic-gate 				/* Check if reprobe for any IOC is pending */
7760Sstevel@tonic-gate 				/* CONSTCOND */
7770Sstevel@tonic-gate 				while (1) {
7780Sstevel@tonic-gate 					ioc_reprobe_pending = 0;
7790Sstevel@tonic-gate 					for (scanp = ibnex.ibnex_ioc_node_head;
7800Sstevel@tonic-gate 					    scanp;
7810Sstevel@tonic-gate 					    scanp = scanp->node_next) {
7820Sstevel@tonic-gate 						if (scanp->node_reprobe_state
7830Sstevel@tonic-gate 						    != 0) {
7840Sstevel@tonic-gate 							ioc_reprobe_pending =
7850Sstevel@tonic-gate 							    1;
7860Sstevel@tonic-gate 							break;
7870Sstevel@tonic-gate 						}
7880Sstevel@tonic-gate 					}
7890Sstevel@tonic-gate 					if (ioc_reprobe_pending == 0) {
7900Sstevel@tonic-gate 						ibnex.ibnex_reprobe_state &=
7910Sstevel@tonic-gate 						    ~IBNEX_REPROBE_IOC_WAIT;
7920Sstevel@tonic-gate 						break;
7930Sstevel@tonic-gate 					}
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate 					ibnex.ibnex_reprobe_state =
7960Sstevel@tonic-gate 					    IBNEX_REPROBE_IOC_WAIT;
7970Sstevel@tonic-gate 					cv_wait(&ibnex.ibnex_reprobe_cv,
7980Sstevel@tonic-gate 					    &ibnex.ibnex_mutex);
7990Sstevel@tonic-gate 				}
8000Sstevel@tonic-gate 
8010Sstevel@tonic-gate 				/*
8020Sstevel@tonic-gate 				 * Set the REPROBE_ALL_PROGRESS state &
8030Sstevel@tonic-gate 				 * start reprobe
8040Sstevel@tonic-gate 				 */
8050Sstevel@tonic-gate 				ibnex.ibnex_reprobe_state =
8060Sstevel@tonic-gate 				    IBNEX_REPROBE_ALL_PROGRESS;
8070Sstevel@tonic-gate 				mutex_exit(&ibnex.ibnex_mutex);
8080Sstevel@tonic-gate 				ibnex_reprobe_ioc_all();
8090Sstevel@tonic-gate 				mutex_enter(&ibnex.ibnex_mutex);
8100Sstevel@tonic-gate 			} else if (ioc.misc_arg == IBNEX_DYN_APID) {
8110Sstevel@tonic-gate 				rv = ibnex_get_dip_from_apid(apid_n, &apid_dip,
8120Sstevel@tonic-gate 				    &nodep);
8130Sstevel@tonic-gate 				ASSERT(rv == IBNEX_DYN_APID);
8140Sstevel@tonic-gate 
8150Sstevel@tonic-gate 				/* Device unconfigured: return */
8160Sstevel@tonic-gate 				if (apid_dip == NULL)
8170Sstevel@tonic-gate 					break;
8180Sstevel@tonic-gate 
8190Sstevel@tonic-gate 				ndi_rele_devi(apid_dip);
8200Sstevel@tonic-gate 				/* Reset return value back to 0 */
8210Sstevel@tonic-gate 				rv = 0;
8220Sstevel@tonic-gate 				if (ibnex.ibnex_reprobe_state != 0 ||
8230Sstevel@tonic-gate 				    nodep->node_reprobe_state != 0) {
8240Sstevel@tonic-gate 					while (ibnex.ibnex_reprobe_state != 0 &&
8250Sstevel@tonic-gate 					    nodep->node_reprobe_state != 0) {
8260Sstevel@tonic-gate 						cv_wait(&ibnex.ibnex_reprobe_cv,
8270Sstevel@tonic-gate 						    &ibnex.ibnex_mutex);
8280Sstevel@tonic-gate 					}
8290Sstevel@tonic-gate 					/* Pending reprobe completed, return */
8300Sstevel@tonic-gate 					break;
8310Sstevel@tonic-gate 				}
8320Sstevel@tonic-gate 
8330Sstevel@tonic-gate 				/* Set node_reprobe_state and start reprobe */
8340Sstevel@tonic-gate 				nodep->node_reprobe_state =
8350Sstevel@tonic-gate 				    IBNEX_NODE_REPROBE_NOTIFY_ON_UPDATE;
8360Sstevel@tonic-gate 				mutex_exit(&ibnex.ibnex_mutex);
8370Sstevel@tonic-gate 				ibnex_reprobe_ioc_dev((void *)apid_dip);
8380Sstevel@tonic-gate 				mutex_enter(&ibnex.ibnex_mutex);
8390Sstevel@tonic-gate 			} else {
8400Sstevel@tonic-gate 				rv = EINVAL;
8410Sstevel@tonic-gate 			}
8420Sstevel@tonic-gate 
8430Sstevel@tonic-gate 			break;
8440Sstevel@tonic-gate 
8450Sstevel@tonic-gate 		default:
8460Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
8470Sstevel@tonic-gate 			    "DEVCTL_AP_CONTROL: ioc:unknown cmd = %x", ioc.cmd);
8480Sstevel@tonic-gate 			break;
8490Sstevel@tonic-gate 		}
8500Sstevel@tonic-gate 	}
8510Sstevel@tonic-gate 	break;
8520Sstevel@tonic-gate 
8530Sstevel@tonic-gate 	case DEVCTL_AP_UNCONFIGURE:
8540Sstevel@tonic-gate 		msg = "DEVCTL_AP_UNCONFIGURE";
8550Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "%s", msg);
8560Sstevel@tonic-gate 
8570Sstevel@tonic-gate 		/* Check for write permissions */
8580Sstevel@tonic-gate 		if (!(mode & FWRITE)) {
8590Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "%s: invalid mode %x",
8600Sstevel@tonic-gate 			    msg, mode);
8610Sstevel@tonic-gate 			rv = EPERM;
8620Sstevel@tonic-gate 			break;
8630Sstevel@tonic-gate 		}
8640Sstevel@tonic-gate 
8650Sstevel@tonic-gate 		if ((apid_n = ibnex_get_apid(dcp)) == '\0') {
8660Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
8670Sstevel@tonic-gate 			    "%s: ibnex_get_apid failed", msg);
8680Sstevel@tonic-gate 			rv = EIO;
8690Sstevel@tonic-gate 			break;
8700Sstevel@tonic-gate 		}
8710Sstevel@tonic-gate 
8720Sstevel@tonic-gate 		/*
8730Sstevel@tonic-gate 		 * If this apid is already seen by IBNEX, get the dip
8740Sstevel@tonic-gate 		 * NOTE: ibnex_get_dip_from_apid() finds a valid dip
8750Sstevel@tonic-gate 		 * and also does a ndi_devi_hold() on the child.
8760Sstevel@tonic-gate 		 */
8770Sstevel@tonic-gate 		rv = ibnex_get_dip_from_apid(apid_n, &apid_dip, &nodep);
8780Sstevel@tonic-gate 		if ((rv != IBNEX_DYN_APID) || (apid_dip == NULL)) {
8790Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "%s: get_dip_from_apid "
8800Sstevel@tonic-gate 			    "failed with 0x%x", msg, rv);
8810Sstevel@tonic-gate 			rv = EIO;
8820Sstevel@tonic-gate 			break;
8830Sstevel@tonic-gate 		}
8840Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "%s: DIP = %p", msg, apid_dip);
8850Sstevel@tonic-gate 
8860Sstevel@tonic-gate 		/* Check if it is a valid node type? */
8870Sstevel@tonic-gate 		if (!IBNEX_VALID_NODE_TYPE(nodep)) {
8880Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "%s: invalid IB node", msg);
8890Sstevel@tonic-gate 			rv = ENODEV;
8900Sstevel@tonic-gate 			ndi_rele_devi(apid_dip);
8910Sstevel@tonic-gate 			break;
8920Sstevel@tonic-gate 		}
8930Sstevel@tonic-gate 
8940Sstevel@tonic-gate 		/*
8950Sstevel@tonic-gate 		 * continue unconfigure operation, only if device node
8960Sstevel@tonic-gate 		 * is already configured. Return EBUSY if another
8970Sstevel@tonic-gate 		 * configure/unconfigure operation is in progress.
8980Sstevel@tonic-gate 		 */
8990Sstevel@tonic-gate 		if (nodep->node_state == IBNEX_CFGADM_CONFIGURING ||
9000Sstevel@tonic-gate 		    nodep->node_state == IBNEX_CFGADM_UNCONFIGURING) {
9010Sstevel@tonic-gate 			rv = EBUSY;
9020Sstevel@tonic-gate 			ndi_rele_devi(apid_dip);
9030Sstevel@tonic-gate 			break;
9040Sstevel@tonic-gate 		}
9050Sstevel@tonic-gate 
9060Sstevel@tonic-gate 		/* do this before to avoid races */
9070Sstevel@tonic-gate 		nodep->node_dip = NULL;
9080Sstevel@tonic-gate 		nodep->node_state = IBNEX_CFGADM_UNCONFIGURING;
9090Sstevel@tonic-gate 
9100Sstevel@tonic-gate 		/*
9110Sstevel@tonic-gate 		 * Call devfs_clean first
9120Sstevel@tonic-gate 		 * NOTE: The code so far is protected by holding ibnex_mutex
9130Sstevel@tonic-gate 		 * and by doing a ndi_devi_hold() on the child.
9140Sstevel@tonic-gate 		 */
9150Sstevel@tonic-gate 		pdip = ddi_get_parent(apid_dip);
9160Sstevel@tonic-gate 		if (i_ddi_node_state(apid_dip) >= DS_INITIALIZED) {
9170Sstevel@tonic-gate 			devnm = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
9180Sstevel@tonic-gate 			(void) ddi_deviname(apid_dip, devnm);
9190Sstevel@tonic-gate 			mutex_exit(&ibnex.ibnex_mutex);
9204411Svikram 			(void) devfs_clean(pdip, devnm + 1, DV_CLEAN_FORCE);
9210Sstevel@tonic-gate 			mutex_enter(&ibnex.ibnex_mutex);
9220Sstevel@tonic-gate 			kmem_free(devnm, MAXNAMELEN + 1);
9230Sstevel@tonic-gate 		}
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate 		mutex_exit(&ibnex.ibnex_mutex);
9260Sstevel@tonic-gate 		ndi_devi_enter(pdip, &circ);
9270Sstevel@tonic-gate 		ndi_rele_devi(apid_dip);
9280Sstevel@tonic-gate 		mutex_enter(&ibnex.ibnex_mutex);
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate 		/* unconfigure the Port/VPPA/HCA_SVC node */
9310Sstevel@tonic-gate 		if (IBNEX_COMMSVC_NODE_TYPE(nodep)) {
9320Sstevel@tonic-gate 			ret_val = ibnex_commsvc_fininode(apid_dip);
9330Sstevel@tonic-gate 		} else if (nodep->node_type == IBNEX_IOC_NODE) {
9340Sstevel@tonic-gate 			/* unconfigure the IOC node */
9350Sstevel@tonic-gate 			ret_val = ibnex_ioc_fininode(apid_dip,
9360Sstevel@tonic-gate 			    &nodep->node_data.ioc_node);
9370Sstevel@tonic-gate 		} else if (nodep->node_type == IBNEX_PSEUDO_NODE) {
9380Sstevel@tonic-gate 			/* unconfigure the pseudo node */
9390Sstevel@tonic-gate 			ret_val = ibnex_pseudo_fininode(apid_dip);
9400Sstevel@tonic-gate 		}
9410Sstevel@tonic-gate 
9420Sstevel@tonic-gate 		/* reset upon failure */
9430Sstevel@tonic-gate 		if (ret_val != IBNEX_SUCCESS) {
9440Sstevel@tonic-gate 			nodep->node_dip = apid_dip;
9450Sstevel@tonic-gate 			nodep->node_state = IBNEX_CFGADM_CONFIGURED;
9468082SRamaswamy.Tummala@Sun.COM 		} else {
9470Sstevel@tonic-gate 			nodep->node_state = IBNEX_CFGADM_UNCONFIGURED;
9488082SRamaswamy.Tummala@Sun.COM 			nodep->node_ap_state = IBNEX_NODE_AP_UNCONFIGURED;
9498082SRamaswamy.Tummala@Sun.COM 		}
9500Sstevel@tonic-gate 
9510Sstevel@tonic-gate 		rv = (ret_val != IBNEX_SUCCESS) ? EIO : 0;
9520Sstevel@tonic-gate 		ndi_devi_exit(pdip, circ);
9530Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "%s: DONE !! It %s", msg,
9540Sstevel@tonic-gate 		    rv ? "failed" : "succeeded");
9550Sstevel@tonic-gate 		break;
9560Sstevel@tonic-gate 
9570Sstevel@tonic-gate 	case DEVCTL_AP_CONFIGURE:
9580Sstevel@tonic-gate 		msg = "DEVCTL_AP_CONFIGURE";
9590Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "%s", msg);
9600Sstevel@tonic-gate 		mutex_exit(&ibnex.ibnex_mutex);
9610Sstevel@tonic-gate 		ndi_devi_enter(ibnex.ibnex_dip, &circ);
9620Sstevel@tonic-gate 		mutex_enter(&ibnex.ibnex_mutex);
9630Sstevel@tonic-gate 
9640Sstevel@tonic-gate 		/* Check for write permissions */
9650Sstevel@tonic-gate 		if (!(mode & FWRITE)) {
9660Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "%s: invalid mode %x",
9670Sstevel@tonic-gate 			    msg, mode);
9680Sstevel@tonic-gate 			rv = EPERM;
9690Sstevel@tonic-gate 			ndi_devi_exit(ibnex.ibnex_dip, circ);
9700Sstevel@tonic-gate 			break;
9710Sstevel@tonic-gate 		}
9720Sstevel@tonic-gate 
9730Sstevel@tonic-gate 		if ((apid_n = ibnex_get_apid(dcp)) == '\0') {
9740Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
9750Sstevel@tonic-gate 			    "%s: ibnex_get_apid failed", msg);
9760Sstevel@tonic-gate 			rv = EIO;
9770Sstevel@tonic-gate 			ndi_devi_exit(ibnex.ibnex_dip, circ);
9780Sstevel@tonic-gate 			break;
9790Sstevel@tonic-gate 		}
9800Sstevel@tonic-gate 
9810Sstevel@tonic-gate 		/*
9828082SRamaswamy.Tummala@Sun.COM 		 * Let's get the node if it already exists.
9838082SRamaswamy.Tummala@Sun.COM 		 * NOTE: ibnex_get_dip_from_apid() finds a valid dip
9848082SRamaswamy.Tummala@Sun.COM 		 * and also does a ndi_devi_hold() on the child.
9858082SRamaswamy.Tummala@Sun.COM 		 */
9868082SRamaswamy.Tummala@Sun.COM 		nodep = NULL;
9878082SRamaswamy.Tummala@Sun.COM 		ret_val = ibnex_get_dip_from_apid(apid_n, &apid_dip, &nodep);
9888082SRamaswamy.Tummala@Sun.COM 		/*
9898082SRamaswamy.Tummala@Sun.COM 		 * We need the node_data but not the dip. If we get a dip for
9908082SRamaswamy.Tummala@Sun.COM 		 * this apid, it means it's already configured. We need to
9918082SRamaswamy.Tummala@Sun.COM 		 * return.
9928082SRamaswamy.Tummala@Sun.COM 		 */
9938082SRamaswamy.Tummala@Sun.COM 		if (apid_dip != NULL) {
9948082SRamaswamy.Tummala@Sun.COM 			ndi_rele_devi(apid_dip);
9958082SRamaswamy.Tummala@Sun.COM 			ndi_devi_exit(ibnex.ibnex_dip, circ);
9968082SRamaswamy.Tummala@Sun.COM 			rv = 0;
9978082SRamaswamy.Tummala@Sun.COM 			break;
9988082SRamaswamy.Tummala@Sun.COM 		}
9998082SRamaswamy.Tummala@Sun.COM 
10008082SRamaswamy.Tummala@Sun.COM 		/*
10018082SRamaswamy.Tummala@Sun.COM 		 * A node exits for this apid but not a dip. So we must have
10028082SRamaswamy.Tummala@Sun.COM 		 * unconfigured it earlier. Set the node_ap_state to configuring
10038082SRamaswamy.Tummala@Sun.COM 		 * to allow configure operation.
10048082SRamaswamy.Tummala@Sun.COM 		 */
10058082SRamaswamy.Tummala@Sun.COM 		if (nodep != NULL) {
10068082SRamaswamy.Tummala@Sun.COM 			nodep->node_ap_state = IBNEX_NODE_AP_CONFIGURING;
10078082SRamaswamy.Tummala@Sun.COM 		}
10088082SRamaswamy.Tummala@Sun.COM 
10098082SRamaswamy.Tummala@Sun.COM 
10108082SRamaswamy.Tummala@Sun.COM 		/*
10110Sstevel@tonic-gate 		 * Five types of APIDs are supported:
10120Sstevel@tonic-gate 		 *	o HCA_GUID,0,service-name	(HCA-SVC device)
10130Sstevel@tonic-gate 		 *	o IOC_GUID 			(IOC device)
10140Sstevel@tonic-gate 		 *	o PORT_GUID,0,service-name	(Port device)
10150Sstevel@tonic-gate 		 *	o pseudo_name,unit-address, 	(Pseudo device)
10160Sstevel@tonic-gate 		 *	o PORT_GUID,P_Key,service-name	(VPPA device)
10170Sstevel@tonic-gate 		 * If the apid doesn't have "," then treat it as an IOC
10180Sstevel@tonic-gate 		 * If the apid has one "," then it is Pseudo device
10190Sstevel@tonic-gate 		 * If the apid has 2 ","s then it is one of the
10200Sstevel@tonic-gate 		 * Port,VPPA,HCA_SVC devices
10210Sstevel@tonic-gate 		 */
10220Sstevel@tonic-gate 		if (strrchr(apid_n, ',') == NULL) {
10230Sstevel@tonic-gate 			ret_val = ibnex_handle_ioc_configure(apid_n);
10240Sstevel@tonic-gate 		} else {
10250Sstevel@tonic-gate 			char *first = strchr(apid_n, ',');
10260Sstevel@tonic-gate 			char *second;
10270Sstevel@tonic-gate 
10280Sstevel@tonic-gate 			second = first ? strchr(first + 1, ',') : NULL;
10290Sstevel@tonic-gate 			if (first != NULL && second == NULL) {
10300Sstevel@tonic-gate 				ret_val = ibnex_handle_pseudo_configure(apid_n);
10310Sstevel@tonic-gate 			} else if (first != NULL && second != NULL) {
10320Sstevel@tonic-gate 				ret_val = ibnex_handle_commsvcnode_configure(
10330Sstevel@tonic-gate 				    apid_n);
10340Sstevel@tonic-gate 			}
10350Sstevel@tonic-gate 		} /* end of else */
10360Sstevel@tonic-gate 
10378082SRamaswamy.Tummala@Sun.COM 		if (ret_val != IBNEX_SUCCESS) {
10380Sstevel@tonic-gate 			rv = (ret_val == IBNEX_BUSY) ? EBUSY : EIO;
10398082SRamaswamy.Tummala@Sun.COM 		} else {
10408082SRamaswamy.Tummala@Sun.COM 			/*
10418082SRamaswamy.Tummala@Sun.COM 			 * Get the newly created node and set the state to
10428082SRamaswamy.Tummala@Sun.COM 			 * IBNEX_NODE_AP_CONFIGURED.
10438082SRamaswamy.Tummala@Sun.COM 			 * NOTE: ibnex_get_dip_from_apid() finds a valid dip
10448082SRamaswamy.Tummala@Sun.COM 			 * and also does a ndi_devi_hold() on the child.
10458082SRamaswamy.Tummala@Sun.COM 			 */
10468082SRamaswamy.Tummala@Sun.COM 			if (!nodep)
10478082SRamaswamy.Tummala@Sun.COM 				ret_val = ibnex_get_dip_from_apid(apid_n,
10488082SRamaswamy.Tummala@Sun.COM 				    &apid_dip, &nodep);
10498082SRamaswamy.Tummala@Sun.COM 			if (nodep != NULL) {
10508082SRamaswamy.Tummala@Sun.COM 				nodep->node_ap_state = IBNEX_NODE_AP_CONFIGURED;
10518082SRamaswamy.Tummala@Sun.COM 			}
10528082SRamaswamy.Tummala@Sun.COM 			if (apid_dip != NULL) {
10538082SRamaswamy.Tummala@Sun.COM 				ndi_rele_devi(apid_dip);
10548082SRamaswamy.Tummala@Sun.COM 			}
10558082SRamaswamy.Tummala@Sun.COM 		}
10560Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "%s: DONE !! It %s", msg,
10570Sstevel@tonic-gate 		    rv ? "failed" : "succeeded");
10580Sstevel@tonic-gate 		ndi_devi_exit(ibnex.ibnex_dip, circ);
10590Sstevel@tonic-gate 		break;
10600Sstevel@tonic-gate 
10610Sstevel@tonic-gate 	default:
10620Sstevel@tonic-gate 		rv = EIO;
10630Sstevel@tonic-gate 		break;
10640Sstevel@tonic-gate 	}
10650Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
10660Sstevel@tonic-gate 
10670Sstevel@tonic-gate 	if ((apid_alloced == B_TRUE) && (apid_n != NULL)) {
10680Sstevel@tonic-gate 		kmem_free(apid_n, apid_len);
10690Sstevel@tonic-gate 	}
10700Sstevel@tonic-gate 
10710Sstevel@tonic-gate 	if (dcp) {
10720Sstevel@tonic-gate 		ndi_dc_freehdl(dcp);
10730Sstevel@tonic-gate 	}
10740Sstevel@tonic-gate 	return (rv);
10750Sstevel@tonic-gate }
10760Sstevel@tonic-gate 
10770Sstevel@tonic-gate 
10780Sstevel@tonic-gate /*
10790Sstevel@tonic-gate  * ibnex_get_num_devices()
10800Sstevel@tonic-gate  *	Figure out how many IOC, VPPA, Pseudo, HCA_SVC and Port devices exist
10810Sstevel@tonic-gate  */
10820Sstevel@tonic-gate static int
ibnex_get_num_devices(void)10830Sstevel@tonic-gate ibnex_get_num_devices(void)
10840Sstevel@tonic-gate {
10850Sstevel@tonic-gate 	int			j, k, l, hca_count;
10860Sstevel@tonic-gate 	int			num_nodes = 0;
10870Sstevel@tonic-gate 	ibdm_hca_list_t		*hca_list, *hcap;
10880Sstevel@tonic-gate 	ibdm_port_attr_t	*pattr;
10890Sstevel@tonic-gate 	ibnex_node_data_t	*nodep;
10900Sstevel@tonic-gate 
10910Sstevel@tonic-gate 	ASSERT(mutex_owned(&ibnex.ibnex_mutex));
10920Sstevel@tonic-gate 
10930Sstevel@tonic-gate 	/* Get a count of HCAs, first. */
10940Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
10950Sstevel@tonic-gate 	ibdm_ibnex_get_hca_list(&hca_list, &hca_count);
10960Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
10970Sstevel@tonic-gate 	for (hcap = hca_list; hca_list != NULL; hca_list = hca_list->hl_next) {
10980Sstevel@tonic-gate 		for (j = 0; j < ibnex.ibnex_nhcasvc_comm_svcs; j++)
10990Sstevel@tonic-gate 			num_nodes++;
11000Sstevel@tonic-gate 		for (j = 0; j < hca_list->hl_nports; j++) {
11010Sstevel@tonic-gate 			for (k = 0; k < ibnex.ibnex_num_comm_svcs; k++)
11020Sstevel@tonic-gate 				num_nodes++;
11030Sstevel@tonic-gate 
11040Sstevel@tonic-gate 			pattr = &hca_list->hl_port_attr[j];
11050Sstevel@tonic-gate 			for (k = 0; k < pattr->pa_npkeys; k++) {
11060Sstevel@tonic-gate 				if (IBNEX_INVALID_PKEY(pattr->pa_pkey_tbl[k].
11070Sstevel@tonic-gate 				    pt_pkey))
11080Sstevel@tonic-gate 					continue;
11090Sstevel@tonic-gate 
11100Sstevel@tonic-gate 				for (l = 0; l < ibnex.ibnex_nvppa_comm_svcs;
11118082SRamaswamy.Tummala@Sun.COM 				    l++, ++num_nodes)
11128082SRamaswamy.Tummala@Sun.COM 					;
11130Sstevel@tonic-gate 			} /* end of pa_npkeys */
11140Sstevel@tonic-gate 		} /* end of  hl_nports */
11150Sstevel@tonic-gate 	} /* end of hca_list != NULL */
11160Sstevel@tonic-gate 	if (hcap)
11170Sstevel@tonic-gate 		ibdm_ibnex_free_hca_list(hcap);
11180Sstevel@tonic-gate 
11190Sstevel@tonic-gate 	/*
11200Sstevel@tonic-gate 	 * Now figure out how many IOC nodes are present.
11210Sstevel@tonic-gate 	 * Add count of configured "diconnected" IOCs
11220Sstevel@tonic-gate 	 */
11230Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
11240Sstevel@tonic-gate 	num_nodes += ibdm_ibnex_get_ioc_count();
11250Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
11260Sstevel@tonic-gate 	num_nodes += ibnex.ibnex_num_disconnect_iocs;
11270Sstevel@tonic-gate 
11280Sstevel@tonic-gate 	/* Last: figure out how many Pseudo nodes are present. */
11290Sstevel@tonic-gate 	for (nodep = ibnex.ibnex_pseudo_node_head; nodep;
11301093Shiremath 	    nodep = nodep->node_next) {
11311093Shiremath 		if (nodep->node_data.pseudo_node.pseudo_merge_node == 1)
11321093Shiremath 			continue;
11331093Shiremath 
11341093Shiremath 		num_nodes++;
11351093Shiremath 	}
11360Sstevel@tonic-gate 	return (num_nodes);
11370Sstevel@tonic-gate }
11380Sstevel@tonic-gate 
11390Sstevel@tonic-gate 
11400Sstevel@tonic-gate /*
11410Sstevel@tonic-gate  * ibnex_get_snapshot()
11420Sstevel@tonic-gate  *	Get a snapshot of all Port/IOC/VPPA/HCA_SVC/Pseudo nodes
11430Sstevel@tonic-gate  *	Snapshot includes IBNEX_NODE_INFO_NVL, IBNEX_NODE_TYPE_NVL,
11440Sstevel@tonic-gate  *	IBNEX_NODE_RSTATE_NVL, IBNEX_NODE_OSTATE_NVL and
11450Sstevel@tonic-gate  *	IBNEX_NODE_COND_NVL
11460Sstevel@tonic-gate  */
11470Sstevel@tonic-gate static int
ibnex_get_snapshot(char ** buf,size_t * sz,int allow_probe)11480Sstevel@tonic-gate ibnex_get_snapshot(char **buf, size_t *sz, int allow_probe)
11490Sstevel@tonic-gate {
11500Sstevel@tonic-gate 	int			i, j, k, l, hca_count;
11510Sstevel@tonic-gate 	nvlist_t		*nvl;
11520Sstevel@tonic-gate 	ib_pkey_t 		pkey;
11530Sstevel@tonic-gate 	boolean_t		found;
11540Sstevel@tonic-gate 	ibdm_ioc_info_t		*ioc_listp;
11550Sstevel@tonic-gate 	ibdm_ioc_info_t		*iocp;
11560Sstevel@tonic-gate 	ibdm_hca_list_t		*hca_list, *hcap;
11570Sstevel@tonic-gate 	ibdm_port_attr_t	*port_attr;
11580Sstevel@tonic-gate 	ibnex_node_data_t	*nodep;
11590Sstevel@tonic-gate 
11600Sstevel@tonic-gate 	ASSERT(mutex_owned(&ibnex.ibnex_mutex));
11610Sstevel@tonic-gate 
11620Sstevel@tonic-gate 	*buf = NULL;
11630Sstevel@tonic-gate 	*sz = 0;
11640Sstevel@tonic-gate 
11650Sstevel@tonic-gate 	if (!ibnex.ibnex_pseudo_inited) {
11660Sstevel@tonic-gate 		mutex_exit(&ibnex.ibnex_mutex);
11670Sstevel@tonic-gate 		ibnex_pseudo_initnodes();
11680Sstevel@tonic-gate 		mutex_enter(&ibnex.ibnex_mutex);
11690Sstevel@tonic-gate 		ibnex.ibnex_pseudo_inited = 1;
11700Sstevel@tonic-gate 	}
11710Sstevel@tonic-gate 
11720Sstevel@tonic-gate 	/* First, Port/VPPA/HCA_SVC nodes */
11730Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
11740Sstevel@tonic-gate 	ibdm_ibnex_get_hca_list(&hca_list, &hca_count);
11750Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
11760Sstevel@tonic-gate 
11770Sstevel@tonic-gate 	(void) nvlist_alloc(&nvl, 0, KM_SLEEP);
11780Sstevel@tonic-gate 
11790Sstevel@tonic-gate 	/* Go thru all the ports of all the HCAs and all the port-svc indices */
11800Sstevel@tonic-gate 	for (hcap = hca_list, i = 0; i < hca_count;
11810Sstevel@tonic-gate 	    hca_list = hca_list->hl_next, i++) {
11820Sstevel@tonic-gate 
11830Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "ibnex_get_snapshot: "
11840Sstevel@tonic-gate 		    "fill in  COMM service HCA_SVC nodes");
11850Sstevel@tonic-gate 		port_attr = hca_list->hl_hca_port_attr;
11860Sstevel@tonic-gate 		for (j = 0; j < ibnex.ibnex_nhcasvc_comm_svcs; j++) {
11870Sstevel@tonic-gate 			if (ibnex_get_commsvcnode_snapshot(&nvl,
11880Sstevel@tonic-gate 			    port_attr->pa_hca_guid,
11890Sstevel@tonic-gate 			    port_attr->pa_hca_guid, j, (ib_pkey_t)0,
11900Sstevel@tonic-gate 			    IBNEX_HCASVC_COMMSVC_NODE) != 0) {
11910Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex",
11920Sstevel@tonic-gate 				    "ibnex_get_snapshot: failed to fill"
11930Sstevel@tonic-gate 				    " HCA_SVC device (%x %x)", i, j);
11940Sstevel@tonic-gate 				ibdm_ibnex_free_hca_list(hcap);
11950Sstevel@tonic-gate 				nvlist_free(nvl);
11960Sstevel@tonic-gate 				return (-1);
11970Sstevel@tonic-gate 			}
11980Sstevel@tonic-gate 
11990Sstevel@tonic-gate 		}
12000Sstevel@tonic-gate 
12010Sstevel@tonic-gate 		for (j = 0; j < hca_list->hl_nports; j++) {
12020Sstevel@tonic-gate 			port_attr = &hca_list->hl_port_attr[j];
12030Sstevel@tonic-gate 
12040Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "ibnex_get_snapshot: "
12050Sstevel@tonic-gate 			    "fill in  COMM service Port nodes");
12060Sstevel@tonic-gate 			for (k = 0; k < ibnex.ibnex_num_comm_svcs; k++) {
12070Sstevel@tonic-gate 
12080Sstevel@tonic-gate 				if (ibnex_get_commsvcnode_snapshot(&nvl,
12090Sstevel@tonic-gate 				    port_attr->pa_hca_guid,
12100Sstevel@tonic-gate 				    port_attr->pa_port_guid, k, (ib_pkey_t)0,
12110Sstevel@tonic-gate 				    IBNEX_PORT_COMMSVC_NODE) != 0) {
12120Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
12130Sstevel@tonic-gate 					    "ibnex_get_snapshot: failed to fill"
12140Sstevel@tonic-gate 					    " Port device (%x %x %x)", i, j, k);
12150Sstevel@tonic-gate 					ibdm_ibnex_free_hca_list(hcap);
12160Sstevel@tonic-gate 					nvlist_free(nvl);
12170Sstevel@tonic-gate 					return (-1);
12180Sstevel@tonic-gate 				}
12190Sstevel@tonic-gate 
12200Sstevel@tonic-gate 			} /* end of num_comm_svcs for loop */
12210Sstevel@tonic-gate 
12220Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "ibnex_get_snapshot: "
12230Sstevel@tonic-gate 			    "fill in  VPPA service port nodes");
12240Sstevel@tonic-gate 			for (l = 0; l < port_attr->pa_npkeys; l++) {
12250Sstevel@tonic-gate 				pkey = port_attr->pa_pkey_tbl[l].pt_pkey;
12260Sstevel@tonic-gate 				if (IBNEX_INVALID_PKEY(pkey))
12270Sstevel@tonic-gate 					continue;
12280Sstevel@tonic-gate 
12290Sstevel@tonic-gate 				for (k = 0; k < ibnex.ibnex_nvppa_comm_svcs;
12300Sstevel@tonic-gate 				    k++) {
12310Sstevel@tonic-gate 
12320Sstevel@tonic-gate 					if (ibnex_get_commsvcnode_snapshot(&nvl,
12330Sstevel@tonic-gate 					    port_attr->pa_hca_guid,
12340Sstevel@tonic-gate 					    port_attr->pa_port_guid, k, pkey,
12350Sstevel@tonic-gate 					    IBNEX_VPPA_COMMSVC_NODE) != 0) {
12360Sstevel@tonic-gate 						IBTF_DPRINTF_L2("ibnex",
12370Sstevel@tonic-gate 						    "ibnex_get_snapshot: "
12380Sstevel@tonic-gate 						    "failed to fill VPPA "
12390Sstevel@tonic-gate 						    "device (%x %x %x % x)",
12400Sstevel@tonic-gate 						    i, j, k, l);
12410Sstevel@tonic-gate 						ibdm_ibnex_free_hca_list(hcap);
12420Sstevel@tonic-gate 						nvlist_free(nvl);
12430Sstevel@tonic-gate 						return (-1);
12440Sstevel@tonic-gate 					}
12450Sstevel@tonic-gate 				} /* end of ibnex_nvppa_comm_svcs loop */
12460Sstevel@tonic-gate 
12470Sstevel@tonic-gate 			} /* end of pa_npkeys for loop */
12480Sstevel@tonic-gate 
12490Sstevel@tonic-gate 		} /* end of hl_nports for loop */
12500Sstevel@tonic-gate 
12510Sstevel@tonic-gate 	} /* end of hca_count for loop */
12520Sstevel@tonic-gate 
12530Sstevel@tonic-gate 	if (hcap)
12540Sstevel@tonic-gate 		ibdm_ibnex_free_hca_list(hcap);
12550Sstevel@tonic-gate 
12560Sstevel@tonic-gate 	/* save it to free up the entire list */
12570Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
12580Sstevel@tonic-gate 	iocp = ioc_listp = ibdm_ibnex_get_ioc_list(allow_probe);
12590Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
12600Sstevel@tonic-gate 	for (; ioc_listp != NULL; ioc_listp = ioc_listp->ioc_next) {
12610Sstevel@tonic-gate 
12620Sstevel@tonic-gate 		/*
12630Sstevel@tonic-gate 		 * Say we have N IOCs and all were deleted from ibnex
12640Sstevel@tonic-gate 		 * but not from IBDM
12650Sstevel@tonic-gate 		 */
12660Sstevel@tonic-gate 		if (ibnex.ibnex_ioc_node_head == NULL) {
12670Sstevel@tonic-gate 			if (ibnex_fill_ioc_tmp(&nvl, ioc_listp) != 0) {
12680Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "ibnex_get_snapshot: "
12690Sstevel@tonic-gate 				    "filling NVL data failed");
12700Sstevel@tonic-gate 				ibdm_ibnex_free_ioc_list(iocp);
12710Sstevel@tonic-gate 				nvlist_free(nvl);
12720Sstevel@tonic-gate 				return (-1);
12730Sstevel@tonic-gate 			}
12740Sstevel@tonic-gate 			continue;
12750Sstevel@tonic-gate 
12760Sstevel@tonic-gate 		} else {
12770Sstevel@tonic-gate 			found = B_FALSE;
12780Sstevel@tonic-gate 
12790Sstevel@tonic-gate 			/* Check first, if we have already seen this IOC? */
12800Sstevel@tonic-gate 			for (nodep = ibnex.ibnex_ioc_node_head; nodep != NULL;
12810Sstevel@tonic-gate 			    nodep = nodep->node_next) {
12820Sstevel@tonic-gate 				if (ioc_listp->ioc_profile.ioc_guid ==
12830Sstevel@tonic-gate 				    nodep->node_data.ioc_node.ioc_guid) {
12840Sstevel@tonic-gate 					found = B_TRUE;
12850Sstevel@tonic-gate 					break;
12860Sstevel@tonic-gate 				}
12870Sstevel@tonic-gate 			}
12880Sstevel@tonic-gate 
12890Sstevel@tonic-gate 
12900Sstevel@tonic-gate 			/* have we seen this IOC before? */
12910Sstevel@tonic-gate 			if (found == B_TRUE) {
12920Sstevel@tonic-gate 				if (ibnex_fill_nodeinfo(&nvl, nodep,
12930Sstevel@tonic-gate 				    &ioc_listp->ioc_profile) != 0) {
12940Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
12950Sstevel@tonic-gate 					    "ibnex_get_snapshot: filling NVL "
12960Sstevel@tonic-gate 					    "for IOC node %p failed", nodep);
12970Sstevel@tonic-gate 					ibdm_ibnex_free_ioc_list(iocp);
12980Sstevel@tonic-gate 					nvlist_free(nvl);
12990Sstevel@tonic-gate 					return (-1);
13000Sstevel@tonic-gate 				}
13010Sstevel@tonic-gate 
13020Sstevel@tonic-gate 			} else {
13030Sstevel@tonic-gate 
13040Sstevel@tonic-gate 				if (ibnex_fill_ioc_tmp(&nvl, ioc_listp) != 0) {
13050Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
13060Sstevel@tonic-gate 					    "ibnex_get_snapshot: filling NVL "
13070Sstevel@tonic-gate 					    "tmp for IOC node %p failed",
13080Sstevel@tonic-gate 					    ioc_listp);
13090Sstevel@tonic-gate 					ibdm_ibnex_free_ioc_list(iocp);
13100Sstevel@tonic-gate 					nvlist_free(nvl);
13110Sstevel@tonic-gate 					return (-1);
13120Sstevel@tonic-gate 				}
13130Sstevel@tonic-gate 			}
13140Sstevel@tonic-gate 
13150Sstevel@tonic-gate 		} /* end of else ibnex_ioc_node_head == NULL */
13160Sstevel@tonic-gate 	} /* end of external for */
13170Sstevel@tonic-gate 
13180Sstevel@tonic-gate 	ibdm_ibnex_free_ioc_list(iocp);
13190Sstevel@tonic-gate 
13200Sstevel@tonic-gate 	/*
13210Sstevel@tonic-gate 	 * Add list of "disconnected" IOCs, not unconfigured.
13220Sstevel@tonic-gate 	 */
13230Sstevel@tonic-gate 	for (nodep = ibnex.ibnex_ioc_node_head; nodep != NULL;
13240Sstevel@tonic-gate 	    nodep = nodep->node_next) {
13250Sstevel@tonic-gate 		if (nodep->node_data.ioc_node.ioc_ngids == 0 &&
13260Sstevel@tonic-gate 		    nodep->node_data.ioc_node.ioc_profile != NULL &&
13270Sstevel@tonic-gate 		    nodep->node_state != IBNEX_CFGADM_UNCONFIGURED) {
13280Sstevel@tonic-gate 			if (ibnex_fill_nodeinfo(&nvl, nodep,
13290Sstevel@tonic-gate 			    nodep->node_data.ioc_node.ioc_profile) != 0) {
13300Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
13310Sstevel@tonic-gate 					    "ibnex_get_snapshot: filling NVL "
13320Sstevel@tonic-gate 					    "for disconnected IOC node %p "
13330Sstevel@tonic-gate 					    "failed", nodep);
13340Sstevel@tonic-gate 					nvlist_free(nvl);
13350Sstevel@tonic-gate 					return (-1);
13360Sstevel@tonic-gate 			}
13370Sstevel@tonic-gate 		}
13380Sstevel@tonic-gate 	}
13390Sstevel@tonic-gate 
13400Sstevel@tonic-gate 	/* lastly; pseudo nodes */
13410Sstevel@tonic-gate 	for (nodep = ibnex.ibnex_pseudo_node_head; nodep;
13420Sstevel@tonic-gate 	    nodep = nodep->node_next) {
13431093Shiremath 		if (nodep->node_data.pseudo_node.pseudo_merge_node == 1)
13441093Shiremath 			continue;
13450Sstevel@tonic-gate 		if (ibnex_fill_nodeinfo(&nvl, nodep, NULL) != 0) {
13460Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_get_snapshot: "
13470Sstevel@tonic-gate 			    "filling NVL data for Pseudo %p failed", nodep);
13480Sstevel@tonic-gate 			nvlist_free(nvl);
13490Sstevel@tonic-gate 			return (-1);
13500Sstevel@tonic-gate 		}
13510Sstevel@tonic-gate 	}
13520Sstevel@tonic-gate 
13530Sstevel@tonic-gate 	/* pack the data into the buffer */
13540Sstevel@tonic-gate 	if (nvlist_pack(nvl, buf, sz, NV_ENCODE_NATIVE, KM_SLEEP)) {
13550Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex",
13560Sstevel@tonic-gate 		    "ibnex_get_snapshot: nvlist_pack failed");
13570Sstevel@tonic-gate 		nvlist_free(nvl);
13580Sstevel@tonic-gate 		return (-1);
13590Sstevel@tonic-gate 	}
13600Sstevel@tonic-gate 
13610Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "ibnex_get_snapshot: size = 0x%x", *sz);
13620Sstevel@tonic-gate 	nvlist_free(nvl);
13630Sstevel@tonic-gate 	return (0);
13640Sstevel@tonic-gate }
13650Sstevel@tonic-gate 
13660Sstevel@tonic-gate 
13670Sstevel@tonic-gate /*
13680Sstevel@tonic-gate  * ibnex_get_commsvcnode_snapshot()
13690Sstevel@tonic-gate  *	A utility function to fill in a "dummy" Port/VPPA/HCA_SVC
13700Sstevel@tonic-gate  *	information. Cfgadm plugin will display all Port/VPPA/
13710Sstevel@tonic-gate  *	HCA_SVCs seen even if they are not all configured by IBNEX.
13720Sstevel@tonic-gate  *
13730Sstevel@tonic-gate  *	This function uses information from IBDM to fill up Port/VPPA/
13740Sstevel@tonic-gate  *	HCA_SVC snapshot. If none exists then it makes up a "temporary"
13750Sstevel@tonic-gate  *	node which will be displayed as "connected/unconfigured/unknown".
13760Sstevel@tonic-gate  *
13770Sstevel@tonic-gate  *	For HCA_SVC node port_guid will be same as hca_guid.
13780Sstevel@tonic-gate  */
13790Sstevel@tonic-gate static int
ibnex_get_commsvcnode_snapshot(nvlist_t ** nvlpp,ib_guid_t hca_guid,ib_guid_t port_guid,int svc_index,ib_pkey_t p_key,ibnex_node_type_t node_type)13800Sstevel@tonic-gate ibnex_get_commsvcnode_snapshot(nvlist_t **nvlpp, ib_guid_t hca_guid,
13810Sstevel@tonic-gate     ib_guid_t port_guid, int svc_index, ib_pkey_t p_key,
13820Sstevel@tonic-gate     ibnex_node_type_t node_type)
13830Sstevel@tonic-gate {
13840Sstevel@tonic-gate 	int			rval;
13850Sstevel@tonic-gate 	dev_info_t		*dip = NULL;
13860Sstevel@tonic-gate 	ibnex_node_data_t	*nodep;
13870Sstevel@tonic-gate 	ibnex_node_data_t	dummy;
13880Sstevel@tonic-gate 	ibnex_node_data_t	*tmp = &dummy;
13890Sstevel@tonic-gate 
13900Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "ibnex_get_commsvcnode_snapshot: "
13910Sstevel@tonic-gate 	    "HCA GUID: %llX Port GUID: %llX svc_index = %x pkey = %x "
13920Sstevel@tonic-gate 	    "node_type = %x", hca_guid, port_guid, svc_index, p_key, node_type);
13930Sstevel@tonic-gate 
13940Sstevel@tonic-gate 	/* check if this node was seen before? */
1395*12163SRamaswamy.Tummala@Sun.COM 	rval = ibnex_get_node_and_dip_from_guid(port_guid, svc_index, p_key,
1396*12163SRamaswamy.Tummala@Sun.COM 	    &nodep, &dip);
1397*12163SRamaswamy.Tummala@Sun.COM 	if (rval == IBNEX_SUCCESS && nodep != NULL) {
13980Sstevel@tonic-gate 
13990Sstevel@tonic-gate 		if (ibnex_fill_nodeinfo(nvlpp, nodep, NULL) != 0) {
14000Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
14010Sstevel@tonic-gate 			    "ibnex_get_commsvcnode_snapshot: failed to fill "
14020Sstevel@tonic-gate 			    "Port/VPPA device node %p NVL data", nodep);
14030Sstevel@tonic-gate 			return (-1);
14040Sstevel@tonic-gate 		}
14050Sstevel@tonic-gate 
14060Sstevel@tonic-gate 	} else {
14070Sstevel@tonic-gate 		/* Fake up a Port/VPPA/HCA_SVC node */
14080Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "ibnex_get_commsvcnode_snapshot: "
14090Sstevel@tonic-gate 		    "VPPA/Port/HCA_SVC not seen by ibnex");
14100Sstevel@tonic-gate 		bzero(tmp, sizeof (ibnex_node_data_t));
14110Sstevel@tonic-gate 		tmp->node_type = node_type;
14120Sstevel@tonic-gate 		tmp->node_data.port_node.port_guid = port_guid;
14130Sstevel@tonic-gate 		tmp->node_data.port_node.port_hcaguid = hca_guid;
14140Sstevel@tonic-gate 		tmp->node_data.port_node.port_commsvc_idx = svc_index;
14150Sstevel@tonic-gate 		/* Fill P_Key only for VPPA nodes */
14160Sstevel@tonic-gate 		if (node_type == IBNEX_VPPA_COMMSVC_NODE) {
14170Sstevel@tonic-gate 			tmp->node_data.port_node.port_pkey = p_key;
14180Sstevel@tonic-gate 		}
14190Sstevel@tonic-gate 
14200Sstevel@tonic-gate 		if (ibnex_fill_nodeinfo(nvlpp, tmp, NULL) != 0) {
14210Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
14220Sstevel@tonic-gate 			    "ibnex_get_commsvcnode_snapshot: failed to fill "
14230Sstevel@tonic-gate 			    "tmp Port/VPPA device node %p NVL data", tmp);
14240Sstevel@tonic-gate 			return (-1);
14250Sstevel@tonic-gate 		}
14260Sstevel@tonic-gate 	}
14270Sstevel@tonic-gate 
14280Sstevel@tonic-gate 	return (0);
14290Sstevel@tonic-gate }
14300Sstevel@tonic-gate 
14310Sstevel@tonic-gate 
14320Sstevel@tonic-gate /*
14330Sstevel@tonic-gate  * ibnex_fill_ioc_tmp()
14340Sstevel@tonic-gate  *	A utility function to fill in a "dummy" IOC information.
14350Sstevel@tonic-gate  *	Cfgadm plugin will display all IOCs seen by IBDM even if they
14360Sstevel@tonic-gate  *	are configured or not by IBNEX.
14370Sstevel@tonic-gate  *
14380Sstevel@tonic-gate  *	This function uses information from IBDM to fill up a
14390Sstevel@tonic-gate  *	dummy IOC information. It will be displayed as
14400Sstevel@tonic-gate  *	"connected/unconfigured/unknown".
14410Sstevel@tonic-gate  */
14420Sstevel@tonic-gate static int
ibnex_fill_ioc_tmp(nvlist_t ** nvlpp,ibdm_ioc_info_t * ioc_listp)14430Sstevel@tonic-gate ibnex_fill_ioc_tmp(nvlist_t **nvlpp, ibdm_ioc_info_t *ioc_listp)
14440Sstevel@tonic-gate {
14450Sstevel@tonic-gate 	ibnex_node_data_t	dummy;
14460Sstevel@tonic-gate 	ibnex_node_data_t	*nodep = &dummy;
14470Sstevel@tonic-gate 
14480Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tibnex_fill_ioc_tmp:");
14490Sstevel@tonic-gate 
14500Sstevel@tonic-gate 	bzero(nodep, sizeof (ibnex_node_data_t));
14510Sstevel@tonic-gate 	nodep->node_type = IBNEX_IOC_NODE;
14520Sstevel@tonic-gate 	nodep->node_data.ioc_node.ioc_guid = ioc_listp->ioc_profile.ioc_guid;
14530Sstevel@tonic-gate 	nodep->node_data.ioc_node.iou_guid = ioc_listp->ioc_iou_guid;
14540Sstevel@tonic-gate 	(void) strncpy(nodep->node_data.ioc_node.ioc_id_string,
14550Sstevel@tonic-gate 	    (char *)ioc_listp->ioc_profile.ioc_id_string,
14560Sstevel@tonic-gate 	    IB_DM_IOC_ID_STRING_LEN);
14570Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tibnex_fill_ioc_tmp: %s",
14580Sstevel@tonic-gate 	    nodep->node_data.ioc_node.ioc_id_string);
14590Sstevel@tonic-gate 
14600Sstevel@tonic-gate 	if (ibnex_fill_nodeinfo(nvlpp, nodep, &ioc_listp->ioc_profile) != 0) {
14610Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "\tibnex_fill_ioc_tmp: filling NVL "
14620Sstevel@tonic-gate 		    "data for IOC node %p failed", nodep);
14630Sstevel@tonic-gate 		return (-1);
14640Sstevel@tonic-gate 	}
14650Sstevel@tonic-gate 
14660Sstevel@tonic-gate 	return (0);
14670Sstevel@tonic-gate }
14680Sstevel@tonic-gate 
14690Sstevel@tonic-gate 
14700Sstevel@tonic-gate /*
14710Sstevel@tonic-gate  * ibnex_fill_nodeinfo()
14720Sstevel@tonic-gate  *	A utility function to fill in to the NVLIST information about
14730Sstevel@tonic-gate  *	a Port/IOC/VPPA/HCA_SVC/Pseudo driver that is then passed over
14740Sstevel@tonic-gate  *	to cfgadm utility for display. This information is used only
14750Sstevel@tonic-gate  *	for cfgadm -ll displays.
14760Sstevel@tonic-gate  *
14770Sstevel@tonic-gate  *	Information that is filled in here is:-
14780Sstevel@tonic-gate  *		AP_ID_NAME
14790Sstevel@tonic-gate  *		AP_ID_INFO
14800Sstevel@tonic-gate  *		AP_ID_TYPE
14810Sstevel@tonic-gate  *		AP_ID_OCCUPANT_STATE
14820Sstevel@tonic-gate  *		AP_ID_RECEPTACLE_STATE
14830Sstevel@tonic-gate  *		AP_ID_CONDITION
14840Sstevel@tonic-gate  */
14850Sstevel@tonic-gate static int
ibnex_fill_nodeinfo(nvlist_t ** nvlpp,ibnex_node_data_t * node_datap,void * tmp)14860Sstevel@tonic-gate ibnex_fill_nodeinfo(nvlist_t **nvlpp, ibnex_node_data_t *node_datap, void *tmp)
14870Sstevel@tonic-gate {
14880Sstevel@tonic-gate 	char			*svcname;
14890Sstevel@tonic-gate 	char			*node_name;
14900Sstevel@tonic-gate 	char			apid[IBTL_IBNEX_APID_LEN];
14910Sstevel@tonic-gate 	char			info_data[MAXNAMELEN];
14920Sstevel@tonic-gate 	ib_dm_ioc_ctrl_profile_t *profilep;
14930Sstevel@tonic-gate 	devctl_ap_state_t	state;
14940Sstevel@tonic-gate 
14950Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: 0x%x addr is %p",
14960Sstevel@tonic-gate 	    node_datap->node_type, node_datap);
14970Sstevel@tonic-gate 
14980Sstevel@tonic-gate 	if (node_datap->node_type == IBNEX_PORT_COMMSVC_NODE) {
14990Sstevel@tonic-gate 		svcname = ibnex.ibnex_comm_svc_names[node_datap->node_data.
15000Sstevel@tonic-gate 		    port_node.port_commsvc_idx];
15010Sstevel@tonic-gate 		(void) snprintf(apid, IBTL_IBNEX_APID_LEN, "%llX,0,%s",
15020Sstevel@tonic-gate 		    (longlong_t)node_datap->node_data.port_node.port_guid,
15030Sstevel@tonic-gate 		    svcname);
15040Sstevel@tonic-gate 
15050Sstevel@tonic-gate 		/* Node APID */
15060Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_APID_NVL, apid)) {
15070Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
15080Sstevel@tonic-gate 			    "failed to fill %s", IBNEX_NODE_APID_NVL);
15090Sstevel@tonic-gate 			return (-1);
15100Sstevel@tonic-gate 		}
15110Sstevel@tonic-gate 
15120Sstevel@tonic-gate 		/* Node Info */
15130Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_INFO_NVL, svcname)) {
15140Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
15150Sstevel@tonic-gate 			    "failed to fill Port %s", IBNEX_NODE_INFO_NVL);
15160Sstevel@tonic-gate 			return (-1);
15170Sstevel@tonic-gate 		}
15180Sstevel@tonic-gate 
15190Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: "
15200Sstevel@tonic-gate 		    "Port %s = %s, %s = %s",
15210Sstevel@tonic-gate 		    IBNEX_NODE_INFO_NVL, apid, IBNEX_NODE_APID_NVL, svcname);
15220Sstevel@tonic-gate 
15230Sstevel@tonic-gate 	} else if (node_datap->node_type == IBNEX_VPPA_COMMSVC_NODE) {
15240Sstevel@tonic-gate 		svcname = ibnex.ibnex_vppa_comm_svc_names[node_datap->node_data.
15250Sstevel@tonic-gate 		    port_node.port_commsvc_idx];
15260Sstevel@tonic-gate 		(void) snprintf(apid, IBTL_IBNEX_APID_LEN, "%llX,%x,%s",
15270Sstevel@tonic-gate 		    (longlong_t)node_datap->node_data.port_node.port_guid,
15280Sstevel@tonic-gate 		    node_datap->node_data.port_node.port_pkey, svcname);
15290Sstevel@tonic-gate 
15300Sstevel@tonic-gate 		/* Node APID */
15310Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_APID_NVL, apid)) {
15320Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
15330Sstevel@tonic-gate 			    "failed to fill %s", IBNEX_NODE_APID_NVL);
15340Sstevel@tonic-gate 			return (-1);
15350Sstevel@tonic-gate 		}
15360Sstevel@tonic-gate 
15370Sstevel@tonic-gate 		/* Node Info */
15380Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_INFO_NVL, svcname)) {
15390Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
15400Sstevel@tonic-gate 			    "failed to fill VPPA %s", IBNEX_NODE_INFO_NVL);
15410Sstevel@tonic-gate 			return (-1);
15420Sstevel@tonic-gate 		}
15430Sstevel@tonic-gate 
15440Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: "
15450Sstevel@tonic-gate 		    "VPPA %s = %s, %s = %s",
15460Sstevel@tonic-gate 		    IBNEX_NODE_APID_NVL, apid, IBNEX_NODE_INFO_NVL, svcname);
15470Sstevel@tonic-gate 
15480Sstevel@tonic-gate 	} else if (node_datap->node_type == IBNEX_HCASVC_COMMSVC_NODE) {
15490Sstevel@tonic-gate 		svcname = ibnex.ibnex_hcasvc_comm_svc_names[node_datap->
15500Sstevel@tonic-gate 		    node_data.port_node.port_commsvc_idx];
15510Sstevel@tonic-gate 		(void) snprintf(apid, IBTL_IBNEX_APID_LEN, "%llX,0,%s",
15520Sstevel@tonic-gate 		    (longlong_t)node_datap->node_data.port_node.port_guid,
15530Sstevel@tonic-gate 		    svcname);
15540Sstevel@tonic-gate 
15550Sstevel@tonic-gate 		/* Node APID */
15560Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_APID_NVL, apid)) {
15570Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
15580Sstevel@tonic-gate 			    "failed to fill %s", IBNEX_NODE_APID_NVL);
15590Sstevel@tonic-gate 			return (-1);
15600Sstevel@tonic-gate 		}
15610Sstevel@tonic-gate 
15620Sstevel@tonic-gate 		/* Node Info */
15630Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_INFO_NVL, svcname)) {
15640Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
15650Sstevel@tonic-gate 			    "failed to fill Port %s", IBNEX_NODE_INFO_NVL);
15660Sstevel@tonic-gate 			return (-1);
15670Sstevel@tonic-gate 		}
15680Sstevel@tonic-gate 
15690Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: "
15700Sstevel@tonic-gate 		    "Port %s = %s, %s = %s",
15710Sstevel@tonic-gate 		    IBNEX_NODE_INFO_NVL, apid, IBNEX_NODE_APID_NVL, svcname);
15720Sstevel@tonic-gate 
15730Sstevel@tonic-gate 	} else if (node_datap->node_type == IBNEX_IOC_NODE) {
15740Sstevel@tonic-gate 
15750Sstevel@tonic-gate 		/*
15760Sstevel@tonic-gate 		 * get the IOC profile pointer from the args
15770Sstevel@tonic-gate 		 */
15780Sstevel@tonic-gate 		profilep = (ib_dm_ioc_ctrl_profile_t *)tmp;
15790Sstevel@tonic-gate 		IBNEX_FORM_GUID(apid, IBTL_IBNEX_APID_LEN, profilep->ioc_guid);
15800Sstevel@tonic-gate 
15810Sstevel@tonic-gate 		/* Node APID */
15820Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_APID_NVL, apid)) {
15830Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
15840Sstevel@tonic-gate 			    "failed to fill in %s", IBNEX_NODE_APID_NVL);
15850Sstevel@tonic-gate 			return (-1);
15860Sstevel@tonic-gate 		}
15870Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: %s %s",
15880Sstevel@tonic-gate 		    IBNEX_NODE_APID_NVL, apid);
15890Sstevel@tonic-gate 
15900Sstevel@tonic-gate 		/*
15910Sstevel@tonic-gate 		 * IOC "info" filed will display the following fields
15920Sstevel@tonic-gate 		 * VendorID, IOCDeviceID, DeviceVersion, SubsystemVendorID,
15930Sstevel@tonic-gate 		 * SubsystemID, Class, Subclass, Protocol, ProtocolVersion
15940Sstevel@tonic-gate 		 */
15950Sstevel@tonic-gate 		(void) snprintf(info_data, MAXNAMELEN,
15960Sstevel@tonic-gate 		    "VID: 0x%x DEVID: 0x%x VER: 0x%x SUBSYS_VID: 0x%x "
15970Sstevel@tonic-gate 		    "SUBSYS_ID: 0x%x CLASS: 0x%x SUBCLASS: 0x%x PROTO: 0x%x "
15980Sstevel@tonic-gate 		    "PROTOVER: 0x%x ID_STRING: %s", profilep->ioc_vendorid,
15990Sstevel@tonic-gate 		    profilep->ioc_deviceid, profilep->ioc_device_ver,
16000Sstevel@tonic-gate 		    profilep->ioc_subsys_vendorid, profilep->ioc_subsys_id,
16010Sstevel@tonic-gate 		    profilep->ioc_io_class, profilep->ioc_io_subclass,
16020Sstevel@tonic-gate 		    profilep->ioc_protocol, profilep->ioc_protocol_ver,
16030Sstevel@tonic-gate 		    (char *)profilep->ioc_id_string);
16040Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: %s", info_data);
16050Sstevel@tonic-gate 
16060Sstevel@tonic-gate 		/* Node Info */
16070Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_INFO_NVL, info_data)) {
16080Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
16090Sstevel@tonic-gate 			    "failed to fill IOC %s", IBNEX_NODE_INFO_NVL);
16100Sstevel@tonic-gate 			return (-1);
16110Sstevel@tonic-gate 		}
16120Sstevel@tonic-gate 
16130Sstevel@tonic-gate 	} else if (node_datap->node_type == IBNEX_PSEUDO_NODE) {
16140Sstevel@tonic-gate 		(void) snprintf(apid, IBTL_IBNEX_APID_LEN, "%s",
16150Sstevel@tonic-gate 		    node_datap->node_data.pseudo_node.pseudo_node_addr);
16160Sstevel@tonic-gate 
16170Sstevel@tonic-gate 		/* Node APID */
16180Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_APID_NVL, apid)) {
16190Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
16200Sstevel@tonic-gate 			    "failed to fill in %s", IBNEX_NODE_APID_NVL);
16210Sstevel@tonic-gate 			return (-1);
16220Sstevel@tonic-gate 		}
16230Sstevel@tonic-gate 
16240Sstevel@tonic-gate 		/* Node Info */
16250Sstevel@tonic-gate 		node_name = node_datap->node_data.pseudo_node.pseudo_devi_name;
16260Sstevel@tonic-gate 		(void) snprintf(info_data, MAXNAMELEN,
16270Sstevel@tonic-gate 		    "Pseudo Driver = \"%s\", Unit-address = \"%s\"",
16280Sstevel@tonic-gate 		    node_name, apid + strlen(node_name) + 1);
16290Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_INFO_NVL, info_data)) {
16300Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
16310Sstevel@tonic-gate 			    "failed to fill Pseudo %s", IBNEX_NODE_INFO_NVL);
16320Sstevel@tonic-gate 			return (-1);
16330Sstevel@tonic-gate 		}
16340Sstevel@tonic-gate 
16350Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: Pseudo %s = %s,"
16360Sstevel@tonic-gate 		    "%s = %s", IBNEX_NODE_APID_NVL, apid, IBNEX_NODE_INFO_NVL,
16370Sstevel@tonic-gate 		    info_data);
16380Sstevel@tonic-gate 	}
16390Sstevel@tonic-gate 
16400Sstevel@tonic-gate 	/* Node type */
16410Sstevel@tonic-gate 	if (nvlist_add_int32(*nvlpp, IBNEX_NODE_TYPE_NVL,
16420Sstevel@tonic-gate 	    node_datap->node_type)) {
16430Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
16440Sstevel@tonic-gate 		    "failed to fill in %s", IBNEX_NODE_TYPE_NVL);
16450Sstevel@tonic-gate 		return (-1);
16460Sstevel@tonic-gate 	}
16470Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: %s %d",
16480Sstevel@tonic-gate 	    IBNEX_NODE_TYPE_NVL, node_datap->node_type);
16490Sstevel@tonic-gate 
16500Sstevel@tonic-gate 	/* figure out "ostate", "rstate" and "condition" */
1651*12163SRamaswamy.Tummala@Sun.COM 	ibnex_figure_ap_devstate(node_datap, &state);
16520Sstevel@tonic-gate 
16530Sstevel@tonic-gate 	if (nvlist_add_int32(*nvlpp, IBNEX_NODE_RSTATE_NVL, state.ap_rstate)) {
16540Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
16550Sstevel@tonic-gate 		    "failed to fill in %s", IBNEX_NODE_RSTATE_NVL);
16560Sstevel@tonic-gate 		return (-1);
16570Sstevel@tonic-gate 	}
16580Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: %s %d",
16590Sstevel@tonic-gate 	    IBNEX_NODE_RSTATE_NVL, state.ap_rstate);
16600Sstevel@tonic-gate 
16610Sstevel@tonic-gate 	if (nvlist_add_int32(*nvlpp, IBNEX_NODE_OSTATE_NVL, state.ap_ostate)) {
16620Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
16630Sstevel@tonic-gate 		    "failed to fill in %s", IBNEX_NODE_OSTATE_NVL);
16640Sstevel@tonic-gate 		return (-1);
16650Sstevel@tonic-gate 	}
16660Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: %s %d",
16670Sstevel@tonic-gate 	    IBNEX_NODE_OSTATE_NVL, state.ap_ostate);
16680Sstevel@tonic-gate 
16690Sstevel@tonic-gate 	if (nvlist_add_int32(*nvlpp, IBNEX_NODE_COND_NVL, state.ap_condition)) {
16700Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
16710Sstevel@tonic-gate 		    "failed to fill in %s", IBNEX_NODE_COND_NVL);
16720Sstevel@tonic-gate 		return (-1);
16730Sstevel@tonic-gate 	}
16740Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: %s %d",
16750Sstevel@tonic-gate 	    IBNEX_NODE_COND_NVL, state.ap_condition);
16760Sstevel@tonic-gate 
16770Sstevel@tonic-gate 	return (0);
16780Sstevel@tonic-gate }
16790Sstevel@tonic-gate 
16800Sstevel@tonic-gate 
16810Sstevel@tonic-gate /*
16820Sstevel@tonic-gate  * ibnex_figure_ap_devstate()
16830Sstevel@tonic-gate  *	Fills the "devctl_ap_state_t" for a given ap_id
16840Sstevel@tonic-gate  *
16850Sstevel@tonic-gate  *	currently it assumes that we don't support "error_code" and
16860Sstevel@tonic-gate  *	"last_change" value.
16870Sstevel@tonic-gate  */
16880Sstevel@tonic-gate static void
ibnex_figure_ap_devstate(ibnex_node_data_t * nodep,devctl_ap_state_t * ap_state)1689*12163SRamaswamy.Tummala@Sun.COM ibnex_figure_ap_devstate(ibnex_node_data_t *nodep, devctl_ap_state_t *ap_state)
16900Sstevel@tonic-gate {
1691*12163SRamaswamy.Tummala@Sun.COM 	IBTF_DPRINTF_L5("ibnex", "ibnex_figure_ap_devstate: nodep = %p", nodep);
16920Sstevel@tonic-gate 
16930Sstevel@tonic-gate 	ap_state->ap_rstate = AP_RSTATE_CONNECTED;
1694*12163SRamaswamy.Tummala@Sun.COM 	if (nodep == NULL) {	/* for nodes not seen by IBNEX yet */
16950Sstevel@tonic-gate 		ap_state->ap_ostate = AP_OSTATE_UNCONFIGURED;
16960Sstevel@tonic-gate 		ap_state->ap_condition = AP_COND_UNKNOWN;
16970Sstevel@tonic-gate 	} else {
1698*12163SRamaswamy.Tummala@Sun.COM 		/*
1699*12163SRamaswamy.Tummala@Sun.COM 		 * IBNEX_NODE_AP_UNCONFIGURED & IBNEX_NODE_AP_CONFIGURING.
1700*12163SRamaswamy.Tummala@Sun.COM 		 */
1701*12163SRamaswamy.Tummala@Sun.COM 		if (nodep->node_ap_state >= IBNEX_NODE_AP_UNCONFIGURED) {
17020Sstevel@tonic-gate 			ap_state->ap_ostate = AP_OSTATE_UNCONFIGURED;
17030Sstevel@tonic-gate 			ap_state->ap_condition = AP_COND_UNKNOWN;
17040Sstevel@tonic-gate 		} else {
17050Sstevel@tonic-gate 			ap_state->ap_ostate = AP_OSTATE_CONFIGURED;
17060Sstevel@tonic-gate 			ap_state->ap_condition = AP_COND_OK;
17070Sstevel@tonic-gate 		}
17080Sstevel@tonic-gate 	}
17090Sstevel@tonic-gate 	ap_state->ap_last_change = (time_t)-1;
17100Sstevel@tonic-gate 	ap_state->ap_error_code = 0;
17110Sstevel@tonic-gate 	ap_state->ap_in_transition = 0;
17120Sstevel@tonic-gate }
17130Sstevel@tonic-gate 
17140Sstevel@tonic-gate 
17150Sstevel@tonic-gate /*
17160Sstevel@tonic-gate  * ibnex_figure_ib_apid_devstate()
17170Sstevel@tonic-gate  *	Fills the "devctl_ap_state_t" for a IB static ap_id
17180Sstevel@tonic-gate  */
17190Sstevel@tonic-gate static void
ibnex_figure_ib_apid_devstate(devctl_ap_state_t * ap_state)17200Sstevel@tonic-gate ibnex_figure_ib_apid_devstate(devctl_ap_state_t *ap_state)
17210Sstevel@tonic-gate {
17220Sstevel@tonic-gate 	ap_state->ap_rstate = AP_RSTATE_CONNECTED;
17230Sstevel@tonic-gate 	ap_state->ap_condition = AP_COND_OK;
17240Sstevel@tonic-gate 	ap_state->ap_ostate = (ibt_get_hca_list(NULL) == 0) ?
17250Sstevel@tonic-gate 	    AP_OSTATE_UNCONFIGURED : AP_OSTATE_CONFIGURED;
17260Sstevel@tonic-gate 	ap_state->ap_last_change = (time_t)-1;
17270Sstevel@tonic-gate 	ap_state->ap_error_code = 0;
17280Sstevel@tonic-gate 	ap_state->ap_in_transition = 0;
17290Sstevel@tonic-gate }
17300Sstevel@tonic-gate 
17310Sstevel@tonic-gate 
17320Sstevel@tonic-gate /*
17330Sstevel@tonic-gate  * ibnex_get_apid()
17340Sstevel@tonic-gate  *	Reads in the ap_id passed as an nvlist_string from user-land
17350Sstevel@tonic-gate  */
17360Sstevel@tonic-gate static char *
ibnex_get_apid(struct devctl_iocdata * dcp)17370Sstevel@tonic-gate ibnex_get_apid(struct devctl_iocdata *dcp)
17380Sstevel@tonic-gate {
17390Sstevel@tonic-gate 	char *ap_id;
17400Sstevel@tonic-gate 
17410Sstevel@tonic-gate 	ASSERT(mutex_owned(&ibnex.ibnex_mutex));
17420Sstevel@tonic-gate 
17430Sstevel@tonic-gate 	/* Get which ap_id to operate on.  */
17440Sstevel@tonic-gate 	if (nvlist_lookup_string(ndi_dc_get_ap_data(dcp), "apid",
17450Sstevel@tonic-gate 	    &ap_id) != 0) {
17460Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "ibnex_get_apid: ap_id lookup failed");
17470Sstevel@tonic-gate 		ap_id = NULL;
17480Sstevel@tonic-gate 	}
17490Sstevel@tonic-gate 
17500Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "ibnex_get_apid: ap_id=%s", ap_id);
17510Sstevel@tonic-gate 	return (ap_id);
17520Sstevel@tonic-gate }
17530Sstevel@tonic-gate 
17540Sstevel@tonic-gate 
17550Sstevel@tonic-gate /*
17560Sstevel@tonic-gate  * ibnex_get_dip_from_apid()
17570Sstevel@tonic-gate  *	Figures out the dip/node_data from an ap_id given that this ap_id
17580Sstevel@tonic-gate  *	exists as a "name" in the "ibnex" list
17590Sstevel@tonic-gate  *
17600Sstevel@tonic-gate  * NOTE: ap_id was on stack earlier and gets manipulated here. Since this
17610Sstevel@tonic-gate  * function may be called twice; it is better to make a local copy of
17620Sstevel@tonic-gate  * ap_id; if the ap_id were to be reused.
17630Sstevel@tonic-gate  */
17640Sstevel@tonic-gate static int
ibnex_get_dip_from_apid(char * apid,dev_info_t ** ret_dip,ibnex_node_data_t ** ret_node_datap)17650Sstevel@tonic-gate ibnex_get_dip_from_apid(char *apid, dev_info_t **ret_dip,
17660Sstevel@tonic-gate     ibnex_node_data_t **ret_node_datap)
17670Sstevel@tonic-gate {
17680Sstevel@tonic-gate 	int			rv, ret;
17690Sstevel@tonic-gate 	int			index;
17700Sstevel@tonic-gate 	int			len = strlen((char *)apid) + 1;
17710Sstevel@tonic-gate 	char			*dyn;
17720Sstevel@tonic-gate 	char			*ap_id;
17730Sstevel@tonic-gate 	char			*first;
17740Sstevel@tonic-gate 	char			*second = NULL;
17750Sstevel@tonic-gate 	char			*node_addr;
17760Sstevel@tonic-gate 	char			name[100];
17770Sstevel@tonic-gate 	ibnex_node_data_t	*nodep = NULL;
17780Sstevel@tonic-gate 
17790Sstevel@tonic-gate 	ap_id = i_ddi_strdup(apid, KM_SLEEP);
17800Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tibnex_get_dip_from_apid: %s", ap_id);
17810Sstevel@tonic-gate 	ASSERT(mutex_owned(&ibnex.ibnex_mutex));
17820Sstevel@tonic-gate 
17830Sstevel@tonic-gate 	if ((dyn = GET_DYN(ap_id)) != NULL) {
17840Sstevel@tonic-gate 		rv = IBNEX_DYN_APID;
17850Sstevel@tonic-gate 	} else {	/* either static, hca or unknown */
17860Sstevel@tonic-gate 		*ret_dip = NULL;
17870Sstevel@tonic-gate 		if (strstr(ap_id, "hca") != 0) {
17880Sstevel@tonic-gate 			rv = IBNEX_HCA_APID;
17890Sstevel@tonic-gate 		} else if (strstr(ap_id, IBNEX_FABRIC) != 0) {
17900Sstevel@tonic-gate 			rv = IBNEX_BASE_APID;
17910Sstevel@tonic-gate 		} else {
17920Sstevel@tonic-gate 			rv = IBNEX_UNKNOWN_APID;
17930Sstevel@tonic-gate 		}
17940Sstevel@tonic-gate 		kmem_free(ap_id, len);
17950Sstevel@tonic-gate 		return (rv);
17960Sstevel@tonic-gate 	}
17970Sstevel@tonic-gate 
17980Sstevel@tonic-gate 	dyn += strlen(DYN_SEP);
17990Sstevel@tonic-gate 	if (*dyn == '\0') {
18000Sstevel@tonic-gate 		*ret_dip = NULL;
18010Sstevel@tonic-gate 		kmem_free(ap_id, len);
18020Sstevel@tonic-gate 		return (IBNEX_UNKNOWN_APID);
18030Sstevel@tonic-gate 	}
18040Sstevel@tonic-gate 
18050Sstevel@tonic-gate 	/* APID */
18060Sstevel@tonic-gate 	first = strchr(dyn, ',');
18070Sstevel@tonic-gate 	if (first != NULL)
18080Sstevel@tonic-gate 		second = strchr(first+1, ',');
18090Sstevel@tonic-gate 
18100Sstevel@tonic-gate 	/* Implies Port or VPPA or HCA_SVC Driver ap_id */
18110Sstevel@tonic-gate 	if (first != NULL && second != NULL) {
18120Sstevel@tonic-gate 		int	str_len;
18130Sstevel@tonic-gate 		int	pkey_val = 0;
18140Sstevel@tonic-gate 		char	*pkey_str = strchr(ap_id, ',');
18150Sstevel@tonic-gate 		char	*svc_str = strrchr(pkey_str, ',');
18160Sstevel@tonic-gate 
18170Sstevel@tonic-gate 		/* dyn contains ,GUID,p_key,svc_name. Change it to GUID */
18180Sstevel@tonic-gate 		str_len = strlen(dyn) - strlen(pkey_str);
18190Sstevel@tonic-gate 		dyn[str_len] = '\0';
18200Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "\tibnex_get_dip_from_apid: "
18210Sstevel@tonic-gate 		    "Port / Node Guid %s", dyn);
18220Sstevel@tonic-gate 
18230Sstevel@tonic-gate 		/* figure out comm or vppa. figure out pkey  */
18240Sstevel@tonic-gate 		++pkey_str; /* pkey_str used to point to ",p_key,svc_name" */
18250Sstevel@tonic-gate 
18260Sstevel@tonic-gate 		/* pkey_str contains p_key,svc_name. Change it to p_key */
18270Sstevel@tonic-gate 		str_len = strlen(pkey_str) - strlen(svc_str);
18280Sstevel@tonic-gate 		pkey_str[str_len] = '\0';
18290Sstevel@tonic-gate 
18300Sstevel@tonic-gate 		/* convert the string P_KEY to hex value */
18310Sstevel@tonic-gate 		pkey_val = ibnex_str2hex(pkey_str, strlen(pkey_str), &ret);
18320Sstevel@tonic-gate 		if (ret != IBNEX_SUCCESS) {
18330Sstevel@tonic-gate 			*ret_dip = NULL;
18340Sstevel@tonic-gate 			kmem_free(ap_id, len);
18350Sstevel@tonic-gate 			return (IBNEX_UNKNOWN_APID);
18360Sstevel@tonic-gate 		}
18370Sstevel@tonic-gate 
18380Sstevel@tonic-gate 		++svc_str;	/* svc_str used to point to ",svc_name" */
18390Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibnex", "\tibnex_get_dip_from_apid: pkey %s"
18400Sstevel@tonic-gate 		    ":%x service name = %s", pkey_str, pkey_val, svc_str);
18410Sstevel@tonic-gate 
18420Sstevel@tonic-gate 		for (nodep = ibnex.ibnex_port_node_head;
18430Sstevel@tonic-gate 		    nodep != NULL; nodep = nodep->node_next) {
18440Sstevel@tonic-gate 			index = nodep->node_data.port_node.port_commsvc_idx;
18450Sstevel@tonic-gate 			IBNEX_FORM_GUID(name, IBTL_IBNEX_APID_LEN,
18460Sstevel@tonic-gate 			    nodep->node_data.port_node.port_guid);
18470Sstevel@tonic-gate 
18480Sstevel@tonic-gate 			/*
18490Sstevel@tonic-gate 			 * Match P_Key, name string & service string:
18500Sstevel@tonic-gate 			 * For COMM / HCA_SVC services these should be true:
18510Sstevel@tonic-gate 			 *	P_Key matches to 0, svc_str in comm_svc_names[]
18520Sstevel@tonic-gate 			 *	and name matches the dynamic part of the ap_id
18530Sstevel@tonic-gate 			 * For VPPA services this should be true:
18540Sstevel@tonic-gate 			 *	P_Key != 0 & matches, svc_str in
18550Sstevel@tonic-gate 			 *	vppa_comm_svc_names[] and the name matches the
18560Sstevel@tonic-gate 			 *	dynamic part of the ap_id.
18570Sstevel@tonic-gate 			 */
18580Sstevel@tonic-gate 			if ((pkey_val == nodep->node_data.port_node.
18590Sstevel@tonic-gate 			    port_pkey) && (strstr(dyn, name) != NULL)) {
18600Sstevel@tonic-gate 
18610Sstevel@tonic-gate 				/* pkey != 0, COMM / HCA_SVC service */
18620Sstevel@tonic-gate 				if (((pkey_val == 0) && (
18630Sstevel@tonic-gate 					/* Port Service */
18640Sstevel@tonic-gate 				    ((ibnex.ibnex_comm_svc_names != NULL) &&
18650Sstevel@tonic-gate 				    (index < ibnex.ibnex_num_comm_svcs) &&
18660Sstevel@tonic-gate 				    (strstr(svc_str, ibnex.
18670Sstevel@tonic-gate 				    ibnex_comm_svc_names[index]) != NULL)) ||
18680Sstevel@tonic-gate 					/* HCA_SVC service */
18690Sstevel@tonic-gate 				    ((ibnex.ibnex_hcasvc_comm_svc_names !=
18700Sstevel@tonic-gate 				    NULL) && (index <
18710Sstevel@tonic-gate 				    ibnex.ibnex_nhcasvc_comm_svcs) &&
18720Sstevel@tonic-gate 				    (strstr(svc_str, ibnex.
18730Sstevel@tonic-gate 				    ibnex_hcasvc_comm_svc_names[index])
18748082SRamaswamy.Tummala@Sun.COM 				    != NULL)))) ||
18750Sstevel@tonic-gate 					/* next the VPPA strings */
18760Sstevel@tonic-gate 				    ((pkey_val != 0) && (strstr(svc_str, ibnex.
18770Sstevel@tonic-gate 				    ibnex_vppa_comm_svc_names[index]) !=
18780Sstevel@tonic-gate 				    NULL))) {
18790Sstevel@tonic-gate 					if (nodep->node_dip)
18800Sstevel@tonic-gate 						ndi_hold_devi(nodep->node_dip);
18810Sstevel@tonic-gate 					*ret_node_datap = nodep;
18820Sstevel@tonic-gate 					*ret_dip = nodep->node_dip;
18830Sstevel@tonic-gate 					kmem_free(ap_id, len);
18840Sstevel@tonic-gate 					return (rv);
18850Sstevel@tonic-gate 				}
18860Sstevel@tonic-gate 			}
18870Sstevel@tonic-gate 
18880Sstevel@tonic-gate 		} /* end of for */
18890Sstevel@tonic-gate 
18900Sstevel@tonic-gate 	} else if (first != NULL && second == NULL) {
18910Sstevel@tonic-gate 		/* pseudo ap_id */
18920Sstevel@tonic-gate 		for (nodep = ibnex.ibnex_pseudo_node_head; nodep;
18930Sstevel@tonic-gate 		    nodep = nodep->node_next) {
18941093Shiremath 			if (nodep->node_data.pseudo_node.pseudo_merge_node
18951093Shiremath 			    == 1)
18961093Shiremath 				continue;
18970Sstevel@tonic-gate 			node_addr = nodep->node_data.pseudo_node.
18980Sstevel@tonic-gate 			    pseudo_node_addr;
18990Sstevel@tonic-gate 			if (strncmp(dyn, node_addr, strlen(node_addr)) == 0) {
19000Sstevel@tonic-gate 				if (nodep->node_dip)
19010Sstevel@tonic-gate 					ndi_hold_devi(nodep->node_dip);
19020Sstevel@tonic-gate 				*ret_node_datap = nodep;
19030Sstevel@tonic-gate 				*ret_dip = nodep->node_dip;
19040Sstevel@tonic-gate 				kmem_free(ap_id, len);
19050Sstevel@tonic-gate 				return (rv);
19060Sstevel@tonic-gate 			}
19070Sstevel@tonic-gate 		}
19080Sstevel@tonic-gate 
19090Sstevel@tonic-gate 	} else if (first == NULL && second == NULL) {
19100Sstevel@tonic-gate 		/* This is an IOC ap_id */
19110Sstevel@tonic-gate 		for (nodep = ibnex.ibnex_ioc_node_head; nodep != NULL;
19120Sstevel@tonic-gate 		    nodep = nodep->node_next) {
19130Sstevel@tonic-gate 			IBNEX_FORM_GUID(name, IBTL_IBNEX_APID_LEN,
19140Sstevel@tonic-gate 			    nodep->node_data.ioc_node.ioc_guid);
19150Sstevel@tonic-gate 			if (strstr(dyn, name) != NULL) {
19160Sstevel@tonic-gate 				if (nodep->node_dip)
19170Sstevel@tonic-gate 					ndi_hold_devi(nodep->node_dip);
19180Sstevel@tonic-gate 				*ret_node_datap = nodep;
19190Sstevel@tonic-gate 				*ret_dip = nodep->node_dip;
19200Sstevel@tonic-gate 				kmem_free(ap_id, len);
19210Sstevel@tonic-gate 				return (rv);
19220Sstevel@tonic-gate 			}
19230Sstevel@tonic-gate 		}
19240Sstevel@tonic-gate 	}
19250Sstevel@tonic-gate 
19260Sstevel@tonic-gate 	/* Could not find a matching IB device */
19270Sstevel@tonic-gate 	*ret_dip = (nodep) ? nodep->node_dip : NULL;
19280Sstevel@tonic-gate 	kmem_free(ap_id, len);
19290Sstevel@tonic-gate 	return (rv);
19300Sstevel@tonic-gate }
19310Sstevel@tonic-gate 
19320Sstevel@tonic-gate 
19330Sstevel@tonic-gate /*
19340Sstevel@tonic-gate  * ibnex_handle_pseudo_configure()
19350Sstevel@tonic-gate  *	Do DEVCTL_AP_CONNECT processing for Pseudo devices only.
19360Sstevel@tonic-gate  *	The code also checks if the given ap_id is valid or not.
19370Sstevel@tonic-gate  */
19380Sstevel@tonic-gate static ibnex_rval_t
ibnex_handle_pseudo_configure(char * apid)19390Sstevel@tonic-gate ibnex_handle_pseudo_configure(char *apid)
19400Sstevel@tonic-gate {
19410Sstevel@tonic-gate 	char			*node_addr;
19420Sstevel@tonic-gate 	char			*last = strrchr(apid, ':') + 1;
19430Sstevel@tonic-gate 	ibnex_rval_t		retval = IBNEX_FAILURE;
19440Sstevel@tonic-gate 	ibnex_node_data_t	*nodep;
19450Sstevel@tonic-gate 
19460Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tibnex_handle_pseudo_configure: "
19470Sstevel@tonic-gate 	    "last = %s\n\t\tapid = %s", last, apid);
19480Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
19490Sstevel@tonic-gate 
19500Sstevel@tonic-gate 	/* Check if the APID is valid first */
19510Sstevel@tonic-gate 	if (apid == NULL || last == NULL) {
19520Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "\tibnex_handle_pseudo_configure: "
19530Sstevel@tonic-gate 		    "invalid apid %s", apid);
19540Sstevel@tonic-gate 		return (retval);
19550Sstevel@tonic-gate 	}
19560Sstevel@tonic-gate 
19570Sstevel@tonic-gate 	/* find the matching entry and configure it */
19580Sstevel@tonic-gate 	for (nodep = ibnex.ibnex_pseudo_node_head; nodep != NULL;
19590Sstevel@tonic-gate 	    nodep = nodep->node_next) {
19601093Shiremath 		if (nodep->node_data.pseudo_node.pseudo_merge_node == 1)
19611093Shiremath 			continue;
19620Sstevel@tonic-gate 		node_addr = nodep->node_data.pseudo_node.pseudo_node_addr;
19630Sstevel@tonic-gate 		if (strncmp(node_addr, last, strlen(last)))
19640Sstevel@tonic-gate 			continue;
19650Sstevel@tonic-gate 
19660Sstevel@tonic-gate 		if (nodep->node_dip != NULL) {
19670Sstevel@tonic-gate 			/*
19680Sstevel@tonic-gate 			 * Return BUSY if another configure
19690Sstevel@tonic-gate 			 * operation is in progress
19700Sstevel@tonic-gate 			 */
19710Sstevel@tonic-gate 			if (nodep->node_state ==
19720Sstevel@tonic-gate 			    IBNEX_CFGADM_CONFIGURING)
19730Sstevel@tonic-gate 				return (IBNEX_BUSY);
19740Sstevel@tonic-gate 			else
19750Sstevel@tonic-gate 				return (IBNEX_SUCCESS);
19760Sstevel@tonic-gate 		}
19770Sstevel@tonic-gate 
19780Sstevel@tonic-gate 		/*
19790Sstevel@tonic-gate 		 * Return BUSY if another unconfigure operation is
19800Sstevel@tonic-gate 		 * in progress
19810Sstevel@tonic-gate 		 */
19820Sstevel@tonic-gate 		if (nodep->node_state == IBNEX_CFGADM_UNCONFIGURING)
19830Sstevel@tonic-gate 			return (IBNEX_BUSY);
19840Sstevel@tonic-gate 
19850Sstevel@tonic-gate 		ASSERT(nodep->node_state != IBNEX_CFGADM_CONFIGURED);
19860Sstevel@tonic-gate 		nodep->node_state = IBNEX_CFGADM_CONFIGURING;
19870Sstevel@tonic-gate 
19880Sstevel@tonic-gate 		mutex_exit(&ibnex.ibnex_mutex);
19898082SRamaswamy.Tummala@Sun.COM 		retval = ibnex_pseudo_create_all_pi(nodep);
19900Sstevel@tonic-gate 		mutex_enter(&ibnex.ibnex_mutex);
19910Sstevel@tonic-gate 		if (retval == NDI_SUCCESS) {
19920Sstevel@tonic-gate 			nodep->node_state = IBNEX_CFGADM_CONFIGURED;
19930Sstevel@tonic-gate 			return (IBNEX_SUCCESS);
19940Sstevel@tonic-gate 		} else {
19950Sstevel@tonic-gate 			nodep->node_state = IBNEX_CFGADM_UNCONFIGURED;
19960Sstevel@tonic-gate 			return (IBNEX_FAILURE);
19970Sstevel@tonic-gate 		}
19980Sstevel@tonic-gate 	}
19990Sstevel@tonic-gate 
20000Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\thandle_pseudo_configure: retval=%d",
20010Sstevel@tonic-gate 	    retval);
20020Sstevel@tonic-gate 	return (retval);
20030Sstevel@tonic-gate }
20040Sstevel@tonic-gate 
20050Sstevel@tonic-gate 
20060Sstevel@tonic-gate /*
20070Sstevel@tonic-gate  * ibnex_handle_ioc_configure()
20080Sstevel@tonic-gate  *	Do DEVCTL_AP_CONNECT processing for IOCs only.
20090Sstevel@tonic-gate  *	The code also checks if the given ap_id is valid or not.
20100Sstevel@tonic-gate  */
20110Sstevel@tonic-gate static ibnex_rval_t
ibnex_handle_ioc_configure(char * apid)20120Sstevel@tonic-gate ibnex_handle_ioc_configure(char *apid)
20130Sstevel@tonic-gate {
20140Sstevel@tonic-gate 	int			ret;
20150Sstevel@tonic-gate 	char			*guid_str = strrchr(apid, ':') + 1;
20160Sstevel@tonic-gate 	ib_guid_t		ioc_guid;
20170Sstevel@tonic-gate 	ibnex_rval_t		retval = IBNEX_FAILURE;
20180Sstevel@tonic-gate 	ibdm_ioc_info_t		*ioc_info;
20190Sstevel@tonic-gate 
20200Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
20210Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tibnex_handle_ioc_configure: %s", apid);
20220Sstevel@tonic-gate 
20230Sstevel@tonic-gate 	/* Check if the APID is valid first */
20240Sstevel@tonic-gate 	if (guid_str == NULL) {
20250Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex",
20260Sstevel@tonic-gate 		    "\tibnex_handle_ioc_configure: invalid apid %s", apid);
20270Sstevel@tonic-gate 		return (retval);
20280Sstevel@tonic-gate 	}
20290Sstevel@tonic-gate 
20300Sstevel@tonic-gate 	/*
20310Sstevel@tonic-gate 	 * Call into IBDM to get IOC information
20320Sstevel@tonic-gate 	 */
20330Sstevel@tonic-gate 	ioc_guid = ibnex_str2hex(guid_str, strlen(guid_str), &ret);
20340Sstevel@tonic-gate 	if (ret != IBNEX_SUCCESS)
20350Sstevel@tonic-gate 		return (ret);
20360Sstevel@tonic-gate 
20370Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex",
20380Sstevel@tonic-gate 	    "\tibnex_handle_ioc_configure: IOC GUID = %llX", ioc_guid);
20390Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
20400Sstevel@tonic-gate 	ioc_info = ibdm_ibnex_get_ioc_info(ioc_guid);
20410Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
20420Sstevel@tonic-gate 	if (ioc_info == NULL) {
20430Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex",
20440Sstevel@tonic-gate 		    "\tibnex_handle_ioc_configure: probe_iocguid failed");
20450Sstevel@tonic-gate 		return (retval);
20460Sstevel@tonic-gate 	}
20470Sstevel@tonic-gate 
20488082SRamaswamy.Tummala@Sun.COM 	retval = ibnex_ioc_initnode_all_pi(ioc_info);
20490Sstevel@tonic-gate 	ibdm_ibnex_free_ioc_list(ioc_info);
20500Sstevel@tonic-gate 
20510Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tibnex_handle_ioc_configure: "
20520Sstevel@tonic-gate 	    "done retval = %d", retval);
20530Sstevel@tonic-gate 	return (retval);
20540Sstevel@tonic-gate }
20550Sstevel@tonic-gate 
20560Sstevel@tonic-gate 
20570Sstevel@tonic-gate /*
20580Sstevel@tonic-gate  * ibnex_handle_commsvcnode_configure()
20590Sstevel@tonic-gate  *	Do DEVCTL_AP_CONNECT processing
20600Sstevel@tonic-gate  *	This is done for Port/VPPA/HCA_SVC drivers Only.
20610Sstevel@tonic-gate  *	The code also checks if the given ap_id is valid or not.
20620Sstevel@tonic-gate  */
20630Sstevel@tonic-gate static ibnex_rval_t
ibnex_handle_commsvcnode_configure(char * apid)20640Sstevel@tonic-gate ibnex_handle_commsvcnode_configure(char *apid)
20650Sstevel@tonic-gate {
20668082SRamaswamy.Tummala@Sun.COM 	int			ret, str_len, circ;
20670Sstevel@tonic-gate 	int			sndx;
20680Sstevel@tonic-gate 	int			port_pkey = 0;
20690Sstevel@tonic-gate 	char			*pkey_str = strchr(apid, ',');
20700Sstevel@tonic-gate 	char			*guid_str = strrchr(apid, ':') + 1;
20710Sstevel@tonic-gate 	char			*svc_str = strrchr(pkey_str, ',');
20720Sstevel@tonic-gate 	boolean_t		found = B_FALSE;
20730Sstevel@tonic-gate 	boolean_t		is_hcasvc_node = B_FALSE;
20740Sstevel@tonic-gate 	ib_guid_t		guid;	/* Port / Node GUID */
20750Sstevel@tonic-gate 	dev_info_t		*parent;
20760Sstevel@tonic-gate 	ibnex_rval_t		retval = IBNEX_FAILURE;
20770Sstevel@tonic-gate 	ibdm_port_attr_t	*port_attr;
20780Sstevel@tonic-gate 	int			node_type;
20790Sstevel@tonic-gate 	ibdm_hca_list_t		*hca_list;
20800Sstevel@tonic-gate 
20810Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
20820Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tibnex_handle_commsvcnode_configure: %s",
20830Sstevel@tonic-gate 	    apid);
20840Sstevel@tonic-gate 
20850Sstevel@tonic-gate 	/* Check if the APID is valid first */
20860Sstevel@tonic-gate 	if (guid_str == NULL || ((guid_str != NULL) &&
20870Sstevel@tonic-gate 	    (pkey_str == NULL || svc_str == NULL))) {
20880Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex",
20890Sstevel@tonic-gate 		    "\tibnex_handle_commsvcnode_configure: "
20900Sstevel@tonic-gate 		    "invalid apid %s", apid);
20910Sstevel@tonic-gate 		return (retval);
20920Sstevel@tonic-gate 	}
20930Sstevel@tonic-gate 
20940Sstevel@tonic-gate 	/* guid_str contains GUID,p_key,svc_name. Change it to GUID */
20950Sstevel@tonic-gate 	str_len = strlen(guid_str) - strlen(pkey_str);
20960Sstevel@tonic-gate 	guid_str[str_len] = '\0';
20970Sstevel@tonic-gate 
20980Sstevel@tonic-gate 	/* convert the string GUID to hex value */
20990Sstevel@tonic-gate 	guid = ibnex_str2hex(guid_str, strlen(guid_str), &ret);
21000Sstevel@tonic-gate 	if (ret == IBNEX_FAILURE)
21010Sstevel@tonic-gate 		return (ret);
21020Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tibnex_handle_commsvcnode_configure: "
21030Sstevel@tonic-gate 	    "Port / Node Guid %llX", guid);
21040Sstevel@tonic-gate 
21050Sstevel@tonic-gate 	/* figure out Port/HCA_SVC or VPPA. Also figure out the P_Key.  */
21060Sstevel@tonic-gate 	++pkey_str;	/* pkey_str used to point to ",p_key,svc_name" */
21070Sstevel@tonic-gate 
21080Sstevel@tonic-gate 	/* pkey_str contains p_key,svc_name. Change it to P_Key */
21090Sstevel@tonic-gate 	str_len = strlen(pkey_str) - strlen(svc_str);
21100Sstevel@tonic-gate 	pkey_str[str_len] = '\0';
21110Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibnex", "\tibnex_handle_commsvcnode_configure: "
21120Sstevel@tonic-gate 	    "p_key %s", pkey_str);
21130Sstevel@tonic-gate 
21140Sstevel@tonic-gate 	/* convert the string P_Key to a hexadecimal value */
21150Sstevel@tonic-gate 	port_pkey = ibnex_str2hex(pkey_str, strlen(pkey_str), &ret);
21160Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibnex", "\tibnex_handle_commsvcnode_configure: "
21170Sstevel@tonic-gate 	    "PKEY num %x", port_pkey);
21180Sstevel@tonic-gate 	if (ret == IBNEX_FAILURE)
21190Sstevel@tonic-gate 		return (ret);
21200Sstevel@tonic-gate 
21210Sstevel@tonic-gate 	++svc_str;	/* svc_str used to point to ",svc_name" */
21220Sstevel@tonic-gate 
21230Sstevel@tonic-gate 	/* find the service index */
21240Sstevel@tonic-gate 	if (port_pkey == 0) {
21250Sstevel@tonic-gate 		/* PORT Devices */
21260Sstevel@tonic-gate 		for (sndx = 0; sndx < ibnex.ibnex_num_comm_svcs; sndx++) {
21270Sstevel@tonic-gate 			if (strncmp(ibnex.ibnex_comm_svc_names[sndx],
21280Sstevel@tonic-gate 			    svc_str, strlen(svc_str)) == 0) {
21290Sstevel@tonic-gate 				found = B_TRUE;
21300Sstevel@tonic-gate 				break;
21310Sstevel@tonic-gate 			}
21320Sstevel@tonic-gate 		}
21330Sstevel@tonic-gate 
21340Sstevel@tonic-gate 		/* HCA_SVC Devices */
21350Sstevel@tonic-gate 		if (found == B_FALSE) {
21360Sstevel@tonic-gate 			for (sndx = 0; sndx < ibnex.ibnex_nhcasvc_comm_svcs;
21370Sstevel@tonic-gate 			    sndx++) {
21380Sstevel@tonic-gate 				if (strncmp(ibnex.ibnex_hcasvc_comm_svc_names
21390Sstevel@tonic-gate 				    [sndx], svc_str, strlen(svc_str)) == 0) {
21400Sstevel@tonic-gate 					found = B_TRUE;
21410Sstevel@tonic-gate 					is_hcasvc_node = B_TRUE;
21420Sstevel@tonic-gate 					break;
21430Sstevel@tonic-gate 				}
21440Sstevel@tonic-gate 			}
21450Sstevel@tonic-gate 		}
21460Sstevel@tonic-gate 
21470Sstevel@tonic-gate 	} else {
21480Sstevel@tonic-gate 		for (sndx = 0; sndx < ibnex.ibnex_nvppa_comm_svcs; sndx++) {
21490Sstevel@tonic-gate 			if (strncmp(ibnex.ibnex_vppa_comm_svc_names[sndx],
21500Sstevel@tonic-gate 			    svc_str, strlen(svc_str)) == 0) {
21510Sstevel@tonic-gate 				found = B_TRUE;
21520Sstevel@tonic-gate 				break;
21530Sstevel@tonic-gate 			}
21540Sstevel@tonic-gate 		}
21550Sstevel@tonic-gate 	}
21560Sstevel@tonic-gate 
21570Sstevel@tonic-gate 	if (found == B_FALSE) {
21580Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex",
21590Sstevel@tonic-gate 		    "\tibnex_handle_commsvcnode_configure: "
21600Sstevel@tonic-gate 		    "invalid service %s", svc_str);
21610Sstevel@tonic-gate 		return (retval);
21620Sstevel@tonic-gate 	}
21630Sstevel@tonic-gate 
21640Sstevel@tonic-gate 	/* get Port attributes structure */
21650Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
21660Sstevel@tonic-gate 	if (is_hcasvc_node == B_FALSE) {
21670Sstevel@tonic-gate 		port_attr = ibdm_ibnex_get_port_attrs(guid);
21680Sstevel@tonic-gate 		if (port_attr == NULL) {
21690Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
21700Sstevel@tonic-gate 			    "\tibnex_handle_commsvcnode_configure: "
21710Sstevel@tonic-gate 			    "ibdm_ibnex_get_port_attrs failed");
21720Sstevel@tonic-gate 			mutex_enter(&ibnex.ibnex_mutex);
21730Sstevel@tonic-gate 			return (retval);
21740Sstevel@tonic-gate 		}
21750Sstevel@tonic-gate 	} else {
21760Sstevel@tonic-gate 		hca_list = ibdm_ibnex_get_hca_info_by_guid(guid);
21770Sstevel@tonic-gate 		if (hca_list == NULL) {
21780Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
21790Sstevel@tonic-gate 			    "\tibnex_handle_commsvcnode_configure: "
21800Sstevel@tonic-gate 			    "ibdm_ibnex_get_hca_info_by_guid failed");
21810Sstevel@tonic-gate 			mutex_enter(&ibnex.ibnex_mutex);
21820Sstevel@tonic-gate 			return (retval);
21830Sstevel@tonic-gate 		}
21840Sstevel@tonic-gate 		port_attr = hca_list->hl_hca_port_attr;
21850Sstevel@tonic-gate 	}
21860Sstevel@tonic-gate 
21870Sstevel@tonic-gate 	/* get HCA's dip */
21880Sstevel@tonic-gate 	parent = ibtl_ibnex_hcaguid2dip(port_attr->pa_hca_guid);
21890Sstevel@tonic-gate 
21900Sstevel@tonic-gate 	if (parent == NULL) {
21910Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex",
21920Sstevel@tonic-gate 		    "\tibnex_handle_commsvcnode_configure: "
21930Sstevel@tonic-gate 		    "no HCA present");
21940Sstevel@tonic-gate 		mutex_enter(&ibnex.ibnex_mutex);
21950Sstevel@tonic-gate 		if (is_hcasvc_node == B_FALSE)
21960Sstevel@tonic-gate 			ibdm_ibnex_free_port_attr(port_attr);
21970Sstevel@tonic-gate 		else
21980Sstevel@tonic-gate 			ibdm_ibnex_free_hca_list(hca_list);
21990Sstevel@tonic-gate 		return (retval);
22000Sstevel@tonic-gate 	}
22010Sstevel@tonic-gate 
22020Sstevel@tonic-gate 	if (port_pkey == 0)
22030Sstevel@tonic-gate 		node_type = (is_hcasvc_node == B_FALSE) ?
22040Sstevel@tonic-gate 		    IBNEX_PORT_COMMSVC_NODE : IBNEX_HCASVC_COMMSVC_NODE;
22050Sstevel@tonic-gate 	else
22060Sstevel@tonic-gate 		node_type = IBNEX_VPPA_COMMSVC_NODE;
22070Sstevel@tonic-gate 
22080Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
22098082SRamaswamy.Tummala@Sun.COM 	ndi_devi_enter(parent, &circ);
22100Sstevel@tonic-gate 	if (ibnex_commsvc_initnode(parent, port_attr, sndx, node_type,
22110Sstevel@tonic-gate 	    port_pkey, &ret, IBNEX_CFGADM_ENUMERATE) != NULL) {
22120Sstevel@tonic-gate 		retval = IBNEX_SUCCESS;
22130Sstevel@tonic-gate 	} else {
22140Sstevel@tonic-gate 		retval = (ret == IBNEX_BUSY) ? IBNEX_BUSY : IBNEX_FAILURE;
22150Sstevel@tonic-gate 	}
22168082SRamaswamy.Tummala@Sun.COM 	ndi_devi_exit(parent, circ);
22170Sstevel@tonic-gate 
22180Sstevel@tonic-gate 	if (is_hcasvc_node == B_FALSE)
22190Sstevel@tonic-gate 		ibdm_ibnex_free_port_attr(port_attr);
22200Sstevel@tonic-gate 	else
22210Sstevel@tonic-gate 		ibdm_ibnex_free_hca_list(hca_list);
22220Sstevel@tonic-gate 
22230Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tibnex_handle_commsvcnode_configure: "
22240Sstevel@tonic-gate 	    "done retval = %d", retval);
22250Sstevel@tonic-gate 
22260Sstevel@tonic-gate 	return (retval);
22270Sstevel@tonic-gate }
22280Sstevel@tonic-gate 
22290Sstevel@tonic-gate 
22300Sstevel@tonic-gate /*
22310Sstevel@tonic-gate  * ibnex_return_apid()
22320Sstevel@tonic-gate  *	Construct the ap_id of a given IBTF client in kernel
22330Sstevel@tonic-gate  */
22340Sstevel@tonic-gate static void
ibnex_return_apid(dev_info_t * childp,char ** ret_apid)22350Sstevel@tonic-gate ibnex_return_apid(dev_info_t *childp, char **ret_apid)
22360Sstevel@tonic-gate {
22370Sstevel@tonic-gate 	ibnex_node_data_t	*nodep;
22380Sstevel@tonic-gate 
22390Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "ibnex_return_apid:");
22400Sstevel@tonic-gate 
22410Sstevel@tonic-gate 	ASSERT(childp != NULL);
22420Sstevel@tonic-gate 	nodep = ddi_get_parent_data(childp);
22430Sstevel@tonic-gate 
22440Sstevel@tonic-gate 	if (nodep->node_type == IBNEX_PORT_COMMSVC_NODE) {
22450Sstevel@tonic-gate 		(void) snprintf(*ret_apid, IBTL_IBNEX_APID_LEN,
22460Sstevel@tonic-gate 		    "ib%s%llX,0,%s", DYN_SEP,
22470Sstevel@tonic-gate 		    (longlong_t)nodep->node_data.port_node.port_guid,
22480Sstevel@tonic-gate 		    ibnex.ibnex_comm_svc_names[nodep->node_data.port_node.
22490Sstevel@tonic-gate 		    port_commsvc_idx]);
22500Sstevel@tonic-gate 
22510Sstevel@tonic-gate 	} else if (nodep->node_type == IBNEX_HCASVC_COMMSVC_NODE) {
22520Sstevel@tonic-gate 		(void) snprintf(*ret_apid, IBTL_IBNEX_APID_LEN,
22530Sstevel@tonic-gate 		    "ib%s%llX,0,%s", DYN_SEP,
22540Sstevel@tonic-gate 		    (longlong_t)nodep->node_data.port_node.port_guid, ibnex.
22550Sstevel@tonic-gate 		    ibnex_hcasvc_comm_svc_names[nodep->node_data.port_node.
22560Sstevel@tonic-gate 		    port_commsvc_idx]);
22570Sstevel@tonic-gate 
22580Sstevel@tonic-gate 	} else if (nodep->node_type == IBNEX_VPPA_COMMSVC_NODE) {
22590Sstevel@tonic-gate 		(void) snprintf(*ret_apid, IBTL_IBNEX_APID_LEN,
22600Sstevel@tonic-gate 		    "ib%s%llX,%x,%s", DYN_SEP,
22610Sstevel@tonic-gate 		    (longlong_t)nodep->node_data.port_node.port_guid,
22620Sstevel@tonic-gate 		    nodep->node_data.port_node.port_pkey,
22630Sstevel@tonic-gate 		    ibnex.ibnex_vppa_comm_svc_names[nodep->node_data.port_node.
22640Sstevel@tonic-gate 		    port_commsvc_idx]);
22650Sstevel@tonic-gate 
22660Sstevel@tonic-gate 	} else if (nodep->node_type == IBNEX_IOC_NODE) {
22670Sstevel@tonic-gate 		(void) snprintf(*ret_apid, IBTL_IBNEX_APID_LEN,
22680Sstevel@tonic-gate 		    "ib%s%llX", DYN_SEP,
22690Sstevel@tonic-gate 		    (longlong_t)nodep->node_data.ioc_node.ioc_guid);
22700Sstevel@tonic-gate 
22710Sstevel@tonic-gate 	} else if (nodep->node_type == IBNEX_PSEUDO_NODE) {
22720Sstevel@tonic-gate 		(void) snprintf(*ret_apid, IBTL_IBNEX_APID_LEN, "ib%s%s",
22730Sstevel@tonic-gate 		    DYN_SEP, nodep->node_data.pseudo_node.pseudo_node_addr);
22740Sstevel@tonic-gate 
22750Sstevel@tonic-gate 	} else {
22760Sstevel@tonic-gate 		(void) snprintf(*ret_apid, IBTL_IBNEX_APID_LEN, "%s", "-");
22770Sstevel@tonic-gate 	}
22780Sstevel@tonic-gate 
22790Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "ibnex_return_apid: %x %s",
22800Sstevel@tonic-gate 	    nodep->node_type, ret_apid);
22810Sstevel@tonic-gate }
22820Sstevel@tonic-gate 
22830Sstevel@tonic-gate 
22840Sstevel@tonic-gate /*
22850Sstevel@tonic-gate  * ibnex_vppa_conf_entry_add()
22860Sstevel@tonic-gate  *	Add a new service to the ibnex data base of VPPA communication
22870Sstevel@tonic-gate  *	services.
22880Sstevel@tonic-gate  */
22890Sstevel@tonic-gate static void
ibnex_vppa_conf_entry_add(char * service)22900Sstevel@tonic-gate ibnex_vppa_conf_entry_add(char *service)
22910Sstevel@tonic-gate {
22920Sstevel@tonic-gate 	int	i, nsvcs;
22930Sstevel@tonic-gate 	char	**service_name;
22940Sstevel@tonic-gate 
22950Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
22960Sstevel@tonic-gate 	nsvcs = ibnex.ibnex_nvppa_comm_svcs;
22970Sstevel@tonic-gate 
22980Sstevel@tonic-gate 	/* Allocate space for new "ibnex.ibnex_nvppa_comm_svcs + 1" */
22990Sstevel@tonic-gate 	service_name = kmem_alloc((nsvcs + 1) * sizeof (char *), KM_SLEEP);
23000Sstevel@tonic-gate 	/*
23010Sstevel@tonic-gate 	 * Copy over the existing "ibnex.ibnex_vppa_comm_svc_names"
23020Sstevel@tonic-gate 	 * array. Add the new service at the end.
23030Sstevel@tonic-gate 	 */
23040Sstevel@tonic-gate 	for (i = 0; i < nsvcs; i++)
23050Sstevel@tonic-gate 		service_name[i] = ibnex.ibnex_vppa_comm_svc_names[i];
23060Sstevel@tonic-gate 	service_name[i] = kmem_alloc(strlen(service) + 1, KM_SLEEP);
23070Sstevel@tonic-gate 	(void) snprintf(service_name[i], 5, "%s", service);
23080Sstevel@tonic-gate 
23090Sstevel@tonic-gate 	/* Replace existing pointer to VPPA services w/ newly allocated one */
23100Sstevel@tonic-gate 	if (ibnex.ibnex_vppa_comm_svc_names) {
23110Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_vppa_comm_svc_names, nsvcs *
23120Sstevel@tonic-gate 		    sizeof (char *));
23130Sstevel@tonic-gate 	}
23140Sstevel@tonic-gate 	ibnex.ibnex_nvppa_comm_svcs++;
23150Sstevel@tonic-gate 	ibnex.ibnex_vppa_comm_svc_names = service_name;
23160Sstevel@tonic-gate }
23170Sstevel@tonic-gate 
23180Sstevel@tonic-gate /*
23190Sstevel@tonic-gate  * ibnex_port_conf_entry_add()
23200Sstevel@tonic-gate  *	Add a new service to the ibnex data base of Port communication
23210Sstevel@tonic-gate  *	services.
23220Sstevel@tonic-gate  */
23230Sstevel@tonic-gate static void
ibnex_port_conf_entry_add(char * service)23240Sstevel@tonic-gate ibnex_port_conf_entry_add(char *service)
23250Sstevel@tonic-gate {
23260Sstevel@tonic-gate 	int	i, nsvcs;
23270Sstevel@tonic-gate 	char	**service_name;
23280Sstevel@tonic-gate 
23290Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
23300Sstevel@tonic-gate 	nsvcs = ibnex.ibnex_num_comm_svcs;
23310Sstevel@tonic-gate 
23320Sstevel@tonic-gate 	/* Allocate space for new "ibnex.ibnex_num_comm_svcs + 1" */
23330Sstevel@tonic-gate 	service_name = kmem_alloc((nsvcs + 1) * sizeof (char *), KM_SLEEP);
23340Sstevel@tonic-gate 	/*
23350Sstevel@tonic-gate 	 * Copy over the existing "ibnex.ibnex_comm_svc_names" array.
23360Sstevel@tonic-gate 	 * Add the new service to the end.
23370Sstevel@tonic-gate 	 */
23380Sstevel@tonic-gate 	for (i = 0; i < nsvcs; i++)
23390Sstevel@tonic-gate 		service_name[i] = ibnex.ibnex_comm_svc_names[i];
23400Sstevel@tonic-gate 	service_name[i] = kmem_alloc(strlen(service) + 1, KM_SLEEP);
23410Sstevel@tonic-gate 	(void) snprintf(service_name[i], 5, "%s", service);
23420Sstevel@tonic-gate 
23430Sstevel@tonic-gate 	/* Replace existing pointer to Port services w/ newly allocated one */
23440Sstevel@tonic-gate 	if (ibnex.ibnex_comm_svc_names) {
23450Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_comm_svc_names, nsvcs * sizeof (char *));
23460Sstevel@tonic-gate 	}
23470Sstevel@tonic-gate 	ibnex.ibnex_num_comm_svcs++;
23480Sstevel@tonic-gate 	ibnex.ibnex_comm_svc_names = service_name;
23490Sstevel@tonic-gate }
23500Sstevel@tonic-gate 
23510Sstevel@tonic-gate /*
23520Sstevel@tonic-gate  * ibnex_hcasvc_conf_entry_add()
23530Sstevel@tonic-gate  *	Add a new service to the ibnex data base of HCA_SVC communication
23540Sstevel@tonic-gate  *	services.
23550Sstevel@tonic-gate  */
23560Sstevel@tonic-gate static void
ibnex_hcasvc_conf_entry_add(char * service)23570Sstevel@tonic-gate ibnex_hcasvc_conf_entry_add(char *service)
23580Sstevel@tonic-gate {
23590Sstevel@tonic-gate 	int	i, nsvcs;
23600Sstevel@tonic-gate 	char	**service_name;
23610Sstevel@tonic-gate 
23620Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
23630Sstevel@tonic-gate 	nsvcs = ibnex.ibnex_nhcasvc_comm_svcs;
23640Sstevel@tonic-gate 
23650Sstevel@tonic-gate 	/* Allocate space for new "ibnex.ibnex_nvppa_comm_svcs + 1" */
23660Sstevel@tonic-gate 	service_name = kmem_alloc((nsvcs + 1) * sizeof (char *), KM_SLEEP);
23670Sstevel@tonic-gate 	/*
23680Sstevel@tonic-gate 	 * Copy over the existing "ibnex.ibnex_hcasvc_comm_svc_names"
23690Sstevel@tonic-gate 	 * array. Add the new service at the end.
23700Sstevel@tonic-gate 	 */
23710Sstevel@tonic-gate 	for (i = 0; i < nsvcs; i++)
23720Sstevel@tonic-gate 		service_name[i] = ibnex.ibnex_hcasvc_comm_svc_names[i];
23730Sstevel@tonic-gate 	service_name[i] = kmem_alloc(strlen(service) + 1, KM_SLEEP);
23740Sstevel@tonic-gate 	(void) snprintf(service_name[i], 5, "%s", service);
23750Sstevel@tonic-gate 
23760Sstevel@tonic-gate 	/*
23770Sstevel@tonic-gate 	 * Replace existing pointer to HCA_SVC services w/ newly
23780Sstevel@tonic-gate 	 * allocated one
23790Sstevel@tonic-gate 	 */
23800Sstevel@tonic-gate 	if (ibnex.ibnex_hcasvc_comm_svc_names) {
23810Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_hcasvc_comm_svc_names, nsvcs *
23820Sstevel@tonic-gate 		    sizeof (char *));
23830Sstevel@tonic-gate 	}
23840Sstevel@tonic-gate 	ibnex.ibnex_nhcasvc_comm_svcs++;
23850Sstevel@tonic-gate 	ibnex.ibnex_hcasvc_comm_svc_names = service_name;
23860Sstevel@tonic-gate }
23870Sstevel@tonic-gate 
23880Sstevel@tonic-gate 
23890Sstevel@tonic-gate /*
23900Sstevel@tonic-gate  * ibnex_vppa_conf_entry_delete()
23910Sstevel@tonic-gate  *	Delete an existing service entry from ibnex data base of
23920Sstevel@tonic-gate  *	VPPA communication services.
23930Sstevel@tonic-gate  */
23940Sstevel@tonic-gate static int
ibnex_vppa_conf_entry_delete(char * msg,char * service)23950Sstevel@tonic-gate ibnex_vppa_conf_entry_delete(char *msg, char *service)
23960Sstevel@tonic-gate {
23970Sstevel@tonic-gate 	int			i, j, nsvcs;
23980Sstevel@tonic-gate 	int			len;
23990Sstevel@tonic-gate 	int			match_ndx;
24000Sstevel@tonic-gate 	char			**service_name;
24010Sstevel@tonic-gate 	boolean_t		found = B_FALSE;
24020Sstevel@tonic-gate 	ibnex_node_data_t	*node_datap = ibnex.ibnex_port_node_head;
24030Sstevel@tonic-gate 
24040Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tvppa_conf_entry_delete: %s", service);
24050Sstevel@tonic-gate 
24060Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
24070Sstevel@tonic-gate 	nsvcs = ibnex.ibnex_nvppa_comm_svcs;
24080Sstevel@tonic-gate 
24090Sstevel@tonic-gate 	/* find matching index */
24100Sstevel@tonic-gate 	for (i = 0; i < nsvcs; i++) {
24119713SBill.Taylor@Sun.COM 		if (strcmp(ibnex.ibnex_vppa_comm_svc_names[i], service))
24120Sstevel@tonic-gate 			continue;
24130Sstevel@tonic-gate 		found = B_TRUE;
24140Sstevel@tonic-gate 		match_ndx = i;
24150Sstevel@tonic-gate 		break;
24160Sstevel@tonic-gate 	}
24170Sstevel@tonic-gate 
24180Sstevel@tonic-gate 	/* check for valid "nsvcs" */
24190Sstevel@tonic-gate 	if (found == B_FALSE || nsvcs == 0) {
24200Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "%s: invalid vppa services %x",
24210Sstevel@tonic-gate 		    msg, nsvcs);
24220Sstevel@tonic-gate 		return (EIO);
24230Sstevel@tonic-gate 	}
24240Sstevel@tonic-gate 
24250Sstevel@tonic-gate 	/* Check if service is in use; return failure if so */
24260Sstevel@tonic-gate 	for (; node_datap; node_datap = node_datap->node_next) {
24270Sstevel@tonic-gate 		if ((node_datap->node_data.port_node.port_commsvc_idx == i) &&
24280Sstevel@tonic-gate 		    node_datap->node_type == IBNEX_VPPA_COMMSVC_NODE &&
24290Sstevel@tonic-gate 		    node_datap->node_dip) {
24300Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "%s: service %s is in use",
24310Sstevel@tonic-gate 			    msg, service);
24320Sstevel@tonic-gate 			return (EIO);
24330Sstevel@tonic-gate 		}
24340Sstevel@tonic-gate 	}
24350Sstevel@tonic-gate 
24360Sstevel@tonic-gate 	/* if nsvcs == 1, bailout early */
24370Sstevel@tonic-gate 	if (nsvcs == 1) {
24380Sstevel@tonic-gate 		/* free up that single entry */
24390Sstevel@tonic-gate 		len = strlen(ibnex.ibnex_vppa_comm_svc_names[0]) + 1;
24400Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_vppa_comm_svc_names[0], len);
24410Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_vppa_comm_svc_names, sizeof (char *));
24420Sstevel@tonic-gate 		ibnex.ibnex_vppa_comm_svc_names = NULL;
24430Sstevel@tonic-gate 		ibnex.ibnex_nvppa_comm_svcs = 0;
24440Sstevel@tonic-gate 		return (0);
24450Sstevel@tonic-gate 	}
24460Sstevel@tonic-gate 
24470Sstevel@tonic-gate 	/* Allocate space for new "ibnex.ibnex_nvppa_comm_svcs - 1" */
24480Sstevel@tonic-gate 	service_name = kmem_alloc((nsvcs - 1) * sizeof (char *), KM_SLEEP);
24490Sstevel@tonic-gate 	/*
24500Sstevel@tonic-gate 	 * Copy over the existing "ibnex.ibnex_vppa_comm_svc_names"
24510Sstevel@tonic-gate 	 * array. Do not copy over the matching service.
24520Sstevel@tonic-gate 	 */
24530Sstevel@tonic-gate 	for (i = 0, j = 0; i < nsvcs; i++) {
24540Sstevel@tonic-gate 		if (i == match_ndx) {
24550Sstevel@tonic-gate 			/* free up that entry */
24560Sstevel@tonic-gate 			len = strlen(ibnex.ibnex_vppa_comm_svc_names[i]) + 1;
24570Sstevel@tonic-gate 			kmem_free(ibnex.ibnex_vppa_comm_svc_names[i], len);
24580Sstevel@tonic-gate 			continue;
24590Sstevel@tonic-gate 		}
24600Sstevel@tonic-gate 		service_name[j++] = ibnex.ibnex_vppa_comm_svc_names[i];
24610Sstevel@tonic-gate 	}
24620Sstevel@tonic-gate 
24630Sstevel@tonic-gate 	/* Replace existing pointer to VPPA services w/ newly adjusted one */
24640Sstevel@tonic-gate 	if (ibnex.ibnex_vppa_comm_svc_names) {
24650Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_vppa_comm_svc_names, nsvcs *
24660Sstevel@tonic-gate 		    sizeof (char *));
24670Sstevel@tonic-gate 		ibnex.ibnex_nvppa_comm_svcs--;
24680Sstevel@tonic-gate 		ibnex.ibnex_vppa_comm_svc_names = service_name;
24690Sstevel@tonic-gate 	}
24700Sstevel@tonic-gate 	return (0);
24710Sstevel@tonic-gate }
24720Sstevel@tonic-gate 
24730Sstevel@tonic-gate 
24740Sstevel@tonic-gate /*
24750Sstevel@tonic-gate  * ibnex_port_conf_entry_delete()
24760Sstevel@tonic-gate  *	Delete an existing service entry from ibnex data base of
24770Sstevel@tonic-gate  *	Port communication services.
24780Sstevel@tonic-gate  */
24790Sstevel@tonic-gate static int
ibnex_port_conf_entry_delete(char * msg,char * service)24800Sstevel@tonic-gate ibnex_port_conf_entry_delete(char *msg, char *service)
24810Sstevel@tonic-gate {
24820Sstevel@tonic-gate 	int			i, j, nsvcs;
24830Sstevel@tonic-gate 	int			match_ndx;
24840Sstevel@tonic-gate 	int			len;
24850Sstevel@tonic-gate 	char			**service_name;
24860Sstevel@tonic-gate 	boolean_t		found = B_FALSE;
24870Sstevel@tonic-gate 	ibnex_node_data_t	*node_datap = ibnex.ibnex_port_node_head;
24880Sstevel@tonic-gate 
24890Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tport_conf_entry_delete: %s", service);
24900Sstevel@tonic-gate 
24910Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
24920Sstevel@tonic-gate 	nsvcs = ibnex.ibnex_num_comm_svcs;
24930Sstevel@tonic-gate 
24940Sstevel@tonic-gate 	/* find matching index */
24950Sstevel@tonic-gate 	for (i = 0; i < nsvcs; i++) {
24969713SBill.Taylor@Sun.COM 		if (strcmp(ibnex.ibnex_comm_svc_names[i], service))
24970Sstevel@tonic-gate 			continue;
24980Sstevel@tonic-gate 		found = B_TRUE;
24990Sstevel@tonic-gate 		match_ndx = i;
25000Sstevel@tonic-gate 		break;
25010Sstevel@tonic-gate 	}
25020Sstevel@tonic-gate 
25030Sstevel@tonic-gate 	/* check for valid "nsvcs" */
25040Sstevel@tonic-gate 	if (found == B_FALSE || nsvcs == 0) {
25050Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "%s: invalid services %x", msg, nsvcs);
25060Sstevel@tonic-gate 		return (EIO);
25070Sstevel@tonic-gate 	}
25080Sstevel@tonic-gate 
25090Sstevel@tonic-gate 	/* Check if service is in use; return failure if so */
25100Sstevel@tonic-gate 	for (; node_datap; node_datap = node_datap->node_next) {
25110Sstevel@tonic-gate 		if ((node_datap->node_data.port_node.port_commsvc_idx == i) &&
25120Sstevel@tonic-gate 		    node_datap->node_type == IBNEX_PORT_COMMSVC_NODE &&
25130Sstevel@tonic-gate 		    node_datap->node_dip)
25140Sstevel@tonic-gate 			return (EIO);
25150Sstevel@tonic-gate 	}
25160Sstevel@tonic-gate 
25170Sstevel@tonic-gate 	/* if nsvcs == 1, bailout early */
25180Sstevel@tonic-gate 	if (nsvcs == 1) {
25190Sstevel@tonic-gate 		/* free up that single entry */
25200Sstevel@tonic-gate 		len = strlen(ibnex.ibnex_comm_svc_names[0]) + 1;
25210Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_comm_svc_names[0], len);
25220Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_comm_svc_names, sizeof (char *));
25230Sstevel@tonic-gate 		ibnex.ibnex_comm_svc_names = NULL;
25240Sstevel@tonic-gate 		ibnex.ibnex_num_comm_svcs = 0;
25250Sstevel@tonic-gate 		return (0);
25260Sstevel@tonic-gate 	}
25270Sstevel@tonic-gate 
25280Sstevel@tonic-gate 	/* Allocate space for new "ibnex.ibnex_num_comm_svcs - 1" */
25290Sstevel@tonic-gate 	service_name = kmem_alloc((nsvcs - 1) * sizeof (char *), KM_SLEEP);
25300Sstevel@tonic-gate 	/*
25310Sstevel@tonic-gate 	 * Copy over the existing "ibnex.ibnex_comm_svc_names" array.
25320Sstevel@tonic-gate 	 * Skip the matching service.
25330Sstevel@tonic-gate 	 */
25340Sstevel@tonic-gate 	for (i = 0, j = 0; i < nsvcs; i++) {
25350Sstevel@tonic-gate 		if (i == match_ndx) {
25360Sstevel@tonic-gate 			/* free up that entry */
25370Sstevel@tonic-gate 			len = strlen(ibnex.ibnex_comm_svc_names[i]) + 1;
25380Sstevel@tonic-gate 			kmem_free(ibnex.ibnex_comm_svc_names[i], len);
25390Sstevel@tonic-gate 			continue;
25400Sstevel@tonic-gate 		}
25410Sstevel@tonic-gate 		service_name[j++] = ibnex.ibnex_comm_svc_names[i];
25420Sstevel@tonic-gate 	}
25430Sstevel@tonic-gate 
25440Sstevel@tonic-gate 	/* Replace existing pointer to Port services w/ newly adjusted one */
25450Sstevel@tonic-gate 	if (ibnex.ibnex_comm_svc_names) {
25460Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_comm_svc_names, nsvcs * sizeof (char *));
25470Sstevel@tonic-gate 		ibnex.ibnex_num_comm_svcs--;
25480Sstevel@tonic-gate 		ibnex.ibnex_comm_svc_names = service_name;
25490Sstevel@tonic-gate 	}
25500Sstevel@tonic-gate 	return (0);
25510Sstevel@tonic-gate }
25520Sstevel@tonic-gate 
25530Sstevel@tonic-gate /*
25540Sstevel@tonic-gate  * ibnex_hcasvc_conf_entry_delete()
25550Sstevel@tonic-gate  *	Delete an existing service entry from ibnex data base of
25560Sstevel@tonic-gate  *	HCA_SVC communication services.
25570Sstevel@tonic-gate  */
25580Sstevel@tonic-gate static int
ibnex_hcasvc_conf_entry_delete(char * msg,char * service)25590Sstevel@tonic-gate ibnex_hcasvc_conf_entry_delete(char *msg, char *service)
25600Sstevel@tonic-gate {
25610Sstevel@tonic-gate 	int			i, j, nsvcs;
25620Sstevel@tonic-gate 	int			len;
25630Sstevel@tonic-gate 	int			match_ndx;
25640Sstevel@tonic-gate 	char			**service_name;
25650Sstevel@tonic-gate 	boolean_t		found = B_FALSE;
25660Sstevel@tonic-gate 	ibnex_node_data_t	*node_datap = ibnex.ibnex_port_node_head;
25670Sstevel@tonic-gate 
25680Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\thcasvc_conf_entry_delete: %s", service);
25690Sstevel@tonic-gate 
25700Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
25710Sstevel@tonic-gate 	nsvcs = ibnex.ibnex_nhcasvc_comm_svcs;
25720Sstevel@tonic-gate 
25730Sstevel@tonic-gate 	/* find matching index */
25740Sstevel@tonic-gate 	for (i = 0; i < nsvcs; i++) {
25759713SBill.Taylor@Sun.COM 		if (strcmp(ibnex.ibnex_hcasvc_comm_svc_names[i], service))
25760Sstevel@tonic-gate 			continue;
25770Sstevel@tonic-gate 		found = B_TRUE;
25780Sstevel@tonic-gate 		match_ndx = i;
25790Sstevel@tonic-gate 		break;
25800Sstevel@tonic-gate 	}
25810Sstevel@tonic-gate 
25820Sstevel@tonic-gate 	/* check for valid "nsvcs" */
25830Sstevel@tonic-gate 	if (found == B_FALSE || nsvcs == 0) {
25840Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "%s: invalid hca_svc services %x",
25850Sstevel@tonic-gate 		    msg, nsvcs);
25860Sstevel@tonic-gate 		return (EIO);
25870Sstevel@tonic-gate 	}
25880Sstevel@tonic-gate 
25890Sstevel@tonic-gate 	/* Check if service is in use; return failure if so */
25900Sstevel@tonic-gate 	for (; node_datap; node_datap = node_datap->node_next) {
25910Sstevel@tonic-gate 		if ((node_datap->node_data.port_node.port_commsvc_idx == i) &&
25920Sstevel@tonic-gate 		    node_datap->node_type == IBNEX_HCASVC_COMMSVC_NODE &&
25930Sstevel@tonic-gate 		    node_datap->node_dip) {
25940Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "%s: service %s is in use",
25950Sstevel@tonic-gate 			    msg, service);
25960Sstevel@tonic-gate 			return (EIO);
25970Sstevel@tonic-gate 		}
25980Sstevel@tonic-gate 	}
25990Sstevel@tonic-gate 
26000Sstevel@tonic-gate 	/* if nsvcs == 1, bailout early */
26010Sstevel@tonic-gate 	if (nsvcs == 1) {
26020Sstevel@tonic-gate 		/* free up that single entry */
26030Sstevel@tonic-gate 		len = strlen(ibnex.ibnex_hcasvc_comm_svc_names[0]) + 1;
26040Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_hcasvc_comm_svc_names[0], len);
26050Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_hcasvc_comm_svc_names, sizeof (char *));
26060Sstevel@tonic-gate 		ibnex.ibnex_hcasvc_comm_svc_names = NULL;
26070Sstevel@tonic-gate 		ibnex.ibnex_nhcasvc_comm_svcs = 0;
26080Sstevel@tonic-gate 		return (0);
26090Sstevel@tonic-gate 	}
26100Sstevel@tonic-gate 
26110Sstevel@tonic-gate 	/* Allocate space for new "ibnex.ibnex_nhcasvc_comm_svcs - 1" */
26120Sstevel@tonic-gate 	service_name = kmem_alloc((nsvcs - 1) * sizeof (char *), KM_SLEEP);
26130Sstevel@tonic-gate 	/*
26140Sstevel@tonic-gate 	 * Copy over the existing "ibnex.ibnex_hcasvc_comm_svc_names"
26150Sstevel@tonic-gate 	 * array. Do not copy over the matching service.
26160Sstevel@tonic-gate 	 */
26170Sstevel@tonic-gate 	for (i = 0, j = 0; i < nsvcs; i++) {
26180Sstevel@tonic-gate 		if (i == match_ndx) {
26190Sstevel@tonic-gate 			/* free up that entry */
26200Sstevel@tonic-gate 			len = strlen(ibnex.ibnex_hcasvc_comm_svc_names[i]) + 1;
26210Sstevel@tonic-gate 			kmem_free(ibnex.ibnex_hcasvc_comm_svc_names[i], len);
26220Sstevel@tonic-gate 			continue;
26230Sstevel@tonic-gate 		}
26240Sstevel@tonic-gate 		service_name[j++] = ibnex.ibnex_hcasvc_comm_svc_names[i];
26250Sstevel@tonic-gate 	}
26260Sstevel@tonic-gate 
26270Sstevel@tonic-gate 	/* Replace existing pointer to VPPA services w/ newly adjusted one */
26280Sstevel@tonic-gate 	if (ibnex.ibnex_hcasvc_comm_svc_names) {
26290Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_hcasvc_comm_svc_names, nsvcs *
26300Sstevel@tonic-gate 		    sizeof (char *));
26310Sstevel@tonic-gate 		ibnex.ibnex_nhcasvc_comm_svcs--;
26320Sstevel@tonic-gate 		ibnex.ibnex_hcasvc_comm_svc_names = service_name;
26330Sstevel@tonic-gate 	}
26340Sstevel@tonic-gate 	return (0);
26350Sstevel@tonic-gate }
26360Sstevel@tonic-gate 
26370Sstevel@tonic-gate 
26380Sstevel@tonic-gate /*
26390Sstevel@tonic-gate  * ibnex_ioc_fininode()
26400Sstevel@tonic-gate  *	Un-initialize a child device node for IOC device node
26410Sstevel@tonic-gate  *	Returns IBNEX_SUCCESS/IBNEX_FAILURE
26420Sstevel@tonic-gate  */
26430Sstevel@tonic-gate static ibnex_rval_t
ibnex_ioc_fininode(dev_info_t * dip,ibnex_ioc_node_t * ioc_nodep)26440Sstevel@tonic-gate ibnex_ioc_fininode(dev_info_t *dip, ibnex_ioc_node_t *ioc_nodep)
26450Sstevel@tonic-gate {
26460Sstevel@tonic-gate 	int	rval = MDI_SUCCESS;
26470Sstevel@tonic-gate 
26480Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
26490Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tioc_fininode");
26500Sstevel@tonic-gate 
26510Sstevel@tonic-gate 	/*
26520Sstevel@tonic-gate 	 * For a dis-connected IOC,
26530Sstevel@tonic-gate 	 *	Free the ioc_profile &&
26540Sstevel@tonic-gate 	 *	decrement ibnex_num_disconnect_iocs
26550Sstevel@tonic-gate 	 */
26560Sstevel@tonic-gate 	if (ioc_nodep->ioc_ngids == 0 && ioc_nodep->ioc_profile) {
26570Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "\tioc_fininode: unconfigure "
26580Sstevel@tonic-gate 		    "disconnected IOC: GUID %lX", ioc_nodep->ioc_guid);
26590Sstevel@tonic-gate 		ibnex.ibnex_num_disconnect_iocs--;
26600Sstevel@tonic-gate 		kmem_free(ioc_nodep->ioc_profile,
26610Sstevel@tonic-gate 		    sizeof (ib_dm_ioc_ctrl_profile_t));
26620Sstevel@tonic-gate 		ioc_nodep->ioc_profile = NULL;
26630Sstevel@tonic-gate 	}
26640Sstevel@tonic-gate 
26650Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
26660Sstevel@tonic-gate 	ASSERT(i_ddi_node_state(dip) >= DS_BOUND);
26670Sstevel@tonic-gate 
26680Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tioc_fininode: offlining the IOC");
26690Sstevel@tonic-gate 	rval = ibnex_offline_childdip(dip);
26700Sstevel@tonic-gate 
26710Sstevel@tonic-gate 	if (rval != MDI_SUCCESS) {
26720Sstevel@tonic-gate 		rval = NDI_FAILURE;
26730Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "\toffline failed for IOC "
26740Sstevel@tonic-gate 		    "dip %p with 0x%x", dip, rval);
26750Sstevel@tonic-gate 	}
26760Sstevel@tonic-gate 
26770Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
26780Sstevel@tonic-gate 	return (rval == MDI_SUCCESS ? IBNEX_SUCCESS : IBNEX_OFFLINE_FAILED);
26790Sstevel@tonic-gate }
26800Sstevel@tonic-gate 
26810Sstevel@tonic-gate 
26820Sstevel@tonic-gate int
ibnex_offline_childdip(dev_info_t * dip)26830Sstevel@tonic-gate ibnex_offline_childdip(dev_info_t *dip)
26840Sstevel@tonic-gate {
26859778SEiji.Ota@Sun.COM 	int		rval = MDI_SUCCESS, rval2;
26860Sstevel@tonic-gate 	mdi_pathinfo_t	*path = NULL, *temp;
26870Sstevel@tonic-gate 
26880Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\toffline_childdip; begin");
26890Sstevel@tonic-gate 	if (dip == NULL) {
26900Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "\toffline_childdip; NULL dip");
26910Sstevel@tonic-gate 		return (MDI_FAILURE);
26920Sstevel@tonic-gate 	}
26930Sstevel@tonic-gate 
26940Sstevel@tonic-gate 	for (path = mdi_get_next_phci_path(dip, path); path; ) {
26950Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "\toffline_childdip: "
26960Sstevel@tonic-gate 		    "offling path %p", path);
26979778SEiji.Ota@Sun.COM 		rval2 = MDI_SUCCESS;
26989778SEiji.Ota@Sun.COM 		if (MDI_PI_IS_ONLINE(path)) {
26999778SEiji.Ota@Sun.COM 			rval2 = mdi_pi_offline(path, NDI_UNCONFIG);
27009778SEiji.Ota@Sun.COM 			/* If it cannot be offlined, log this path and error */
27019778SEiji.Ota@Sun.COM 			if (rval2 != MDI_SUCCESS) {
27029778SEiji.Ota@Sun.COM 				rval = rval2;
27039778SEiji.Ota@Sun.COM 				cmn_err(CE_WARN,
27049778SEiji.Ota@Sun.COM 				    "!ibnex\toffline_childdip (0x%p): "
27059778SEiji.Ota@Sun.COM 				    "mdi_pi_offline path (0x%p) failed with %d",
27069778SEiji.Ota@Sun.COM 				    (void *)dip, (void *)path, rval2);
27079778SEiji.Ota@Sun.COM 			}
27080Sstevel@tonic-gate 		}
27099778SEiji.Ota@Sun.COM 		/* prepare the next path */
27100Sstevel@tonic-gate 		temp = path;
27110Sstevel@tonic-gate 		path = mdi_get_next_phci_path(dip, path);
27129778SEiji.Ota@Sun.COM 		/* free the offline path */
27139778SEiji.Ota@Sun.COM 		if (rval2 == MDI_SUCCESS) {
27149778SEiji.Ota@Sun.COM 			(void) mdi_pi_free(temp, 0);
27159778SEiji.Ota@Sun.COM 		}
27160Sstevel@tonic-gate 	}
27170Sstevel@tonic-gate 	return (rval);
27180Sstevel@tonic-gate }
27190Sstevel@tonic-gate 
27200Sstevel@tonic-gate 
27210Sstevel@tonic-gate /*
27220Sstevel@tonic-gate  * ibnex_commsvc_fininode()
27230Sstevel@tonic-gate  *
27240Sstevel@tonic-gate  * Un-initialize a child device node for HCA port / node GUID
27250Sstevel@tonic-gate  * for a communication service.
27260Sstevel@tonic-gate  *	Returns IBNEX_SUCCESS/IBNEX_FAILURE
27270Sstevel@tonic-gate  */
27280Sstevel@tonic-gate static ibnex_rval_t
ibnex_commsvc_fininode(dev_info_t * dip)27290Sstevel@tonic-gate ibnex_commsvc_fininode(dev_info_t *dip)
27300Sstevel@tonic-gate {
27310Sstevel@tonic-gate 	int	rval = NDI_SUCCESS;
27320Sstevel@tonic-gate 
27330Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
27340Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tcommsvc_fininode");
27350Sstevel@tonic-gate 
27360Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
27370Sstevel@tonic-gate 	if (i_ddi_node_state(dip) < DS_BOUND) {
27380Sstevel@tonic-gate 		/*
27390Sstevel@tonic-gate 		 * if the child hasn't been bound yet, we can
27400Sstevel@tonic-gate 		 * just free the dip. This path is currently
27410Sstevel@tonic-gate 		 * untested.
27420Sstevel@tonic-gate 		 */
27430Sstevel@tonic-gate 		(void) ddi_remove_child(dip, 0);
27440Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex",
27450Sstevel@tonic-gate 		    "\tcommsvc_fininode: ddi_remove_child");
27460Sstevel@tonic-gate 	} else {
27470Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "\tcommsvc_fininode: offlining the "
27480Sstevel@tonic-gate 		    "Commsvc node");
27490Sstevel@tonic-gate 
27500Sstevel@tonic-gate 		rval = ndi_devi_offline(dip, NDI_DEVI_REMOVE | NDI_UNCONFIG);
27510Sstevel@tonic-gate 		if (rval != NDI_SUCCESS)
27520Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "\toffline failed for Commsvc "
27530Sstevel@tonic-gate 			    "dip %p with 0x%x", dip, rval);
27540Sstevel@tonic-gate 	}
27550Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
27560Sstevel@tonic-gate 	return (rval == NDI_SUCCESS ? IBNEX_SUCCESS : IBNEX_OFFLINE_FAILED);
27570Sstevel@tonic-gate }
27580Sstevel@tonic-gate 
27590Sstevel@tonic-gate 
27600Sstevel@tonic-gate /*
27610Sstevel@tonic-gate  * ibnex_pseudo_fininode()
27620Sstevel@tonic-gate  *	Un-initialize a child pseudo device node
27630Sstevel@tonic-gate  *	Returns IBNEX_SUCCESS/IBNEX_FAILURE
27640Sstevel@tonic-gate  */
27650Sstevel@tonic-gate static ibnex_rval_t
ibnex_pseudo_fininode(dev_info_t * dip)27660Sstevel@tonic-gate ibnex_pseudo_fininode(dev_info_t *dip)
27670Sstevel@tonic-gate {
27680Sstevel@tonic-gate 	int	rval = MDI_SUCCESS;
27690Sstevel@tonic-gate 
27700Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
27710Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tpseudo_fininode: dip = %p", dip);
27720Sstevel@tonic-gate 
27730Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
27740Sstevel@tonic-gate 	ASSERT(i_ddi_node_state(dip) >= DS_BOUND);
27750Sstevel@tonic-gate 
27760Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tpseudo_fininode: offlining the "
27770Sstevel@tonic-gate 	    "pseudo device");
27780Sstevel@tonic-gate 	rval = ibnex_offline_childdip(dip);
27790Sstevel@tonic-gate 	if (rval != MDI_SUCCESS) {
27800Sstevel@tonic-gate 		rval = NDI_FAILURE;
27810Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "\tpseudo offline failed for "
27820Sstevel@tonic-gate 		    "dip %p with 0x%x", dip, rval);
27830Sstevel@tonic-gate 	}
27840Sstevel@tonic-gate 
27850Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
27860Sstevel@tonic-gate 	return (rval == MDI_SUCCESS ? IBNEX_SUCCESS : IBNEX_OFFLINE_FAILED);
27870Sstevel@tonic-gate }
27889879SRamaswamy.Tummala@Sun.COM 
27899879SRamaswamy.Tummala@Sun.COM /*
27909879SRamaswamy.Tummala@Sun.COM  * IOCTL implementation to get api version number.
27919879SRamaswamy.Tummala@Sun.COM  */
27929879SRamaswamy.Tummala@Sun.COM static int
ibnex_ctl_get_api_ver(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)27939879SRamaswamy.Tummala@Sun.COM ibnex_ctl_get_api_ver(dev_t dev, int cmd, intptr_t arg, int mode,
27949879SRamaswamy.Tummala@Sun.COM     cred_t *credp, int *rvalp)
27959879SRamaswamy.Tummala@Sun.COM {
27969879SRamaswamy.Tummala@Sun.COM 	ibnex_ctl_api_ver_t	api_ver;
27979879SRamaswamy.Tummala@Sun.COM 
27989879SRamaswamy.Tummala@Sun.COM 	IBTF_DPRINTF_L4("ibnex", "\tctl_get_api_ver: cmd=%x, arg=%p, "
27999879SRamaswamy.Tummala@Sun.COM 	    "mode=%x, cred=%p, rval=%p, dev=0x%x", cmd, arg, mode, credp,
28009879SRamaswamy.Tummala@Sun.COM 	    rvalp, dev);
28019879SRamaswamy.Tummala@Sun.COM 
28029879SRamaswamy.Tummala@Sun.COM 	api_ver.api_ver_num = IBNEX_CTL_API_VERSION;
28039879SRamaswamy.Tummala@Sun.COM 
28049879SRamaswamy.Tummala@Sun.COM 	if (ddi_copyout(&api_ver, (void *)arg, sizeof (ibnex_ctl_api_ver_t),
28059879SRamaswamy.Tummala@Sun.COM 	    mode) != 0) {
28069879SRamaswamy.Tummala@Sun.COM 		IBTF_DPRINTF_L2("ibnex",
28079879SRamaswamy.Tummala@Sun.COM 		    "\tctl_get_api_ver: ddi_copyout err");
28089879SRamaswamy.Tummala@Sun.COM 		return (EFAULT);
28099879SRamaswamy.Tummala@Sun.COM 	}
28109879SRamaswamy.Tummala@Sun.COM 
28119879SRamaswamy.Tummala@Sun.COM 	return (0);
28129879SRamaswamy.Tummala@Sun.COM }
28139879SRamaswamy.Tummala@Sun.COM 
28149879SRamaswamy.Tummala@Sun.COM /*
28159879SRamaswamy.Tummala@Sun.COM  * IOCTL implementation to get the list of HCAs
28169879SRamaswamy.Tummala@Sun.COM  */
28179879SRamaswamy.Tummala@Sun.COM static int
ibnex_ctl_get_hca_list(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)28189879SRamaswamy.Tummala@Sun.COM ibnex_ctl_get_hca_list(dev_t dev, int cmd, intptr_t arg, int mode,
28199879SRamaswamy.Tummala@Sun.COM     cred_t *credp, int *rvalp)
28209879SRamaswamy.Tummala@Sun.COM {
28219879SRamaswamy.Tummala@Sun.COM 	ibnex_ctl_get_hca_list_t hca_list;
28229879SRamaswamy.Tummala@Sun.COM 	int		rv = 0;
28239879SRamaswamy.Tummala@Sun.COM 	uint_t		*in_nhcasp;
28249879SRamaswamy.Tummala@Sun.COM 	uint_t		nhcas, n;
28259879SRamaswamy.Tummala@Sun.COM 	ib_guid_t	*hca_guids;
28269879SRamaswamy.Tummala@Sun.COM 
28279879SRamaswamy.Tummala@Sun.COM 	IBTF_DPRINTF_L4("ibnex", "\tctl_get_hca_list: cmd=%x, arg=%p, "
28289879SRamaswamy.Tummala@Sun.COM 	    "mode=%x, cred=%p, rval=%p, dev=0x%x", cmd, arg, mode, credp,
28299879SRamaswamy.Tummala@Sun.COM 	    rvalp, dev);
28309879SRamaswamy.Tummala@Sun.COM 
28319879SRamaswamy.Tummala@Sun.COM #ifdef	_MULTI_DATAMODEL
28329879SRamaswamy.Tummala@Sun.COM 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
28339879SRamaswamy.Tummala@Sun.COM 		ibnex_ctl_get_hca_list_32_t hca_list_32;
28349879SRamaswamy.Tummala@Sun.COM 
28359879SRamaswamy.Tummala@Sun.COM 		if (ddi_copyin((void *)arg, &hca_list_32,
28369879SRamaswamy.Tummala@Sun.COM 		    sizeof (ibnex_ctl_get_hca_list_32_t), mode) != 0) {
28379879SRamaswamy.Tummala@Sun.COM 			IBTF_DPRINTF_L2("ibnex",
28389879SRamaswamy.Tummala@Sun.COM 			    "\tctl_get_hca_list: ddi_copyin err 1");
28399879SRamaswamy.Tummala@Sun.COM 			return (EFAULT);
28409879SRamaswamy.Tummala@Sun.COM 		}
28419879SRamaswamy.Tummala@Sun.COM 
28429879SRamaswamy.Tummala@Sun.COM 		hca_list.hca_guids_alloc_sz = hca_list_32.hca_guids_alloc_sz;
28439879SRamaswamy.Tummala@Sun.COM 		hca_list.hca_guids =
28449879SRamaswamy.Tummala@Sun.COM 		    (ib_guid_t *)(uintptr_t)hca_list_32.hca_guids;
28459879SRamaswamy.Tummala@Sun.COM 		in_nhcasp = &((ibnex_ctl_get_hca_list_32_t *)arg)->nhcas;
28469879SRamaswamy.Tummala@Sun.COM 	} else
28479879SRamaswamy.Tummala@Sun.COM #endif
28489879SRamaswamy.Tummala@Sun.COM 	{
28499879SRamaswamy.Tummala@Sun.COM 		if (ddi_copyin((void *)arg, &hca_list,
28509879SRamaswamy.Tummala@Sun.COM 		    sizeof (ibnex_ctl_get_hca_list_t), mode) != 0) {
28519879SRamaswamy.Tummala@Sun.COM 			IBTF_DPRINTF_L2("ibnex",
28529879SRamaswamy.Tummala@Sun.COM 			    "\tctl_get_hca_list: ddi_copyin err 2");
28539879SRamaswamy.Tummala@Sun.COM 			return (EFAULT);
28549879SRamaswamy.Tummala@Sun.COM 		}
28559879SRamaswamy.Tummala@Sun.COM 
28569879SRamaswamy.Tummala@Sun.COM 		in_nhcasp = &((ibnex_ctl_get_hca_list_t *)arg)->nhcas;
28579879SRamaswamy.Tummala@Sun.COM 	}
28589879SRamaswamy.Tummala@Sun.COM 
28599879SRamaswamy.Tummala@Sun.COM 	nhcas = ibt_get_hca_list(&hca_guids);
28609879SRamaswamy.Tummala@Sun.COM 
28619879SRamaswamy.Tummala@Sun.COM 	/* copy number of hcas to user space */
28629879SRamaswamy.Tummala@Sun.COM 	if (ddi_copyout(&nhcas, in_nhcasp, sizeof (uint_t), mode) != 0) {
28639879SRamaswamy.Tummala@Sun.COM 		IBTF_DPRINTF_L2("ibnex",
28649879SRamaswamy.Tummala@Sun.COM 		    "\tctl_get_hca_list: ddi_copyout err 1");
28659879SRamaswamy.Tummala@Sun.COM 		rv = EFAULT;
28669879SRamaswamy.Tummala@Sun.COM 		goto out;
28679879SRamaswamy.Tummala@Sun.COM 	}
28689879SRamaswamy.Tummala@Sun.COM 
28699879SRamaswamy.Tummala@Sun.COM 	n = MIN(nhcas, hca_list.hca_guids_alloc_sz);
28709879SRamaswamy.Tummala@Sun.COM 	if (n == 0)
28719879SRamaswamy.Tummala@Sun.COM 		goto out;
28729879SRamaswamy.Tummala@Sun.COM 
28739879SRamaswamy.Tummala@Sun.COM 	/* copy HCA guids to user space */
28749879SRamaswamy.Tummala@Sun.COM 	if (ddi_copyout(hca_guids, hca_list.hca_guids,
28759879SRamaswamy.Tummala@Sun.COM 	    n * sizeof (ib_guid_t), mode) != 0) {
28769879SRamaswamy.Tummala@Sun.COM 		IBTF_DPRINTF_L2("ibnex",
28779879SRamaswamy.Tummala@Sun.COM 		    "\tctl_get_hca_list: ddi_copyout err 2");
28789879SRamaswamy.Tummala@Sun.COM 		rv = EFAULT;
28799879SRamaswamy.Tummala@Sun.COM 	}
28809879SRamaswamy.Tummala@Sun.COM 
28819879SRamaswamy.Tummala@Sun.COM out:
28829879SRamaswamy.Tummala@Sun.COM 	if (nhcas > 0)
28839879SRamaswamy.Tummala@Sun.COM 		ibt_free_hca_list(hca_guids, nhcas);
28849879SRamaswamy.Tummala@Sun.COM 
28859879SRamaswamy.Tummala@Sun.COM 	return (rv);
28869879SRamaswamy.Tummala@Sun.COM }
28879879SRamaswamy.Tummala@Sun.COM 
288810094SRamaswamy.Tummala@Sun.COM #define	IBNEX_CTL_CP_HCA_INFO(x, y, driver_name, instance, device_path, \
288910094SRamaswamy.Tummala@Sun.COM     device_path_alloc_sz, device_path_len)				\
289010094SRamaswamy.Tummala@Sun.COM {									\
289110094SRamaswamy.Tummala@Sun.COM 	(x)->hca_node_guid		= (y)->hca_node_guid;		\
289210094SRamaswamy.Tummala@Sun.COM 	(x)->hca_si_guid		= (y)->hca_si_guid;		\
289310094SRamaswamy.Tummala@Sun.COM 	(x)->hca_nports			= (y)->hca_nports;		\
289410094SRamaswamy.Tummala@Sun.COM 	(x)->hca_flags			= (y)->hca_flags;		\
289510094SRamaswamy.Tummala@Sun.COM 	(x)->hca_flags2			= (y)->hca_flags2;		\
289610094SRamaswamy.Tummala@Sun.COM 	(x)->hca_vendor_id		= (y)->hca_vendor_id;		\
289710094SRamaswamy.Tummala@Sun.COM 	(x)->hca_device_id		= (y)->hca_device_id;		\
289810094SRamaswamy.Tummala@Sun.COM 	(x)->hca_version_id		= (y)->hca_version_id;		\
289910094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_chans		= (y)->hca_max_chans;		\
290010094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_chan_sz		= (y)->hca_max_chan_sz;		\
290110094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_sgl		= (y)->hca_max_sgl;		\
290210094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_cq			= (y)->hca_max_cq;		\
290310094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_cq_sz		= (y)->hca_max_cq_sz;		\
290410094SRamaswamy.Tummala@Sun.COM 	(x)->hca_page_sz		= (y)->hca_page_sz;		\
290510094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_memr		= (y)->hca_max_memr;		\
290610094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_memr_len		= (y)->hca_max_memr_len;	\
290710094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_mem_win		= (y)->hca_max_mem_win;		\
290810094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_rsc		= (y)->hca_max_rsc;		\
290910094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_rdma_in_chan	= (y)->hca_max_rdma_in_chan;	\
291010094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_rdma_out_chan	= (y)->hca_max_rdma_out_chan;	\
291110094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_ipv6_chan		= (y)->hca_max_ipv6_chan;	\
291210094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_ether_chan 	= (y)->hca_max_ether_chan;	\
291310094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_mcg_chans		= (y)->hca_max_mcg_chans;	\
291410094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_mcg		= (y)->hca_max_mcg;		\
291510094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_chan_per_mcg	= (y)->hca_max_chan_per_mcg;	\
291610094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_partitions		= (y)->hca_max_partitions;	\
291710094SRamaswamy.Tummala@Sun.COM 	(x)->hca_local_ack_delay	= (y)->hca_local_ack_delay;	\
291810094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_port_sgid_tbl_sz	= (y)->hca_max_port_sgid_tbl_sz; \
291910094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_port_pkey_tbl_sz	= (y)->hca_max_port_pkey_tbl_sz; \
292010094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_pd			= (y)->hca_max_pd;		\
292110094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_ud_dest		= (y)->hca_max_ud_dest;		\
292210094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_srqs		= (y)->hca_max_srqs;		\
292310094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_srqs_sz		= (y)->hca_max_srqs_sz;		\
292410094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_srq_sgl		= (y)->hca_max_srq_sgl;		\
292510094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_cq_handlers	= (y)->hca_max_cq_handlers;	\
292610094SRamaswamy.Tummala@Sun.COM 	(x)->hca_reserved_lkey		= (y)->hca_reserved_lkey;	\
292710094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_fmrs		= (y)->hca_max_fmrs;		\
292810094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_lso_size		= (y)->hca_max_lso_size;	\
292910094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_lso_hdr_size	= (y)->hca_max_lso_hdr_size;	\
293010094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_inline_size	= (y)->hca_max_inline_size;	\
293110094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_cq_mod_count	= (y)->hca_max_cq_mod_count;	\
293210094SRamaswamy.Tummala@Sun.COM 	(x)->hca_max_cq_mod_usec	= (y)->hca_max_cq_mod_usec;	\
293310094SRamaswamy.Tummala@Sun.COM 	(x)->hca_fw_major_version	= (y)->hca_fw_major_version;	\
293410094SRamaswamy.Tummala@Sun.COM 	(x)->hca_fw_minor_version	= (y)->hca_fw_minor_version;	\
293510094SRamaswamy.Tummala@Sun.COM 	(x)->hca_fw_micro_version	= (y)->hca_fw_micro_version;	\
293610094SRamaswamy.Tummala@Sun.COM 	(x)->hca_ud_send_inline_sz	= (y)->hca_ud_send_inline_sz;	\
293710094SRamaswamy.Tummala@Sun.COM 	(x)->hca_conn_send_inline_sz	= (y)->hca_conn_send_inline_sz;	\
293810094SRamaswamy.Tummala@Sun.COM 	(x)->hca_conn_rdmaw_inline_overhead =				\
293910094SRamaswamy.Tummala@Sun.COM 	    (y)->hca_conn_rdmaw_inline_overhead;			\
294010094SRamaswamy.Tummala@Sun.COM 	(x)->hca_recv_sgl_sz		= (y)->hca_recv_sgl_sz;		\
294110094SRamaswamy.Tummala@Sun.COM 	(x)->hca_ud_send_sgl_sz		= (y)->hca_ud_send_sgl_sz;	\
294210094SRamaswamy.Tummala@Sun.COM 	(x)->hca_conn_send_sgl_sz	= (y)->hca_conn_send_sgl_sz;	\
294310094SRamaswamy.Tummala@Sun.COM 	(x)->hca_conn_rdma_sgl_overhead = (y)->hca_conn_rdma_sgl_overhead; \
294410094SRamaswamy.Tummala@Sun.COM 									\
294510094SRamaswamy.Tummala@Sun.COM 	(void) strlcpy((x)->hca_driver_name, (driver_name),		\
294610094SRamaswamy.Tummala@Sun.COM 	    MAX_HCA_DRVNAME_LEN);					\
294710094SRamaswamy.Tummala@Sun.COM 	(x)->hca_driver_instance	= (instance);			\
294810094SRamaswamy.Tummala@Sun.COM 									\
294910094SRamaswamy.Tummala@Sun.COM 	(x)->hca_device_path = ((device_path_alloc_sz) >= (device_path_len)) \
295010094SRamaswamy.Tummala@Sun.COM 	    ? (device_path) : NULL;					\
295110094SRamaswamy.Tummala@Sun.COM 	(x)->hca_device_path_len	= (device_path_len);		\
295210094SRamaswamy.Tummala@Sun.COM }
295310094SRamaswamy.Tummala@Sun.COM 
29549879SRamaswamy.Tummala@Sun.COM /*
29559879SRamaswamy.Tummala@Sun.COM  * IOCTL implementation to query HCA attributes
29569879SRamaswamy.Tummala@Sun.COM  */
29579879SRamaswamy.Tummala@Sun.COM static int
ibnex_ctl_query_hca(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)29589879SRamaswamy.Tummala@Sun.COM ibnex_ctl_query_hca(dev_t dev, int cmd, intptr_t arg, int mode,
29599879SRamaswamy.Tummala@Sun.COM     cred_t *credp, int *rvalp)
29609879SRamaswamy.Tummala@Sun.COM {
29619879SRamaswamy.Tummala@Sun.COM 	int			rv = 0;
296210094SRamaswamy.Tummala@Sun.COM 	ibnex_ctl_query_hca_t	*query_hca = NULL;
296310094SRamaswamy.Tummala@Sun.COM 	ibnex_ctl_query_hca_32_t *query_hca_32 = NULL;
296410094SRamaswamy.Tummala@Sun.COM 	ibt_hca_attr_t		*hca_attr = NULL;
29659879SRamaswamy.Tummala@Sun.COM 	char			driver_name[MAX_HCA_DRVNAME_LEN];
29669879SRamaswamy.Tummala@Sun.COM 	int			instance;
296710094SRamaswamy.Tummala@Sun.COM 	ib_guid_t		hca_guid;
296810094SRamaswamy.Tummala@Sun.COM 	char			*device_path;
296910094SRamaswamy.Tummala@Sun.COM 	uint_t			device_path_alloc_sz, hca_device_path_len;
297010094SRamaswamy.Tummala@Sun.COM 	char			*hca_device_path = NULL;
29719879SRamaswamy.Tummala@Sun.COM 
29729879SRamaswamy.Tummala@Sun.COM 	IBTF_DPRINTF_L4("ibnex", "\tctl_query_hca: cmd=%x, arg=%p, "
29739879SRamaswamy.Tummala@Sun.COM 	    "mode=%x, cred=%p, rval=%p, dev=0x%x", cmd, arg, mode, credp,
29749879SRamaswamy.Tummala@Sun.COM 	    rvalp, dev);
29759879SRamaswamy.Tummala@Sun.COM 
297610094SRamaswamy.Tummala@Sun.COM #ifdef	_MULTI_DATAMODEL
297710094SRamaswamy.Tummala@Sun.COM 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
297810094SRamaswamy.Tummala@Sun.COM 		query_hca_32 = kmem_zalloc(
297910094SRamaswamy.Tummala@Sun.COM 		    sizeof (ibnex_ctl_query_hca_32_t), KM_SLEEP);
298010094SRamaswamy.Tummala@Sun.COM 
298110094SRamaswamy.Tummala@Sun.COM 		if (ddi_copyin((void *)arg, query_hca_32,
298210094SRamaswamy.Tummala@Sun.COM 		    sizeof (ibnex_ctl_query_hca_32_t), mode) != 0) {
298310094SRamaswamy.Tummala@Sun.COM 			IBTF_DPRINTF_L2("ibnex",
298410094SRamaswamy.Tummala@Sun.COM 			    "\tctl_query_hca: ddi_copyin err 1");
298510094SRamaswamy.Tummala@Sun.COM 			rv = EFAULT;
298610094SRamaswamy.Tummala@Sun.COM 			goto out;
298710094SRamaswamy.Tummala@Sun.COM 		}
298810094SRamaswamy.Tummala@Sun.COM 
298910094SRamaswamy.Tummala@Sun.COM 		hca_guid = query_hca_32->hca_guid;
299010094SRamaswamy.Tummala@Sun.COM 		device_path = (char *)(uintptr_t)query_hca_32->hca_device_path;
299110094SRamaswamy.Tummala@Sun.COM 		device_path_alloc_sz = query_hca_32->hca_device_path_alloc_sz;
299210094SRamaswamy.Tummala@Sun.COM 	} else
299310094SRamaswamy.Tummala@Sun.COM #endif
299410094SRamaswamy.Tummala@Sun.COM 	{
299510094SRamaswamy.Tummala@Sun.COM 		query_hca = kmem_zalloc(sizeof (ibnex_ctl_query_hca_t),
299610094SRamaswamy.Tummala@Sun.COM 		    KM_SLEEP);
299710094SRamaswamy.Tummala@Sun.COM 
299810094SRamaswamy.Tummala@Sun.COM 		if (ddi_copyin((void *)arg, query_hca,
299910094SRamaswamy.Tummala@Sun.COM 		    sizeof (ibnex_ctl_query_hca_t), mode) != 0) {
300010094SRamaswamy.Tummala@Sun.COM 			IBTF_DPRINTF_L2("ibnex",
300110094SRamaswamy.Tummala@Sun.COM 			    "\tctl_query_hca: ddi_copyin err 2");
300210094SRamaswamy.Tummala@Sun.COM 			rv = EFAULT;
300310094SRamaswamy.Tummala@Sun.COM 			goto out;
300410094SRamaswamy.Tummala@Sun.COM 		}
300510094SRamaswamy.Tummala@Sun.COM 
300610094SRamaswamy.Tummala@Sun.COM 		hca_guid = query_hca->hca_guid;
300710094SRamaswamy.Tummala@Sun.COM 		device_path = query_hca->hca_device_path;
300810094SRamaswamy.Tummala@Sun.COM 		device_path_alloc_sz = query_hca->hca_device_path_alloc_sz;
300910094SRamaswamy.Tummala@Sun.COM 	}
301010094SRamaswamy.Tummala@Sun.COM 
30119879SRamaswamy.Tummala@Sun.COM 	hca_attr = kmem_zalloc(sizeof (ibt_hca_attr_t), KM_SLEEP);
301210094SRamaswamy.Tummala@Sun.COM 	hca_device_path = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
301310094SRamaswamy.Tummala@Sun.COM 
301410094SRamaswamy.Tummala@Sun.COM 	if (ibtl_ibnex_query_hca_byguid(hca_guid, hca_attr,
301510094SRamaswamy.Tummala@Sun.COM 	    driver_name, sizeof (driver_name), &instance, hca_device_path)
301610094SRamaswamy.Tummala@Sun.COM 	    != IBT_SUCCESS) {
30179879SRamaswamy.Tummala@Sun.COM 		rv = ENXIO;
30189879SRamaswamy.Tummala@Sun.COM 		goto out;
30199879SRamaswamy.Tummala@Sun.COM 	}
30209879SRamaswamy.Tummala@Sun.COM 
302110094SRamaswamy.Tummala@Sun.COM 	hca_device_path_len = strlen(hca_device_path) + 1;
302210094SRamaswamy.Tummala@Sun.COM 
302310094SRamaswamy.Tummala@Sun.COM #ifdef	_MULTI_DATAMODEL
302410094SRamaswamy.Tummala@Sun.COM 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
302510094SRamaswamy.Tummala@Sun.COM 
302610094SRamaswamy.Tummala@Sun.COM 		IBNEX_CTL_CP_HCA_INFO(&query_hca_32->hca_info, hca_attr,
302710094SRamaswamy.Tummala@Sun.COM 		    driver_name, instance, query_hca_32->hca_device_path,
302810094SRamaswamy.Tummala@Sun.COM 		    device_path_alloc_sz, hca_device_path_len);
302910094SRamaswamy.Tummala@Sun.COM 
303010094SRamaswamy.Tummala@Sun.COM 		/* copy hca information to the user space */
303110094SRamaswamy.Tummala@Sun.COM 		if (ddi_copyout(&query_hca_32->hca_info,
303210094SRamaswamy.Tummala@Sun.COM 		    &((ibnex_ctl_query_hca_32_t *)arg)->hca_info,
303310094SRamaswamy.Tummala@Sun.COM 		    sizeof (ibnex_ctl_hca_info_32_t), mode) != 0) {
303410094SRamaswamy.Tummala@Sun.COM 			IBTF_DPRINTF_L2("ibnex",
303510094SRamaswamy.Tummala@Sun.COM 			    "\tctl_query_hca: ddi_copyout err 1");
303610094SRamaswamy.Tummala@Sun.COM 			rv = EFAULT;
303710094SRamaswamy.Tummala@Sun.COM 			goto out;
303810094SRamaswamy.Tummala@Sun.COM 		}
303910094SRamaswamy.Tummala@Sun.COM 	} else
304010094SRamaswamy.Tummala@Sun.COM #endif
304110094SRamaswamy.Tummala@Sun.COM 	{
304210094SRamaswamy.Tummala@Sun.COM 		IBNEX_CTL_CP_HCA_INFO(&query_hca->hca_info, hca_attr,
304310094SRamaswamy.Tummala@Sun.COM 		    driver_name, instance, device_path,
304410094SRamaswamy.Tummala@Sun.COM 		    device_path_alloc_sz, hca_device_path_len);
304510094SRamaswamy.Tummala@Sun.COM 
304610094SRamaswamy.Tummala@Sun.COM 		/* copy hca information to the user space */
304710094SRamaswamy.Tummala@Sun.COM 		if (ddi_copyout(&query_hca->hca_info,
304810094SRamaswamy.Tummala@Sun.COM 		    &((ibnex_ctl_query_hca_t *)arg)->hca_info,
304910094SRamaswamy.Tummala@Sun.COM 		    sizeof (ibnex_ctl_hca_info_t), mode) != 0) {
305010094SRamaswamy.Tummala@Sun.COM 			IBTF_DPRINTF_L2("ibnex",
305110094SRamaswamy.Tummala@Sun.COM 			    "\tctl_query_hca: ddi_copyout err 2");
305210094SRamaswamy.Tummala@Sun.COM 			rv = EFAULT;
305310094SRamaswamy.Tummala@Sun.COM 			goto out;
305410094SRamaswamy.Tummala@Sun.COM 		}
305510094SRamaswamy.Tummala@Sun.COM 	}
305610094SRamaswamy.Tummala@Sun.COM 
305710094SRamaswamy.Tummala@Sun.COM 	if (device_path_alloc_sz >= hca_device_path_len) {
305810094SRamaswamy.Tummala@Sun.COM 		if (ddi_copyout(hca_device_path,
305910094SRamaswamy.Tummala@Sun.COM 		    device_path,
306010094SRamaswamy.Tummala@Sun.COM 		    hca_device_path_len, mode) != 0) {
306110094SRamaswamy.Tummala@Sun.COM 			IBTF_DPRINTF_L2("ibnex", "\tctl_query_hca: "
306210094SRamaswamy.Tummala@Sun.COM 			    "ddi_copyout err copying device path");
306310094SRamaswamy.Tummala@Sun.COM 			rv = EFAULT;
306410094SRamaswamy.Tummala@Sun.COM 		}
30659879SRamaswamy.Tummala@Sun.COM 	}
30669879SRamaswamy.Tummala@Sun.COM 
30679879SRamaswamy.Tummala@Sun.COM out:
306810094SRamaswamy.Tummala@Sun.COM 	if (query_hca)
306910094SRamaswamy.Tummala@Sun.COM 		kmem_free(query_hca, sizeof (ibnex_ctl_query_hca_t));
307010094SRamaswamy.Tummala@Sun.COM 	if (query_hca_32)
307110094SRamaswamy.Tummala@Sun.COM 		kmem_free(query_hca_32, sizeof (ibnex_ctl_query_hca_32_t));
307210094SRamaswamy.Tummala@Sun.COM 	if (hca_attr)
307310094SRamaswamy.Tummala@Sun.COM 		kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
307410094SRamaswamy.Tummala@Sun.COM 	if (hca_device_path)
307510094SRamaswamy.Tummala@Sun.COM 		kmem_free(hca_device_path, MAXPATHLEN);
307610094SRamaswamy.Tummala@Sun.COM 
30779879SRamaswamy.Tummala@Sun.COM 	return (rv);
30789879SRamaswamy.Tummala@Sun.COM }
30799879SRamaswamy.Tummala@Sun.COM 
30809879SRamaswamy.Tummala@Sun.COM #define	IBNEX_CTL_CP_PORT_INFO(x, y, sgid_tbl, pkey_tbl)	\
30819879SRamaswamy.Tummala@Sun.COM {								\
30829879SRamaswamy.Tummala@Sun.COM 	(x)->p_lid		= (y)->p_opaque1;		\
30839879SRamaswamy.Tummala@Sun.COM 	(x)->p_qkey_violations	= (y)->p_qkey_violations;	\
30849879SRamaswamy.Tummala@Sun.COM 	(x)->p_pkey_violations	= (y)->p_pkey_violations;	\
30859879SRamaswamy.Tummala@Sun.COM 	(x)->p_sm_sl		= (y)->p_sm_sl;			\
30869879SRamaswamy.Tummala@Sun.COM 	(x)->p_phys_state	= (y)->p_phys_state;		\
30879879SRamaswamy.Tummala@Sun.COM 	(x)->p_sm_lid		= (y)->p_sm_lid;		\
30889879SRamaswamy.Tummala@Sun.COM 	(x)->p_linkstate	= (y)->p_linkstate;		\
30899879SRamaswamy.Tummala@Sun.COM 	(x)->p_port_num		= (y)->p_port_num;		\
30909879SRamaswamy.Tummala@Sun.COM 	(x)->p_width_supported	= (y)->p_width_supported;	\
30919879SRamaswamy.Tummala@Sun.COM 	(x)->p_width_enabled	= (y)->p_width_enabled;		\
30929879SRamaswamy.Tummala@Sun.COM 	(x)->p_width_active	= (y)->p_width_active;		\
30939879SRamaswamy.Tummala@Sun.COM 	(x)->p_mtu		= (y)->p_mtu;			\
30949879SRamaswamy.Tummala@Sun.COM 	(x)->p_lmc		= (y)->p_lmc;			\
30959879SRamaswamy.Tummala@Sun.COM 	(x)->p_speed_supported	= (y)->p_speed_supported;	\
30969879SRamaswamy.Tummala@Sun.COM 	(x)->p_speed_enabled	= (y)->p_speed_enabled;		\
30979879SRamaswamy.Tummala@Sun.COM 	(x)->p_speed_active	= (y)->p_speed_active;		\
30989879SRamaswamy.Tummala@Sun.COM 	(x)->p_sgid_tbl		= (sgid_tbl);			\
30999879SRamaswamy.Tummala@Sun.COM 	(x)->p_sgid_tbl_sz	= (y)->p_sgid_tbl_sz;		\
31009879SRamaswamy.Tummala@Sun.COM 	(x)->p_pkey_tbl		= (pkey_tbl);			\
31019879SRamaswamy.Tummala@Sun.COM 	(x)->p_pkey_tbl_sz	= (y)->p_pkey_tbl_sz;		\
31029879SRamaswamy.Tummala@Sun.COM 	(x)->p_def_pkey_ix	= (y)->p_def_pkey_ix;		\
31039879SRamaswamy.Tummala@Sun.COM 	(x)->p_max_vl		= (y)->p_max_vl;		\
31049879SRamaswamy.Tummala@Sun.COM 	(x)->p_init_type_reply	= (y)->p_init_type_reply;	\
31059879SRamaswamy.Tummala@Sun.COM 	(x)->p_subnet_timeout	= (y)->p_subnet_timeout;	\
31069879SRamaswamy.Tummala@Sun.COM 	(x)->p_capabilities	= (y)->p_capabilities;		\
31079879SRamaswamy.Tummala@Sun.COM 	(x)->p_msg_sz		= (y)->p_msg_sz;		\
31089879SRamaswamy.Tummala@Sun.COM }
31099879SRamaswamy.Tummala@Sun.COM 
31109879SRamaswamy.Tummala@Sun.COM /*
31119879SRamaswamy.Tummala@Sun.COM  * IOCTL implementation to query HCA port attributes
31129879SRamaswamy.Tummala@Sun.COM  */
31139879SRamaswamy.Tummala@Sun.COM static int
ibnex_ctl_query_hca_port(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)31149879SRamaswamy.Tummala@Sun.COM ibnex_ctl_query_hca_port(dev_t dev, int cmd, intptr_t arg, int mode,
31159879SRamaswamy.Tummala@Sun.COM     cred_t *credp, int *rvalp)
31169879SRamaswamy.Tummala@Sun.COM {
31179879SRamaswamy.Tummala@Sun.COM 	ibt_hca_portinfo_t		*ibt_pi;
31189879SRamaswamy.Tummala@Sun.COM 	uint_t				nports;
31199879SRamaswamy.Tummala@Sun.COM 	uint_t				size = 0;
31209879SRamaswamy.Tummala@Sun.COM 	int				rv = 0;
31219879SRamaswamy.Tummala@Sun.COM 	ibnex_ctl_query_hca_port_t	*query_hca_port = NULL;
31229879SRamaswamy.Tummala@Sun.COM 	ibnex_ctl_query_hca_port_32_t	*query_hca_port_32 = NULL;
31239879SRamaswamy.Tummala@Sun.COM 	uint_t				sgid_tbl_sz;
31249879SRamaswamy.Tummala@Sun.COM 	uint16_t			pkey_tbl_sz;
312510183SRamaswamy.Tummala@Sun.COM 	ibt_hca_attr_t			hca_attr;
31269879SRamaswamy.Tummala@Sun.COM 
31279879SRamaswamy.Tummala@Sun.COM 	IBTF_DPRINTF_L4("ibnex", "\tctl_query_hca_port: cmd=%x, arg=%p, "
31289879SRamaswamy.Tummala@Sun.COM 	    "mode=%x, cred=%p, rval=%p, dev=0x%x", cmd, arg, mode, credp,
31299879SRamaswamy.Tummala@Sun.COM 	    rvalp, dev);
31309879SRamaswamy.Tummala@Sun.COM 
31319879SRamaswamy.Tummala@Sun.COM 	query_hca_port = kmem_zalloc(sizeof (ibnex_ctl_query_hca_port_t),
31329879SRamaswamy.Tummala@Sun.COM 	    KM_SLEEP);
31339879SRamaswamy.Tummala@Sun.COM 
31349879SRamaswamy.Tummala@Sun.COM #ifdef	_MULTI_DATAMODEL
31359879SRamaswamy.Tummala@Sun.COM 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
31369879SRamaswamy.Tummala@Sun.COM 		query_hca_port_32 = kmem_zalloc(
31379879SRamaswamy.Tummala@Sun.COM 		    sizeof (ibnex_ctl_query_hca_port_32_t), KM_SLEEP);
31389879SRamaswamy.Tummala@Sun.COM 
31399879SRamaswamy.Tummala@Sun.COM 		if (ddi_copyin((void *)arg, query_hca_port_32,
31409879SRamaswamy.Tummala@Sun.COM 		    sizeof (ibnex_ctl_query_hca_port_32_t), mode) != 0) {
31419879SRamaswamy.Tummala@Sun.COM 			IBTF_DPRINTF_L2("ibnex",
314210094SRamaswamy.Tummala@Sun.COM 			    "\tctl_query_hca_port: ddi_copyin err 1");
31439879SRamaswamy.Tummala@Sun.COM 			rv = EFAULT;
31449879SRamaswamy.Tummala@Sun.COM 			goto out;
31459879SRamaswamy.Tummala@Sun.COM 		}
31469879SRamaswamy.Tummala@Sun.COM 
31479879SRamaswamy.Tummala@Sun.COM 		query_hca_port->hca_guid = query_hca_port_32->hca_guid;
31489879SRamaswamy.Tummala@Sun.COM 		query_hca_port->port_num = query_hca_port_32->port_num;
31499879SRamaswamy.Tummala@Sun.COM 
31509879SRamaswamy.Tummala@Sun.COM 		query_hca_port->sgid_tbl =
31519879SRamaswamy.Tummala@Sun.COM 		    (ib_gid_t *)(uintptr_t)query_hca_port_32->sgid_tbl;
31529879SRamaswamy.Tummala@Sun.COM 		query_hca_port->sgid_tbl_alloc_sz =
31539879SRamaswamy.Tummala@Sun.COM 		    query_hca_port_32->sgid_tbl_alloc_sz;
31549879SRamaswamy.Tummala@Sun.COM 
31559879SRamaswamy.Tummala@Sun.COM 		query_hca_port->pkey_tbl =
31569879SRamaswamy.Tummala@Sun.COM 		    (ib_pkey_t *)(uintptr_t)query_hca_port_32->pkey_tbl;
31579879SRamaswamy.Tummala@Sun.COM 		query_hca_port->pkey_tbl_alloc_sz =
31589879SRamaswamy.Tummala@Sun.COM 		    query_hca_port_32->pkey_tbl_alloc_sz;
31599879SRamaswamy.Tummala@Sun.COM 
31609879SRamaswamy.Tummala@Sun.COM 	} else
31619879SRamaswamy.Tummala@Sun.COM #endif
31629879SRamaswamy.Tummala@Sun.COM 	{
31639879SRamaswamy.Tummala@Sun.COM 		if (ddi_copyin((void *)arg, query_hca_port,
31649879SRamaswamy.Tummala@Sun.COM 		    sizeof (ibnex_ctl_query_hca_port_t), mode) != 0) {
31659879SRamaswamy.Tummala@Sun.COM 			IBTF_DPRINTF_L2("ibnex",
31669879SRamaswamy.Tummala@Sun.COM 			    "\tctl_query_hca_port: ddi_copyin err 2");
31679879SRamaswamy.Tummala@Sun.COM 			rv = EFAULT;
31689879SRamaswamy.Tummala@Sun.COM 			goto out;
31699879SRamaswamy.Tummala@Sun.COM 		}
31709879SRamaswamy.Tummala@Sun.COM 	}
31719879SRamaswamy.Tummala@Sun.COM 
317210183SRamaswamy.Tummala@Sun.COM 	if (ibt_query_hca_byguid(query_hca_port->hca_guid, &hca_attr) !=
317310183SRamaswamy.Tummala@Sun.COM 	    IBT_SUCCESS) {
317410183SRamaswamy.Tummala@Sun.COM 		rv = ENXIO;
317510183SRamaswamy.Tummala@Sun.COM 		goto out;
317610183SRamaswamy.Tummala@Sun.COM 	}
317710183SRamaswamy.Tummala@Sun.COM 
317810183SRamaswamy.Tummala@Sun.COM 	if (query_hca_port->port_num == 0 ||
317910183SRamaswamy.Tummala@Sun.COM 	    query_hca_port->port_num > hca_attr.hca_nports) {
318010183SRamaswamy.Tummala@Sun.COM 		rv = ENOENT;
31819879SRamaswamy.Tummala@Sun.COM 		goto out;
31829879SRamaswamy.Tummala@Sun.COM 	}
31839879SRamaswamy.Tummala@Sun.COM 
31849879SRamaswamy.Tummala@Sun.COM 	/*
31859879SRamaswamy.Tummala@Sun.COM 	 * Query hca port attributes and copy them to the user space.
31869879SRamaswamy.Tummala@Sun.COM 	 */
31879879SRamaswamy.Tummala@Sun.COM 
31889879SRamaswamy.Tummala@Sun.COM 	if (ibt_query_hca_ports_byguid(query_hca_port->hca_guid,
31899879SRamaswamy.Tummala@Sun.COM 	    query_hca_port->port_num, &ibt_pi, &nports, &size) != IBT_SUCCESS) {
319010183SRamaswamy.Tummala@Sun.COM 		rv = ENXIO;
31919879SRamaswamy.Tummala@Sun.COM 		goto out;
31929879SRamaswamy.Tummala@Sun.COM 	}
31939879SRamaswamy.Tummala@Sun.COM 
31949879SRamaswamy.Tummala@Sun.COM 	sgid_tbl_sz = MIN(query_hca_port->sgid_tbl_alloc_sz,
31959879SRamaswamy.Tummala@Sun.COM 	    ibt_pi->p_sgid_tbl_sz);
31969879SRamaswamy.Tummala@Sun.COM 
31979879SRamaswamy.Tummala@Sun.COM 	pkey_tbl_sz = MIN(query_hca_port->pkey_tbl_alloc_sz,
31989879SRamaswamy.Tummala@Sun.COM 	    ibt_pi->p_pkey_tbl_sz);
31999879SRamaswamy.Tummala@Sun.COM 
32009879SRamaswamy.Tummala@Sun.COM #ifdef	_MULTI_DATAMODEL
32019879SRamaswamy.Tummala@Sun.COM 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
32029879SRamaswamy.Tummala@Sun.COM 		IBNEX_CTL_CP_PORT_INFO(
32039879SRamaswamy.Tummala@Sun.COM 		    &query_hca_port_32->port_info, ibt_pi,
32049879SRamaswamy.Tummala@Sun.COM 		    query_hca_port_32->sgid_tbl, query_hca_port_32->pkey_tbl);
32059879SRamaswamy.Tummala@Sun.COM 
32069879SRamaswamy.Tummala@Sun.COM 		if (ddi_copyout(&query_hca_port_32->port_info,
32079879SRamaswamy.Tummala@Sun.COM 		    &((ibnex_ctl_query_hca_port_32_t *)arg)->port_info,
32089879SRamaswamy.Tummala@Sun.COM 		    sizeof (ibnex_ctl_hca_port_info_32_t), mode) != 0 ||
32099879SRamaswamy.Tummala@Sun.COM 
32109879SRamaswamy.Tummala@Sun.COM 		    ddi_copyout(ibt_pi->p_sgid_tbl,
32119879SRamaswamy.Tummala@Sun.COM 		    query_hca_port->sgid_tbl,
32129879SRamaswamy.Tummala@Sun.COM 		    sgid_tbl_sz * sizeof (ib_gid_t), mode) != 0 ||
32139879SRamaswamy.Tummala@Sun.COM 
32149879SRamaswamy.Tummala@Sun.COM 		    ddi_copyout(ibt_pi->p_pkey_tbl,
32159879SRamaswamy.Tummala@Sun.COM 		    query_hca_port->pkey_tbl,
32169879SRamaswamy.Tummala@Sun.COM 		    pkey_tbl_sz * sizeof (ib_pkey_t), mode) != 0) {
32179879SRamaswamy.Tummala@Sun.COM 
32189879SRamaswamy.Tummala@Sun.COM 			IBTF_DPRINTF_L2("ibnex",
32199879SRamaswamy.Tummala@Sun.COM 			    "\tctl_query_hca_port: ddi_copyout err 2");
32209879SRamaswamy.Tummala@Sun.COM 			rv = EFAULT;
32219879SRamaswamy.Tummala@Sun.COM 			goto out;
32229879SRamaswamy.Tummala@Sun.COM 		}
32239879SRamaswamy.Tummala@Sun.COM 	} else
32249879SRamaswamy.Tummala@Sun.COM #endif
32259879SRamaswamy.Tummala@Sun.COM 	{
32269879SRamaswamy.Tummala@Sun.COM 		IBNEX_CTL_CP_PORT_INFO(
32279879SRamaswamy.Tummala@Sun.COM 		    &query_hca_port->port_info, ibt_pi,
32289879SRamaswamy.Tummala@Sun.COM 		    query_hca_port->sgid_tbl, query_hca_port->pkey_tbl);
32299879SRamaswamy.Tummala@Sun.COM 
32309879SRamaswamy.Tummala@Sun.COM 		if (ddi_copyout(&query_hca_port->port_info,
32319879SRamaswamy.Tummala@Sun.COM 		    &((ibnex_ctl_query_hca_port_t *)arg)->port_info,
32329879SRamaswamy.Tummala@Sun.COM 		    sizeof (ibnex_ctl_hca_port_info_t), mode) != 0 ||
32339879SRamaswamy.Tummala@Sun.COM 
32349879SRamaswamy.Tummala@Sun.COM 		    ddi_copyout(ibt_pi->p_sgid_tbl,
32359879SRamaswamy.Tummala@Sun.COM 		    query_hca_port->sgid_tbl,
32369879SRamaswamy.Tummala@Sun.COM 		    sgid_tbl_sz * sizeof (ib_gid_t), mode) != 0 ||
32379879SRamaswamy.Tummala@Sun.COM 
32389879SRamaswamy.Tummala@Sun.COM 		    ddi_copyout(ibt_pi->p_pkey_tbl,
32399879SRamaswamy.Tummala@Sun.COM 		    query_hca_port->pkey_tbl,
32409879SRamaswamy.Tummala@Sun.COM 		    pkey_tbl_sz * sizeof (ib_pkey_t), mode) != 0) {
32419879SRamaswamy.Tummala@Sun.COM 
32429879SRamaswamy.Tummala@Sun.COM 			IBTF_DPRINTF_L2("ibnex",
32439879SRamaswamy.Tummala@Sun.COM 			    "\tctl_query_hca_port: ddi_copyout err 2");
32449879SRamaswamy.Tummala@Sun.COM 			rv = EFAULT;
32459879SRamaswamy.Tummala@Sun.COM 			goto out;
32469879SRamaswamy.Tummala@Sun.COM 		}
32479879SRamaswamy.Tummala@Sun.COM 	}
32489879SRamaswamy.Tummala@Sun.COM 
32499879SRamaswamy.Tummala@Sun.COM out:
32509879SRamaswamy.Tummala@Sun.COM 	if (size > 0)
32519879SRamaswamy.Tummala@Sun.COM 		ibt_free_portinfo(ibt_pi, size);
32529879SRamaswamy.Tummala@Sun.COM 
32539879SRamaswamy.Tummala@Sun.COM 	if (query_hca_port)
32549879SRamaswamy.Tummala@Sun.COM 		kmem_free(query_hca_port, sizeof (ibnex_ctl_query_hca_port_t));
32559879SRamaswamy.Tummala@Sun.COM 
32569879SRamaswamy.Tummala@Sun.COM 	if (query_hca_port_32)
32579879SRamaswamy.Tummala@Sun.COM 		kmem_free(query_hca_port_32,
32589879SRamaswamy.Tummala@Sun.COM 		    sizeof (ibnex_ctl_query_hca_port_32_t));
32599879SRamaswamy.Tummala@Sun.COM 	return (rv);
32609879SRamaswamy.Tummala@Sun.COM }
3261