17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
519174f18Svikram  * Common Development and Distribution License (the "License").
619174f18Svikram  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
221cfa752fSRamaswamy Tummala  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
25*3fe80ca4SDan Cross /*
26*3fe80ca4SDan Cross  * Copyright 2023 Oxide Computer Company
27*3fe80ca4SDan Cross  */
28*3fe80ca4SDan Cross 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * This file contains support required for IB cfgadm plugin.
317c478bd9Sstevel@tonic-gate  */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include <sys/conf.h>
347c478bd9Sstevel@tonic-gate #include <sys/stat.h>
357c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
367c478bd9Sstevel@tonic-gate #include <sys/ib/mgt/ibdm/ibdm_impl.h>
377c478bd9Sstevel@tonic-gate #include <sys/ib/ibnex/ibnex.h>
387c478bd9Sstevel@tonic-gate #include <sys/ib/ibnex/ibnex_devctl.h>
397c478bd9Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl_ibnex.h>
40d1a5c838SRamaswamy Tummala #include <sys/ib/ibtl/impl/ibtl.h>
417c478bd9Sstevel@tonic-gate #include <sys/file.h>
427c478bd9Sstevel@tonic-gate #include <sys/sunndi.h>
437c478bd9Sstevel@tonic-gate #include <sys/fs/dv_node.h>
447c478bd9Sstevel@tonic-gate #include <sys/mdi_impldefs.h>
457c478bd9Sstevel@tonic-gate #include <sys/sunmdi.h>
467c478bd9Sstevel@tonic-gate 
47d1a5c838SRamaswamy Tummala /* return the minimum value of (x) and (y) */
48d1a5c838SRamaswamy Tummala #define	MIN(x, y)	((x) < (y) ? (x) : (y))
49d1a5c838SRamaswamy Tummala 
507c478bd9Sstevel@tonic-gate /*
517c478bd9Sstevel@tonic-gate  * function prototypes
527c478bd9Sstevel@tonic-gate  */
537c478bd9Sstevel@tonic-gate int			ibnex_open(dev_t *, int, int, cred_t *);
547c478bd9Sstevel@tonic-gate int			ibnex_close(dev_t, int, int, cred_t *);
557c478bd9Sstevel@tonic-gate int			ibnex_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
567c478bd9Sstevel@tonic-gate int			ibnex_offline_childdip(dev_info_t *);
577c478bd9Sstevel@tonic-gate static int		ibnex_get_num_devices(void);
587c478bd9Sstevel@tonic-gate static int		ibnex_get_snapshot(char **, size_t *, int);
597c478bd9Sstevel@tonic-gate static int		ibnex_get_commsvcnode_snapshot(nvlist_t **, ib_guid_t,
607c478bd9Sstevel@tonic-gate 			    ib_guid_t, int, ib_pkey_t, ibnex_node_type_t);
617c478bd9Sstevel@tonic-gate static int		ibnex_fill_ioc_tmp(nvlist_t **, ibdm_ioc_info_t *);
627c478bd9Sstevel@tonic-gate static int		ibnex_fill_nodeinfo(nvlist_t **, ibnex_node_data_t *,
637c478bd9Sstevel@tonic-gate 			    void *);
641cfa752fSRamaswamy Tummala static void		ibnex_figure_ap_devstate(ibnex_node_data_t *,
657c478bd9Sstevel@tonic-gate 			    devctl_ap_state_t *);
667c478bd9Sstevel@tonic-gate static void		ibnex_figure_ib_apid_devstate(devctl_ap_state_t *);
67bf8d275aSToomas Soome static char		*ibnex_get_apid(struct devctl_iocdata *);
687c478bd9Sstevel@tonic-gate static int		ibnex_get_dip_from_apid(char *, dev_info_t **,
697c478bd9Sstevel@tonic-gate 			    ibnex_node_data_t **);
701cfa752fSRamaswamy Tummala extern int		ibnex_get_node_and_dip_from_guid(ib_guid_t, int,
711cfa752fSRamaswamy Tummala 			    ib_pkey_t, ibnex_node_data_t **, dev_info_t **);
727c478bd9Sstevel@tonic-gate static ibnex_rval_t	ibnex_handle_pseudo_configure(char *);
737c478bd9Sstevel@tonic-gate static ibnex_rval_t	ibnex_handle_ioc_configure(char *);
747c478bd9Sstevel@tonic-gate static ibnex_rval_t	ibnex_handle_commsvcnode_configure(char *);
757c478bd9Sstevel@tonic-gate static void		ibnex_return_apid(dev_info_t *, char **);
767c478bd9Sstevel@tonic-gate static void		ibnex_port_conf_entry_add(char *);
777c478bd9Sstevel@tonic-gate static void		ibnex_vppa_conf_entry_add(char *);
787c478bd9Sstevel@tonic-gate static void		ibnex_hcasvc_conf_entry_add(char *);
797c478bd9Sstevel@tonic-gate static int		ibnex_port_conf_entry_delete(char *, char *);
807c478bd9Sstevel@tonic-gate static int		ibnex_vppa_conf_entry_delete(char *, char *);
817c478bd9Sstevel@tonic-gate static int		ibnex_hcasvc_conf_entry_delete(char *, char *);
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate static ibnex_rval_t	ibnex_ioc_fininode(dev_info_t *, ibnex_ioc_node_t *);
847c478bd9Sstevel@tonic-gate static ibnex_rval_t	ibnex_commsvc_fininode(dev_info_t *);
857c478bd9Sstevel@tonic-gate static ibnex_rval_t	ibnex_pseudo_fininode(dev_info_t *);
867c478bd9Sstevel@tonic-gate 
87d1a5c838SRamaswamy Tummala static int		ibnex_devctl(dev_t, int, intptr_t, int,
88d1a5c838SRamaswamy Tummala 			    cred_t *, int *);
89d1a5c838SRamaswamy Tummala static int		ibnex_ctl_get_api_ver(dev_t, int, intptr_t, int,
90d1a5c838SRamaswamy Tummala 			    cred_t *, int *);
91d1a5c838SRamaswamy Tummala static int		ibnex_ctl_get_hca_list(dev_t, int, intptr_t, int,
92d1a5c838SRamaswamy Tummala 			    cred_t *, int *);
93d1a5c838SRamaswamy Tummala static int		ibnex_ctl_query_hca(dev_t, int, intptr_t, int,
94d1a5c838SRamaswamy Tummala 			    cred_t *, int *);
95d1a5c838SRamaswamy Tummala static int		ibnex_ctl_query_hca_port(dev_t, int, intptr_t, int,
96d1a5c838SRamaswamy Tummala 			    cred_t *, int *);
97d1a5c838SRamaswamy Tummala 
987c478bd9Sstevel@tonic-gate extern uint64_t		ibnex_str2hex(char *, int, int *);
9900a3eaf3SRamaswamy Tummala extern int		ibnex_ioc_initnode_all_pi(ibdm_ioc_info_t *);
1007c478bd9Sstevel@tonic-gate extern dev_info_t	*ibnex_commsvc_initnode(dev_info_t *,
1017c478bd9Sstevel@tonic-gate 			    ibdm_port_attr_t *, int, int, ib_pkey_t, int *,
1027c478bd9Sstevel@tonic-gate 			    int);
1037c478bd9Sstevel@tonic-gate extern int		ibnex_get_dip_from_guid(ib_guid_t, int,
1047c478bd9Sstevel@tonic-gate 			    ib_pkey_t, dev_info_t **);
1057c478bd9Sstevel@tonic-gate extern void		ibnex_reprobe_ioc_dev(void *arg);
1067c478bd9Sstevel@tonic-gate extern void		ibnex_reprobe_ioc_all();
10700a3eaf3SRamaswamy Tummala extern int		ibnex_pseudo_create_all_pi(ibnex_node_data_t *);
1087c478bd9Sstevel@tonic-gate extern void		ibnex_pseudo_initnodes(void);
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate extern ibnex_t	ibnex;
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate /*
1137c478bd9Sstevel@tonic-gate  * ibnex_open()
1147c478bd9Sstevel@tonic-gate  */
1157c478bd9Sstevel@tonic-gate /* ARGSUSED */
1167c478bd9Sstevel@tonic-gate int
ibnex_open(dev_t * dev,int flag,int otyp,cred_t * credp)1177c478bd9Sstevel@tonic-gate ibnex_open(dev_t *dev, int flag, int otyp, cred_t *credp)
1187c478bd9Sstevel@tonic-gate {
1197c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\topen");
1207c478bd9Sstevel@tonic-gate 	return (0);
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate /*
1257c478bd9Sstevel@tonic-gate  * ibnex_close()
1267c478bd9Sstevel@tonic-gate  */
1277c478bd9Sstevel@tonic-gate /* ARGSUSED */
1287c478bd9Sstevel@tonic-gate int
ibnex_close(dev_t dev,int flag,int otyp,cred_t * credp)1297c478bd9Sstevel@tonic-gate ibnex_close(dev_t dev, int flag, int otyp, cred_t *credp)
1307c478bd9Sstevel@tonic-gate {
1317c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tclose");
1327c478bd9Sstevel@tonic-gate 	return (0);
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate 
135d1a5c838SRamaswamy Tummala int
ibnex_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)136d1a5c838SRamaswamy Tummala ibnex_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
137d1a5c838SRamaswamy Tummala     int *rvalp)
138d1a5c838SRamaswamy Tummala {
139d1a5c838SRamaswamy Tummala 	/*
140d1a5c838SRamaswamy Tummala 	 * For all generic devctl ioctls (such as DEVCTL_AP_CONFIGURE),
141d1a5c838SRamaswamy Tummala 	 * call ibnex_devctl().
142d1a5c838SRamaswamy Tummala 	 */
143d1a5c838SRamaswamy Tummala 	if (IS_DEVCTL(cmd))
144d1a5c838SRamaswamy Tummala 		return (ibnex_devctl(dev, cmd, arg, mode, credp, rvalp));
145d1a5c838SRamaswamy Tummala 
146d1a5c838SRamaswamy Tummala 	/*
147d1a5c838SRamaswamy Tummala 	 * The rest are ibnex specific ioctls.
148d1a5c838SRamaswamy Tummala 	 */
149d1a5c838SRamaswamy Tummala 
150d1a5c838SRamaswamy Tummala 	switch (cmd) {
151d1a5c838SRamaswamy Tummala 	case IBNEX_CTL_GET_API_VER:
152d1a5c838SRamaswamy Tummala 		return (ibnex_ctl_get_api_ver(dev, cmd, arg, mode,
153d1a5c838SRamaswamy Tummala 		    credp, rvalp));
154d1a5c838SRamaswamy Tummala 
155d1a5c838SRamaswamy Tummala 	case IBNEX_CTL_GET_HCA_LIST:
156d1a5c838SRamaswamy Tummala 		return (ibnex_ctl_get_hca_list(dev, cmd, arg, mode,
157d1a5c838SRamaswamy Tummala 		    credp, rvalp));
158d1a5c838SRamaswamy Tummala 
159d1a5c838SRamaswamy Tummala 	case IBNEX_CTL_QUERY_HCA:
160d1a5c838SRamaswamy Tummala 		return (ibnex_ctl_query_hca(dev, cmd, arg, mode,
161d1a5c838SRamaswamy Tummala 		    credp, rvalp));
162d1a5c838SRamaswamy Tummala 
163d1a5c838SRamaswamy Tummala 	case IBNEX_CTL_QUERY_HCA_PORT:
164d1a5c838SRamaswamy Tummala 		return (ibnex_ctl_query_hca_port(dev, cmd, arg, mode,
165d1a5c838SRamaswamy Tummala 		    credp, rvalp));
166d1a5c838SRamaswamy Tummala 
167d1a5c838SRamaswamy Tummala 	default:
168d1a5c838SRamaswamy Tummala 		return (EINVAL);
169d1a5c838SRamaswamy Tummala 	}
170d1a5c838SRamaswamy Tummala }
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate /*
1737c478bd9Sstevel@tonic-gate  * ibnex_ioctl()
1747c478bd9Sstevel@tonic-gate  *	Ioctl routine for cfgadm controls
1757c478bd9Sstevel@tonic-gate  *	DEVCTL_AP_GETSTATE:	returns attachment point state
1767c478bd9Sstevel@tonic-gate  *	DEVCTL_AP_CONTROL:	Does "ibnex" specific ioctls listed below
1777c478bd9Sstevel@tonic-gate  *		IBNEX_NUM_DEVICE_NODES	Gives how many device nodes exist?
1787c478bd9Sstevel@tonic-gate  *		IBNEX_NUM_HCA_NODES	Gives how many HCAs exist in the fabric
1797c478bd9Sstevel@tonic-gate  *		IBNEX_UPDATE_PKEY_TBLS	"-x update_pkey_tbls"
1807c478bd9Sstevel@tonic-gate  *		IBNEX_GET_SNAPSHOT	Gets the "snapshot" back to user-land
1817c478bd9Sstevel@tonic-gate  *		IBNEX_SNAPSHOT_SIZE	What is "snapshot" size
1827c478bd9Sstevel@tonic-gate  *		IBNEX_DEVICE_PATH_SZ	What is device-path size
1837c478bd9Sstevel@tonic-gate  *		IBNEX_GET_DEVICE_PATH	Gets the device path for Dynamic ap
1847c478bd9Sstevel@tonic-gate  *		IBNEX_HCA_LIST_SZ	"-x list" option size for the HCA ap_id
1857c478bd9Sstevel@tonic-gate  *		IBNEX_HCA_LIST_INFO	"-x list" option info for the HCA ap_id
1867c478bd9Sstevel@tonic-gate  *		IBNEX_UNCFG_CLNTS_SZ	"-x unconfig_client option size"
1877c478bd9Sstevel@tonic-gate  *		IBNEX_UNCFG_CLNTS_INFO	"-x unconfig_client data"
1887c478bd9Sstevel@tonic-gate  *		IBNEX_CONF_ENTRY_ADD:	"-x add_service"
1897c478bd9Sstevel@tonic-gate  *		IBNEX_CONF_ENTRY_DEL:	"-x delete_service"
1907c478bd9Sstevel@tonic-gate  *		IBNEX_HCA_VERBOSE_SZ:	"-alv hca_apid data size"
1917c478bd9Sstevel@tonic-gate  *		IBNEX_HCA_VERBOSE_INFO: "-alv hca_apid actual data"
1927c478bd9Sstevel@tonic-gate  *		IBNEX_UPDATE_IOC_CONF	"-x update_ioc_conf"
1937c478bd9Sstevel@tonic-gate  *	DEVCTL_AP_CONFIGURE:	"configure" the attachment point
1947c478bd9Sstevel@tonic-gate  *	DEVCTL_AP_UNCONFIGURE:	"unconfigure" the attachment point
1957c478bd9Sstevel@tonic-gate  */
1967c478bd9Sstevel@tonic-gate /* ARGSUSED */
197d1a5c838SRamaswamy Tummala static int
ibnex_devctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)198d1a5c838SRamaswamy Tummala ibnex_devctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
1997c478bd9Sstevel@tonic-gate     int *rvalp)
2007c478bd9Sstevel@tonic-gate {
2017c478bd9Sstevel@tonic-gate 	int			ret, rv = 0, ioc_reprobe_pending = 0;
2027c478bd9Sstevel@tonic-gate 	char			*snapshot = NULL;
2037c478bd9Sstevel@tonic-gate 	char			*apid_n = NULL;
2047c478bd9Sstevel@tonic-gate 	char			*service = NULL;
2057c478bd9Sstevel@tonic-gate 	char			*devnm = NULL;
2067c478bd9Sstevel@tonic-gate 	char			*msg;
2077c478bd9Sstevel@tonic-gate 	char			*guid_str;
2087c478bd9Sstevel@tonic-gate 	uint_t			num_hcas = 0;
2097c478bd9Sstevel@tonic-gate 	size_t			snapshot_sz  = 0;
2107c478bd9Sstevel@tonic-gate 	uint32_t		ssiz;
2117c478bd9Sstevel@tonic-gate 	uint32_t		apid_len;
2127c478bd9Sstevel@tonic-gate 	ib_guid_t		hca_guid;
2137c478bd9Sstevel@tonic-gate 	boolean_t		apid_alloced = B_FALSE;
2147c478bd9Sstevel@tonic-gate 	dev_info_t		*apid_dip = NULL;
2157c478bd9Sstevel@tonic-gate 	dev_info_t		*pdip;
2167c478bd9Sstevel@tonic-gate 	ibnex_rval_t		ret_val;
2177c478bd9Sstevel@tonic-gate 	ib_service_type_t	svc_type = IB_NONE;
2187c478bd9Sstevel@tonic-gate 	devctl_ap_state_t	ap_state;
2191cfa752fSRamaswamy Tummala 	ibnex_node_data_t	*nodep = NULL;
2201cfa752fSRamaswamy Tummala 	ibnex_node_data_t	*scanp;
2217c478bd9Sstevel@tonic-gate 	struct devctl_iocdata	*dcp = NULL;
2227c478bd9Sstevel@tonic-gate 
223d1a5c838SRamaswamy Tummala 	IBTF_DPRINTF_L4("ibnex", "\tdevctl: cmd=%x, arg=%p, mode=%x, cred=%p, "
2247c478bd9Sstevel@tonic-gate 	    "\t\trval=%p dev=0x%x", cmd, arg, mode, credp, rvalp, dev);
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	/* read devctl ioctl data */
2277c478bd9Sstevel@tonic-gate 	if ((cmd != DEVCTL_AP_CONTROL) &&
2287c478bd9Sstevel@tonic-gate 	    (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS)) {
2297c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex",
230d1a5c838SRamaswamy Tummala 		    "\tdevctl: ndi_dc_allochdl failed\n");
2317c478bd9Sstevel@tonic-gate 		return (EFAULT);
2327c478bd9Sstevel@tonic-gate 	}
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
2357c478bd9Sstevel@tonic-gate 	switch (cmd) {
2367c478bd9Sstevel@tonic-gate 	case DEVCTL_AP_GETSTATE:
237d1a5c838SRamaswamy Tummala 		msg = "\tdevctl: DEVCTL_AP_GETSTATE";
2387c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "%s:", msg);
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 		apid_n = ibnex_get_apid(dcp);
2417c478bd9Sstevel@tonic-gate 		if (*apid_n == '\0') {
2427c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
2437c478bd9Sstevel@tonic-gate 			    "%s: ibnex_get_apid failed", msg);
2447c478bd9Sstevel@tonic-gate 			rv = EIO;
2457c478bd9Sstevel@tonic-gate 			break;
2467c478bd9Sstevel@tonic-gate 		}
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 		if (strncmp(apid_n, IBNEX_FABRIC, strlen(IBNEX_FABRIC)) == 0) {
2497c478bd9Sstevel@tonic-gate 			ibnex_figure_ib_apid_devstate(&ap_state);
2507c478bd9Sstevel@tonic-gate 			apid_dip = ibnex.ibnex_dip;
2517c478bd9Sstevel@tonic-gate 		} else {
2527c478bd9Sstevel@tonic-gate 			/* if this apid is already seen by IBNEX, get the dip */
2537c478bd9Sstevel@tonic-gate 			rv = ibnex_get_dip_from_apid(apid_n, &apid_dip, &nodep);
2547c478bd9Sstevel@tonic-gate 			if (rv != IBNEX_DYN_APID) {
2557c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex",
2567c478bd9Sstevel@tonic-gate 				    "%s: ibnex_get_dip_from_apid failed", msg);
2577c478bd9Sstevel@tonic-gate 				rv = EIO;
2587c478bd9Sstevel@tonic-gate 				break;
2597c478bd9Sstevel@tonic-gate 			}
2607c478bd9Sstevel@tonic-gate 			if (apid_dip)
2617c478bd9Sstevel@tonic-gate 				ndi_rele_devi(apid_dip);
2627c478bd9Sstevel@tonic-gate 			/* rv could be something undesirable, so reset it */
2637c478bd9Sstevel@tonic-gate 			rv = 0;
2647c478bd9Sstevel@tonic-gate 
2651cfa752fSRamaswamy Tummala 			ibnex_figure_ap_devstate(nodep, &ap_state);
2667c478bd9Sstevel@tonic-gate 		}
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 		/* copy the return-AP-state information to the user space */
2697c478bd9Sstevel@tonic-gate 		if (ndi_dc_return_ap_state(&ap_state, dcp) != NDI_SUCCESS) {
2707c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
2717c478bd9Sstevel@tonic-gate 			    "%s: ndi_dc_return_ap_state failed", msg);
2727c478bd9Sstevel@tonic-gate 			rv = EFAULT;
2737c478bd9Sstevel@tonic-gate 		}
2747c478bd9Sstevel@tonic-gate 		break;
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	case DEVCTL_AP_CONTROL:
2777c478bd9Sstevel@tonic-gate 	{
2787c478bd9Sstevel@tonic-gate 		int			num_nodes = 0;
2797c478bd9Sstevel@tonic-gate 		ibnex_ioctl_data_t	ioc;	/* for 64-bit copies only */
2807c478bd9Sstevel@tonic-gate 
281d1a5c838SRamaswamy Tummala 		msg = "\tdevctl: DEVCTL_AP_CONTROL";
2827c478bd9Sstevel@tonic-gate #ifdef	_MULTI_DATAMODEL
2837c478bd9Sstevel@tonic-gate 		if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
2847c478bd9Sstevel@tonic-gate 			ibnex_ioctl_data_32_t ioc32;
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &ioc32,
2877c478bd9Sstevel@tonic-gate 			    sizeof (ioc32), mode) != 0) {
2887c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex",
2897c478bd9Sstevel@tonic-gate 				    "%s: ddi_copyin err 1", msg);
2907c478bd9Sstevel@tonic-gate 				rv = EFAULT;
2917c478bd9Sstevel@tonic-gate 				break;
2927c478bd9Sstevel@tonic-gate 			}
2937c478bd9Sstevel@tonic-gate 			ioc.cmd		= (uint_t)ioc32.cmd;
2947c478bd9Sstevel@tonic-gate 			ioc.buf		= (caddr_t)(uintptr_t)ioc32.buf;
2957c478bd9Sstevel@tonic-gate 			ioc.bufsiz	= (uint_t)ioc32.bufsiz;
2967c478bd9Sstevel@tonic-gate 			ioc.ap_id	= (caddr_t)(uintptr_t)ioc32.ap_id;
2977c478bd9Sstevel@tonic-gate 			ioc.ap_id_len	= (uint_t)ioc32.ap_id_len;
2987c478bd9Sstevel@tonic-gate 			ioc.misc_arg	= (uint_t)ioc32.misc_arg;
2997c478bd9Sstevel@tonic-gate 		}
3007c478bd9Sstevel@tonic-gate #else
3017c478bd9Sstevel@tonic-gate 		if (ddi_copyin((void *)arg, &ioc, sizeof (ioc),
3027c478bd9Sstevel@tonic-gate 		    mode) != 0) {
3037c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
3047c478bd9Sstevel@tonic-gate 			    "%s: ddi_copyin 2 failed", msg);
3057c478bd9Sstevel@tonic-gate 			rv = EFAULT;
3067c478bd9Sstevel@tonic-gate 			break;
3077c478bd9Sstevel@tonic-gate 		}
3087c478bd9Sstevel@tonic-gate #endif	/* _MULTI_DATAMODEL */
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "%s: \n\tioc: cmd=%x buf=%p, "
3117c478bd9Sstevel@tonic-gate 		    "bufsiz=%d", msg, ioc.cmd, ioc.buf, ioc.bufsiz);
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 		/*
3147c478bd9Sstevel@tonic-gate 		 * figure out ap_id name as passed from user-land
3157c478bd9Sstevel@tonic-gate 		 * NOTE: We don't need to figure out ap_id for these
3167c478bd9Sstevel@tonic-gate 		 * two sub-commands:-
3177c478bd9Sstevel@tonic-gate 		 *	IBNEX_NUM_DEVICE_NODES, IBNEX_NUM_HCA_NODES
3187c478bd9Sstevel@tonic-gate 		 *
3197c478bd9Sstevel@tonic-gate 		 * Hence, In user-land, these two ioctls force "ap_id_len" to 0.
3207c478bd9Sstevel@tonic-gate 		 */
3217c478bd9Sstevel@tonic-gate 		if (ioc.ap_id_len > 0) {
3227c478bd9Sstevel@tonic-gate 			apid_alloced = B_TRUE;
3237c478bd9Sstevel@tonic-gate 			apid_len = ioc.ap_id_len + 1;
3247c478bd9Sstevel@tonic-gate 			apid_n = kmem_zalloc(apid_len, KM_SLEEP);
3257c478bd9Sstevel@tonic-gate 			if (ddi_copyin((void *)ioc.ap_id, apid_n,
3267c478bd9Sstevel@tonic-gate 			    ioc.ap_id_len, mode) != 0) {
3277c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex",
3287c478bd9Sstevel@tonic-gate 				    "%s: ddi_copyin err 3", msg);
3297c478bd9Sstevel@tonic-gate 				rv = EFAULT;
3307c478bd9Sstevel@tonic-gate 				break;
3317c478bd9Sstevel@tonic-gate 			}
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L3("ibnex", "%s: apid_n= %s", msg, apid_n);
3347c478bd9Sstevel@tonic-gate 		}
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 		/* process sub-commands */
3387c478bd9Sstevel@tonic-gate 		switch (ioc.cmd) {
3397c478bd9Sstevel@tonic-gate 		case IBNEX_NUM_DEVICE_NODES:
340d1a5c838SRamaswamy Tummala 			msg = "\tdevctl: DEVCTL_AP_CONTROL: NUM_DEVICE_NODES";
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 			/*
3437c478bd9Sstevel@tonic-gate 			 * figure out how many IOC, VPPA,
3447c478bd9Sstevel@tonic-gate 			 * Pseudo and Port nodes are present
3457c478bd9Sstevel@tonic-gate 			 */
3467c478bd9Sstevel@tonic-gate 			num_nodes = ibnex_get_num_devices();
3477c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s: num_nodes = %d",
3487c478bd9Sstevel@tonic-gate 			    msg, num_nodes);
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 			if (ddi_copyout(&num_nodes, ioc.buf,
3517c478bd9Sstevel@tonic-gate 			    ioc.bufsiz, mode) != 0) {
3527c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: copyout", msg);
3537c478bd9Sstevel@tonic-gate 				rv = EIO;
3547c478bd9Sstevel@tonic-gate 			}
3557c478bd9Sstevel@tonic-gate 			mutex_exit(&ibnex.ibnex_mutex);
3567c478bd9Sstevel@tonic-gate 			return (rv);
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 		case IBNEX_NUM_HCA_NODES:
359d1a5c838SRamaswamy Tummala 			msg = "\tdevctl: DEVCTL_AP_CONTROL: NUM_HCA_NODES";
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 			/* figure out how many HCAs are present in the host */
3627c478bd9Sstevel@tonic-gate 			mutex_exit(&ibnex.ibnex_mutex);
3637c478bd9Sstevel@tonic-gate 			num_hcas = ibt_get_hca_list(NULL);
3647c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s: num %d", msg, num_hcas);
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 			if (ddi_copyout(&num_hcas, ioc.buf,
3677c478bd9Sstevel@tonic-gate 			    ioc.bufsiz, mode) != 0) {
3687c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: copyout", msg);
3697c478bd9Sstevel@tonic-gate 				rv = EIO;
3707c478bd9Sstevel@tonic-gate 			}
3717c478bd9Sstevel@tonic-gate 			return (rv);
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 		case IBNEX_UPDATE_PKEY_TBLS:
374d1a5c838SRamaswamy Tummala 			msg = "\tdevctl: DEVCTL_AP_CONTROL: UPDATE_PKEY_TBLS";
3757c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s", msg);
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 			/*
3787c478bd9Sstevel@tonic-gate 			 * update P_Key tables:
3797c478bd9Sstevel@tonic-gate 			 *	ibdm_ibnex_update_pkey_tbls() calls
3807c478bd9Sstevel@tonic-gate 			 *	ibt_query_hca_ports_byguids() for all the
3817c478bd9Sstevel@tonic-gate 			 *	HCAs that the IBDM has "seen" in the system.
3827c478bd9Sstevel@tonic-gate 			 *	This ends up updating the IBTL P_Key database.
3837c478bd9Sstevel@tonic-gate 			 *	NOTE: Changes in this area will break this
3847c478bd9Sstevel@tonic-gate 			 *	assumption. Initially the plan was to call
3857c478bd9Sstevel@tonic-gate 			 *	ibt_query_hca_ports_byguids() in IBTL but
3867c478bd9Sstevel@tonic-gate 			 *	IBDM needs to call it as well. So, eliminating
3877c478bd9Sstevel@tonic-gate 			 *	the first invocation.
3887c478bd9Sstevel@tonic-gate 			 *
3897c478bd9Sstevel@tonic-gate 			 *	It next updates the DM P_Key database.
3907c478bd9Sstevel@tonic-gate 			 *	Note that the DM P_Key database updating
3917c478bd9Sstevel@tonic-gate 			 *	will always be driven through cfgadm.
3927c478bd9Sstevel@tonic-gate 			 */
3937c478bd9Sstevel@tonic-gate 			mutex_exit(&ibnex.ibnex_mutex);
3947c478bd9Sstevel@tonic-gate 			ibdm_ibnex_update_pkey_tbls();
3957c478bd9Sstevel@tonic-gate 			mutex_enter(&ibnex.ibnex_mutex);
3967c478bd9Sstevel@tonic-gate 			break;
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 		case IBNEX_GET_SNAPSHOT:
3997c478bd9Sstevel@tonic-gate 		case IBNEX_SNAPSHOT_SIZE:
4007c478bd9Sstevel@tonic-gate 			msg = (ioc.cmd == IBNEX_SNAPSHOT_SIZE) ?
401d1a5c838SRamaswamy Tummala 			    "\tdevctl: DEVCTL_AP_CONTROL: IBNEX_SNAPSHOT_SIZE" :
402d1a5c838SRamaswamy Tummala 			    "\tdevctl: DEVCTL_AP_CONTROL: IBNEX_GET_SNAPSHOT";
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s:", msg);
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 			if (ibnex_get_snapshot(&snapshot, &snapshot_sz,
4077c478bd9Sstevel@tonic-gate 			    ioc.misc_arg) != 0) {
4087c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex",
4097c478bd9Sstevel@tonic-gate 				    "%s:\n\tibnex_get_snapshot failed", msg);
4107c478bd9Sstevel@tonic-gate 				rv = EIO;
4117c478bd9Sstevel@tonic-gate 				break;
4127c478bd9Sstevel@tonic-gate 			}
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 			/* ssiz needs to be reinitialized again */
4157c478bd9Sstevel@tonic-gate 			ssiz = snapshot_sz;
4167c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex",
4177c478bd9Sstevel@tonic-gate 			    "%s:\n\tsize =%x", msg, snapshot_sz);
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 			if (ioc.cmd == IBNEX_SNAPSHOT_SIZE) {
4207c478bd9Sstevel@tonic-gate 				if (ddi_copyout(&ssiz, ioc.buf,
4217c478bd9Sstevel@tonic-gate 				    ioc.bufsiz, mode) != 0) {
4227c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
4237c478bd9Sstevel@tonic-gate 					    "%s:\n\tddi_copyout 2 failed", msg);
4247c478bd9Sstevel@tonic-gate 					rv = EFAULT;
4257c478bd9Sstevel@tonic-gate 				}
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 			} else {
4287c478bd9Sstevel@tonic-gate 				if (ioc.bufsiz != snapshot_sz) {
4297c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
4307c478bd9Sstevel@tonic-gate 					    "%s:\n\tinvalid buffer size (%x %x)"
4317c478bd9Sstevel@tonic-gate 					    " ", msg, ioc.bufsiz, snapshot_sz);
4327c478bd9Sstevel@tonic-gate 					rv = EINVAL;
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 				} else if (ddi_copyout(snapshot, ioc.buf,
4357c478bd9Sstevel@tonic-gate 				    ioc.bufsiz, mode) != 0) {
4367c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
4377c478bd9Sstevel@tonic-gate 					    "%s:\n\tddi_copyout 3 failed", msg);
4387c478bd9Sstevel@tonic-gate 					rv = EFAULT;
4397c478bd9Sstevel@tonic-gate 				}
4407c478bd9Sstevel@tonic-gate 			}
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 			kmem_free(snapshot, snapshot_sz);
4437c478bd9Sstevel@tonic-gate 			break;
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 		case IBNEX_DEVICE_PATH_SZ:
4467c478bd9Sstevel@tonic-gate 		case IBNEX_GET_DEVICE_PATH:
4477c478bd9Sstevel@tonic-gate 		{
4487c478bd9Sstevel@tonic-gate 			char	 path[MAXPATHLEN];
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate 			msg = (ioc.cmd == IBNEX_DEVICE_PATH_SZ) ?
451d1a5c838SRamaswamy Tummala 			    "\tdevctl:DEVCTL_AP_CONTROL: IBNEX_DEVICE_PATH_SZ" :
452d1a5c838SRamaswamy Tummala 			    "\tdevctl:DEVCTL_AP_CONTROL: IBNEX_GET_DEVICE_PATH";
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s: apid = %s", msg, apid_n);
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 			/* if this apid is already seen by IBNEX, get the dip */
4577c478bd9Sstevel@tonic-gate 			rv = ibnex_get_dip_from_apid(apid_n, &apid_dip, &nodep);
4587c478bd9Sstevel@tonic-gate 			if (rv != IBNEX_DYN_APID || apid_dip == NULL) {
4597c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex",
4607c478bd9Sstevel@tonic-gate 				    "%s:\n\tget_dip_from_apid failed", msg);
4617c478bd9Sstevel@tonic-gate 				rv = EIO;
4627c478bd9Sstevel@tonic-gate 				break;
4637c478bd9Sstevel@tonic-gate 			}
4647c478bd9Sstevel@tonic-gate 			ndi_rele_devi(apid_dip);
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 			/* ddi_pathname doesn't supply /devices, so we do. */
4677c478bd9Sstevel@tonic-gate 			(void) strcpy(path, "/devices");
4687c478bd9Sstevel@tonic-gate 			(void) ddi_pathname(apid_dip, path + strlen(path));
4697c478bd9Sstevel@tonic-gate 			ssiz = (uint32_t)strlen(path) + 1;
4707c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex",
4717c478bd9Sstevel@tonic-gate 			    "%s: len = %x\n\tpath = %s", msg, ssiz, path);
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 			/* rv could be something undesirable, so reset it */
4747c478bd9Sstevel@tonic-gate 			rv = 0;
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 			if (ioc.cmd == IBNEX_DEVICE_PATH_SZ) {
4777c478bd9Sstevel@tonic-gate 				if (ddi_copyout(&ssiz, ioc.buf,
4787c478bd9Sstevel@tonic-gate 				    ioc.bufsiz, mode) != 0) {
4797c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
4807c478bd9Sstevel@tonic-gate 					    "%s: ddi_copyout 4 failed", msg);
4817c478bd9Sstevel@tonic-gate 					rv = EFAULT;
4827c478bd9Sstevel@tonic-gate 				}
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 			} else {
4857c478bd9Sstevel@tonic-gate 				if (ioc.bufsiz != ssiz) {
4867c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
4877c478bd9Sstevel@tonic-gate 					    "%s: invalid size (%x, %x)",
4887c478bd9Sstevel@tonic-gate 					    msg, ioc.bufsiz, ssiz);
4897c478bd9Sstevel@tonic-gate 					rv = EINVAL;
4907c478bd9Sstevel@tonic-gate 				} else if (ddi_copyout(&path, ioc.buf,
4917c478bd9Sstevel@tonic-gate 				    ioc.bufsiz, mode) != 0) {
4927c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex", "%s "
4937c478bd9Sstevel@tonic-gate 					    "ddi_copyout 5 failed", msg);
4947c478bd9Sstevel@tonic-gate 					rv = EFAULT;
4957c478bd9Sstevel@tonic-gate 				}
4967c478bd9Sstevel@tonic-gate 			}
4977c478bd9Sstevel@tonic-gate 			break;
4987c478bd9Sstevel@tonic-gate 		}
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate 		case IBNEX_HCA_LIST_SZ:
5017c478bd9Sstevel@tonic-gate 		case IBNEX_HCA_LIST_INFO:
5027c478bd9Sstevel@tonic-gate 			msg = (ioc.cmd == IBNEX_HCA_LIST_SZ) ?
5037c478bd9Sstevel@tonic-gate 			    "DEVCTL_AP_CONTROL: IBNEX_HCA_LIST_SZ" :
5047c478bd9Sstevel@tonic-gate 			    "DEVCTL_AP_CONTROL: IBNEX_HCA_LIST_INFO";
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 			guid_str = strrchr(apid_n, ':') + 1;
5077c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s, input apid = %s, "
5087c478bd9Sstevel@tonic-gate 			    "guid = %s", msg, apid_n, guid_str);
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 			if (guid_str == NULL) {
5117c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: invalid input "
5127c478bd9Sstevel@tonic-gate 				    "GUID passed %s", msg, guid_str);
5137c478bd9Sstevel@tonic-gate 				rv = EFAULT;
5147c478bd9Sstevel@tonic-gate 				break;
5157c478bd9Sstevel@tonic-gate 			}
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate 			/* Get the GUID(hex value) from apid_n */
5187c478bd9Sstevel@tonic-gate 			hca_guid = ibnex_str2hex(guid_str, strlen(guid_str),
5197c478bd9Sstevel@tonic-gate 			    &ret);
5207c478bd9Sstevel@tonic-gate 			if (ret != IBNEX_SUCCESS) {
5217c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: Invalid HCA "
5227c478bd9Sstevel@tonic-gate 				    "GUID string", msg);
5237c478bd9Sstevel@tonic-gate 				rv = EIO;
5247c478bd9Sstevel@tonic-gate 				break;
5257c478bd9Sstevel@tonic-gate 			}
5267c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s HCA GUID = %llX",
5277c478bd9Sstevel@tonic-gate 			    msg, hca_guid);
5287c478bd9Sstevel@tonic-gate 			if (ibtl_ibnex_get_hca_info(hca_guid,
5297c478bd9Sstevel@tonic-gate 			    IBTL_IBNEX_LIST_CLNTS_FLAG, &snapshot, &snapshot_sz,
5307c478bd9Sstevel@tonic-gate 			    ibnex_return_apid) != IBT_SUCCESS) {
5317c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex",
5327c478bd9Sstevel@tonic-gate 				    "%s: get HCA consumers failed", msg);
5337c478bd9Sstevel@tonic-gate 				rv = EIO;
5347c478bd9Sstevel@tonic-gate 				break;
5357c478bd9Sstevel@tonic-gate 			}
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 			ssiz = snapshot_sz;
5387c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s: size =%x", msg, ssiz);
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 			if (ioc.cmd == IBNEX_HCA_LIST_SZ) {
5417c478bd9Sstevel@tonic-gate 				if (ddi_copyout(&ssiz, ioc.buf,
5427c478bd9Sstevel@tonic-gate 				    ioc.bufsiz, mode) != 0) {
5437c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
5447c478bd9Sstevel@tonic-gate 					    "%s: ddi_copyout 6 failed", msg);
5457c478bd9Sstevel@tonic-gate 					rv = EFAULT;
5467c478bd9Sstevel@tonic-gate 				}
5477c478bd9Sstevel@tonic-gate 			} else {
5487c478bd9Sstevel@tonic-gate 				if (ioc.bufsiz != ssiz) {
5497c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex", "%s: invalid "
5507c478bd9Sstevel@tonic-gate 					    "size (%x, %x)", msg, ioc.bufsiz,
5517c478bd9Sstevel@tonic-gate 					    ssiz);
5527c478bd9Sstevel@tonic-gate 					rv = EINVAL;
5537c478bd9Sstevel@tonic-gate 				} else if (ddi_copyout(snapshot, ioc.buf,
5547c478bd9Sstevel@tonic-gate 				    ioc.bufsiz, mode) != 0) {
5557c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex", "%s "
5567c478bd9Sstevel@tonic-gate 					    "ddi_copyout 7 failed", msg);
5577c478bd9Sstevel@tonic-gate 					rv = EFAULT;
5587c478bd9Sstevel@tonic-gate 				}
5597c478bd9Sstevel@tonic-gate 			}
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 			kmem_free(snapshot, snapshot_sz);
5627c478bd9Sstevel@tonic-gate 			break;
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate 		case IBNEX_UNCFG_CLNTS_SZ:
5657c478bd9Sstevel@tonic-gate 		case IBNEX_UNCFG_CLNTS_INFO:
5667c478bd9Sstevel@tonic-gate 			msg = (ioc.cmd == IBNEX_UNCFG_CLNTS_SZ) ?
567d1a5c838SRamaswamy Tummala 			    "\tdevctl:DEVCTL_AP_CONTROL: IBNEX_UNCFG_CLNTS_SZ" :
568d1a5c838SRamaswamy Tummala 			    "\tdevctl:DEVCTL_AP_CONTROL: "
569d1a5c838SRamaswamy Tummala 			    "IBNEX_UNCFG_CLNTS_INFO";
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 			guid_str = strrchr(apid_n, ':') + 1;
5727c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s, apid = %s, guid = %s",
5737c478bd9Sstevel@tonic-gate 			    msg, apid_n, guid_str);
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 			if (guid_str == NULL) {
5767c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: invalid input "
5777c478bd9Sstevel@tonic-gate 				    "GUID %s", msg, guid_str);
5787c478bd9Sstevel@tonic-gate 				rv = EFAULT;
5797c478bd9Sstevel@tonic-gate 				break;
5807c478bd9Sstevel@tonic-gate 			}
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 			/* Get the GUID(hex value) from apid_n */
5837c478bd9Sstevel@tonic-gate 			hca_guid = ibnex_str2hex(guid_str, strlen(guid_str),
5847c478bd9Sstevel@tonic-gate 			    &ret);
5857c478bd9Sstevel@tonic-gate 			if (ret != IBNEX_SUCCESS) {
5867c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: Invalid HCA "
5877c478bd9Sstevel@tonic-gate 				    "GUID string passed", msg);
5887c478bd9Sstevel@tonic-gate 				rv = EIO;
5897c478bd9Sstevel@tonic-gate 				break;
5907c478bd9Sstevel@tonic-gate 			}
5917c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s G = %llX", msg, hca_guid);
5927c478bd9Sstevel@tonic-gate 			if (ibtl_ibnex_get_hca_info(hca_guid,
5937c478bd9Sstevel@tonic-gate 			    IBTL_IBNEX_UNCFG_CLNTS_FLAG, &snapshot,
5947c478bd9Sstevel@tonic-gate 			    &snapshot_sz, ibnex_return_apid) != IBT_SUCCESS) {
5957c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex",
5967c478bd9Sstevel@tonic-gate 				    "%s: get HCA consumers failed", msg);
5977c478bd9Sstevel@tonic-gate 				rv = EIO;
5987c478bd9Sstevel@tonic-gate 				break;
5997c478bd9Sstevel@tonic-gate 			}
6007c478bd9Sstevel@tonic-gate 			/* ssiz needs to be reinitialized again */
6017c478bd9Sstevel@tonic-gate 			ssiz = snapshot_sz;
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s: size =%x", msg, ssiz);
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate 			if (ioc.cmd == IBNEX_UNCFG_CLNTS_SZ) {
6067c478bd9Sstevel@tonic-gate 				if (ddi_copyout(&ssiz, ioc.buf,
6077c478bd9Sstevel@tonic-gate 				    ioc.bufsiz, mode) != 0) {
6087c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
6097c478bd9Sstevel@tonic-gate 					    "%s: ddi_copyout 9 failed", msg);
6107c478bd9Sstevel@tonic-gate 					rv = EFAULT;
6117c478bd9Sstevel@tonic-gate 				}
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 			} else {
6147c478bd9Sstevel@tonic-gate 				if (ioc.bufsiz != ssiz) {
6157c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
6167c478bd9Sstevel@tonic-gate 					    "%s: invalid size (%x, %x)",
6177c478bd9Sstevel@tonic-gate 					    msg, ioc.bufsiz, ssiz);
6187c478bd9Sstevel@tonic-gate 					rv = EINVAL;
6197c478bd9Sstevel@tonic-gate 				} else if (ddi_copyout(snapshot, ioc.buf,
6207c478bd9Sstevel@tonic-gate 				    ioc.bufsiz, mode) != 0) {
6217c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex", "%s "
6227c478bd9Sstevel@tonic-gate 					    "ddi_copyout 10 failed", msg);
6237c478bd9Sstevel@tonic-gate 					rv = EFAULT;
6247c478bd9Sstevel@tonic-gate 				}
6257c478bd9Sstevel@tonic-gate 			}
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 			kmem_free(snapshot, snapshot_sz);
6287c478bd9Sstevel@tonic-gate 			break;
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 		case IBNEX_CONF_ENTRY_ADD:
631d1a5c838SRamaswamy Tummala 			msg = "\tdevctl: IBNEX_CONF_ENTRY_ADD: ";
6327c478bd9Sstevel@tonic-gate 			service = kmem_zalloc(ioc.bufsiz + 1, KM_SLEEP);
6337c478bd9Sstevel@tonic-gate 			/* read in the "service" name */
6347c478bd9Sstevel@tonic-gate 			if (ddi_copyin(ioc.buf, service,
6357c478bd9Sstevel@tonic-gate 			    ioc.bufsiz, mode) != 0) {
6367c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: ddi_copyin err 6",
6377c478bd9Sstevel@tonic-gate 				    msg);
6387c478bd9Sstevel@tonic-gate 				rv = EFAULT;
6397c478bd9Sstevel@tonic-gate 				break;
6407c478bd9Sstevel@tonic-gate 			}
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 			/* read in the "service type" */
6437c478bd9Sstevel@tonic-gate 			svc_type = ioc.misc_arg;
6447c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s: service = %s, type = %d",
6457c478bd9Sstevel@tonic-gate 			    msg, service, svc_type);
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 			if (svc_type == IB_PORT_SERVICE) {
6487c478bd9Sstevel@tonic-gate 				ibnex_port_conf_entry_add(service);
6497c478bd9Sstevel@tonic-gate 			} else if (svc_type == IB_VPPA_SERVICE) {
6507c478bd9Sstevel@tonic-gate 				ibnex_vppa_conf_entry_add(service);
6517c478bd9Sstevel@tonic-gate 			} else if (svc_type == IB_HCASVC_SERVICE) {
6527c478bd9Sstevel@tonic-gate 				ibnex_hcasvc_conf_entry_add(service);
6537c478bd9Sstevel@tonic-gate 			}
6547c478bd9Sstevel@tonic-gate 			kmem_free(service, ioc.bufsiz + 1);
6557c478bd9Sstevel@tonic-gate 			break;
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 		case IBNEX_CONF_ENTRY_DEL:
658d1a5c838SRamaswamy Tummala 			msg = "\tdevctl:IBNEX_CONF_ENTRY_DEL: ";
6597c478bd9Sstevel@tonic-gate 			service = kmem_zalloc(ioc.bufsiz + 1, KM_SLEEP);
6607c478bd9Sstevel@tonic-gate 			/* read in the "service" name */
6617c478bd9Sstevel@tonic-gate 			if (ddi_copyin(ioc.buf, service,
6627c478bd9Sstevel@tonic-gate 			    ioc.bufsiz, mode) != 0) {
6637c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: ddi_copyin err 7",
6647c478bd9Sstevel@tonic-gate 				    msg);
6657c478bd9Sstevel@tonic-gate 				rv = EFAULT;
6667c478bd9Sstevel@tonic-gate 				break;
6677c478bd9Sstevel@tonic-gate 			}
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate 			/* read in the "service type" */
6707c478bd9Sstevel@tonic-gate 			svc_type = ioc.misc_arg;
6717c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s: service = %s, type = %d",
6727c478bd9Sstevel@tonic-gate 			    msg, service, svc_type);
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate 			if (svc_type == IB_PORT_SERVICE) {
6757c478bd9Sstevel@tonic-gate 				rv = ibnex_port_conf_entry_delete(msg, service);
6767c478bd9Sstevel@tonic-gate 			} else if (svc_type == IB_VPPA_SERVICE) {
6777c478bd9Sstevel@tonic-gate 				rv = ibnex_vppa_conf_entry_delete(msg, service);
6787c478bd9Sstevel@tonic-gate 			} else if (svc_type == IB_HCASVC_SERVICE) {
6797c478bd9Sstevel@tonic-gate 				rv = ibnex_hcasvc_conf_entry_delete(msg,
6807c478bd9Sstevel@tonic-gate 				    service);
6817c478bd9Sstevel@tonic-gate 			}
6827c478bd9Sstevel@tonic-gate 			kmem_free(service, ioc.bufsiz + 1);
6837c478bd9Sstevel@tonic-gate 			break;
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate 		case IBNEX_HCA_VERBOSE_SZ:
6867c478bd9Sstevel@tonic-gate 		case IBNEX_HCA_VERBOSE_INFO:
6877c478bd9Sstevel@tonic-gate 			msg = (ioc.cmd == IBNEX_HCA_VERBOSE_SZ) ?
6887c478bd9Sstevel@tonic-gate 			    "DEVCTL_AP_CONTROL: IBNEX_HCA_VERBOSE_SZ" :
6897c478bd9Sstevel@tonic-gate 			    "DEVCTL_AP_CONTROL: IBNEX_HCA_VERBOSE_INFO";
6907c478bd9Sstevel@tonic-gate 
6917c478bd9Sstevel@tonic-gate 			guid_str = strrchr(apid_n, ':') + 1;
6927c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s, apid = %s, guid = %s",
6937c478bd9Sstevel@tonic-gate 			    msg, apid_n, guid_str);
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 			if (guid_str == NULL) {
6967c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: invalid GUID %s",
6977c478bd9Sstevel@tonic-gate 				    msg, guid_str);
6987c478bd9Sstevel@tonic-gate 				rv = EFAULT;
6997c478bd9Sstevel@tonic-gate 				break;
7007c478bd9Sstevel@tonic-gate 			}
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 			/* Get the GUID(hex value) from apid_n */
7037c478bd9Sstevel@tonic-gate 			hca_guid = ibnex_str2hex(guid_str, strlen(guid_str),
7047c478bd9Sstevel@tonic-gate 			    &ret);
7057c478bd9Sstevel@tonic-gate 			if (ret != IBNEX_SUCCESS) {
7067c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: Invalid HCA GUID "
7077c478bd9Sstevel@tonic-gate 				    "string", msg);
7087c478bd9Sstevel@tonic-gate 				rv = EIO;
7097c478bd9Sstevel@tonic-gate 				break;
7107c478bd9Sstevel@tonic-gate 			}
7117c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s HCA GUID = 0x%llX",
7127c478bd9Sstevel@tonic-gate 			    msg, hca_guid);
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 			if (ibtl_ibnex_get_hca_verbose_data(hca_guid, &snapshot,
7157c478bd9Sstevel@tonic-gate 			    &snapshot_sz) != IBT_SUCCESS) {
7167c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "%s: get HCA verbose "
7177c478bd9Sstevel@tonic-gate 				    "data failed", msg);
7187c478bd9Sstevel@tonic-gate 				rv = EIO;
7197c478bd9Sstevel@tonic-gate 				break;
7207c478bd9Sstevel@tonic-gate 			}
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate 			ssiz = snapshot_sz;
7237c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "%s: size =%x", msg, ssiz);
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 			if (ioc.cmd == IBNEX_HCA_VERBOSE_SZ) {
7267c478bd9Sstevel@tonic-gate 				if (ddi_copyout(&ssiz, ioc.buf,
7277c478bd9Sstevel@tonic-gate 				    ioc.bufsiz, mode) != 0) {
7287c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
7297c478bd9Sstevel@tonic-gate 					    "%s: ddi_copyout 11 failed", msg);
7307c478bd9Sstevel@tonic-gate 					rv = EFAULT;
7317c478bd9Sstevel@tonic-gate 				}
7327c478bd9Sstevel@tonic-gate 			} else {
7337c478bd9Sstevel@tonic-gate 				if (ioc.bufsiz != ssiz) {
7347c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
7357c478bd9Sstevel@tonic-gate 					    "%s: invalid size (%x, %x)",
7367c478bd9Sstevel@tonic-gate 					    msg, ioc.bufsiz, ssiz);
7377c478bd9Sstevel@tonic-gate 					rv = EINVAL;
7387c478bd9Sstevel@tonic-gate 				} else if (ddi_copyout(snapshot,
7397c478bd9Sstevel@tonic-gate 				    ioc.buf, ioc.bufsiz, mode) != 0) {
7407c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex", "%s "
7417c478bd9Sstevel@tonic-gate 					    "ddi_copyout 12 failed", msg);
7427c478bd9Sstevel@tonic-gate 					rv = EFAULT;
7437c478bd9Sstevel@tonic-gate 				}
7447c478bd9Sstevel@tonic-gate 			}
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate 			kmem_free(snapshot, snapshot_sz);
7477c478bd9Sstevel@tonic-gate 			break;
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 		case IBNEX_UPDATE_IOC_CONF :
750d1a5c838SRamaswamy Tummala 			msg = "\tdevctl:IBNEX_UPDATE_IOC_CONF: ";
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate 			/*
7537c478bd9Sstevel@tonic-gate 			 * If IB fabric APID, call ibnex_update_all
7547c478bd9Sstevel@tonic-gate 			 * If IOC APID, get the apid dip and call
7557c478bd9Sstevel@tonic-gate 			 * ibnex_update_ioc
7567c478bd9Sstevel@tonic-gate 			 */
7577c478bd9Sstevel@tonic-gate 			if (ioc.misc_arg == IBNEX_BASE_APID) {
7587c478bd9Sstevel@tonic-gate 				/*
7597c478bd9Sstevel@tonic-gate 				 * If reprobe is in progress or another reprobe
7607c478bd9Sstevel@tonic-gate 				 * is already waiting, wait.
7617c478bd9Sstevel@tonic-gate 				 */
7627c478bd9Sstevel@tonic-gate 				if (ibnex.ibnex_reprobe_state != 0) {
7637c478bd9Sstevel@tonic-gate 					if (ibnex.ibnex_reprobe_state ==
7647c478bd9Sstevel@tonic-gate 					    IBNEX_REPROBE_ALL_PROGRESS)
7657c478bd9Sstevel@tonic-gate 						ibnex.ibnex_reprobe_state =
7667c478bd9Sstevel@tonic-gate 						    IBNEX_REPROBE_ALL_WAIT;
7677c478bd9Sstevel@tonic-gate 					while (ibnex.ibnex_reprobe_state) {
7687c478bd9Sstevel@tonic-gate 						cv_wait(&ibnex.ibnex_reprobe_cv,
7697c478bd9Sstevel@tonic-gate 						    &ibnex.ibnex_mutex);
7707c478bd9Sstevel@tonic-gate 					}
7717c478bd9Sstevel@tonic-gate 
7727c478bd9Sstevel@tonic-gate 					/*
7737c478bd9Sstevel@tonic-gate 					 * Pending reprobe all completed, return
7747c478bd9Sstevel@tonic-gate 					 */
7757c478bd9Sstevel@tonic-gate 					break;
7767c478bd9Sstevel@tonic-gate 				}
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 				/* Check if reprobe for any IOC is pending */
7797c478bd9Sstevel@tonic-gate 				/* CONSTCOND */
7807c478bd9Sstevel@tonic-gate 				while (1) {
7817c478bd9Sstevel@tonic-gate 					ioc_reprobe_pending = 0;
7827c478bd9Sstevel@tonic-gate 					for (scanp = ibnex.ibnex_ioc_node_head;
7837c478bd9Sstevel@tonic-gate 					    scanp;
7847c478bd9Sstevel@tonic-gate 					    scanp = scanp->node_next) {
7857c478bd9Sstevel@tonic-gate 						if (scanp->node_reprobe_state
7867c478bd9Sstevel@tonic-gate 						    != 0) {
7877c478bd9Sstevel@tonic-gate 							ioc_reprobe_pending =
7887c478bd9Sstevel@tonic-gate 							    1;
7897c478bd9Sstevel@tonic-gate 							break;
7907c478bd9Sstevel@tonic-gate 						}
7917c478bd9Sstevel@tonic-gate 					}
7927c478bd9Sstevel@tonic-gate 					if (ioc_reprobe_pending == 0) {
7937c478bd9Sstevel@tonic-gate 						ibnex.ibnex_reprobe_state &=
7947c478bd9Sstevel@tonic-gate 						    ~IBNEX_REPROBE_IOC_WAIT;
7957c478bd9Sstevel@tonic-gate 						break;
7967c478bd9Sstevel@tonic-gate 					}
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate 					ibnex.ibnex_reprobe_state =
7997c478bd9Sstevel@tonic-gate 					    IBNEX_REPROBE_IOC_WAIT;
8007c478bd9Sstevel@tonic-gate 					cv_wait(&ibnex.ibnex_reprobe_cv,
8017c478bd9Sstevel@tonic-gate 					    &ibnex.ibnex_mutex);
8027c478bd9Sstevel@tonic-gate 				}
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate 				/*
8057c478bd9Sstevel@tonic-gate 				 * Set the REPROBE_ALL_PROGRESS state &
8067c478bd9Sstevel@tonic-gate 				 * start reprobe
8077c478bd9Sstevel@tonic-gate 				 */
8087c478bd9Sstevel@tonic-gate 				ibnex.ibnex_reprobe_state =
8097c478bd9Sstevel@tonic-gate 				    IBNEX_REPROBE_ALL_PROGRESS;
8107c478bd9Sstevel@tonic-gate 				mutex_exit(&ibnex.ibnex_mutex);
8117c478bd9Sstevel@tonic-gate 				ibnex_reprobe_ioc_all();
8127c478bd9Sstevel@tonic-gate 				mutex_enter(&ibnex.ibnex_mutex);
8137c478bd9Sstevel@tonic-gate 			} else if (ioc.misc_arg == IBNEX_DYN_APID) {
8147c478bd9Sstevel@tonic-gate 				rv = ibnex_get_dip_from_apid(apid_n, &apid_dip,
8157c478bd9Sstevel@tonic-gate 				    &nodep);
8167c478bd9Sstevel@tonic-gate 				ASSERT(rv == IBNEX_DYN_APID);
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 				/* Device unconfigured: return */
8197c478bd9Sstevel@tonic-gate 				if (apid_dip == NULL)
8207c478bd9Sstevel@tonic-gate 					break;
8217c478bd9Sstevel@tonic-gate 
8227c478bd9Sstevel@tonic-gate 				ndi_rele_devi(apid_dip);
8237c478bd9Sstevel@tonic-gate 				/* Reset return value back to 0 */
8247c478bd9Sstevel@tonic-gate 				rv = 0;
8257c478bd9Sstevel@tonic-gate 				if (ibnex.ibnex_reprobe_state != 0 ||
8267c478bd9Sstevel@tonic-gate 				    nodep->node_reprobe_state != 0) {
8277c478bd9Sstevel@tonic-gate 					while (ibnex.ibnex_reprobe_state != 0 &&
8287c478bd9Sstevel@tonic-gate 					    nodep->node_reprobe_state != 0) {
8297c478bd9Sstevel@tonic-gate 						cv_wait(&ibnex.ibnex_reprobe_cv,
8307c478bd9Sstevel@tonic-gate 						    &ibnex.ibnex_mutex);
8317c478bd9Sstevel@tonic-gate 					}
8327c478bd9Sstevel@tonic-gate 					/* Pending reprobe completed, return */
8337c478bd9Sstevel@tonic-gate 					break;
8347c478bd9Sstevel@tonic-gate 				}
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 				/* Set node_reprobe_state and start reprobe */
8377c478bd9Sstevel@tonic-gate 				nodep->node_reprobe_state =
8387c478bd9Sstevel@tonic-gate 				    IBNEX_NODE_REPROBE_NOTIFY_ON_UPDATE;
8397c478bd9Sstevel@tonic-gate 				mutex_exit(&ibnex.ibnex_mutex);
8407c478bd9Sstevel@tonic-gate 				ibnex_reprobe_ioc_dev((void *)apid_dip);
8417c478bd9Sstevel@tonic-gate 				mutex_enter(&ibnex.ibnex_mutex);
8427c478bd9Sstevel@tonic-gate 			} else {
8437c478bd9Sstevel@tonic-gate 				rv = EINVAL;
8447c478bd9Sstevel@tonic-gate 			}
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 			break;
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 		default:
8497c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
8507c478bd9Sstevel@tonic-gate 			    "DEVCTL_AP_CONTROL: ioc:unknown cmd = %x", ioc.cmd);
8517c478bd9Sstevel@tonic-gate 			break;
8527c478bd9Sstevel@tonic-gate 		}
8537c478bd9Sstevel@tonic-gate 	}
8547c478bd9Sstevel@tonic-gate 	break;
8557c478bd9Sstevel@tonic-gate 
8567c478bd9Sstevel@tonic-gate 	case DEVCTL_AP_UNCONFIGURE:
8577c478bd9Sstevel@tonic-gate 		msg = "DEVCTL_AP_UNCONFIGURE";
8587c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "%s", msg);
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate 		/* Check for write permissions */
8617c478bd9Sstevel@tonic-gate 		if (!(mode & FWRITE)) {
8627c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "%s: invalid mode %x",
8637c478bd9Sstevel@tonic-gate 			    msg, mode);
8647c478bd9Sstevel@tonic-gate 			rv = EPERM;
8657c478bd9Sstevel@tonic-gate 			break;
8667c478bd9Sstevel@tonic-gate 		}
8677c478bd9Sstevel@tonic-gate 
868cf95dd16SToomas Soome 		if ((apid_n = ibnex_get_apid(dcp)) == NULL) {
8697c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
8707c478bd9Sstevel@tonic-gate 			    "%s: ibnex_get_apid failed", msg);
8717c478bd9Sstevel@tonic-gate 			rv = EIO;
8727c478bd9Sstevel@tonic-gate 			break;
8737c478bd9Sstevel@tonic-gate 		}
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate 		/*
8767c478bd9Sstevel@tonic-gate 		 * If this apid is already seen by IBNEX, get the dip
8777c478bd9Sstevel@tonic-gate 		 * NOTE: ibnex_get_dip_from_apid() finds a valid dip
8787c478bd9Sstevel@tonic-gate 		 * and also does a ndi_devi_hold() on the child.
8797c478bd9Sstevel@tonic-gate 		 */
8807c478bd9Sstevel@tonic-gate 		rv = ibnex_get_dip_from_apid(apid_n, &apid_dip, &nodep);
8817c478bd9Sstevel@tonic-gate 		if ((rv != IBNEX_DYN_APID) || (apid_dip == NULL)) {
8827c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "%s: get_dip_from_apid "
8837c478bd9Sstevel@tonic-gate 			    "failed with 0x%x", msg, rv);
8847c478bd9Sstevel@tonic-gate 			rv = EIO;
8857c478bd9Sstevel@tonic-gate 			break;
8867c478bd9Sstevel@tonic-gate 		}
8877c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "%s: DIP = %p", msg, apid_dip);
8887c478bd9Sstevel@tonic-gate 
8897c478bd9Sstevel@tonic-gate 		/* Check if it is a valid node type? */
8907c478bd9Sstevel@tonic-gate 		if (!IBNEX_VALID_NODE_TYPE(nodep)) {
8917c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "%s: invalid IB node", msg);
8927c478bd9Sstevel@tonic-gate 			rv = ENODEV;
8937c478bd9Sstevel@tonic-gate 			ndi_rele_devi(apid_dip);
8947c478bd9Sstevel@tonic-gate 			break;
8957c478bd9Sstevel@tonic-gate 		}
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate 		/*
8987c478bd9Sstevel@tonic-gate 		 * continue unconfigure operation, only if device node
8997c478bd9Sstevel@tonic-gate 		 * is already configured. Return EBUSY if another
9007c478bd9Sstevel@tonic-gate 		 * configure/unconfigure operation is in progress.
9017c478bd9Sstevel@tonic-gate 		 */
9027c478bd9Sstevel@tonic-gate 		if (nodep->node_state == IBNEX_CFGADM_CONFIGURING ||
9037c478bd9Sstevel@tonic-gate 		    nodep->node_state == IBNEX_CFGADM_UNCONFIGURING) {
9047c478bd9Sstevel@tonic-gate 			rv = EBUSY;
9057c478bd9Sstevel@tonic-gate 			ndi_rele_devi(apid_dip);
9067c478bd9Sstevel@tonic-gate 			break;
9077c478bd9Sstevel@tonic-gate 		}
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate 		/* do this before to avoid races */
9107c478bd9Sstevel@tonic-gate 		nodep->node_dip = NULL;
9117c478bd9Sstevel@tonic-gate 		nodep->node_state = IBNEX_CFGADM_UNCONFIGURING;
9127c478bd9Sstevel@tonic-gate 
9137c478bd9Sstevel@tonic-gate 		/*
9147c478bd9Sstevel@tonic-gate 		 * Call devfs_clean first
9157c478bd9Sstevel@tonic-gate 		 * NOTE: The code so far is protected by holding ibnex_mutex
9167c478bd9Sstevel@tonic-gate 		 * and by doing a ndi_devi_hold() on the child.
9177c478bd9Sstevel@tonic-gate 		 */
9187c478bd9Sstevel@tonic-gate 		pdip = ddi_get_parent(apid_dip);
9197c478bd9Sstevel@tonic-gate 		if (i_ddi_node_state(apid_dip) >= DS_INITIALIZED) {
9207c478bd9Sstevel@tonic-gate 			devnm = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
9217c478bd9Sstevel@tonic-gate 			(void) ddi_deviname(apid_dip, devnm);
9227c478bd9Sstevel@tonic-gate 			mutex_exit(&ibnex.ibnex_mutex);
92319174f18Svikram 			(void) devfs_clean(pdip, devnm + 1, DV_CLEAN_FORCE);
9247c478bd9Sstevel@tonic-gate 			mutex_enter(&ibnex.ibnex_mutex);
9257c478bd9Sstevel@tonic-gate 			kmem_free(devnm, MAXNAMELEN + 1);
9267c478bd9Sstevel@tonic-gate 		}
9277c478bd9Sstevel@tonic-gate 
9287c478bd9Sstevel@tonic-gate 		mutex_exit(&ibnex.ibnex_mutex);
929*3fe80ca4SDan Cross 		ndi_devi_enter(pdip);
9307c478bd9Sstevel@tonic-gate 		ndi_rele_devi(apid_dip);
9317c478bd9Sstevel@tonic-gate 		mutex_enter(&ibnex.ibnex_mutex);
9327c478bd9Sstevel@tonic-gate 
9337c478bd9Sstevel@tonic-gate 		/* unconfigure the Port/VPPA/HCA_SVC node */
9347c478bd9Sstevel@tonic-gate 		if (IBNEX_COMMSVC_NODE_TYPE(nodep)) {
9357c478bd9Sstevel@tonic-gate 			ret_val = ibnex_commsvc_fininode(apid_dip);
9367c478bd9Sstevel@tonic-gate 		} else if (nodep->node_type == IBNEX_IOC_NODE) {
9377c478bd9Sstevel@tonic-gate 			/* unconfigure the IOC node */
9387c478bd9Sstevel@tonic-gate 			ret_val = ibnex_ioc_fininode(apid_dip,
9397c478bd9Sstevel@tonic-gate 			    &nodep->node_data.ioc_node);
9407c478bd9Sstevel@tonic-gate 		} else if (nodep->node_type == IBNEX_PSEUDO_NODE) {
9417c478bd9Sstevel@tonic-gate 			/* unconfigure the pseudo node */
9427c478bd9Sstevel@tonic-gate 			ret_val = ibnex_pseudo_fininode(apid_dip);
9437c478bd9Sstevel@tonic-gate 		}
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 		/* reset upon failure */
9467c478bd9Sstevel@tonic-gate 		if (ret_val != IBNEX_SUCCESS) {
9477c478bd9Sstevel@tonic-gate 			nodep->node_dip = apid_dip;
9487c478bd9Sstevel@tonic-gate 			nodep->node_state = IBNEX_CFGADM_CONFIGURED;
94900a3eaf3SRamaswamy Tummala 		} else {
9507c478bd9Sstevel@tonic-gate 			nodep->node_state = IBNEX_CFGADM_UNCONFIGURED;
95100a3eaf3SRamaswamy Tummala 			nodep->node_ap_state = IBNEX_NODE_AP_UNCONFIGURED;
95200a3eaf3SRamaswamy Tummala 		}
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate 		rv = (ret_val != IBNEX_SUCCESS) ? EIO : 0;
955*3fe80ca4SDan Cross 		ndi_devi_exit(pdip);
9567c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "%s: DONE !! It %s", msg,
9577c478bd9Sstevel@tonic-gate 		    rv ? "failed" : "succeeded");
9587c478bd9Sstevel@tonic-gate 		break;
9597c478bd9Sstevel@tonic-gate 
9607c478bd9Sstevel@tonic-gate 	case DEVCTL_AP_CONFIGURE:
9617c478bd9Sstevel@tonic-gate 		msg = "DEVCTL_AP_CONFIGURE";
9627c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "%s", msg);
9637c478bd9Sstevel@tonic-gate 		mutex_exit(&ibnex.ibnex_mutex);
964*3fe80ca4SDan Cross 		ndi_devi_enter(ibnex.ibnex_dip);
9657c478bd9Sstevel@tonic-gate 		mutex_enter(&ibnex.ibnex_mutex);
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate 		/* Check for write permissions */
9687c478bd9Sstevel@tonic-gate 		if (!(mode & FWRITE)) {
9697c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "%s: invalid mode %x",
9707c478bd9Sstevel@tonic-gate 			    msg, mode);
9717c478bd9Sstevel@tonic-gate 			rv = EPERM;
972*3fe80ca4SDan Cross 			ndi_devi_exit(ibnex.ibnex_dip);
9737c478bd9Sstevel@tonic-gate 			break;
9747c478bd9Sstevel@tonic-gate 		}
9757c478bd9Sstevel@tonic-gate 
976cf95dd16SToomas Soome 		if ((apid_n = ibnex_get_apid(dcp)) == NULL) {
9777c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
9787c478bd9Sstevel@tonic-gate 			    "%s: ibnex_get_apid failed", msg);
9797c478bd9Sstevel@tonic-gate 			rv = EIO;
980*3fe80ca4SDan Cross 			ndi_devi_exit(ibnex.ibnex_dip);
9817c478bd9Sstevel@tonic-gate 			break;
9827c478bd9Sstevel@tonic-gate 		}
9837c478bd9Sstevel@tonic-gate 
98400a3eaf3SRamaswamy Tummala 		/*
98500a3eaf3SRamaswamy Tummala 		 * Let's get the node if it already exists.
98600a3eaf3SRamaswamy Tummala 		 * NOTE: ibnex_get_dip_from_apid() finds a valid dip
98700a3eaf3SRamaswamy Tummala 		 * and also does a ndi_devi_hold() on the child.
98800a3eaf3SRamaswamy Tummala 		 */
98900a3eaf3SRamaswamy Tummala 		nodep = NULL;
99000a3eaf3SRamaswamy Tummala 		ret_val = ibnex_get_dip_from_apid(apid_n, &apid_dip, &nodep);
99100a3eaf3SRamaswamy Tummala 		/*
99200a3eaf3SRamaswamy Tummala 		 * We need the node_data but not the dip. If we get a dip for
99300a3eaf3SRamaswamy Tummala 		 * this apid, it means it's already configured. We need to
99400a3eaf3SRamaswamy Tummala 		 * return.
99500a3eaf3SRamaswamy Tummala 		 */
99600a3eaf3SRamaswamy Tummala 		if (apid_dip != NULL) {
99700a3eaf3SRamaswamy Tummala 			ndi_rele_devi(apid_dip);
998*3fe80ca4SDan Cross 			ndi_devi_exit(ibnex.ibnex_dip);
99900a3eaf3SRamaswamy Tummala 			rv = 0;
100000a3eaf3SRamaswamy Tummala 			break;
100100a3eaf3SRamaswamy Tummala 		}
100200a3eaf3SRamaswamy Tummala 
100300a3eaf3SRamaswamy Tummala 		/*
100400a3eaf3SRamaswamy Tummala 		 * A node exits for this apid but not a dip. So we must have
100500a3eaf3SRamaswamy Tummala 		 * unconfigured it earlier. Set the node_ap_state to configuring
100600a3eaf3SRamaswamy Tummala 		 * to allow configure operation.
100700a3eaf3SRamaswamy Tummala 		 */
100800a3eaf3SRamaswamy Tummala 		if (nodep != NULL) {
100900a3eaf3SRamaswamy Tummala 			nodep->node_ap_state = IBNEX_NODE_AP_CONFIGURING;
101000a3eaf3SRamaswamy Tummala 		}
101100a3eaf3SRamaswamy Tummala 
101200a3eaf3SRamaswamy Tummala 
10137c478bd9Sstevel@tonic-gate 		/*
10147c478bd9Sstevel@tonic-gate 		 * Five types of APIDs are supported:
10157c478bd9Sstevel@tonic-gate 		 *	o HCA_GUID,0,service-name	(HCA-SVC device)
1016bf8d275aSToomas Soome 		 *	o IOC_GUID			(IOC device)
10177c478bd9Sstevel@tonic-gate 		 *	o PORT_GUID,0,service-name	(Port device)
1018bf8d275aSToomas Soome 		 *	o pseudo_name,unit-address,	(Pseudo device)
10197c478bd9Sstevel@tonic-gate 		 *	o PORT_GUID,P_Key,service-name	(VPPA device)
10207c478bd9Sstevel@tonic-gate 		 * If the apid doesn't have "," then treat it as an IOC
10217c478bd9Sstevel@tonic-gate 		 * If the apid has one "," then it is Pseudo device
10227c478bd9Sstevel@tonic-gate 		 * If the apid has 2 ","s then it is one of the
10237c478bd9Sstevel@tonic-gate 		 * Port,VPPA,HCA_SVC devices
10247c478bd9Sstevel@tonic-gate 		 */
10257c478bd9Sstevel@tonic-gate 		if (strrchr(apid_n, ',') == NULL) {
10267c478bd9Sstevel@tonic-gate 			ret_val = ibnex_handle_ioc_configure(apid_n);
10277c478bd9Sstevel@tonic-gate 		} else {
10287c478bd9Sstevel@tonic-gate 			char *first = strchr(apid_n, ',');
10297c478bd9Sstevel@tonic-gate 			char *second;
10307c478bd9Sstevel@tonic-gate 
10317c478bd9Sstevel@tonic-gate 			second = first ? strchr(first + 1, ',') : NULL;
10327c478bd9Sstevel@tonic-gate 			if (first != NULL && second == NULL) {
10337c478bd9Sstevel@tonic-gate 				ret_val = ibnex_handle_pseudo_configure(apid_n);
10347c478bd9Sstevel@tonic-gate 			} else if (first != NULL && second != NULL) {
10357c478bd9Sstevel@tonic-gate 				ret_val = ibnex_handle_commsvcnode_configure(
10367c478bd9Sstevel@tonic-gate 				    apid_n);
10377c478bd9Sstevel@tonic-gate 			}
10387c478bd9Sstevel@tonic-gate 		} /* end of else */
10397c478bd9Sstevel@tonic-gate 
104000a3eaf3SRamaswamy Tummala 		if (ret_val != IBNEX_SUCCESS) {
10417c478bd9Sstevel@tonic-gate 			rv = (ret_val == IBNEX_BUSY) ? EBUSY : EIO;
104200a3eaf3SRamaswamy Tummala 		} else {
104300a3eaf3SRamaswamy Tummala 			/*
104400a3eaf3SRamaswamy Tummala 			 * Get the newly created node and set the state to
104500a3eaf3SRamaswamy Tummala 			 * IBNEX_NODE_AP_CONFIGURED.
104600a3eaf3SRamaswamy Tummala 			 * NOTE: ibnex_get_dip_from_apid() finds a valid dip
104700a3eaf3SRamaswamy Tummala 			 * and also does a ndi_devi_hold() on the child.
104800a3eaf3SRamaswamy Tummala 			 */
104900a3eaf3SRamaswamy Tummala 			if (!nodep)
105000a3eaf3SRamaswamy Tummala 				ret_val = ibnex_get_dip_from_apid(apid_n,
105100a3eaf3SRamaswamy Tummala 				    &apid_dip, &nodep);
105200a3eaf3SRamaswamy Tummala 			if (nodep != NULL) {
105300a3eaf3SRamaswamy Tummala 				nodep->node_ap_state = IBNEX_NODE_AP_CONFIGURED;
105400a3eaf3SRamaswamy Tummala 			}
105500a3eaf3SRamaswamy Tummala 			if (apid_dip != NULL) {
105600a3eaf3SRamaswamy Tummala 				ndi_rele_devi(apid_dip);
105700a3eaf3SRamaswamy Tummala 			}
105800a3eaf3SRamaswamy Tummala 		}
10597c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "%s: DONE !! It %s", msg,
10607c478bd9Sstevel@tonic-gate 		    rv ? "failed" : "succeeded");
1061*3fe80ca4SDan Cross 		ndi_devi_exit(ibnex.ibnex_dip);
10627c478bd9Sstevel@tonic-gate 		break;
10637c478bd9Sstevel@tonic-gate 
10647c478bd9Sstevel@tonic-gate 	default:
10657c478bd9Sstevel@tonic-gate 		rv = EIO;
10667c478bd9Sstevel@tonic-gate 		break;
10677c478bd9Sstevel@tonic-gate 	}
10687c478bd9Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
10697c478bd9Sstevel@tonic-gate 
10707c478bd9Sstevel@tonic-gate 	if ((apid_alloced == B_TRUE) && (apid_n != NULL)) {
10717c478bd9Sstevel@tonic-gate 		kmem_free(apid_n, apid_len);
10727c478bd9Sstevel@tonic-gate 	}
10737c478bd9Sstevel@tonic-gate 
10747c478bd9Sstevel@tonic-gate 	if (dcp) {
10757c478bd9Sstevel@tonic-gate 		ndi_dc_freehdl(dcp);
10767c478bd9Sstevel@tonic-gate 	}
10777c478bd9Sstevel@tonic-gate 	return (rv);
10787c478bd9Sstevel@tonic-gate }
10797c478bd9Sstevel@tonic-gate 
10807c478bd9Sstevel@tonic-gate 
10817c478bd9Sstevel@tonic-gate /*
10827c478bd9Sstevel@tonic-gate  * ibnex_get_num_devices()
10837c478bd9Sstevel@tonic-gate  *	Figure out how many IOC, VPPA, Pseudo, HCA_SVC and Port devices exist
10847c478bd9Sstevel@tonic-gate  */
10857c478bd9Sstevel@tonic-gate static int
ibnex_get_num_devices(void)10867c478bd9Sstevel@tonic-gate ibnex_get_num_devices(void)
10877c478bd9Sstevel@tonic-gate {
10887c478bd9Sstevel@tonic-gate 	int			j, k, l, hca_count;
10897c478bd9Sstevel@tonic-gate 	int			num_nodes = 0;
10907c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*hca_list, *hcap;
10917c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t	*pattr;
10927c478bd9Sstevel@tonic-gate 	ibnex_node_data_t	*nodep;
10937c478bd9Sstevel@tonic-gate 
10947c478bd9Sstevel@tonic-gate 	ASSERT(mutex_owned(&ibnex.ibnex_mutex));
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate 	/* Get a count of HCAs, first. */
10977c478bd9Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
10987c478bd9Sstevel@tonic-gate 	ibdm_ibnex_get_hca_list(&hca_list, &hca_count);
10997c478bd9Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
11007c478bd9Sstevel@tonic-gate 	for (hcap = hca_list; hca_list != NULL; hca_list = hca_list->hl_next) {
11017c478bd9Sstevel@tonic-gate 		for (j = 0; j < ibnex.ibnex_nhcasvc_comm_svcs; j++)
11027c478bd9Sstevel@tonic-gate 			num_nodes++;
11037c478bd9Sstevel@tonic-gate 		for (j = 0; j < hca_list->hl_nports; j++) {
11047c478bd9Sstevel@tonic-gate 			for (k = 0; k < ibnex.ibnex_num_comm_svcs; k++)
11057c478bd9Sstevel@tonic-gate 				num_nodes++;
11067c478bd9Sstevel@tonic-gate 
11077c478bd9Sstevel@tonic-gate 			pattr = &hca_list->hl_port_attr[j];
11087c478bd9Sstevel@tonic-gate 			for (k = 0; k < pattr->pa_npkeys; k++) {
11097c478bd9Sstevel@tonic-gate 				if (IBNEX_INVALID_PKEY(pattr->pa_pkey_tbl[k].
11107c478bd9Sstevel@tonic-gate 				    pt_pkey))
11117c478bd9Sstevel@tonic-gate 					continue;
11127c478bd9Sstevel@tonic-gate 
11137c478bd9Sstevel@tonic-gate 				for (l = 0; l < ibnex.ibnex_nvppa_comm_svcs;
111400a3eaf3SRamaswamy Tummala 				    l++, ++num_nodes)
111500a3eaf3SRamaswamy Tummala 					;
11167c478bd9Sstevel@tonic-gate 			} /* end of pa_npkeys */
11177c478bd9Sstevel@tonic-gate 		} /* end of  hl_nports */
11187c478bd9Sstevel@tonic-gate 	} /* end of hca_list != NULL */
11197c478bd9Sstevel@tonic-gate 	if (hcap)
11207c478bd9Sstevel@tonic-gate 		ibdm_ibnex_free_hca_list(hcap);
11217c478bd9Sstevel@tonic-gate 
11227c478bd9Sstevel@tonic-gate 	/*
11237c478bd9Sstevel@tonic-gate 	 * Now figure out how many IOC nodes are present.
11247c478bd9Sstevel@tonic-gate 	 * Add count of configured "diconnected" IOCs
11257c478bd9Sstevel@tonic-gate 	 */
11267c478bd9Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
11277c478bd9Sstevel@tonic-gate 	num_nodes += ibdm_ibnex_get_ioc_count();
11287c478bd9Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
11297c478bd9Sstevel@tonic-gate 	num_nodes += ibnex.ibnex_num_disconnect_iocs;
11307c478bd9Sstevel@tonic-gate 
11317c478bd9Sstevel@tonic-gate 	/* Last: figure out how many Pseudo nodes are present. */
11327c478bd9Sstevel@tonic-gate 	for (nodep = ibnex.ibnex_pseudo_node_head; nodep;
11339d3d2ed0Shiremath 	    nodep = nodep->node_next) {
11349d3d2ed0Shiremath 		if (nodep->node_data.pseudo_node.pseudo_merge_node == 1)
11359d3d2ed0Shiremath 			continue;
11369d3d2ed0Shiremath 
11379d3d2ed0Shiremath 		num_nodes++;
11389d3d2ed0Shiremath 	}
11397c478bd9Sstevel@tonic-gate 	return (num_nodes);
11407c478bd9Sstevel@tonic-gate }
11417c478bd9Sstevel@tonic-gate 
11427c478bd9Sstevel@tonic-gate 
11437c478bd9Sstevel@tonic-gate /*
11447c478bd9Sstevel@tonic-gate  * ibnex_get_snapshot()
11457c478bd9Sstevel@tonic-gate  *	Get a snapshot of all Port/IOC/VPPA/HCA_SVC/Pseudo nodes
11467c478bd9Sstevel@tonic-gate  *	Snapshot includes IBNEX_NODE_INFO_NVL, IBNEX_NODE_TYPE_NVL,
11477c478bd9Sstevel@tonic-gate  *	IBNEX_NODE_RSTATE_NVL, IBNEX_NODE_OSTATE_NVL and
11487c478bd9Sstevel@tonic-gate  *	IBNEX_NODE_COND_NVL
11497c478bd9Sstevel@tonic-gate  */
11507c478bd9Sstevel@tonic-gate static int
ibnex_get_snapshot(char ** buf,size_t * sz,int allow_probe)11517c478bd9Sstevel@tonic-gate ibnex_get_snapshot(char **buf, size_t *sz, int allow_probe)
11527c478bd9Sstevel@tonic-gate {
11537c478bd9Sstevel@tonic-gate 	int			i, j, k, l, hca_count;
11547c478bd9Sstevel@tonic-gate 	nvlist_t		*nvl;
1155bf8d275aSToomas Soome 	ib_pkey_t		pkey;
11567c478bd9Sstevel@tonic-gate 	boolean_t		found;
11577c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t		*ioc_listp;
11587c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t		*iocp;
11597c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*hca_list, *hcap;
11607c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t	*port_attr;
11617c478bd9Sstevel@tonic-gate 	ibnex_node_data_t	*nodep;
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate 	ASSERT(mutex_owned(&ibnex.ibnex_mutex));
11647c478bd9Sstevel@tonic-gate 
11657c478bd9Sstevel@tonic-gate 	*buf = NULL;
11667c478bd9Sstevel@tonic-gate 	*sz = 0;
11677c478bd9Sstevel@tonic-gate 
11687c478bd9Sstevel@tonic-gate 	if (!ibnex.ibnex_pseudo_inited) {
11697c478bd9Sstevel@tonic-gate 		mutex_exit(&ibnex.ibnex_mutex);
11707c478bd9Sstevel@tonic-gate 		ibnex_pseudo_initnodes();
11717c478bd9Sstevel@tonic-gate 		mutex_enter(&ibnex.ibnex_mutex);
11727c478bd9Sstevel@tonic-gate 		ibnex.ibnex_pseudo_inited = 1;
11737c478bd9Sstevel@tonic-gate 	}
11747c478bd9Sstevel@tonic-gate 
11757c478bd9Sstevel@tonic-gate 	/* First, Port/VPPA/HCA_SVC nodes */
11767c478bd9Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
11777c478bd9Sstevel@tonic-gate 	ibdm_ibnex_get_hca_list(&hca_list, &hca_count);
11787c478bd9Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
11797c478bd9Sstevel@tonic-gate 
11807c478bd9Sstevel@tonic-gate 	(void) nvlist_alloc(&nvl, 0, KM_SLEEP);
11817c478bd9Sstevel@tonic-gate 
11827c478bd9Sstevel@tonic-gate 	/* Go thru all the ports of all the HCAs and all the port-svc indices */
11837c478bd9Sstevel@tonic-gate 	for (hcap = hca_list, i = 0; i < hca_count;
11847c478bd9Sstevel@tonic-gate 	    hca_list = hca_list->hl_next, i++) {
11857c478bd9Sstevel@tonic-gate 
11867c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "ibnex_get_snapshot: "
11877c478bd9Sstevel@tonic-gate 		    "fill in  COMM service HCA_SVC nodes");
11887c478bd9Sstevel@tonic-gate 		port_attr = hca_list->hl_hca_port_attr;
11897c478bd9Sstevel@tonic-gate 		for (j = 0; j < ibnex.ibnex_nhcasvc_comm_svcs; j++) {
11907c478bd9Sstevel@tonic-gate 			if (ibnex_get_commsvcnode_snapshot(&nvl,
11917c478bd9Sstevel@tonic-gate 			    port_attr->pa_hca_guid,
11927c478bd9Sstevel@tonic-gate 			    port_attr->pa_hca_guid, j, (ib_pkey_t)0,
11937c478bd9Sstevel@tonic-gate 			    IBNEX_HCASVC_COMMSVC_NODE) != 0) {
11947c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex",
11957c478bd9Sstevel@tonic-gate 				    "ibnex_get_snapshot: failed to fill"
11967c478bd9Sstevel@tonic-gate 				    " HCA_SVC device (%x %x)", i, j);
11977c478bd9Sstevel@tonic-gate 				ibdm_ibnex_free_hca_list(hcap);
11987c478bd9Sstevel@tonic-gate 				nvlist_free(nvl);
11997c478bd9Sstevel@tonic-gate 				return (-1);
12007c478bd9Sstevel@tonic-gate 			}
12017c478bd9Sstevel@tonic-gate 
12027c478bd9Sstevel@tonic-gate 		}
12037c478bd9Sstevel@tonic-gate 
12047c478bd9Sstevel@tonic-gate 		for (j = 0; j < hca_list->hl_nports; j++) {
12057c478bd9Sstevel@tonic-gate 			port_attr = &hca_list->hl_port_attr[j];
12067c478bd9Sstevel@tonic-gate 
12077c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "ibnex_get_snapshot: "
12087c478bd9Sstevel@tonic-gate 			    "fill in  COMM service Port nodes");
12097c478bd9Sstevel@tonic-gate 			for (k = 0; k < ibnex.ibnex_num_comm_svcs; k++) {
12107c478bd9Sstevel@tonic-gate 
12117c478bd9Sstevel@tonic-gate 				if (ibnex_get_commsvcnode_snapshot(&nvl,
12127c478bd9Sstevel@tonic-gate 				    port_attr->pa_hca_guid,
12137c478bd9Sstevel@tonic-gate 				    port_attr->pa_port_guid, k, (ib_pkey_t)0,
12147c478bd9Sstevel@tonic-gate 				    IBNEX_PORT_COMMSVC_NODE) != 0) {
12157c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
12167c478bd9Sstevel@tonic-gate 					    "ibnex_get_snapshot: failed to fill"
12177c478bd9Sstevel@tonic-gate 					    " Port device (%x %x %x)", i, j, k);
12187c478bd9Sstevel@tonic-gate 					ibdm_ibnex_free_hca_list(hcap);
12197c478bd9Sstevel@tonic-gate 					nvlist_free(nvl);
12207c478bd9Sstevel@tonic-gate 					return (-1);
12217c478bd9Sstevel@tonic-gate 				}
12227c478bd9Sstevel@tonic-gate 
12237c478bd9Sstevel@tonic-gate 			} /* end of num_comm_svcs for loop */
12247c478bd9Sstevel@tonic-gate 
12257c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibnex", "ibnex_get_snapshot: "
12267c478bd9Sstevel@tonic-gate 			    "fill in  VPPA service port nodes");
12277c478bd9Sstevel@tonic-gate 			for (l = 0; l < port_attr->pa_npkeys; l++) {
12287c478bd9Sstevel@tonic-gate 				pkey = port_attr->pa_pkey_tbl[l].pt_pkey;
12297c478bd9Sstevel@tonic-gate 				if (IBNEX_INVALID_PKEY(pkey))
12307c478bd9Sstevel@tonic-gate 					continue;
12317c478bd9Sstevel@tonic-gate 
12327c478bd9Sstevel@tonic-gate 				for (k = 0; k < ibnex.ibnex_nvppa_comm_svcs;
12337c478bd9Sstevel@tonic-gate 				    k++) {
12347c478bd9Sstevel@tonic-gate 
12357c478bd9Sstevel@tonic-gate 					if (ibnex_get_commsvcnode_snapshot(&nvl,
12367c478bd9Sstevel@tonic-gate 					    port_attr->pa_hca_guid,
12377c478bd9Sstevel@tonic-gate 					    port_attr->pa_port_guid, k, pkey,
12387c478bd9Sstevel@tonic-gate 					    IBNEX_VPPA_COMMSVC_NODE) != 0) {
12397c478bd9Sstevel@tonic-gate 						IBTF_DPRINTF_L2("ibnex",
12407c478bd9Sstevel@tonic-gate 						    "ibnex_get_snapshot: "
12417c478bd9Sstevel@tonic-gate 						    "failed to fill VPPA "
12427c478bd9Sstevel@tonic-gate 						    "device (%x %x %x % x)",
12437c478bd9Sstevel@tonic-gate 						    i, j, k, l);
12447c478bd9Sstevel@tonic-gate 						ibdm_ibnex_free_hca_list(hcap);
12457c478bd9Sstevel@tonic-gate 						nvlist_free(nvl);
12467c478bd9Sstevel@tonic-gate 						return (-1);
12477c478bd9Sstevel@tonic-gate 					}
12487c478bd9Sstevel@tonic-gate 				} /* end of ibnex_nvppa_comm_svcs loop */
12497c478bd9Sstevel@tonic-gate 
12507c478bd9Sstevel@tonic-gate 			} /* end of pa_npkeys for loop */
12517c478bd9Sstevel@tonic-gate 
12527c478bd9Sstevel@tonic-gate 		} /* end of hl_nports for loop */
12537c478bd9Sstevel@tonic-gate 
12547c478bd9Sstevel@tonic-gate 	} /* end of hca_count for loop */
12557c478bd9Sstevel@tonic-gate 
12567c478bd9Sstevel@tonic-gate 	if (hcap)
12577c478bd9Sstevel@tonic-gate 		ibdm_ibnex_free_hca_list(hcap);
12587c478bd9Sstevel@tonic-gate 
12597c478bd9Sstevel@tonic-gate 	/* save it to free up the entire list */
12607c478bd9Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
12617c478bd9Sstevel@tonic-gate 	iocp = ioc_listp = ibdm_ibnex_get_ioc_list(allow_probe);
12627c478bd9Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
12637c478bd9Sstevel@tonic-gate 	for (; ioc_listp != NULL; ioc_listp = ioc_listp->ioc_next) {
12647c478bd9Sstevel@tonic-gate 
12657c478bd9Sstevel@tonic-gate 		/*
12667c478bd9Sstevel@tonic-gate 		 * Say we have N IOCs and all were deleted from ibnex
12677c478bd9Sstevel@tonic-gate 		 * but not from IBDM
12687c478bd9Sstevel@tonic-gate 		 */
12697c478bd9Sstevel@tonic-gate 		if (ibnex.ibnex_ioc_node_head == NULL) {
12707c478bd9Sstevel@tonic-gate 			if (ibnex_fill_ioc_tmp(&nvl, ioc_listp) != 0) {
12717c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibnex", "ibnex_get_snapshot: "
12727c478bd9Sstevel@tonic-gate 				    "filling NVL data failed");
12737c478bd9Sstevel@tonic-gate 				ibdm_ibnex_free_ioc_list(iocp);
12747c478bd9Sstevel@tonic-gate 				nvlist_free(nvl);
12757c478bd9Sstevel@tonic-gate 				return (-1);
12767c478bd9Sstevel@tonic-gate 			}
12777c478bd9Sstevel@tonic-gate 			continue;
12787c478bd9Sstevel@tonic-gate 
12797c478bd9Sstevel@tonic-gate 		} else {
12807c478bd9Sstevel@tonic-gate 			found = B_FALSE;
12817c478bd9Sstevel@tonic-gate 
12827c478bd9Sstevel@tonic-gate 			/* Check first, if we have already seen this IOC? */
12837c478bd9Sstevel@tonic-gate 			for (nodep = ibnex.ibnex_ioc_node_head; nodep != NULL;
12847c478bd9Sstevel@tonic-gate 			    nodep = nodep->node_next) {
12857c478bd9Sstevel@tonic-gate 				if (ioc_listp->ioc_profile.ioc_guid ==
12867c478bd9Sstevel@tonic-gate 				    nodep->node_data.ioc_node.ioc_guid) {
12877c478bd9Sstevel@tonic-gate 					found = B_TRUE;
12887c478bd9Sstevel@tonic-gate 					break;
12897c478bd9Sstevel@tonic-gate 				}
12907c478bd9Sstevel@tonic-gate 			}
12917c478bd9Sstevel@tonic-gate 
12927c478bd9Sstevel@tonic-gate 
12937c478bd9Sstevel@tonic-gate 			/* have we seen this IOC before? */
12947c478bd9Sstevel@tonic-gate 			if (found == B_TRUE) {
12957c478bd9Sstevel@tonic-gate 				if (ibnex_fill_nodeinfo(&nvl, nodep,
12967c478bd9Sstevel@tonic-gate 				    &ioc_listp->ioc_profile) != 0) {
12977c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
12987c478bd9Sstevel@tonic-gate 					    "ibnex_get_snapshot: filling NVL "
12997c478bd9Sstevel@tonic-gate 					    "for IOC node %p failed", nodep);
13007c478bd9Sstevel@tonic-gate 					ibdm_ibnex_free_ioc_list(iocp);
13017c478bd9Sstevel@tonic-gate 					nvlist_free(nvl);
13027c478bd9Sstevel@tonic-gate 					return (-1);
13037c478bd9Sstevel@tonic-gate 				}
13047c478bd9Sstevel@tonic-gate 
13057c478bd9Sstevel@tonic-gate 			} else {
13067c478bd9Sstevel@tonic-gate 
13077c478bd9Sstevel@tonic-gate 				if (ibnex_fill_ioc_tmp(&nvl, ioc_listp) != 0) {
13087c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
13097c478bd9Sstevel@tonic-gate 					    "ibnex_get_snapshot: filling NVL "
13107c478bd9Sstevel@tonic-gate 					    "tmp for IOC node %p failed",
13117c478bd9Sstevel@tonic-gate 					    ioc_listp);
13127c478bd9Sstevel@tonic-gate 					ibdm_ibnex_free_ioc_list(iocp);
13137c478bd9Sstevel@tonic-gate 					nvlist_free(nvl);
13147c478bd9Sstevel@tonic-gate 					return (-1);
13157c478bd9Sstevel@tonic-gate 				}
13167c478bd9Sstevel@tonic-gate 			}
13177c478bd9Sstevel@tonic-gate 
13187c478bd9Sstevel@tonic-gate 		} /* end of else ibnex_ioc_node_head == NULL */
13197c478bd9Sstevel@tonic-gate 	} /* end of external for */
13207c478bd9Sstevel@tonic-gate 
13217c478bd9Sstevel@tonic-gate 	ibdm_ibnex_free_ioc_list(iocp);
13227c478bd9Sstevel@tonic-gate 
13237c478bd9Sstevel@tonic-gate 	/*
13247c478bd9Sstevel@tonic-gate 	 * Add list of "disconnected" IOCs, not unconfigured.
13257c478bd9Sstevel@tonic-gate 	 */
13267c478bd9Sstevel@tonic-gate 	for (nodep = ibnex.ibnex_ioc_node_head; nodep != NULL;
13277c478bd9Sstevel@tonic-gate 	    nodep = nodep->node_next) {
13287c478bd9Sstevel@tonic-gate 		if (nodep->node_data.ioc_node.ioc_ngids == 0 &&
13297c478bd9Sstevel@tonic-gate 		    nodep->node_data.ioc_node.ioc_profile != NULL &&
13307c478bd9Sstevel@tonic-gate 		    nodep->node_state != IBNEX_CFGADM_UNCONFIGURED) {
13317c478bd9Sstevel@tonic-gate 			if (ibnex_fill_nodeinfo(&nvl, nodep,
13327c478bd9Sstevel@tonic-gate 			    nodep->node_data.ioc_node.ioc_profile) != 0) {
13337c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibnex",
13347c478bd9Sstevel@tonic-gate 					    "ibnex_get_snapshot: filling NVL "
13357c478bd9Sstevel@tonic-gate 					    "for disconnected IOC node %p "
13367c478bd9Sstevel@tonic-gate 					    "failed", nodep);
13377c478bd9Sstevel@tonic-gate 					nvlist_free(nvl);
13387c478bd9Sstevel@tonic-gate 					return (-1);
13397c478bd9Sstevel@tonic-gate 			}
13407c478bd9Sstevel@tonic-gate 		}
13417c478bd9Sstevel@tonic-gate 	}
13427c478bd9Sstevel@tonic-gate 
13437c478bd9Sstevel@tonic-gate 	/* lastly; pseudo nodes */
13447c478bd9Sstevel@tonic-gate 	for (nodep = ibnex.ibnex_pseudo_node_head; nodep;
13457c478bd9Sstevel@tonic-gate 	    nodep = nodep->node_next) {
13469d3d2ed0Shiremath 		if (nodep->node_data.pseudo_node.pseudo_merge_node == 1)
13479d3d2ed0Shiremath 			continue;
13487c478bd9Sstevel@tonic-gate 		if (ibnex_fill_nodeinfo(&nvl, nodep, NULL) != 0) {
13497c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_get_snapshot: "
13507c478bd9Sstevel@tonic-gate 			    "filling NVL data for Pseudo %p failed", nodep);
13517c478bd9Sstevel@tonic-gate 			nvlist_free(nvl);
13527c478bd9Sstevel@tonic-gate 			return (-1);
13537c478bd9Sstevel@tonic-gate 		}
13547c478bd9Sstevel@tonic-gate 	}
13557c478bd9Sstevel@tonic-gate 
13567c478bd9Sstevel@tonic-gate 	/* pack the data into the buffer */
13577c478bd9Sstevel@tonic-gate 	if (nvlist_pack(nvl, buf, sz, NV_ENCODE_NATIVE, KM_SLEEP)) {
13587c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex",
13597c478bd9Sstevel@tonic-gate 		    "ibnex_get_snapshot: nvlist_pack failed");
13607c478bd9Sstevel@tonic-gate 		nvlist_free(nvl);
13617c478bd9Sstevel@tonic-gate 		return (-1);
13627c478bd9Sstevel@tonic-gate 	}
13637c478bd9Sstevel@tonic-gate 
13647c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "ibnex_get_snapshot: size = 0x%x", *sz);
13657c478bd9Sstevel@tonic-gate 	nvlist_free(nvl);
13667c478bd9Sstevel@tonic-gate 	return (0);
13677c478bd9Sstevel@tonic-gate }
13687c478bd9Sstevel@tonic-gate 
13697c478bd9Sstevel@tonic-gate 
13707c478bd9Sstevel@tonic-gate /*
13717c478bd9Sstevel@tonic-gate  * ibnex_get_commsvcnode_snapshot()
13727c478bd9Sstevel@tonic-gate  *	A utility function to fill in a "dummy" Port/VPPA/HCA_SVC
13737c478bd9Sstevel@tonic-gate  *	information. Cfgadm plugin will display all Port/VPPA/
13747c478bd9Sstevel@tonic-gate  *	HCA_SVCs seen even if they are not all configured by IBNEX.
13757c478bd9Sstevel@tonic-gate  *
13767c478bd9Sstevel@tonic-gate  *	This function uses information from IBDM to fill up Port/VPPA/
13777c478bd9Sstevel@tonic-gate  *	HCA_SVC snapshot. If none exists then it makes up a "temporary"
13787c478bd9Sstevel@tonic-gate  *	node which will be displayed as "connected/unconfigured/unknown".
13797c478bd9Sstevel@tonic-gate  *
13807c478bd9Sstevel@tonic-gate  *	For HCA_SVC node port_guid will be same as hca_guid.
13817c478bd9Sstevel@tonic-gate  */
13827c478bd9Sstevel@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)13837c478bd9Sstevel@tonic-gate ibnex_get_commsvcnode_snapshot(nvlist_t **nvlpp, ib_guid_t hca_guid,
13847c478bd9Sstevel@tonic-gate     ib_guid_t port_guid, int svc_index, ib_pkey_t p_key,
13857c478bd9Sstevel@tonic-gate     ibnex_node_type_t node_type)
13867c478bd9Sstevel@tonic-gate {
13877c478bd9Sstevel@tonic-gate 	int			rval;
13887c478bd9Sstevel@tonic-gate 	dev_info_t		*dip = NULL;
13897c478bd9Sstevel@tonic-gate 	ibnex_node_data_t	*nodep;
13907c478bd9Sstevel@tonic-gate 	ibnex_node_data_t	dummy;
13917c478bd9Sstevel@tonic-gate 	ibnex_node_data_t	*tmp = &dummy;
13927c478bd9Sstevel@tonic-gate 
13937c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "ibnex_get_commsvcnode_snapshot: "
13947c478bd9Sstevel@tonic-gate 	    "HCA GUID: %llX Port GUID: %llX svc_index = %x pkey = %x "
13957c478bd9Sstevel@tonic-gate 	    "node_type = %x", hca_guid, port_guid, svc_index, p_key, node_type);
13967c478bd9Sstevel@tonic-gate 
13977c478bd9Sstevel@tonic-gate 	/* check if this node was seen before? */
13981cfa752fSRamaswamy Tummala 	rval = ibnex_get_node_and_dip_from_guid(port_guid, svc_index, p_key,
13991cfa752fSRamaswamy Tummala 	    &nodep, &dip);
14001cfa752fSRamaswamy Tummala 	if (rval == IBNEX_SUCCESS && nodep != NULL) {
14017c478bd9Sstevel@tonic-gate 
14027c478bd9Sstevel@tonic-gate 		if (ibnex_fill_nodeinfo(nvlpp, nodep, NULL) != 0) {
14037c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
14047c478bd9Sstevel@tonic-gate 			    "ibnex_get_commsvcnode_snapshot: failed to fill "
14057c478bd9Sstevel@tonic-gate 			    "Port/VPPA device node %p NVL data", nodep);
14067c478bd9Sstevel@tonic-gate 			return (-1);
14077c478bd9Sstevel@tonic-gate 		}
14087c478bd9Sstevel@tonic-gate 
14097c478bd9Sstevel@tonic-gate 	} else {
14107c478bd9Sstevel@tonic-gate 		/* Fake up a Port/VPPA/HCA_SVC node */
14117c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "ibnex_get_commsvcnode_snapshot: "
14127c478bd9Sstevel@tonic-gate 		    "VPPA/Port/HCA_SVC not seen by ibnex");
14137c478bd9Sstevel@tonic-gate 		bzero(tmp, sizeof (ibnex_node_data_t));
14147c478bd9Sstevel@tonic-gate 		tmp->node_type = node_type;
14157c478bd9Sstevel@tonic-gate 		tmp->node_data.port_node.port_guid = port_guid;
14167c478bd9Sstevel@tonic-gate 		tmp->node_data.port_node.port_hcaguid = hca_guid;
14177c478bd9Sstevel@tonic-gate 		tmp->node_data.port_node.port_commsvc_idx = svc_index;
14187c478bd9Sstevel@tonic-gate 		/* Fill P_Key only for VPPA nodes */
14197c478bd9Sstevel@tonic-gate 		if (node_type == IBNEX_VPPA_COMMSVC_NODE) {
14207c478bd9Sstevel@tonic-gate 			tmp->node_data.port_node.port_pkey = p_key;
14217c478bd9Sstevel@tonic-gate 		}
14227c478bd9Sstevel@tonic-gate 
14237c478bd9Sstevel@tonic-gate 		if (ibnex_fill_nodeinfo(nvlpp, tmp, NULL) != 0) {
14247c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
14257c478bd9Sstevel@tonic-gate 			    "ibnex_get_commsvcnode_snapshot: failed to fill "
14267c478bd9Sstevel@tonic-gate 			    "tmp Port/VPPA device node %p NVL data", tmp);
14277c478bd9Sstevel@tonic-gate 			return (-1);
14287c478bd9Sstevel@tonic-gate 		}
14297c478bd9Sstevel@tonic-gate 	}
14307c478bd9Sstevel@tonic-gate 
14317c478bd9Sstevel@tonic-gate 	return (0);
14327c478bd9Sstevel@tonic-gate }
14337c478bd9Sstevel@tonic-gate 
14347c478bd9Sstevel@tonic-gate 
14357c478bd9Sstevel@tonic-gate /*
14367c478bd9Sstevel@tonic-gate  * ibnex_fill_ioc_tmp()
14377c478bd9Sstevel@tonic-gate  *	A utility function to fill in a "dummy" IOC information.
14387c478bd9Sstevel@tonic-gate  *	Cfgadm plugin will display all IOCs seen by IBDM even if they
14397c478bd9Sstevel@tonic-gate  *	are configured or not by IBNEX.
14407c478bd9Sstevel@tonic-gate  *
14417c478bd9Sstevel@tonic-gate  *	This function uses information from IBDM to fill up a
14427c478bd9Sstevel@tonic-gate  *	dummy IOC information. It will be displayed as
14437c478bd9Sstevel@tonic-gate  *	"connected/unconfigured/unknown".
14447c478bd9Sstevel@tonic-gate  */
14457c478bd9Sstevel@tonic-gate static int
ibnex_fill_ioc_tmp(nvlist_t ** nvlpp,ibdm_ioc_info_t * ioc_listp)14467c478bd9Sstevel@tonic-gate ibnex_fill_ioc_tmp(nvlist_t **nvlpp, ibdm_ioc_info_t *ioc_listp)
14477c478bd9Sstevel@tonic-gate {
14487c478bd9Sstevel@tonic-gate 	ibnex_node_data_t	dummy;
14497c478bd9Sstevel@tonic-gate 	ibnex_node_data_t	*nodep = &dummy;
14507c478bd9Sstevel@tonic-gate 
14517c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tibnex_fill_ioc_tmp:");
14527c478bd9Sstevel@tonic-gate 
14537c478bd9Sstevel@tonic-gate 	bzero(nodep, sizeof (ibnex_node_data_t));
14547c478bd9Sstevel@tonic-gate 	nodep->node_type = IBNEX_IOC_NODE;
14557c478bd9Sstevel@tonic-gate 	nodep->node_data.ioc_node.ioc_guid = ioc_listp->ioc_profile.ioc_guid;
14567c478bd9Sstevel@tonic-gate 	nodep->node_data.ioc_node.iou_guid = ioc_listp->ioc_iou_guid;
14577c478bd9Sstevel@tonic-gate 	(void) strncpy(nodep->node_data.ioc_node.ioc_id_string,
14587c478bd9Sstevel@tonic-gate 	    (char *)ioc_listp->ioc_profile.ioc_id_string,
14597c478bd9Sstevel@tonic-gate 	    IB_DM_IOC_ID_STRING_LEN);
14607c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tibnex_fill_ioc_tmp: %s",
14617c478bd9Sstevel@tonic-gate 	    nodep->node_data.ioc_node.ioc_id_string);
14627c478bd9Sstevel@tonic-gate 
14637c478bd9Sstevel@tonic-gate 	if (ibnex_fill_nodeinfo(nvlpp, nodep, &ioc_listp->ioc_profile) != 0) {
14647c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "\tibnex_fill_ioc_tmp: filling NVL "
14657c478bd9Sstevel@tonic-gate 		    "data for IOC node %p failed", nodep);
14667c478bd9Sstevel@tonic-gate 		return (-1);
14677c478bd9Sstevel@tonic-gate 	}
14687c478bd9Sstevel@tonic-gate 
14697c478bd9Sstevel@tonic-gate 	return (0);
14707c478bd9Sstevel@tonic-gate }
14717c478bd9Sstevel@tonic-gate 
14727c478bd9Sstevel@tonic-gate 
14737c478bd9Sstevel@tonic-gate /*
14747c478bd9Sstevel@tonic-gate  * ibnex_fill_nodeinfo()
14757c478bd9Sstevel@tonic-gate  *	A utility function to fill in to the NVLIST information about
14767c478bd9Sstevel@tonic-gate  *	a Port/IOC/VPPA/HCA_SVC/Pseudo driver that is then passed over
14777c478bd9Sstevel@tonic-gate  *	to cfgadm utility for display. This information is used only
14787c478bd9Sstevel@tonic-gate  *	for cfgadm -ll displays.
14797c478bd9Sstevel@tonic-gate  *
14807c478bd9Sstevel@tonic-gate  *	Information that is filled in here is:-
14817c478bd9Sstevel@tonic-gate  *		AP_ID_NAME
14827c478bd9Sstevel@tonic-gate  *		AP_ID_INFO
14837c478bd9Sstevel@tonic-gate  *		AP_ID_TYPE
14847c478bd9Sstevel@tonic-gate  *		AP_ID_OCCUPANT_STATE
14857c478bd9Sstevel@tonic-gate  *		AP_ID_RECEPTACLE_STATE
14867c478bd9Sstevel@tonic-gate  *		AP_ID_CONDITION
14877c478bd9Sstevel@tonic-gate  */
14887c478bd9Sstevel@tonic-gate static int
ibnex_fill_nodeinfo(nvlist_t ** nvlpp,ibnex_node_data_t * node_datap,void * tmp)14897c478bd9Sstevel@tonic-gate ibnex_fill_nodeinfo(nvlist_t **nvlpp, ibnex_node_data_t *node_datap, void *tmp)
14907c478bd9Sstevel@tonic-gate {
14917c478bd9Sstevel@tonic-gate 	char			*svcname;
14927c478bd9Sstevel@tonic-gate 	char			*node_name;
14937c478bd9Sstevel@tonic-gate 	char			apid[IBTL_IBNEX_APID_LEN];
14947c478bd9Sstevel@tonic-gate 	char			info_data[MAXNAMELEN];
14957c478bd9Sstevel@tonic-gate 	ib_dm_ioc_ctrl_profile_t *profilep;
14967c478bd9Sstevel@tonic-gate 	devctl_ap_state_t	state;
14977c478bd9Sstevel@tonic-gate 
14987c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: 0x%x addr is %p",
14997c478bd9Sstevel@tonic-gate 	    node_datap->node_type, node_datap);
15007c478bd9Sstevel@tonic-gate 
15017c478bd9Sstevel@tonic-gate 	if (node_datap->node_type == IBNEX_PORT_COMMSVC_NODE) {
15027c478bd9Sstevel@tonic-gate 		svcname = ibnex.ibnex_comm_svc_names[node_datap->node_data.
15037c478bd9Sstevel@tonic-gate 		    port_node.port_commsvc_idx];
15047c478bd9Sstevel@tonic-gate 		(void) snprintf(apid, IBTL_IBNEX_APID_LEN, "%llX,0,%s",
15057c478bd9Sstevel@tonic-gate 		    (longlong_t)node_datap->node_data.port_node.port_guid,
15067c478bd9Sstevel@tonic-gate 		    svcname);
15077c478bd9Sstevel@tonic-gate 
15087c478bd9Sstevel@tonic-gate 		/* Node APID */
15097c478bd9Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_APID_NVL, apid)) {
15107c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
15117c478bd9Sstevel@tonic-gate 			    "failed to fill %s", IBNEX_NODE_APID_NVL);
15127c478bd9Sstevel@tonic-gate 			return (-1);
15137c478bd9Sstevel@tonic-gate 		}
15147c478bd9Sstevel@tonic-gate 
15157c478bd9Sstevel@tonic-gate 		/* Node Info */
15167c478bd9Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_INFO_NVL, svcname)) {
15177c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
15187c478bd9Sstevel@tonic-gate 			    "failed to fill Port %s", IBNEX_NODE_INFO_NVL);
15197c478bd9Sstevel@tonic-gate 			return (-1);
15207c478bd9Sstevel@tonic-gate 		}
15217c478bd9Sstevel@tonic-gate 
15227c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: "
15237c478bd9Sstevel@tonic-gate 		    "Port %s = %s, %s = %s",
15247c478bd9Sstevel@tonic-gate 		    IBNEX_NODE_INFO_NVL, apid, IBNEX_NODE_APID_NVL, svcname);
15257c478bd9Sstevel@tonic-gate 
15267c478bd9Sstevel@tonic-gate 	} else if (node_datap->node_type == IBNEX_VPPA_COMMSVC_NODE) {
15277c478bd9Sstevel@tonic-gate 		svcname = ibnex.ibnex_vppa_comm_svc_names[node_datap->node_data.
15287c478bd9Sstevel@tonic-gate 		    port_node.port_commsvc_idx];
15297c478bd9Sstevel@tonic-gate 		(void) snprintf(apid, IBTL_IBNEX_APID_LEN, "%llX,%x,%s",
15307c478bd9Sstevel@tonic-gate 		    (longlong_t)node_datap->node_data.port_node.port_guid,
15317c478bd9Sstevel@tonic-gate 		    node_datap->node_data.port_node.port_pkey, svcname);
15327c478bd9Sstevel@tonic-gate 
15337c478bd9Sstevel@tonic-gate 		/* Node APID */
15347c478bd9Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_APID_NVL, apid)) {
15357c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
15367c478bd9Sstevel@tonic-gate 			    "failed to fill %s", IBNEX_NODE_APID_NVL);
15377c478bd9Sstevel@tonic-gate 			return (-1);
15387c478bd9Sstevel@tonic-gate 		}
15397c478bd9Sstevel@tonic-gate 
15407c478bd9Sstevel@tonic-gate 		/* Node Info */
15417c478bd9Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_INFO_NVL, svcname)) {
15427c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
15437c478bd9Sstevel@tonic-gate 			    "failed to fill VPPA %s", IBNEX_NODE_INFO_NVL);
15447c478bd9Sstevel@tonic-gate 			return (-1);
15457c478bd9Sstevel@tonic-gate 		}
15467c478bd9Sstevel@tonic-gate 
15477c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: "
15487c478bd9Sstevel@tonic-gate 		    "VPPA %s = %s, %s = %s",
15497c478bd9Sstevel@tonic-gate 		    IBNEX_NODE_APID_NVL, apid, IBNEX_NODE_INFO_NVL, svcname);
15507c478bd9Sstevel@tonic-gate 
15517c478bd9Sstevel@tonic-gate 	} else if (node_datap->node_type == IBNEX_HCASVC_COMMSVC_NODE) {
15527c478bd9Sstevel@tonic-gate 		svcname = ibnex.ibnex_hcasvc_comm_svc_names[node_datap->
15537c478bd9Sstevel@tonic-gate 		    node_data.port_node.port_commsvc_idx];
15547c478bd9Sstevel@tonic-gate 		(void) snprintf(apid, IBTL_IBNEX_APID_LEN, "%llX,0,%s",
15557c478bd9Sstevel@tonic-gate 		    (longlong_t)node_datap->node_data.port_node.port_guid,
15567c478bd9Sstevel@tonic-gate 		    svcname);
15577c478bd9Sstevel@tonic-gate 
15587c478bd9Sstevel@tonic-gate 		/* Node APID */
15597c478bd9Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_APID_NVL, apid)) {
15607c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
15617c478bd9Sstevel@tonic-gate 			    "failed to fill %s", IBNEX_NODE_APID_NVL);
15627c478bd9Sstevel@tonic-gate 			return (-1);
15637c478bd9Sstevel@tonic-gate 		}
15647c478bd9Sstevel@tonic-gate 
15657c478bd9Sstevel@tonic-gate 		/* Node Info */
15667c478bd9Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_INFO_NVL, svcname)) {
15677c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
15687c478bd9Sstevel@tonic-gate 			    "failed to fill Port %s", IBNEX_NODE_INFO_NVL);
15697c478bd9Sstevel@tonic-gate 			return (-1);
15707c478bd9Sstevel@tonic-gate 		}
15717c478bd9Sstevel@tonic-gate 
15727c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: "
15737c478bd9Sstevel@tonic-gate 		    "Port %s = %s, %s = %s",
15747c478bd9Sstevel@tonic-gate 		    IBNEX_NODE_INFO_NVL, apid, IBNEX_NODE_APID_NVL, svcname);
15757c478bd9Sstevel@tonic-gate 
15767c478bd9Sstevel@tonic-gate 	} else if (node_datap->node_type == IBNEX_IOC_NODE) {
15777c478bd9Sstevel@tonic-gate 
15787c478bd9Sstevel@tonic-gate 		/*
15797c478bd9Sstevel@tonic-gate 		 * get the IOC profile pointer from the args
15807c478bd9Sstevel@tonic-gate 		 */
15817c478bd9Sstevel@tonic-gate 		profilep = (ib_dm_ioc_ctrl_profile_t *)tmp;
15827c478bd9Sstevel@tonic-gate 		IBNEX_FORM_GUID(apid, IBTL_IBNEX_APID_LEN, profilep->ioc_guid);
15837c478bd9Sstevel@tonic-gate 
15847c478bd9Sstevel@tonic-gate 		/* Node APID */
15857c478bd9Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_APID_NVL, apid)) {
15867c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
15877c478bd9Sstevel@tonic-gate 			    "failed to fill in %s", IBNEX_NODE_APID_NVL);
15887c478bd9Sstevel@tonic-gate 			return (-1);
15897c478bd9Sstevel@tonic-gate 		}
15907c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: %s %s",
15917c478bd9Sstevel@tonic-gate 		    IBNEX_NODE_APID_NVL, apid);
15927c478bd9Sstevel@tonic-gate 
15937c478bd9Sstevel@tonic-gate 		/*
15947c478bd9Sstevel@tonic-gate 		 * IOC "info" filed will display the following fields
15957c478bd9Sstevel@tonic-gate 		 * VendorID, IOCDeviceID, DeviceVersion, SubsystemVendorID,
15967c478bd9Sstevel@tonic-gate 		 * SubsystemID, Class, Subclass, Protocol, ProtocolVersion
15977c478bd9Sstevel@tonic-gate 		 */
15987c478bd9Sstevel@tonic-gate 		(void) snprintf(info_data, MAXNAMELEN,
15997c478bd9Sstevel@tonic-gate 		    "VID: 0x%x DEVID: 0x%x VER: 0x%x SUBSYS_VID: 0x%x "
16007c478bd9Sstevel@tonic-gate 		    "SUBSYS_ID: 0x%x CLASS: 0x%x SUBCLASS: 0x%x PROTO: 0x%x "
16017c478bd9Sstevel@tonic-gate 		    "PROTOVER: 0x%x ID_STRING: %s", profilep->ioc_vendorid,
16027c478bd9Sstevel@tonic-gate 		    profilep->ioc_deviceid, profilep->ioc_device_ver,
16037c478bd9Sstevel@tonic-gate 		    profilep->ioc_subsys_vendorid, profilep->ioc_subsys_id,
16047c478bd9Sstevel@tonic-gate 		    profilep->ioc_io_class, profilep->ioc_io_subclass,
16057c478bd9Sstevel@tonic-gate 		    profilep->ioc_protocol, profilep->ioc_protocol_ver,
16067c478bd9Sstevel@tonic-gate 		    (char *)profilep->ioc_id_string);
16077c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: %s", info_data);
16087c478bd9Sstevel@tonic-gate 
16097c478bd9Sstevel@tonic-gate 		/* Node Info */
16107c478bd9Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_INFO_NVL, info_data)) {
16117c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
16127c478bd9Sstevel@tonic-gate 			    "failed to fill IOC %s", IBNEX_NODE_INFO_NVL);
16137c478bd9Sstevel@tonic-gate 			return (-1);
16147c478bd9Sstevel@tonic-gate 		}
16157c478bd9Sstevel@tonic-gate 
16167c478bd9Sstevel@tonic-gate 	} else if (node_datap->node_type == IBNEX_PSEUDO_NODE) {
16177c478bd9Sstevel@tonic-gate 		(void) snprintf(apid, IBTL_IBNEX_APID_LEN, "%s",
16187c478bd9Sstevel@tonic-gate 		    node_datap->node_data.pseudo_node.pseudo_node_addr);
16197c478bd9Sstevel@tonic-gate 
16207c478bd9Sstevel@tonic-gate 		/* Node APID */
16217c478bd9Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_APID_NVL, apid)) {
16227c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
16237c478bd9Sstevel@tonic-gate 			    "failed to fill in %s", IBNEX_NODE_APID_NVL);
16247c478bd9Sstevel@tonic-gate 			return (-1);
16257c478bd9Sstevel@tonic-gate 		}
16267c478bd9Sstevel@tonic-gate 
16277c478bd9Sstevel@tonic-gate 		/* Node Info */
16287c478bd9Sstevel@tonic-gate 		node_name = node_datap->node_data.pseudo_node.pseudo_devi_name;
16297c478bd9Sstevel@tonic-gate 		(void) snprintf(info_data, MAXNAMELEN,
16307c478bd9Sstevel@tonic-gate 		    "Pseudo Driver = \"%s\", Unit-address = \"%s\"",
16317c478bd9Sstevel@tonic-gate 		    node_name, apid + strlen(node_name) + 1);
16327c478bd9Sstevel@tonic-gate 		if (nvlist_add_string(*nvlpp, IBNEX_NODE_INFO_NVL, info_data)) {
16337c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
16347c478bd9Sstevel@tonic-gate 			    "failed to fill Pseudo %s", IBNEX_NODE_INFO_NVL);
16357c478bd9Sstevel@tonic-gate 			return (-1);
16367c478bd9Sstevel@tonic-gate 		}
16377c478bd9Sstevel@tonic-gate 
16387c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: Pseudo %s = %s,"
16397c478bd9Sstevel@tonic-gate 		    "%s = %s", IBNEX_NODE_APID_NVL, apid, IBNEX_NODE_INFO_NVL,
16407c478bd9Sstevel@tonic-gate 		    info_data);
16417c478bd9Sstevel@tonic-gate 	}
16427c478bd9Sstevel@tonic-gate 
16437c478bd9Sstevel@tonic-gate 	/* Node type */
16447c478bd9Sstevel@tonic-gate 	if (nvlist_add_int32(*nvlpp, IBNEX_NODE_TYPE_NVL,
16457c478bd9Sstevel@tonic-gate 	    node_datap->node_type)) {
16467c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
16477c478bd9Sstevel@tonic-gate 		    "failed to fill in %s", IBNEX_NODE_TYPE_NVL);
16487c478bd9Sstevel@tonic-gate 		return (-1);
16497c478bd9Sstevel@tonic-gate 	}
16507c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: %s %d",
16517c478bd9Sstevel@tonic-gate 	    IBNEX_NODE_TYPE_NVL, node_datap->node_type);
16527c478bd9Sstevel@tonic-gate 
16537c478bd9Sstevel@tonic-gate 	/* figure out "ostate", "rstate" and "condition" */
16541cfa752fSRamaswamy Tummala 	ibnex_figure_ap_devstate(node_datap, &state);
16557c478bd9Sstevel@tonic-gate 
16567c478bd9Sstevel@tonic-gate 	if (nvlist_add_int32(*nvlpp, IBNEX_NODE_RSTATE_NVL, state.ap_rstate)) {
16577c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
16587c478bd9Sstevel@tonic-gate 		    "failed to fill in %s", IBNEX_NODE_RSTATE_NVL);
16597c478bd9Sstevel@tonic-gate 		return (-1);
16607c478bd9Sstevel@tonic-gate 	}
16617c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: %s %d",
16627c478bd9Sstevel@tonic-gate 	    IBNEX_NODE_RSTATE_NVL, state.ap_rstate);
16637c478bd9Sstevel@tonic-gate 
16647c478bd9Sstevel@tonic-gate 	if (nvlist_add_int32(*nvlpp, IBNEX_NODE_OSTATE_NVL, state.ap_ostate)) {
16657c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
16667c478bd9Sstevel@tonic-gate 		    "failed to fill in %s", IBNEX_NODE_OSTATE_NVL);
16677c478bd9Sstevel@tonic-gate 		return (-1);
16687c478bd9Sstevel@tonic-gate 	}
16697c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: %s %d",
16707c478bd9Sstevel@tonic-gate 	    IBNEX_NODE_OSTATE_NVL, state.ap_ostate);
16717c478bd9Sstevel@tonic-gate 
16727c478bd9Sstevel@tonic-gate 	if (nvlist_add_int32(*nvlpp, IBNEX_NODE_COND_NVL, state.ap_condition)) {
16737c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "ibnex_fill_nodeinfo: "
16747c478bd9Sstevel@tonic-gate 		    "failed to fill in %s", IBNEX_NODE_COND_NVL);
16757c478bd9Sstevel@tonic-gate 		return (-1);
16767c478bd9Sstevel@tonic-gate 	}
16777c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibnex", "ibnex_fill_nodeinfo: %s %d",
16787c478bd9Sstevel@tonic-gate 	    IBNEX_NODE_COND_NVL, state.ap_condition);
16797c478bd9Sstevel@tonic-gate 
16807c478bd9Sstevel@tonic-gate 	return (0);
16817c478bd9Sstevel@tonic-gate }
16827c478bd9Sstevel@tonic-gate 
16837c478bd9Sstevel@tonic-gate 
16847c478bd9Sstevel@tonic-gate /*
16857c478bd9Sstevel@tonic-gate  * ibnex_figure_ap_devstate()
16867c478bd9Sstevel@tonic-gate  *	Fills the "devctl_ap_state_t" for a given ap_id
16877c478bd9Sstevel@tonic-gate  *
16887c478bd9Sstevel@tonic-gate  *	currently it assumes that we don't support "error_code" and
16897c478bd9Sstevel@tonic-gate  *	"last_change" value.
16907c478bd9Sstevel@tonic-gate  */
16917c478bd9Sstevel@tonic-gate static void
ibnex_figure_ap_devstate(ibnex_node_data_t * nodep,devctl_ap_state_t * ap_state)16921cfa752fSRamaswamy Tummala ibnex_figure_ap_devstate(ibnex_node_data_t *nodep, devctl_ap_state_t *ap_state)
16937c478bd9Sstevel@tonic-gate {
16941cfa752fSRamaswamy Tummala 	IBTF_DPRINTF_L5("ibnex", "ibnex_figure_ap_devstate: nodep = %p", nodep);
16957c478bd9Sstevel@tonic-gate 
16967c478bd9Sstevel@tonic-gate 	ap_state->ap_rstate = AP_RSTATE_CONNECTED;
16971cfa752fSRamaswamy Tummala 	if (nodep == NULL) {	/* for nodes not seen by IBNEX yet */
16987c478bd9Sstevel@tonic-gate 		ap_state->ap_ostate = AP_OSTATE_UNCONFIGURED;
16997c478bd9Sstevel@tonic-gate 		ap_state->ap_condition = AP_COND_UNKNOWN;
17007c478bd9Sstevel@tonic-gate 	} else {
17011cfa752fSRamaswamy Tummala 		/*
17021cfa752fSRamaswamy Tummala 		 * IBNEX_NODE_AP_UNCONFIGURED & IBNEX_NODE_AP_CONFIGURING.
17031cfa752fSRamaswamy Tummala 		 */
17041cfa752fSRamaswamy Tummala 		if (nodep->node_ap_state >= IBNEX_NODE_AP_UNCONFIGURED) {
17057c478bd9Sstevel@tonic-gate 			ap_state->ap_ostate = AP_OSTATE_UNCONFIGURED;
17067c478bd9Sstevel@tonic-gate 			ap_state->ap_condition = AP_COND_UNKNOWN;
17077c478bd9Sstevel@tonic-gate 		} else {
17087c478bd9Sstevel@tonic-gate 			ap_state->ap_ostate = AP_OSTATE_CONFIGURED;
17097c478bd9Sstevel@tonic-gate 			ap_state->ap_condition = AP_COND_OK;
17107c478bd9Sstevel@tonic-gate 		}
17117c478bd9Sstevel@tonic-gate 	}
17127c478bd9Sstevel@tonic-gate 	ap_state->ap_last_change = (time_t)-1;
17137c478bd9Sstevel@tonic-gate 	ap_state->ap_error_code = 0;
17147c478bd9Sstevel@tonic-gate 	ap_state->ap_in_transition = 0;
17157c478bd9Sstevel@tonic-gate }
17167c478bd9Sstevel@tonic-gate 
17177c478bd9Sstevel@tonic-gate 
17187c478bd9Sstevel@tonic-gate /*
17197c478bd9Sstevel@tonic-gate  * ibnex_figure_ib_apid_devstate()
17207c478bd9Sstevel@tonic-gate  *	Fills the "devctl_ap_state_t" for a IB static ap_id
17217c478bd9Sstevel@tonic-gate  */
17227c478bd9Sstevel@tonic-gate static void
ibnex_figure_ib_apid_devstate(devctl_ap_state_t * ap_state)17237c478bd9Sstevel@tonic-gate ibnex_figure_ib_apid_devstate(devctl_ap_state_t *ap_state)
17247c478bd9Sstevel@tonic-gate {
17257c478bd9Sstevel@tonic-gate 	ap_state->ap_rstate = AP_RSTATE_CONNECTED;
17267c478bd9Sstevel@tonic-gate 	ap_state->ap_condition = AP_COND_OK;
17277c478bd9Sstevel@tonic-gate 	ap_state->ap_ostate = (ibt_get_hca_list(NULL) == 0) ?
17287c478bd9Sstevel@tonic-gate 	    AP_OSTATE_UNCONFIGURED : AP_OSTATE_CONFIGURED;
17297c478bd9Sstevel@tonic-gate 	ap_state->ap_last_change = (time_t)-1;
17307c478bd9Sstevel@tonic-gate 	ap_state->ap_error_code = 0;
17317c478bd9Sstevel@tonic-gate 	ap_state->ap_in_transition = 0;
17327c478bd9Sstevel@tonic-gate }
17337c478bd9Sstevel@tonic-gate 
17347c478bd9Sstevel@tonic-gate 
17357c478bd9Sstevel@tonic-gate /*
17367c478bd9Sstevel@tonic-gate  * ibnex_get_apid()
17377c478bd9Sstevel@tonic-gate  *	Reads in the ap_id passed as an nvlist_string from user-land
17387c478bd9Sstevel@tonic-gate  */
17397c478bd9Sstevel@tonic-gate static char *
ibnex_get_apid(struct devctl_iocdata * dcp)17407c478bd9Sstevel@tonic-gate ibnex_get_apid(struct devctl_iocdata *dcp)
17417c478bd9Sstevel@tonic-gate {
17427c478bd9Sstevel@tonic-gate 	char *ap_id;
17437c478bd9Sstevel@tonic-gate 
17447c478bd9Sstevel@tonic-gate 	ASSERT(mutex_owned(&ibnex.ibnex_mutex));
17457c478bd9Sstevel@tonic-gate 
17467c478bd9Sstevel@tonic-gate 	/* Get which ap_id to operate on.  */
17477c478bd9Sstevel@tonic-gate 	if (nvlist_lookup_string(ndi_dc_get_ap_data(dcp), "apid",
17487c478bd9Sstevel@tonic-gate 	    &ap_id) != 0) {
17497c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "ibnex_get_apid: ap_id lookup failed");
17507c478bd9Sstevel@tonic-gate 		ap_id = NULL;
17517c478bd9Sstevel@tonic-gate 	}
17527c478bd9Sstevel@tonic-gate 
17537c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "ibnex_get_apid: ap_id=%s", ap_id);
17547c478bd9Sstevel@tonic-gate 	return (ap_id);
17557c478bd9Sstevel@tonic-gate }
17567c478bd9Sstevel@tonic-gate 
17577c478bd9Sstevel@tonic-gate 
17587c478bd9Sstevel@tonic-gate /*
17597c478bd9Sstevel@tonic-gate  * ibnex_get_dip_from_apid()
17607c478bd9Sstevel@tonic-gate  *	Figures out the dip/node_data from an ap_id given that this ap_id
17617c478bd9Sstevel@tonic-gate  *	exists as a "name" in the "ibnex" list
17627c478bd9Sstevel@tonic-gate  *
17637c478bd9Sstevel@tonic-gate  * NOTE: ap_id was on stack earlier and gets manipulated here. Since this
17647c478bd9Sstevel@tonic-gate  * function may be called twice; it is better to make a local copy of
17657c478bd9Sstevel@tonic-gate  * ap_id; if the ap_id were to be reused.
17667c478bd9Sstevel@tonic-gate  */
17677c478bd9Sstevel@tonic-gate static int
ibnex_get_dip_from_apid(char * apid,dev_info_t ** ret_dip,ibnex_node_data_t ** ret_node_datap)17687c478bd9Sstevel@tonic-gate ibnex_get_dip_from_apid(char *apid, dev_info_t **ret_dip,
17697c478bd9Sstevel@tonic-gate     ibnex_node_data_t **ret_node_datap)
17707c478bd9Sstevel@tonic-gate {
17717c478bd9Sstevel@tonic-gate 	int			rv, ret;
17727c478bd9Sstevel@tonic-gate 	int			index;
17737c478bd9Sstevel@tonic-gate 	int			len = strlen((char *)apid) + 1;
17747c478bd9Sstevel@tonic-gate 	char			*dyn;
17757c478bd9Sstevel@tonic-gate 	char			*ap_id;
17767c478bd9Sstevel@tonic-gate 	char			*first;
17777c478bd9Sstevel@tonic-gate 	char			*second = NULL;
17787c478bd9Sstevel@tonic-gate 	char			*node_addr;
17797c478bd9Sstevel@tonic-gate 	char			name[100];
17807c478bd9Sstevel@tonic-gate 	ibnex_node_data_t	*nodep = NULL;
17817c478bd9Sstevel@tonic-gate 
17827c478bd9Sstevel@tonic-gate 	ap_id = i_ddi_strdup(apid, KM_SLEEP);
17837c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tibnex_get_dip_from_apid: %s", ap_id);
17847c478bd9Sstevel@tonic-gate 	ASSERT(mutex_owned(&ibnex.ibnex_mutex));
17857c478bd9Sstevel@tonic-gate 
17867c478bd9Sstevel@tonic-gate 	if ((dyn = GET_DYN(ap_id)) != NULL) {
17877c478bd9Sstevel@tonic-gate 		rv = IBNEX_DYN_APID;
17887c478bd9Sstevel@tonic-gate 	} else {	/* either static, hca or unknown */
17897c478bd9Sstevel@tonic-gate 		*ret_dip = NULL;
17907c478bd9Sstevel@tonic-gate 		if (strstr(ap_id, "hca") != 0) {
17917c478bd9Sstevel@tonic-gate 			rv = IBNEX_HCA_APID;
17927c478bd9Sstevel@tonic-gate 		} else if (strstr(ap_id, IBNEX_FABRIC) != 0) {
17937c478bd9Sstevel@tonic-gate 			rv = IBNEX_BASE_APID;
17947c478bd9Sstevel@tonic-gate 		} else {
17957c478bd9Sstevel@tonic-gate 			rv = IBNEX_UNKNOWN_APID;
17967c478bd9Sstevel@tonic-gate 		}
17977c478bd9Sstevel@tonic-gate 		kmem_free(ap_id, len);
17987c478bd9Sstevel@tonic-gate 		return (rv);
17997c478bd9Sstevel@tonic-gate 	}
18007c478bd9Sstevel@tonic-gate 
18017c478bd9Sstevel@tonic-gate 	dyn += strlen(DYN_SEP);
18027c478bd9Sstevel@tonic-gate 	if (*dyn == '\0') {
18037c478bd9Sstevel@tonic-gate 		*ret_dip = NULL;
18047c478bd9Sstevel@tonic-gate 		kmem_free(ap_id, len);
18057c478bd9Sstevel@tonic-gate 		return (IBNEX_UNKNOWN_APID);
18067c478bd9Sstevel@tonic-gate 	}
18077c478bd9Sstevel@tonic-gate 
18087c478bd9Sstevel@tonic-gate 	/* APID */
18097c478bd9Sstevel@tonic-gate 	first = strchr(dyn, ',');
18107c478bd9Sstevel@tonic-gate 	if (first != NULL)
18117c478bd9Sstevel@tonic-gate 		second = strchr(first+1, ',');
18127c478bd9Sstevel@tonic-gate 
18137c478bd9Sstevel@tonic-gate 	/* Implies Port or VPPA or HCA_SVC Driver ap_id */
18147c478bd9Sstevel@tonic-gate 	if (first != NULL && second != NULL) {
18157c478bd9Sstevel@tonic-gate 		int	str_len;
18167c478bd9Sstevel@tonic-gate 		int	pkey_val = 0;
18177c478bd9Sstevel@tonic-gate 		char	*pkey_str = strchr(ap_id, ',');
18187c478bd9Sstevel@tonic-gate 		char	*svc_str = strrchr(pkey_str, ',');
18197c478bd9Sstevel@tonic-gate 
18207c478bd9Sstevel@tonic-gate 		/* dyn contains ,GUID,p_key,svc_name. Change it to GUID */
18217c478bd9Sstevel@tonic-gate 		str_len = strlen(dyn) - strlen(pkey_str);
18227c478bd9Sstevel@tonic-gate 		dyn[str_len] = '\0';
18237c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "\tibnex_get_dip_from_apid: "
18247c478bd9Sstevel@tonic-gate 		    "Port / Node Guid %s", dyn);
18257c478bd9Sstevel@tonic-gate 
18267c478bd9Sstevel@tonic-gate 		/* figure out comm or vppa. figure out pkey  */
18277c478bd9Sstevel@tonic-gate 		++pkey_str; /* pkey_str used to point to ",p_key,svc_name" */
18287c478bd9Sstevel@tonic-gate 
18297c478bd9Sstevel@tonic-gate 		/* pkey_str contains p_key,svc_name. Change it to p_key */
18307c478bd9Sstevel@tonic-gate 		str_len = strlen(pkey_str) - strlen(svc_str);
18317c478bd9Sstevel@tonic-gate 		pkey_str[str_len] = '\0';
18327c478bd9Sstevel@tonic-gate 
18337c478bd9Sstevel@tonic-gate 		/* convert the string P_KEY to hex value */
18347c478bd9Sstevel@tonic-gate 		pkey_val = ibnex_str2hex(pkey_str, strlen(pkey_str), &ret);
18357c478bd9Sstevel@tonic-gate 		if (ret != IBNEX_SUCCESS) {
18367c478bd9Sstevel@tonic-gate 			*ret_dip = NULL;
18377c478bd9Sstevel@tonic-gate 			kmem_free(ap_id, len);
18387c478bd9Sstevel@tonic-gate 			return (IBNEX_UNKNOWN_APID);
18397c478bd9Sstevel@tonic-gate 		}
18407c478bd9Sstevel@tonic-gate 
18417c478bd9Sstevel@tonic-gate 		++svc_str;	/* svc_str used to point to ",svc_name" */
18427c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibnex", "\tibnex_get_dip_from_apid: pkey %s"
18437c478bd9Sstevel@tonic-gate 		    ":%x service name = %s", pkey_str, pkey_val, svc_str);
18447c478bd9Sstevel@tonic-gate 
18457c478bd9Sstevel@tonic-gate 		for (nodep = ibnex.ibnex_port_node_head;
18467c478bd9Sstevel@tonic-gate 		    nodep != NULL; nodep = nodep->node_next) {
18477c478bd9Sstevel@tonic-gate 			index = nodep->node_data.port_node.port_commsvc_idx;
18487c478bd9Sstevel@tonic-gate 			IBNEX_FORM_GUID(name, IBTL_IBNEX_APID_LEN,
18497c478bd9Sstevel@tonic-gate 			    nodep->node_data.port_node.port_guid);
18507c478bd9Sstevel@tonic-gate 
18517c478bd9Sstevel@tonic-gate 			/*
18527c478bd9Sstevel@tonic-gate 			 * Match P_Key, name string & service string:
18537c478bd9Sstevel@tonic-gate 			 * For COMM / HCA_SVC services these should be true:
18547c478bd9Sstevel@tonic-gate 			 *	P_Key matches to 0, svc_str in comm_svc_names[]
18557c478bd9Sstevel@tonic-gate 			 *	and name matches the dynamic part of the ap_id
18567c478bd9Sstevel@tonic-gate 			 * For VPPA services this should be true:
18577c478bd9Sstevel@tonic-gate 			 *	P_Key != 0 & matches, svc_str in
18587c478bd9Sstevel@tonic-gate 			 *	vppa_comm_svc_names[] and the name matches the
18597c478bd9Sstevel@tonic-gate 			 *	dynamic part of the ap_id.
18607c478bd9Sstevel@tonic-gate 			 */
18617c478bd9Sstevel@tonic-gate 			if ((pkey_val == nodep->node_data.port_node.
18627c478bd9Sstevel@tonic-gate 			    port_pkey) && (strstr(dyn, name) != NULL)) {
18637c478bd9Sstevel@tonic-gate 
18647c478bd9Sstevel@tonic-gate 				/* pkey != 0, COMM / HCA_SVC service */
18657c478bd9Sstevel@tonic-gate 				if (((pkey_val == 0) && (
18667c478bd9Sstevel@tonic-gate 					/* Port Service */
18677c478bd9Sstevel@tonic-gate 				    ((ibnex.ibnex_comm_svc_names != NULL) &&
18687c478bd9Sstevel@tonic-gate 				    (index < ibnex.ibnex_num_comm_svcs) &&
18697c478bd9Sstevel@tonic-gate 				    (strstr(svc_str, ibnex.
18707c478bd9Sstevel@tonic-gate 				    ibnex_comm_svc_names[index]) != NULL)) ||
18717c478bd9Sstevel@tonic-gate 					/* HCA_SVC service */
18727c478bd9Sstevel@tonic-gate 				    ((ibnex.ibnex_hcasvc_comm_svc_names !=
18737c478bd9Sstevel@tonic-gate 				    NULL) && (index <
18747c478bd9Sstevel@tonic-gate 				    ibnex.ibnex_nhcasvc_comm_svcs) &&
18757c478bd9Sstevel@tonic-gate 				    (strstr(svc_str, ibnex.
18767c478bd9Sstevel@tonic-gate 				    ibnex_hcasvc_comm_svc_names[index])
187700a3eaf3SRamaswamy Tummala 				    != NULL)))) ||
18787c478bd9Sstevel@tonic-gate 					/* next the VPPA strings */
18797c478bd9Sstevel@tonic-gate 				    ((pkey_val != 0) && (strstr(svc_str, ibnex.
18807c478bd9Sstevel@tonic-gate 				    ibnex_vppa_comm_svc_names[index]) !=
18817c478bd9Sstevel@tonic-gate 				    NULL))) {
18827c478bd9Sstevel@tonic-gate 					if (nodep->node_dip)
18837c478bd9Sstevel@tonic-gate 						ndi_hold_devi(nodep->node_dip);
18847c478bd9Sstevel@tonic-gate 					*ret_node_datap = nodep;
18857c478bd9Sstevel@tonic-gate 					*ret_dip = nodep->node_dip;
18867c478bd9Sstevel@tonic-gate 					kmem_free(ap_id, len);
18877c478bd9Sstevel@tonic-gate 					return (rv);
18887c478bd9Sstevel@tonic-gate 				}
18897c478bd9Sstevel@tonic-gate 			}
18907c478bd9Sstevel@tonic-gate 
18917c478bd9Sstevel@tonic-gate 		} /* end of for */
18927c478bd9Sstevel@tonic-gate 
18937c478bd9Sstevel@tonic-gate 	} else if (first != NULL && second == NULL) {
18947c478bd9Sstevel@tonic-gate 		/* pseudo ap_id */
18957c478bd9Sstevel@tonic-gate 		for (nodep = ibnex.ibnex_pseudo_node_head; nodep;
18967c478bd9Sstevel@tonic-gate 		    nodep = nodep->node_next) {
18979d3d2ed0Shiremath 			if (nodep->node_data.pseudo_node.pseudo_merge_node
18989d3d2ed0Shiremath 			    == 1)
18999d3d2ed0Shiremath 				continue;
19007c478bd9Sstevel@tonic-gate 			node_addr = nodep->node_data.pseudo_node.
19017c478bd9Sstevel@tonic-gate 			    pseudo_node_addr;
19027c478bd9Sstevel@tonic-gate 			if (strncmp(dyn, node_addr, strlen(node_addr)) == 0) {
19037c478bd9Sstevel@tonic-gate 				if (nodep->node_dip)
19047c478bd9Sstevel@tonic-gate 					ndi_hold_devi(nodep->node_dip);
19057c478bd9Sstevel@tonic-gate 				*ret_node_datap = nodep;
19067c478bd9Sstevel@tonic-gate 				*ret_dip = nodep->node_dip;
19077c478bd9Sstevel@tonic-gate 				kmem_free(ap_id, len);
19087c478bd9Sstevel@tonic-gate 				return (rv);
19097c478bd9Sstevel@tonic-gate 			}
19107c478bd9Sstevel@tonic-gate 		}
19117c478bd9Sstevel@tonic-gate 
19127c478bd9Sstevel@tonic-gate 	} else if (first == NULL && second == NULL) {
19137c478bd9Sstevel@tonic-gate 		/* This is an IOC ap_id */
19147c478bd9Sstevel@tonic-gate 		for (nodep = ibnex.ibnex_ioc_node_head; nodep != NULL;
19157c478bd9Sstevel@tonic-gate 		    nodep = nodep->node_next) {
19167c478bd9Sstevel@tonic-gate 			IBNEX_FORM_GUID(name, IBTL_IBNEX_APID_LEN,
19177c478bd9Sstevel@tonic-gate 			    nodep->node_data.ioc_node.ioc_guid);
19187c478bd9Sstevel@tonic-gate 			if (strstr(dyn, name) != NULL) {
19197c478bd9Sstevel@tonic-gate 				if (nodep->node_dip)
19207c478bd9Sstevel@tonic-gate 					ndi_hold_devi(nodep->node_dip);
19217c478bd9Sstevel@tonic-gate 				*ret_node_datap = nodep;
19227c478bd9Sstevel@tonic-gate 				*ret_dip = nodep->node_dip;
19237c478bd9Sstevel@tonic-gate 				kmem_free(ap_id, len);
19247c478bd9Sstevel@tonic-gate 				return (rv);
19257c478bd9Sstevel@tonic-gate 			}
19267c478bd9Sstevel@tonic-gate 		}
19277c478bd9Sstevel@tonic-gate 	}
19287c478bd9Sstevel@tonic-gate 
19297c478bd9Sstevel@tonic-gate 	/* Could not find a matching IB device */
19307c478bd9Sstevel@tonic-gate 	*ret_dip = (nodep) ? nodep->node_dip : NULL;
19317c478bd9Sstevel@tonic-gate 	kmem_free(ap_id, len);
19327c478bd9Sstevel@tonic-gate 	return (rv);
19337c478bd9Sstevel@tonic-gate }
19347c478bd9Sstevel@tonic-gate 
19357c478bd9Sstevel@tonic-gate 
19367c478bd9Sstevel@tonic-gate /*
19377c478bd9Sstevel@tonic-gate  * ibnex_handle_pseudo_configure()
19387c478bd9Sstevel@tonic-gate  *	Do DEVCTL_AP_CONNECT processing for Pseudo devices only.
19397c478bd9Sstevel@tonic-gate  *	The code also checks if the given ap_id is valid or not.
19407c478bd9Sstevel@tonic-gate  */
19417c478bd9Sstevel@tonic-gate static ibnex_rval_t
ibnex_handle_pseudo_configure(char * apid)19427c478bd9Sstevel@tonic-gate ibnex_handle_pseudo_configure(char *apid)
19437c478bd9Sstevel@tonic-gate {
19447c478bd9Sstevel@tonic-gate 	char			*node_addr;
19457c478bd9Sstevel@tonic-gate 	char			*last = strrchr(apid, ':') + 1;
19467c478bd9Sstevel@tonic-gate 	ibnex_rval_t		retval = IBNEX_FAILURE;
19477c478bd9Sstevel@tonic-gate 	ibnex_node_data_t	*nodep;
19487c478bd9Sstevel@tonic-gate 
19497c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tibnex_handle_pseudo_configure: "
19507c478bd9Sstevel@tonic-gate 	    "last = %s\n\t\tapid = %s", last, apid);
19517c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
19527c478bd9Sstevel@tonic-gate 
19537c478bd9Sstevel@tonic-gate 	/* Check if the APID is valid first */
19547c478bd9Sstevel@tonic-gate 	if (apid == NULL || last == NULL) {
19557c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "\tibnex_handle_pseudo_configure: "
19567c478bd9Sstevel@tonic-gate 		    "invalid apid %s", apid);
19577c478bd9Sstevel@tonic-gate 		return (retval);
19587c478bd9Sstevel@tonic-gate 	}
19597c478bd9Sstevel@tonic-gate 
19607c478bd9Sstevel@tonic-gate 	/* find the matching entry and configure it */
19617c478bd9Sstevel@tonic-gate 	for (nodep = ibnex.ibnex_pseudo_node_head; nodep != NULL;
19627c478bd9Sstevel@tonic-gate 	    nodep = nodep->node_next) {
19639d3d2ed0Shiremath 		if (nodep->node_data.pseudo_node.pseudo_merge_node == 1)
19649d3d2ed0Shiremath 			continue;
19657c478bd9Sstevel@tonic-gate 		node_addr = nodep->node_data.pseudo_node.pseudo_node_addr;
19667c478bd9Sstevel@tonic-gate 		if (strncmp(node_addr, last, strlen(last)))
19677c478bd9Sstevel@tonic-gate 			continue;
19687c478bd9Sstevel@tonic-gate 
19697c478bd9Sstevel@tonic-gate 		if (nodep->node_dip != NULL) {
19707c478bd9Sstevel@tonic-gate 			/*
19717c478bd9Sstevel@tonic-gate 			 * Return BUSY if another configure
19727c478bd9Sstevel@tonic-gate 			 * operation is in progress
19737c478bd9Sstevel@tonic-gate 			 */
19747c478bd9Sstevel@tonic-gate 			if (nodep->node_state ==
19757c478bd9Sstevel@tonic-gate 			    IBNEX_CFGADM_CONFIGURING)
19767c478bd9Sstevel@tonic-gate 				return (IBNEX_BUSY);
19777c478bd9Sstevel@tonic-gate 			else
19787c478bd9Sstevel@tonic-gate 				return (IBNEX_SUCCESS);
19797c478bd9Sstevel@tonic-gate 		}
19807c478bd9Sstevel@tonic-gate 
19817c478bd9Sstevel@tonic-gate 		/*
19827c478bd9Sstevel@tonic-gate 		 * Return BUSY if another unconfigure operation is
19837c478bd9Sstevel@tonic-gate 		 * in progress
19847c478bd9Sstevel@tonic-gate 		 */
19857c478bd9Sstevel@tonic-gate 		if (nodep->node_state == IBNEX_CFGADM_UNCONFIGURING)
19867c478bd9Sstevel@tonic-gate 			return (IBNEX_BUSY);
19877c478bd9Sstevel@tonic-gate 
19887c478bd9Sstevel@tonic-gate 		ASSERT(nodep->node_state != IBNEX_CFGADM_CONFIGURED);
19897c478bd9Sstevel@tonic-gate 		nodep->node_state = IBNEX_CFGADM_CONFIGURING;
19907c478bd9Sstevel@tonic-gate 
19917c478bd9Sstevel@tonic-gate 		mutex_exit(&ibnex.ibnex_mutex);
199200a3eaf3SRamaswamy Tummala 		retval = ibnex_pseudo_create_all_pi(nodep);
19937c478bd9Sstevel@tonic-gate 		mutex_enter(&ibnex.ibnex_mutex);
19947c478bd9Sstevel@tonic-gate 		if (retval == NDI_SUCCESS) {
19957c478bd9Sstevel@tonic-gate 			nodep->node_state = IBNEX_CFGADM_CONFIGURED;
19967c478bd9Sstevel@tonic-gate 			return (IBNEX_SUCCESS);
19977c478bd9Sstevel@tonic-gate 		} else {
19987c478bd9Sstevel@tonic-gate 			nodep->node_state = IBNEX_CFGADM_UNCONFIGURED;
19997c478bd9Sstevel@tonic-gate 			return (IBNEX_FAILURE);
20007c478bd9Sstevel@tonic-gate 		}
20017c478bd9Sstevel@tonic-gate 	}
20027c478bd9Sstevel@tonic-gate 
20037c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\thandle_pseudo_configure: retval=%d",
20047c478bd9Sstevel@tonic-gate 	    retval);
20057c478bd9Sstevel@tonic-gate 	return (retval);
20067c478bd9Sstevel@tonic-gate }
20077c478bd9Sstevel@tonic-gate 
20087c478bd9Sstevel@tonic-gate 
20097c478bd9Sstevel@tonic-gate /*
20107c478bd9Sstevel@tonic-gate  * ibnex_handle_ioc_configure()
20117c478bd9Sstevel@tonic-gate  *	Do DEVCTL_AP_CONNECT processing for IOCs only.
20127c478bd9Sstevel@tonic-gate  *	The code also checks if the given ap_id is valid or not.
20137c478bd9Sstevel@tonic-gate  */
20147c478bd9Sstevel@tonic-gate static ibnex_rval_t
ibnex_handle_ioc_configure(char * apid)20157c478bd9Sstevel@tonic-gate ibnex_handle_ioc_configure(char *apid)
20167c478bd9Sstevel@tonic-gate {
20177c478bd9Sstevel@tonic-gate 	int			ret;
20187c478bd9Sstevel@tonic-gate 	char			*guid_str = strrchr(apid, ':') + 1;
20197c478bd9Sstevel@tonic-gate 	ib_guid_t		ioc_guid;
20207c478bd9Sstevel@tonic-gate 	ibnex_rval_t		retval = IBNEX_FAILURE;
20217c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t		*ioc_info;
20227c478bd9Sstevel@tonic-gate 
20237c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
20247c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tibnex_handle_ioc_configure: %s", apid);
20257c478bd9Sstevel@tonic-gate 
20267c478bd9Sstevel@tonic-gate 	/* Check if the APID is valid first */
20277c478bd9Sstevel@tonic-gate 	if (guid_str == NULL) {
20287c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex",
20297c478bd9Sstevel@tonic-gate 		    "\tibnex_handle_ioc_configure: invalid apid %s", apid);
20307c478bd9Sstevel@tonic-gate 		return (retval);
20317c478bd9Sstevel@tonic-gate 	}
20327c478bd9Sstevel@tonic-gate 
20337c478bd9Sstevel@tonic-gate 	/*
20347c478bd9Sstevel@tonic-gate 	 * Call into IBDM to get IOC information
20357c478bd9Sstevel@tonic-gate 	 */
20367c478bd9Sstevel@tonic-gate 	ioc_guid = ibnex_str2hex(guid_str, strlen(guid_str), &ret);
20377c478bd9Sstevel@tonic-gate 	if (ret != IBNEX_SUCCESS)
20387c478bd9Sstevel@tonic-gate 		return (ret);
20397c478bd9Sstevel@tonic-gate 
20407c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex",
20417c478bd9Sstevel@tonic-gate 	    "\tibnex_handle_ioc_configure: IOC GUID = %llX", ioc_guid);
20427c478bd9Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
20437c478bd9Sstevel@tonic-gate 	ioc_info = ibdm_ibnex_get_ioc_info(ioc_guid);
20447c478bd9Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
20457c478bd9Sstevel@tonic-gate 	if (ioc_info == NULL) {
20467c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex",
20477c478bd9Sstevel@tonic-gate 		    "\tibnex_handle_ioc_configure: probe_iocguid failed");
20487c478bd9Sstevel@tonic-gate 		return (retval);
20497c478bd9Sstevel@tonic-gate 	}
20507c478bd9Sstevel@tonic-gate 
205100a3eaf3SRamaswamy Tummala 	retval = ibnex_ioc_initnode_all_pi(ioc_info);
20527c478bd9Sstevel@tonic-gate 	ibdm_ibnex_free_ioc_list(ioc_info);
20537c478bd9Sstevel@tonic-gate 
20547c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tibnex_handle_ioc_configure: "
20557c478bd9Sstevel@tonic-gate 	    "done retval = %d", retval);
20567c478bd9Sstevel@tonic-gate 	return (retval);
20577c478bd9Sstevel@tonic-gate }
20587c478bd9Sstevel@tonic-gate 
20597c478bd9Sstevel@tonic-gate 
20607c478bd9Sstevel@tonic-gate /*
20617c478bd9Sstevel@tonic-gate  * ibnex_handle_commsvcnode_configure()
20627c478bd9Sstevel@tonic-gate  *	Do DEVCTL_AP_CONNECT processing
20637c478bd9Sstevel@tonic-gate  *	This is done for Port/VPPA/HCA_SVC drivers Only.
20647c478bd9Sstevel@tonic-gate  *	The code also checks if the given ap_id is valid or not.
20657c478bd9Sstevel@tonic-gate  */
20667c478bd9Sstevel@tonic-gate static ibnex_rval_t
ibnex_handle_commsvcnode_configure(char * apid)20677c478bd9Sstevel@tonic-gate ibnex_handle_commsvcnode_configure(char *apid)
20687c478bd9Sstevel@tonic-gate {
2069*3fe80ca4SDan Cross 	int			ret, str_len;
20707c478bd9Sstevel@tonic-gate 	int			sndx;
20717c478bd9Sstevel@tonic-gate 	int			port_pkey = 0;
20727c478bd9Sstevel@tonic-gate 	char			*pkey_str = strchr(apid, ',');
20737c478bd9Sstevel@tonic-gate 	char			*guid_str = strrchr(apid, ':') + 1;
20747c478bd9Sstevel@tonic-gate 	char			*svc_str = strrchr(pkey_str, ',');
20757c478bd9Sstevel@tonic-gate 	boolean_t		found = B_FALSE;
20767c478bd9Sstevel@tonic-gate 	boolean_t		is_hcasvc_node = B_FALSE;
20777c478bd9Sstevel@tonic-gate 	ib_guid_t		guid;	/* Port / Node GUID */
20787c478bd9Sstevel@tonic-gate 	dev_info_t		*parent;
20797c478bd9Sstevel@tonic-gate 	ibnex_rval_t		retval = IBNEX_FAILURE;
20807c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t	*port_attr;
20817c478bd9Sstevel@tonic-gate 	int			node_type;
20827c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*hca_list;
20837c478bd9Sstevel@tonic-gate 
20847c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
20857c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tibnex_handle_commsvcnode_configure: %s",
20867c478bd9Sstevel@tonic-gate 	    apid);
20877c478bd9Sstevel@tonic-gate 
20887c478bd9Sstevel@tonic-gate 	/* Check if the APID is valid first */
20897c478bd9Sstevel@tonic-gate 	if (guid_str == NULL || ((guid_str != NULL) &&
20907c478bd9Sstevel@tonic-gate 	    (pkey_str == NULL || svc_str == NULL))) {
20917c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex",
20927c478bd9Sstevel@tonic-gate 		    "\tibnex_handle_commsvcnode_configure: "
20937c478bd9Sstevel@tonic-gate 		    "invalid apid %s", apid);
20947c478bd9Sstevel@tonic-gate 		return (retval);
20957c478bd9Sstevel@tonic-gate 	}
20967c478bd9Sstevel@tonic-gate 
20977c478bd9Sstevel@tonic-gate 	/* guid_str contains GUID,p_key,svc_name. Change it to GUID */
20987c478bd9Sstevel@tonic-gate 	str_len = strlen(guid_str) - strlen(pkey_str);
20997c478bd9Sstevel@tonic-gate 	guid_str[str_len] = '\0';
21007c478bd9Sstevel@tonic-gate 
21017c478bd9Sstevel@tonic-gate 	/* convert the string GUID to hex value */
21027c478bd9Sstevel@tonic-gate 	guid = ibnex_str2hex(guid_str, strlen(guid_str), &ret);
21037c478bd9Sstevel@tonic-gate 	if (ret == IBNEX_FAILURE)
21047c478bd9Sstevel@tonic-gate 		return (ret);
21057c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tibnex_handle_commsvcnode_configure: "
21067c478bd9Sstevel@tonic-gate 	    "Port / Node Guid %llX", guid);
21077c478bd9Sstevel@tonic-gate 
21087c478bd9Sstevel@tonic-gate 	/* figure out Port/HCA_SVC or VPPA. Also figure out the P_Key.  */
21097c478bd9Sstevel@tonic-gate 	++pkey_str;	/* pkey_str used to point to ",p_key,svc_name" */
21107c478bd9Sstevel@tonic-gate 
21117c478bd9Sstevel@tonic-gate 	/* pkey_str contains p_key,svc_name. Change it to P_Key */
21127c478bd9Sstevel@tonic-gate 	str_len = strlen(pkey_str) - strlen(svc_str);
21137c478bd9Sstevel@tonic-gate 	pkey_str[str_len] = '\0';
21147c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibnex", "\tibnex_handle_commsvcnode_configure: "
21157c478bd9Sstevel@tonic-gate 	    "p_key %s", pkey_str);
21167c478bd9Sstevel@tonic-gate 
21177c478bd9Sstevel@tonic-gate 	/* convert the string P_Key to a hexadecimal value */
21187c478bd9Sstevel@tonic-gate 	port_pkey = ibnex_str2hex(pkey_str, strlen(pkey_str), &ret);
21197c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibnex", "\tibnex_handle_commsvcnode_configure: "
21207c478bd9Sstevel@tonic-gate 	    "PKEY num %x", port_pkey);
21217c478bd9Sstevel@tonic-gate 	if (ret == IBNEX_FAILURE)
21227c478bd9Sstevel@tonic-gate 		return (ret);
21237c478bd9Sstevel@tonic-gate 
21247c478bd9Sstevel@tonic-gate 	++svc_str;	/* svc_str used to point to ",svc_name" */
21257c478bd9Sstevel@tonic-gate 
21267c478bd9Sstevel@tonic-gate 	/* find the service index */
21277c478bd9Sstevel@tonic-gate 	if (port_pkey == 0) {
21287c478bd9Sstevel@tonic-gate 		/* PORT Devices */
21297c478bd9Sstevel@tonic-gate 		for (sndx = 0; sndx < ibnex.ibnex_num_comm_svcs; sndx++) {
21307c478bd9Sstevel@tonic-gate 			if (strncmp(ibnex.ibnex_comm_svc_names[sndx],
21317c478bd9Sstevel@tonic-gate 			    svc_str, strlen(svc_str)) == 0) {
21327c478bd9Sstevel@tonic-gate 				found = B_TRUE;
21337c478bd9Sstevel@tonic-gate 				break;
21347c478bd9Sstevel@tonic-gate 			}
21357c478bd9Sstevel@tonic-gate 		}
21367c478bd9Sstevel@tonic-gate 
21377c478bd9Sstevel@tonic-gate 		/* HCA_SVC Devices */
21387c478bd9Sstevel@tonic-gate 		if (found == B_FALSE) {
21397c478bd9Sstevel@tonic-gate 			for (sndx = 0; sndx < ibnex.ibnex_nhcasvc_comm_svcs;
21407c478bd9Sstevel@tonic-gate 			    sndx++) {
21417c478bd9Sstevel@tonic-gate 				if (strncmp(ibnex.ibnex_hcasvc_comm_svc_names
21427c478bd9Sstevel@tonic-gate 				    [sndx], svc_str, strlen(svc_str)) == 0) {
21437c478bd9Sstevel@tonic-gate 					found = B_TRUE;
21447c478bd9Sstevel@tonic-gate 					is_hcasvc_node = B_TRUE;
21457c478bd9Sstevel@tonic-gate 					break;
21467c478bd9Sstevel@tonic-gate 				}
21477c478bd9Sstevel@tonic-gate 			}
21487c478bd9Sstevel@tonic-gate 		}
21497c478bd9Sstevel@tonic-gate 
21507c478bd9Sstevel@tonic-gate 	} else {
21517c478bd9Sstevel@tonic-gate 		for (sndx = 0; sndx < ibnex.ibnex_nvppa_comm_svcs; sndx++) {
21527c478bd9Sstevel@tonic-gate 			if (strncmp(ibnex.ibnex_vppa_comm_svc_names[sndx],
21537c478bd9Sstevel@tonic-gate 			    svc_str, strlen(svc_str)) == 0) {
21547c478bd9Sstevel@tonic-gate 				found = B_TRUE;
21557c478bd9Sstevel@tonic-gate 				break;
21567c478bd9Sstevel@tonic-gate 			}
21577c478bd9Sstevel@tonic-gate 		}
21587c478bd9Sstevel@tonic-gate 	}
21597c478bd9Sstevel@tonic-gate 
21607c478bd9Sstevel@tonic-gate 	if (found == B_FALSE) {
21617c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex",
21627c478bd9Sstevel@tonic-gate 		    "\tibnex_handle_commsvcnode_configure: "
21637c478bd9Sstevel@tonic-gate 		    "invalid service %s", svc_str);
21647c478bd9Sstevel@tonic-gate 		return (retval);
21657c478bd9Sstevel@tonic-gate 	}
21667c478bd9Sstevel@tonic-gate 
21677c478bd9Sstevel@tonic-gate 	/* get Port attributes structure */
21687c478bd9Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
21697c478bd9Sstevel@tonic-gate 	if (is_hcasvc_node == B_FALSE) {
21707c478bd9Sstevel@tonic-gate 		port_attr = ibdm_ibnex_get_port_attrs(guid);
21717c478bd9Sstevel@tonic-gate 		if (port_attr == NULL) {
21727c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
21737c478bd9Sstevel@tonic-gate 			    "\tibnex_handle_commsvcnode_configure: "
21747c478bd9Sstevel@tonic-gate 			    "ibdm_ibnex_get_port_attrs failed");
21757c478bd9Sstevel@tonic-gate 			mutex_enter(&ibnex.ibnex_mutex);
21767c478bd9Sstevel@tonic-gate 			return (retval);
21777c478bd9Sstevel@tonic-gate 		}
21787c478bd9Sstevel@tonic-gate 	} else {
21797c478bd9Sstevel@tonic-gate 		hca_list = ibdm_ibnex_get_hca_info_by_guid(guid);
21807c478bd9Sstevel@tonic-gate 		if (hca_list == NULL) {
21817c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex",
21827c478bd9Sstevel@tonic-gate 			    "\tibnex_handle_commsvcnode_configure: "
21837c478bd9Sstevel@tonic-gate 			    "ibdm_ibnex_get_hca_info_by_guid failed");
21847c478bd9Sstevel@tonic-gate 			mutex_enter(&ibnex.ibnex_mutex);
21857c478bd9Sstevel@tonic-gate 			return (retval);
21867c478bd9Sstevel@tonic-gate 		}
21877c478bd9Sstevel@tonic-gate 		port_attr = hca_list->hl_hca_port_attr;
21887c478bd9Sstevel@tonic-gate 	}
21897c478bd9Sstevel@tonic-gate 
21907c478bd9Sstevel@tonic-gate 	/* get HCA's dip */
21917c478bd9Sstevel@tonic-gate 	parent = ibtl_ibnex_hcaguid2dip(port_attr->pa_hca_guid);
21927c478bd9Sstevel@tonic-gate 
21937c478bd9Sstevel@tonic-gate 	if (parent == NULL) {
21947c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex",
21957c478bd9Sstevel@tonic-gate 		    "\tibnex_handle_commsvcnode_configure: "
21967c478bd9Sstevel@tonic-gate 		    "no HCA present");
21977c478bd9Sstevel@tonic-gate 		mutex_enter(&ibnex.ibnex_mutex);
21987c478bd9Sstevel@tonic-gate 		if (is_hcasvc_node == B_FALSE)
21997c478bd9Sstevel@tonic-gate 			ibdm_ibnex_free_port_attr(port_attr);
22007c478bd9Sstevel@tonic-gate 		else
22017c478bd9Sstevel@tonic-gate 			ibdm_ibnex_free_hca_list(hca_list);
22027c478bd9Sstevel@tonic-gate 		return (retval);
22037c478bd9Sstevel@tonic-gate 	}
22047c478bd9Sstevel@tonic-gate 
22057c478bd9Sstevel@tonic-gate 	if (port_pkey == 0)
22067c478bd9Sstevel@tonic-gate 		node_type = (is_hcasvc_node == B_FALSE) ?
22077c478bd9Sstevel@tonic-gate 		    IBNEX_PORT_COMMSVC_NODE : IBNEX_HCASVC_COMMSVC_NODE;
22087c478bd9Sstevel@tonic-gate 	else
22097c478bd9Sstevel@tonic-gate 		node_type = IBNEX_VPPA_COMMSVC_NODE;
22107c478bd9Sstevel@tonic-gate 
22117c478bd9Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
2212*3fe80ca4SDan Cross 	ndi_devi_enter(parent);
22137c478bd9Sstevel@tonic-gate 	if (ibnex_commsvc_initnode(parent, port_attr, sndx, node_type,
22147c478bd9Sstevel@tonic-gate 	    port_pkey, &ret, IBNEX_CFGADM_ENUMERATE) != NULL) {
22157c478bd9Sstevel@tonic-gate 		retval = IBNEX_SUCCESS;
22167c478bd9Sstevel@tonic-gate 	} else {
22177c478bd9Sstevel@tonic-gate 		retval = (ret == IBNEX_BUSY) ? IBNEX_BUSY : IBNEX_FAILURE;
22187c478bd9Sstevel@tonic-gate 	}
2219*3fe80ca4SDan Cross 	ndi_devi_exit(parent);
22207c478bd9Sstevel@tonic-gate 
22217c478bd9Sstevel@tonic-gate 	if (is_hcasvc_node == B_FALSE)
22227c478bd9Sstevel@tonic-gate 		ibdm_ibnex_free_port_attr(port_attr);
22237c478bd9Sstevel@tonic-gate 	else
22247c478bd9Sstevel@tonic-gate 		ibdm_ibnex_free_hca_list(hca_list);
22257c478bd9Sstevel@tonic-gate 
22267c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tibnex_handle_commsvcnode_configure: "
22277c478bd9Sstevel@tonic-gate 	    "done retval = %d", retval);
22287c478bd9Sstevel@tonic-gate 
22297c478bd9Sstevel@tonic-gate 	return (retval);
22307c478bd9Sstevel@tonic-gate }
22317c478bd9Sstevel@tonic-gate 
22327c478bd9Sstevel@tonic-gate 
22337c478bd9Sstevel@tonic-gate /*
22347c478bd9Sstevel@tonic-gate  * ibnex_return_apid()
22357c478bd9Sstevel@tonic-gate  *	Construct the ap_id of a given IBTF client in kernel
22367c478bd9Sstevel@tonic-gate  */
22377c478bd9Sstevel@tonic-gate static void
ibnex_return_apid(dev_info_t * childp,char ** ret_apid)22387c478bd9Sstevel@tonic-gate ibnex_return_apid(dev_info_t *childp, char **ret_apid)
22397c478bd9Sstevel@tonic-gate {
22407c478bd9Sstevel@tonic-gate 	ibnex_node_data_t	*nodep;
22417c478bd9Sstevel@tonic-gate 
22427c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "ibnex_return_apid:");
22437c478bd9Sstevel@tonic-gate 
22447c478bd9Sstevel@tonic-gate 	ASSERT(childp != NULL);
22457c478bd9Sstevel@tonic-gate 	nodep = ddi_get_parent_data(childp);
22467c478bd9Sstevel@tonic-gate 
22477c478bd9Sstevel@tonic-gate 	if (nodep->node_type == IBNEX_PORT_COMMSVC_NODE) {
22487c478bd9Sstevel@tonic-gate 		(void) snprintf(*ret_apid, IBTL_IBNEX_APID_LEN,
22497c478bd9Sstevel@tonic-gate 		    "ib%s%llX,0,%s", DYN_SEP,
22507c478bd9Sstevel@tonic-gate 		    (longlong_t)nodep->node_data.port_node.port_guid,
22517c478bd9Sstevel@tonic-gate 		    ibnex.ibnex_comm_svc_names[nodep->node_data.port_node.
22527c478bd9Sstevel@tonic-gate 		    port_commsvc_idx]);
22537c478bd9Sstevel@tonic-gate 
22547c478bd9Sstevel@tonic-gate 	} else if (nodep->node_type == IBNEX_HCASVC_COMMSVC_NODE) {
22557c478bd9Sstevel@tonic-gate 		(void) snprintf(*ret_apid, IBTL_IBNEX_APID_LEN,
22567c478bd9Sstevel@tonic-gate 		    "ib%s%llX,0,%s", DYN_SEP,
22577c478bd9Sstevel@tonic-gate 		    (longlong_t)nodep->node_data.port_node.port_guid, ibnex.
22587c478bd9Sstevel@tonic-gate 		    ibnex_hcasvc_comm_svc_names[nodep->node_data.port_node.
22597c478bd9Sstevel@tonic-gate 		    port_commsvc_idx]);
22607c478bd9Sstevel@tonic-gate 
22617c478bd9Sstevel@tonic-gate 	} else if (nodep->node_type == IBNEX_VPPA_COMMSVC_NODE) {
22627c478bd9Sstevel@tonic-gate 		(void) snprintf(*ret_apid, IBTL_IBNEX_APID_LEN,
22637c478bd9Sstevel@tonic-gate 		    "ib%s%llX,%x,%s", DYN_SEP,
22647c478bd9Sstevel@tonic-gate 		    (longlong_t)nodep->node_data.port_node.port_guid,
22657c478bd9Sstevel@tonic-gate 		    nodep->node_data.port_node.port_pkey,
22667c478bd9Sstevel@tonic-gate 		    ibnex.ibnex_vppa_comm_svc_names[nodep->node_data.port_node.
22677c478bd9Sstevel@tonic-gate 		    port_commsvc_idx]);
22687c478bd9Sstevel@tonic-gate 
22697c478bd9Sstevel@tonic-gate 	} else if (nodep->node_type == IBNEX_IOC_NODE) {
22707c478bd9Sstevel@tonic-gate 		(void) snprintf(*ret_apid, IBTL_IBNEX_APID_LEN,
22717c478bd9Sstevel@tonic-gate 		    "ib%s%llX", DYN_SEP,
22727c478bd9Sstevel@tonic-gate 		    (longlong_t)nodep->node_data.ioc_node.ioc_guid);
22737c478bd9Sstevel@tonic-gate 
22747c478bd9Sstevel@tonic-gate 	} else if (nodep->node_type == IBNEX_PSEUDO_NODE) {
22757c478bd9Sstevel@tonic-gate 		(void) snprintf(*ret_apid, IBTL_IBNEX_APID_LEN, "ib%s%s",
22767c478bd9Sstevel@tonic-gate 		    DYN_SEP, nodep->node_data.pseudo_node.pseudo_node_addr);
22777c478bd9Sstevel@tonic-gate 
22787c478bd9Sstevel@tonic-gate 	} else {
22797c478bd9Sstevel@tonic-gate 		(void) snprintf(*ret_apid, IBTL_IBNEX_APID_LEN, "%s", "-");
22807c478bd9Sstevel@tonic-gate 	}
22817c478bd9Sstevel@tonic-gate 
22827c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "ibnex_return_apid: %x %s",
22837c478bd9Sstevel@tonic-gate 	    nodep->node_type, ret_apid);
22847c478bd9Sstevel@tonic-gate }
22857c478bd9Sstevel@tonic-gate 
22867c478bd9Sstevel@tonic-gate 
22877c478bd9Sstevel@tonic-gate /*
22887c478bd9Sstevel@tonic-gate  * ibnex_vppa_conf_entry_add()
22897c478bd9Sstevel@tonic-gate  *	Add a new service to the ibnex data base of VPPA communication
22907c478bd9Sstevel@tonic-gate  *	services.
22917c478bd9Sstevel@tonic-gate  */
22927c478bd9Sstevel@tonic-gate static void
ibnex_vppa_conf_entry_add(char * service)22937c478bd9Sstevel@tonic-gate ibnex_vppa_conf_entry_add(char *service)
22947c478bd9Sstevel@tonic-gate {
22957c478bd9Sstevel@tonic-gate 	int	i, nsvcs;
22967c478bd9Sstevel@tonic-gate 	char	**service_name;
22977c478bd9Sstevel@tonic-gate 
22987c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
22997c478bd9Sstevel@tonic-gate 	nsvcs = ibnex.ibnex_nvppa_comm_svcs;
23007c478bd9Sstevel@tonic-gate 
23017c478bd9Sstevel@tonic-gate 	/* Allocate space for new "ibnex.ibnex_nvppa_comm_svcs + 1" */
23027c478bd9Sstevel@tonic-gate 	service_name = kmem_alloc((nsvcs + 1) * sizeof (char *), KM_SLEEP);
23037c478bd9Sstevel@tonic-gate 	/*
23047c478bd9Sstevel@tonic-gate 	 * Copy over the existing "ibnex.ibnex_vppa_comm_svc_names"
23057c478bd9Sstevel@tonic-gate 	 * array. Add the new service at the end.
23067c478bd9Sstevel@tonic-gate 	 */
23077c478bd9Sstevel@tonic-gate 	for (i = 0; i < nsvcs; i++)
23087c478bd9Sstevel@tonic-gate 		service_name[i] = ibnex.ibnex_vppa_comm_svc_names[i];
23097c478bd9Sstevel@tonic-gate 	service_name[i] = kmem_alloc(strlen(service) + 1, KM_SLEEP);
23107c478bd9Sstevel@tonic-gate 	(void) snprintf(service_name[i], 5, "%s", service);
23117c478bd9Sstevel@tonic-gate 
23127c478bd9Sstevel@tonic-gate 	/* Replace existing pointer to VPPA services w/ newly allocated one */
23137c478bd9Sstevel@tonic-gate 	if (ibnex.ibnex_vppa_comm_svc_names) {
23147c478bd9Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_vppa_comm_svc_names, nsvcs *
23157c478bd9Sstevel@tonic-gate 		    sizeof (char *));
23167c478bd9Sstevel@tonic-gate 	}
23177c478bd9Sstevel@tonic-gate 	ibnex.ibnex_nvppa_comm_svcs++;
23187c478bd9Sstevel@tonic-gate 	ibnex.ibnex_vppa_comm_svc_names = service_name;
23197c478bd9Sstevel@tonic-gate }
23207c478bd9Sstevel@tonic-gate 
23217c478bd9Sstevel@tonic-gate /*
23227c478bd9Sstevel@tonic-gate  * ibnex_port_conf_entry_add()
23237c478bd9Sstevel@tonic-gate  *	Add a new service to the ibnex data base of Port communication
23247c478bd9Sstevel@tonic-gate  *	services.
23257c478bd9Sstevel@tonic-gate  */
23267c478bd9Sstevel@tonic-gate static void
ibnex_port_conf_entry_add(char * service)23277c478bd9Sstevel@tonic-gate ibnex_port_conf_entry_add(char *service)
23287c478bd9Sstevel@tonic-gate {
23297c478bd9Sstevel@tonic-gate 	int	i, nsvcs;
23307c478bd9Sstevel@tonic-gate 	char	**service_name;
23317c478bd9Sstevel@tonic-gate 
23327c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
23337c478bd9Sstevel@tonic-gate 	nsvcs = ibnex.ibnex_num_comm_svcs;
23347c478bd9Sstevel@tonic-gate 
23357c478bd9Sstevel@tonic-gate 	/* Allocate space for new "ibnex.ibnex_num_comm_svcs + 1" */
23367c478bd9Sstevel@tonic-gate 	service_name = kmem_alloc((nsvcs + 1) * sizeof (char *), KM_SLEEP);
23377c478bd9Sstevel@tonic-gate 	/*
23387c478bd9Sstevel@tonic-gate 	 * Copy over the existing "ibnex.ibnex_comm_svc_names" array.
23397c478bd9Sstevel@tonic-gate 	 * Add the new service to the end.
23407c478bd9Sstevel@tonic-gate 	 */
23417c478bd9Sstevel@tonic-gate 	for (i = 0; i < nsvcs; i++)
23427c478bd9Sstevel@tonic-gate 		service_name[i] = ibnex.ibnex_comm_svc_names[i];
23437c478bd9Sstevel@tonic-gate 	service_name[i] = kmem_alloc(strlen(service) + 1, KM_SLEEP);
23447c478bd9Sstevel@tonic-gate 	(void) snprintf(service_name[i], 5, "%s", service);
23457c478bd9Sstevel@tonic-gate 
23467c478bd9Sstevel@tonic-gate 	/* Replace existing pointer to Port services w/ newly allocated one */
23477c478bd9Sstevel@tonic-gate 	if (ibnex.ibnex_comm_svc_names) {
23487c478bd9Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_comm_svc_names, nsvcs * sizeof (char *));
23497c478bd9Sstevel@tonic-gate 	}
23507c478bd9Sstevel@tonic-gate 	ibnex.ibnex_num_comm_svcs++;
23517c478bd9Sstevel@tonic-gate 	ibnex.ibnex_comm_svc_names = service_name;
23527c478bd9Sstevel@tonic-gate }
23537c478bd9Sstevel@tonic-gate 
23547c478bd9Sstevel@tonic-gate /*
23557c478bd9Sstevel@tonic-gate  * ibnex_hcasvc_conf_entry_add()
23567c478bd9Sstevel@tonic-gate  *	Add a new service to the ibnex data base of HCA_SVC communication
23577c478bd9Sstevel@tonic-gate  *	services.
23587c478bd9Sstevel@tonic-gate  */
23597c478bd9Sstevel@tonic-gate static void
ibnex_hcasvc_conf_entry_add(char * service)23607c478bd9Sstevel@tonic-gate ibnex_hcasvc_conf_entry_add(char *service)
23617c478bd9Sstevel@tonic-gate {
23627c478bd9Sstevel@tonic-gate 	int	i, nsvcs;
23637c478bd9Sstevel@tonic-gate 	char	**service_name;
23647c478bd9Sstevel@tonic-gate 
23657c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
23667c478bd9Sstevel@tonic-gate 	nsvcs = ibnex.ibnex_nhcasvc_comm_svcs;
23677c478bd9Sstevel@tonic-gate 
23687c478bd9Sstevel@tonic-gate 	/* Allocate space for new "ibnex.ibnex_nvppa_comm_svcs + 1" */
23697c478bd9Sstevel@tonic-gate 	service_name = kmem_alloc((nsvcs + 1) * sizeof (char *), KM_SLEEP);
23707c478bd9Sstevel@tonic-gate 	/*
23717c478bd9Sstevel@tonic-gate 	 * Copy over the existing "ibnex.ibnex_hcasvc_comm_svc_names"
23727c478bd9Sstevel@tonic-gate 	 * array. Add the new service at the end.
23737c478bd9Sstevel@tonic-gate 	 */
23747c478bd9Sstevel@tonic-gate 	for (i = 0; i < nsvcs; i++)
23757c478bd9Sstevel@tonic-gate 		service_name[i] = ibnex.ibnex_hcasvc_comm_svc_names[i];
23767c478bd9Sstevel@tonic-gate 	service_name[i] = kmem_alloc(strlen(service) + 1, KM_SLEEP);
23777c478bd9Sstevel@tonic-gate 	(void) snprintf(service_name[i], 5, "%s", service);
23787c478bd9Sstevel@tonic-gate 
23797c478bd9Sstevel@tonic-gate 	/*
23807c478bd9Sstevel@tonic-gate 	 * Replace existing pointer to HCA_SVC services w/ newly
23817c478bd9Sstevel@tonic-gate 	 * allocated one
23827c478bd9Sstevel@tonic-gate 	 */
23837c478bd9Sstevel@tonic-gate 	if (ibnex.ibnex_hcasvc_comm_svc_names) {
23847c478bd9Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_hcasvc_comm_svc_names, nsvcs *
23857c478bd9Sstevel@tonic-gate 		    sizeof (char *));
23867c478bd9Sstevel@tonic-gate 	}
23877c478bd9Sstevel@tonic-gate 	ibnex.ibnex_nhcasvc_comm_svcs++;
23887c478bd9Sstevel@tonic-gate 	ibnex.ibnex_hcasvc_comm_svc_names = service_name;
23897c478bd9Sstevel@tonic-gate }
23907c478bd9Sstevel@tonic-gate 
23917c478bd9Sstevel@tonic-gate 
23927c478bd9Sstevel@tonic-gate /*
23937c478bd9Sstevel@tonic-gate  * ibnex_vppa_conf_entry_delete()
23947c478bd9Sstevel@tonic-gate  *	Delete an existing service entry from ibnex data base of
23957c478bd9Sstevel@tonic-gate  *	VPPA communication services.
23967c478bd9Sstevel@tonic-gate  */
23977c478bd9Sstevel@tonic-gate static int
ibnex_vppa_conf_entry_delete(char * msg,char * service)23987c478bd9Sstevel@tonic-gate ibnex_vppa_conf_entry_delete(char *msg, char *service)
23997c478bd9Sstevel@tonic-gate {
24007c478bd9Sstevel@tonic-gate 	int			i, j, nsvcs;
24017c478bd9Sstevel@tonic-gate 	int			len;
24027c478bd9Sstevel@tonic-gate 	int			match_ndx;
24037c478bd9Sstevel@tonic-gate 	char			**service_name;
24047c478bd9Sstevel@tonic-gate 	boolean_t		found = B_FALSE;
24057c478bd9Sstevel@tonic-gate 	ibnex_node_data_t	*node_datap = ibnex.ibnex_port_node_head;
24067c478bd9Sstevel@tonic-gate 
24077c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tvppa_conf_entry_delete: %s", service);
24087c478bd9Sstevel@tonic-gate 
24097c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
24107c478bd9Sstevel@tonic-gate 	nsvcs = ibnex.ibnex_nvppa_comm_svcs;
24117c478bd9Sstevel@tonic-gate 
24127c478bd9Sstevel@tonic-gate 	/* find matching index */
24137c478bd9Sstevel@tonic-gate 	for (i = 0; i < nsvcs; i++) {
24146cd9e705SBill Taylor 		if (strcmp(ibnex.ibnex_vppa_comm_svc_names[i], service))
24157c478bd9Sstevel@tonic-gate 			continue;
24167c478bd9Sstevel@tonic-gate 		found = B_TRUE;
24177c478bd9Sstevel@tonic-gate 		match_ndx = i;
24187c478bd9Sstevel@tonic-gate 		break;
24197c478bd9Sstevel@tonic-gate 	}
24207c478bd9Sstevel@tonic-gate 
24217c478bd9Sstevel@tonic-gate 	/* check for valid "nsvcs" */
24227c478bd9Sstevel@tonic-gate 	if (found == B_FALSE || nsvcs == 0) {
24237c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "%s: invalid vppa services %x",
24247c478bd9Sstevel@tonic-gate 		    msg, nsvcs);
24257c478bd9Sstevel@tonic-gate 		return (EIO);
24267c478bd9Sstevel@tonic-gate 	}
24277c478bd9Sstevel@tonic-gate 
24287c478bd9Sstevel@tonic-gate 	/* Check if service is in use; return failure if so */
24297c478bd9Sstevel@tonic-gate 	for (; node_datap; node_datap = node_datap->node_next) {
24307c478bd9Sstevel@tonic-gate 		if ((node_datap->node_data.port_node.port_commsvc_idx == i) &&
24317c478bd9Sstevel@tonic-gate 		    node_datap->node_type == IBNEX_VPPA_COMMSVC_NODE &&
24327c478bd9Sstevel@tonic-gate 		    node_datap->node_dip) {
24337c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "%s: service %s is in use",
24347c478bd9Sstevel@tonic-gate 			    msg, service);
24357c478bd9Sstevel@tonic-gate 			return (EIO);
24367c478bd9Sstevel@tonic-gate 		}
24377c478bd9Sstevel@tonic-gate 	}
24387c478bd9Sstevel@tonic-gate 
24397c478bd9Sstevel@tonic-gate 	/* if nsvcs == 1, bailout early */
24407c478bd9Sstevel@tonic-gate 	if (nsvcs == 1) {
24417c478bd9Sstevel@tonic-gate 		/* free up that single entry */
24427c478bd9Sstevel@tonic-gate 		len = strlen(ibnex.ibnex_vppa_comm_svc_names[0]) + 1;
24437c478bd9Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_vppa_comm_svc_names[0], len);
24447c478bd9Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_vppa_comm_svc_names, sizeof (char *));
24457c478bd9Sstevel@tonic-gate 		ibnex.ibnex_vppa_comm_svc_names = NULL;
24467c478bd9Sstevel@tonic-gate 		ibnex.ibnex_nvppa_comm_svcs = 0;
24477c478bd9Sstevel@tonic-gate 		return (0);
24487c478bd9Sstevel@tonic-gate 	}
24497c478bd9Sstevel@tonic-gate 
24507c478bd9Sstevel@tonic-gate 	/* Allocate space for new "ibnex.ibnex_nvppa_comm_svcs - 1" */
24517c478bd9Sstevel@tonic-gate 	service_name = kmem_alloc((nsvcs - 1) * sizeof (char *), KM_SLEEP);
24527c478bd9Sstevel@tonic-gate 	/*
24537c478bd9Sstevel@tonic-gate 	 * Copy over the existing "ibnex.ibnex_vppa_comm_svc_names"
24547c478bd9Sstevel@tonic-gate 	 * array. Do not copy over the matching service.
24557c478bd9Sstevel@tonic-gate 	 */
24567c478bd9Sstevel@tonic-gate 	for (i = 0, j = 0; i < nsvcs; i++) {
24577c478bd9Sstevel@tonic-gate 		if (i == match_ndx) {
24587c478bd9Sstevel@tonic-gate 			/* free up that entry */
24597c478bd9Sstevel@tonic-gate 			len = strlen(ibnex.ibnex_vppa_comm_svc_names[i]) + 1;
24607c478bd9Sstevel@tonic-gate 			kmem_free(ibnex.ibnex_vppa_comm_svc_names[i], len);
24617c478bd9Sstevel@tonic-gate 			continue;
24627c478bd9Sstevel@tonic-gate 		}
24637c478bd9Sstevel@tonic-gate 		service_name[j++] = ibnex.ibnex_vppa_comm_svc_names[i];
24647c478bd9Sstevel@tonic-gate 	}
24657c478bd9Sstevel@tonic-gate 
24667c478bd9Sstevel@tonic-gate 	/* Replace existing pointer to VPPA services w/ newly adjusted one */
24677c478bd9Sstevel@tonic-gate 	if (ibnex.ibnex_vppa_comm_svc_names) {
24687c478bd9Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_vppa_comm_svc_names, nsvcs *
24697c478bd9Sstevel@tonic-gate 		    sizeof (char *));
24707c478bd9Sstevel@tonic-gate 		ibnex.ibnex_nvppa_comm_svcs--;
24717c478bd9Sstevel@tonic-gate 		ibnex.ibnex_vppa_comm_svc_names = service_name;
24727c478bd9Sstevel@tonic-gate 	}
24737c478bd9Sstevel@tonic-gate 	return (0);
24747c478bd9Sstevel@tonic-gate }
24757c478bd9Sstevel@tonic-gate 
24767c478bd9Sstevel@tonic-gate 
24777c478bd9Sstevel@tonic-gate /*
24787c478bd9Sstevel@tonic-gate  * ibnex_port_conf_entry_delete()
24797c478bd9Sstevel@tonic-gate  *	Delete an existing service entry from ibnex data base of
24807c478bd9Sstevel@tonic-gate  *	Port communication services.
24817c478bd9Sstevel@tonic-gate  */
24827c478bd9Sstevel@tonic-gate static int
ibnex_port_conf_entry_delete(char * msg,char * service)24837c478bd9Sstevel@tonic-gate ibnex_port_conf_entry_delete(char *msg, char *service)
24847c478bd9Sstevel@tonic-gate {
24857c478bd9Sstevel@tonic-gate 	int			i, j, nsvcs;
24867c478bd9Sstevel@tonic-gate 	int			match_ndx;
24877c478bd9Sstevel@tonic-gate 	int			len;
24887c478bd9Sstevel@tonic-gate 	char			**service_name;
24897c478bd9Sstevel@tonic-gate 	boolean_t		found = B_FALSE;
24907c478bd9Sstevel@tonic-gate 	ibnex_node_data_t	*node_datap = ibnex.ibnex_port_node_head;
24917c478bd9Sstevel@tonic-gate 
24927c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tport_conf_entry_delete: %s", service);
24937c478bd9Sstevel@tonic-gate 
24947c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
24957c478bd9Sstevel@tonic-gate 	nsvcs = ibnex.ibnex_num_comm_svcs;
24967c478bd9Sstevel@tonic-gate 
24977c478bd9Sstevel@tonic-gate 	/* find matching index */
24987c478bd9Sstevel@tonic-gate 	for (i = 0; i < nsvcs; i++) {
24996cd9e705SBill Taylor 		if (strcmp(ibnex.ibnex_comm_svc_names[i], service))
25007c478bd9Sstevel@tonic-gate 			continue;
25017c478bd9Sstevel@tonic-gate 		found = B_TRUE;
25027c478bd9Sstevel@tonic-gate 		match_ndx = i;
25037c478bd9Sstevel@tonic-gate 		break;
25047c478bd9Sstevel@tonic-gate 	}
25057c478bd9Sstevel@tonic-gate 
25067c478bd9Sstevel@tonic-gate 	/* check for valid "nsvcs" */
25077c478bd9Sstevel@tonic-gate 	if (found == B_FALSE || nsvcs == 0) {
25087c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "%s: invalid services %x", msg, nsvcs);
25097c478bd9Sstevel@tonic-gate 		return (EIO);
25107c478bd9Sstevel@tonic-gate 	}
25117c478bd9Sstevel@tonic-gate 
25127c478bd9Sstevel@tonic-gate 	/* Check if service is in use; return failure if so */
25137c478bd9Sstevel@tonic-gate 	for (; node_datap; node_datap = node_datap->node_next) {
25147c478bd9Sstevel@tonic-gate 		if ((node_datap->node_data.port_node.port_commsvc_idx == i) &&
25157c478bd9Sstevel@tonic-gate 		    node_datap->node_type == IBNEX_PORT_COMMSVC_NODE &&
25167c478bd9Sstevel@tonic-gate 		    node_datap->node_dip)
25177c478bd9Sstevel@tonic-gate 			return (EIO);
25187c478bd9Sstevel@tonic-gate 	}
25197c478bd9Sstevel@tonic-gate 
25207c478bd9Sstevel@tonic-gate 	/* if nsvcs == 1, bailout early */
25217c478bd9Sstevel@tonic-gate 	if (nsvcs == 1) {
25227c478bd9Sstevel@tonic-gate 		/* free up that single entry */
25237c478bd9Sstevel@tonic-gate 		len = strlen(ibnex.ibnex_comm_svc_names[0]) + 1;
25247c478bd9Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_comm_svc_names[0], len);
25257c478bd9Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_comm_svc_names, sizeof (char *));
25267c478bd9Sstevel@tonic-gate 		ibnex.ibnex_comm_svc_names = NULL;
25277c478bd9Sstevel@tonic-gate 		ibnex.ibnex_num_comm_svcs = 0;
25287c478bd9Sstevel@tonic-gate 		return (0);
25297c478bd9Sstevel@tonic-gate 	}
25307c478bd9Sstevel@tonic-gate 
25317c478bd9Sstevel@tonic-gate 	/* Allocate space for new "ibnex.ibnex_num_comm_svcs - 1" */
25327c478bd9Sstevel@tonic-gate 	service_name = kmem_alloc((nsvcs - 1) * sizeof (char *), KM_SLEEP);
25337c478bd9Sstevel@tonic-gate 	/*
25347c478bd9Sstevel@tonic-gate 	 * Copy over the existing "ibnex.ibnex_comm_svc_names" array.
25357c478bd9Sstevel@tonic-gate 	 * Skip the matching service.
25367c478bd9Sstevel@tonic-gate 	 */
25377c478bd9Sstevel@tonic-gate 	for (i = 0, j = 0; i < nsvcs; i++) {
25387c478bd9Sstevel@tonic-gate 		if (i == match_ndx) {
25397c478bd9Sstevel@tonic-gate 			/* free up that entry */
25407c478bd9Sstevel@tonic-gate 			len = strlen(ibnex.ibnex_comm_svc_names[i]) + 1;
25417c478bd9Sstevel@tonic-gate 			kmem_free(ibnex.ibnex_comm_svc_names[i], len);
25427c478bd9Sstevel@tonic-gate 			continue;
25437c478bd9Sstevel@tonic-gate 		}
25447c478bd9Sstevel@tonic-gate 		service_name[j++] = ibnex.ibnex_comm_svc_names[i];
25457c478bd9Sstevel@tonic-gate 	}
25467c478bd9Sstevel@tonic-gate 
25477c478bd9Sstevel@tonic-gate 	/* Replace existing pointer to Port services w/ newly adjusted one */
25487c478bd9Sstevel@tonic-gate 	if (ibnex.ibnex_comm_svc_names) {
25497c478bd9Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_comm_svc_names, nsvcs * sizeof (char *));
25507c478bd9Sstevel@tonic-gate 		ibnex.ibnex_num_comm_svcs--;
25517c478bd9Sstevel@tonic-gate 		ibnex.ibnex_comm_svc_names = service_name;
25527c478bd9Sstevel@tonic-gate 	}
25537c478bd9Sstevel@tonic-gate 	return (0);
25547c478bd9Sstevel@tonic-gate }
25557c478bd9Sstevel@tonic-gate 
25567c478bd9Sstevel@tonic-gate /*
25577c478bd9Sstevel@tonic-gate  * ibnex_hcasvc_conf_entry_delete()
25587c478bd9Sstevel@tonic-gate  *	Delete an existing service entry from ibnex data base of
25597c478bd9Sstevel@tonic-gate  *	HCA_SVC communication services.
25607c478bd9Sstevel@tonic-gate  */
25617c478bd9Sstevel@tonic-gate static int
ibnex_hcasvc_conf_entry_delete(char * msg,char * service)25627c478bd9Sstevel@tonic-gate ibnex_hcasvc_conf_entry_delete(char *msg, char *service)
25637c478bd9Sstevel@tonic-gate {
25647c478bd9Sstevel@tonic-gate 	int			i, j, nsvcs;
25657c478bd9Sstevel@tonic-gate 	int			len;
25667c478bd9Sstevel@tonic-gate 	int			match_ndx;
25677c478bd9Sstevel@tonic-gate 	char			**service_name;
25687c478bd9Sstevel@tonic-gate 	boolean_t		found = B_FALSE;
25697c478bd9Sstevel@tonic-gate 	ibnex_node_data_t	*node_datap = ibnex.ibnex_port_node_head;
25707c478bd9Sstevel@tonic-gate 
25717c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\thcasvc_conf_entry_delete: %s", service);
25727c478bd9Sstevel@tonic-gate 
25737c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
25747c478bd9Sstevel@tonic-gate 	nsvcs = ibnex.ibnex_nhcasvc_comm_svcs;
25757c478bd9Sstevel@tonic-gate 
25767c478bd9Sstevel@tonic-gate 	/* find matching index */
25777c478bd9Sstevel@tonic-gate 	for (i = 0; i < nsvcs; i++) {
25786cd9e705SBill Taylor 		if (strcmp(ibnex.ibnex_hcasvc_comm_svc_names[i], service))
25797c478bd9Sstevel@tonic-gate 			continue;
25807c478bd9Sstevel@tonic-gate 		found = B_TRUE;
25817c478bd9Sstevel@tonic-gate 		match_ndx = i;
25827c478bd9Sstevel@tonic-gate 		break;
25837c478bd9Sstevel@tonic-gate 	}
25847c478bd9Sstevel@tonic-gate 
25857c478bd9Sstevel@tonic-gate 	/* check for valid "nsvcs" */
25867c478bd9Sstevel@tonic-gate 	if (found == B_FALSE || nsvcs == 0) {
25877c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "%s: invalid hca_svc services %x",
25887c478bd9Sstevel@tonic-gate 		    msg, nsvcs);
25897c478bd9Sstevel@tonic-gate 		return (EIO);
25907c478bd9Sstevel@tonic-gate 	}
25917c478bd9Sstevel@tonic-gate 
25927c478bd9Sstevel@tonic-gate 	/* Check if service is in use; return failure if so */
25937c478bd9Sstevel@tonic-gate 	for (; node_datap; node_datap = node_datap->node_next) {
25947c478bd9Sstevel@tonic-gate 		if ((node_datap->node_data.port_node.port_commsvc_idx == i) &&
25957c478bd9Sstevel@tonic-gate 		    node_datap->node_type == IBNEX_HCASVC_COMMSVC_NODE &&
25967c478bd9Sstevel@tonic-gate 		    node_datap->node_dip) {
25977c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "%s: service %s is in use",
25987c478bd9Sstevel@tonic-gate 			    msg, service);
25997c478bd9Sstevel@tonic-gate 			return (EIO);
26007c478bd9Sstevel@tonic-gate 		}
26017c478bd9Sstevel@tonic-gate 	}
26027c478bd9Sstevel@tonic-gate 
26037c478bd9Sstevel@tonic-gate 	/* if nsvcs == 1, bailout early */
26047c478bd9Sstevel@tonic-gate 	if (nsvcs == 1) {
26057c478bd9Sstevel@tonic-gate 		/* free up that single entry */
26067c478bd9Sstevel@tonic-gate 		len = strlen(ibnex.ibnex_hcasvc_comm_svc_names[0]) + 1;
26077c478bd9Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_hcasvc_comm_svc_names[0], len);
26087c478bd9Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_hcasvc_comm_svc_names, sizeof (char *));
26097c478bd9Sstevel@tonic-gate 		ibnex.ibnex_hcasvc_comm_svc_names = NULL;
26107c478bd9Sstevel@tonic-gate 		ibnex.ibnex_nhcasvc_comm_svcs = 0;
26117c478bd9Sstevel@tonic-gate 		return (0);
26127c478bd9Sstevel@tonic-gate 	}
26137c478bd9Sstevel@tonic-gate 
26147c478bd9Sstevel@tonic-gate 	/* Allocate space for new "ibnex.ibnex_nhcasvc_comm_svcs - 1" */
26157c478bd9Sstevel@tonic-gate 	service_name = kmem_alloc((nsvcs - 1) * sizeof (char *), KM_SLEEP);
26167c478bd9Sstevel@tonic-gate 	/*
26177c478bd9Sstevel@tonic-gate 	 * Copy over the existing "ibnex.ibnex_hcasvc_comm_svc_names"
26187c478bd9Sstevel@tonic-gate 	 * array. Do not copy over the matching service.
26197c478bd9Sstevel@tonic-gate 	 */
26207c478bd9Sstevel@tonic-gate 	for (i = 0, j = 0; i < nsvcs; i++) {
26217c478bd9Sstevel@tonic-gate 		if (i == match_ndx) {
26227c478bd9Sstevel@tonic-gate 			/* free up that entry */
26237c478bd9Sstevel@tonic-gate 			len = strlen(ibnex.ibnex_hcasvc_comm_svc_names[i]) + 1;
26247c478bd9Sstevel@tonic-gate 			kmem_free(ibnex.ibnex_hcasvc_comm_svc_names[i], len);
26257c478bd9Sstevel@tonic-gate 			continue;
26267c478bd9Sstevel@tonic-gate 		}
26277c478bd9Sstevel@tonic-gate 		service_name[j++] = ibnex.ibnex_hcasvc_comm_svc_names[i];
26287c478bd9Sstevel@tonic-gate 	}
26297c478bd9Sstevel@tonic-gate 
26307c478bd9Sstevel@tonic-gate 	/* Replace existing pointer to VPPA services w/ newly adjusted one */
26317c478bd9Sstevel@tonic-gate 	if (ibnex.ibnex_hcasvc_comm_svc_names) {
26327c478bd9Sstevel@tonic-gate 		kmem_free(ibnex.ibnex_hcasvc_comm_svc_names, nsvcs *
26337c478bd9Sstevel@tonic-gate 		    sizeof (char *));
26347c478bd9Sstevel@tonic-gate 		ibnex.ibnex_nhcasvc_comm_svcs--;
26357c478bd9Sstevel@tonic-gate 		ibnex.ibnex_hcasvc_comm_svc_names = service_name;
26367c478bd9Sstevel@tonic-gate 	}
26377c478bd9Sstevel@tonic-gate 	return (0);
26387c478bd9Sstevel@tonic-gate }
26397c478bd9Sstevel@tonic-gate 
26407c478bd9Sstevel@tonic-gate 
26417c478bd9Sstevel@tonic-gate /*
26427c478bd9Sstevel@tonic-gate  * ibnex_ioc_fininode()
26437c478bd9Sstevel@tonic-gate  *	Un-initialize a child device node for IOC device node
26447c478bd9Sstevel@tonic-gate  *	Returns IBNEX_SUCCESS/IBNEX_FAILURE
26457c478bd9Sstevel@tonic-gate  */
26467c478bd9Sstevel@tonic-gate static ibnex_rval_t
ibnex_ioc_fininode(dev_info_t * dip,ibnex_ioc_node_t * ioc_nodep)26477c478bd9Sstevel@tonic-gate ibnex_ioc_fininode(dev_info_t *dip, ibnex_ioc_node_t *ioc_nodep)
26487c478bd9Sstevel@tonic-gate {
26497c478bd9Sstevel@tonic-gate 	int	rval = MDI_SUCCESS;
26507c478bd9Sstevel@tonic-gate 
26517c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
26527c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tioc_fininode");
26537c478bd9Sstevel@tonic-gate 
26547c478bd9Sstevel@tonic-gate 	/*
26557c478bd9Sstevel@tonic-gate 	 * For a dis-connected IOC,
26567c478bd9Sstevel@tonic-gate 	 *	Free the ioc_profile &&
26577c478bd9Sstevel@tonic-gate 	 *	decrement ibnex_num_disconnect_iocs
26587c478bd9Sstevel@tonic-gate 	 */
26597c478bd9Sstevel@tonic-gate 	if (ioc_nodep->ioc_ngids == 0 && ioc_nodep->ioc_profile) {
26607c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "\tioc_fininode: unconfigure "
26617c478bd9Sstevel@tonic-gate 		    "disconnected IOC: GUID %lX", ioc_nodep->ioc_guid);
26627c478bd9Sstevel@tonic-gate 		ibnex.ibnex_num_disconnect_iocs--;
26637c478bd9Sstevel@tonic-gate 		kmem_free(ioc_nodep->ioc_profile,
26647c478bd9Sstevel@tonic-gate 		    sizeof (ib_dm_ioc_ctrl_profile_t));
26657c478bd9Sstevel@tonic-gate 		ioc_nodep->ioc_profile = NULL;
26667c478bd9Sstevel@tonic-gate 	}
26677c478bd9Sstevel@tonic-gate 
26687c478bd9Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
26697c478bd9Sstevel@tonic-gate 	ASSERT(i_ddi_node_state(dip) >= DS_BOUND);
26707c478bd9Sstevel@tonic-gate 
26717c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tioc_fininode: offlining the IOC");
26727c478bd9Sstevel@tonic-gate 	rval = ibnex_offline_childdip(dip);
26737c478bd9Sstevel@tonic-gate 
26747c478bd9Sstevel@tonic-gate 	if (rval != MDI_SUCCESS) {
26757c478bd9Sstevel@tonic-gate 		rval = NDI_FAILURE;
26767c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "\toffline failed for IOC "
26777c478bd9Sstevel@tonic-gate 		    "dip %p with 0x%x", dip, rval);
26787c478bd9Sstevel@tonic-gate 	}
26797c478bd9Sstevel@tonic-gate 
26807c478bd9Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
26817c478bd9Sstevel@tonic-gate 	return (rval == MDI_SUCCESS ? IBNEX_SUCCESS : IBNEX_OFFLINE_FAILED);
26827c478bd9Sstevel@tonic-gate }
26837c478bd9Sstevel@tonic-gate 
26847c478bd9Sstevel@tonic-gate 
26857c478bd9Sstevel@tonic-gate int
ibnex_offline_childdip(dev_info_t * dip)26867c478bd9Sstevel@tonic-gate ibnex_offline_childdip(dev_info_t *dip)
26877c478bd9Sstevel@tonic-gate {
2688332f545bSEiji Ota 	int		rval = MDI_SUCCESS, rval2;
26897c478bd9Sstevel@tonic-gate 	mdi_pathinfo_t	*path = NULL, *temp;
26907c478bd9Sstevel@tonic-gate 
26917c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\toffline_childdip; begin");
26927c478bd9Sstevel@tonic-gate 	if (dip == NULL) {
26937c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "\toffline_childdip; NULL dip");
26947c478bd9Sstevel@tonic-gate 		return (MDI_FAILURE);
26957c478bd9Sstevel@tonic-gate 	}
26967c478bd9Sstevel@tonic-gate 
26977c478bd9Sstevel@tonic-gate 	for (path = mdi_get_next_phci_path(dip, path); path; ) {
26987c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "\toffline_childdip: "
26997c478bd9Sstevel@tonic-gate 		    "offling path %p", path);
2700332f545bSEiji Ota 		rval2 = MDI_SUCCESS;
2701332f545bSEiji Ota 		if (MDI_PI_IS_ONLINE(path)) {
2702332f545bSEiji Ota 			rval2 = mdi_pi_offline(path, NDI_UNCONFIG);
2703332f545bSEiji Ota 			/* If it cannot be offlined, log this path and error */
2704332f545bSEiji Ota 			if (rval2 != MDI_SUCCESS) {
2705332f545bSEiji Ota 				rval = rval2;
2706332f545bSEiji Ota 				cmn_err(CE_WARN,
2707332f545bSEiji Ota 				    "!ibnex\toffline_childdip (0x%p): "
2708332f545bSEiji Ota 				    "mdi_pi_offline path (0x%p) failed with %d",
2709332f545bSEiji Ota 				    (void *)dip, (void *)path, rval2);
2710332f545bSEiji Ota 			}
27117c478bd9Sstevel@tonic-gate 		}
2712332f545bSEiji Ota 		/* prepare the next path */
27137c478bd9Sstevel@tonic-gate 		temp = path;
27147c478bd9Sstevel@tonic-gate 		path = mdi_get_next_phci_path(dip, path);
2715332f545bSEiji Ota 		/* free the offline path */
2716332f545bSEiji Ota 		if (rval2 == MDI_SUCCESS) {
2717332f545bSEiji Ota 			(void) mdi_pi_free(temp, 0);
2718332f545bSEiji Ota 		}
27197c478bd9Sstevel@tonic-gate 	}
27207c478bd9Sstevel@tonic-gate 	return (rval);
27217c478bd9Sstevel@tonic-gate }
27227c478bd9Sstevel@tonic-gate 
27237c478bd9Sstevel@tonic-gate 
27247c478bd9Sstevel@tonic-gate /*
27257c478bd9Sstevel@tonic-gate  * ibnex_commsvc_fininode()
27267c478bd9Sstevel@tonic-gate  *
27277c478bd9Sstevel@tonic-gate  * Un-initialize a child device node for HCA port / node GUID
27287c478bd9Sstevel@tonic-gate  * for a communication service.
27297c478bd9Sstevel@tonic-gate  *	Returns IBNEX_SUCCESS/IBNEX_FAILURE
27307c478bd9Sstevel@tonic-gate  */
27317c478bd9Sstevel@tonic-gate static ibnex_rval_t
ibnex_commsvc_fininode(dev_info_t * dip)27327c478bd9Sstevel@tonic-gate ibnex_commsvc_fininode(dev_info_t *dip)
27337c478bd9Sstevel@tonic-gate {
27347c478bd9Sstevel@tonic-gate 	int	rval = NDI_SUCCESS;
27357c478bd9Sstevel@tonic-gate 
27367c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
27377c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tcommsvc_fininode");
27387c478bd9Sstevel@tonic-gate 
27397c478bd9Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
27407c478bd9Sstevel@tonic-gate 	if (i_ddi_node_state(dip) < DS_BOUND) {
27417c478bd9Sstevel@tonic-gate 		/*
27427c478bd9Sstevel@tonic-gate 		 * if the child hasn't been bound yet, we can
27437c478bd9Sstevel@tonic-gate 		 * just free the dip. This path is currently
27447c478bd9Sstevel@tonic-gate 		 * untested.
27457c478bd9Sstevel@tonic-gate 		 */
27467c478bd9Sstevel@tonic-gate 		(void) ddi_remove_child(dip, 0);
27477c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex",
27487c478bd9Sstevel@tonic-gate 		    "\tcommsvc_fininode: ddi_remove_child");
27497c478bd9Sstevel@tonic-gate 	} else {
27507c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibnex", "\tcommsvc_fininode: offlining the "
27517c478bd9Sstevel@tonic-gate 		    "Commsvc node");
27527c478bd9Sstevel@tonic-gate 
27537c478bd9Sstevel@tonic-gate 		rval = ndi_devi_offline(dip, NDI_DEVI_REMOVE | NDI_UNCONFIG);
27547c478bd9Sstevel@tonic-gate 		if (rval != NDI_SUCCESS)
27557c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibnex", "\toffline failed for Commsvc "
27567c478bd9Sstevel@tonic-gate 			    "dip %p with 0x%x", dip, rval);
27577c478bd9Sstevel@tonic-gate 	}
27587c478bd9Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
27597c478bd9Sstevel@tonic-gate 	return (rval == NDI_SUCCESS ? IBNEX_SUCCESS : IBNEX_OFFLINE_FAILED);
27607c478bd9Sstevel@tonic-gate }
27617c478bd9Sstevel@tonic-gate 
27627c478bd9Sstevel@tonic-gate 
27637c478bd9Sstevel@tonic-gate /*
27647c478bd9Sstevel@tonic-gate  * ibnex_pseudo_fininode()
27657c478bd9Sstevel@tonic-gate  *	Un-initialize a child pseudo device node
27667c478bd9Sstevel@tonic-gate  *	Returns IBNEX_SUCCESS/IBNEX_FAILURE
27677c478bd9Sstevel@tonic-gate  */
27687c478bd9Sstevel@tonic-gate static ibnex_rval_t
ibnex_pseudo_fininode(dev_info_t * dip)27697c478bd9Sstevel@tonic-gate ibnex_pseudo_fininode(dev_info_t *dip)
27707c478bd9Sstevel@tonic-gate {
27717c478bd9Sstevel@tonic-gate 	int	rval = MDI_SUCCESS;
27727c478bd9Sstevel@tonic-gate 
27737c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex));
27747c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tpseudo_fininode: dip = %p", dip);
27757c478bd9Sstevel@tonic-gate 
27767c478bd9Sstevel@tonic-gate 	mutex_exit(&ibnex.ibnex_mutex);
27777c478bd9Sstevel@tonic-gate 	ASSERT(i_ddi_node_state(dip) >= DS_BOUND);
27787c478bd9Sstevel@tonic-gate 
27797c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibnex", "\tpseudo_fininode: offlining the "
27807c478bd9Sstevel@tonic-gate 	    "pseudo device");
27817c478bd9Sstevel@tonic-gate 	rval = ibnex_offline_childdip(dip);
27827c478bd9Sstevel@tonic-gate 	if (rval != MDI_SUCCESS) {
27837c478bd9Sstevel@tonic-gate 		rval = NDI_FAILURE;
27847c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibnex", "\tpseudo offline failed for "
27857c478bd9Sstevel@tonic-gate 		    "dip %p with 0x%x", dip, rval);
27867c478bd9Sstevel@tonic-gate 	}
27877c478bd9Sstevel@tonic-gate 
27887c478bd9Sstevel@tonic-gate 	mutex_enter(&ibnex.ibnex_mutex);
27897c478bd9Sstevel@tonic-gate 	return (rval == MDI_SUCCESS ? IBNEX_SUCCESS : IBNEX_OFFLINE_FAILED);
27907c478bd9Sstevel@tonic-gate }
2791d1a5c838SRamaswamy Tummala 
2792d1a5c838SRamaswamy Tummala /*
2793d1a5c838SRamaswamy Tummala  * IOCTL implementation to get api version number.
2794d1a5c838SRamaswamy Tummala  */
2795d1a5c838SRamaswamy Tummala static int
ibnex_ctl_get_api_ver(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)2796d1a5c838SRamaswamy Tummala ibnex_ctl_get_api_ver(dev_t dev, int cmd, intptr_t arg, int mode,
2797d1a5c838SRamaswamy Tummala     cred_t *credp, int *rvalp)
2798d1a5c838SRamaswamy Tummala {
2799d1a5c838SRamaswamy Tummala 	ibnex_ctl_api_ver_t	api_ver;
2800d1a5c838SRamaswamy Tummala 
2801d1a5c838SRamaswamy Tummala 	IBTF_DPRINTF_L4("ibnex", "\tctl_get_api_ver: cmd=%x, arg=%p, "
2802d1a5c838SRamaswamy Tummala 	    "mode=%x, cred=%p, rval=%p, dev=0x%x", cmd, arg, mode, credp,
2803d1a5c838SRamaswamy Tummala 	    rvalp, dev);
2804d1a5c838SRamaswamy Tummala 
2805d1a5c838SRamaswamy Tummala 	api_ver.api_ver_num = IBNEX_CTL_API_VERSION;
2806d1a5c838SRamaswamy Tummala 
2807d1a5c838SRamaswamy Tummala 	if (ddi_copyout(&api_ver, (void *)arg, sizeof (ibnex_ctl_api_ver_t),
2808d1a5c838SRamaswamy Tummala 	    mode) != 0) {
2809d1a5c838SRamaswamy Tummala 		IBTF_DPRINTF_L2("ibnex",
2810d1a5c838SRamaswamy Tummala 		    "\tctl_get_api_ver: ddi_copyout err");
2811d1a5c838SRamaswamy Tummala 		return (EFAULT);
2812d1a5c838SRamaswamy Tummala 	}
2813d1a5c838SRamaswamy Tummala 
2814d1a5c838SRamaswamy Tummala 	return (0);
2815d1a5c838SRamaswamy Tummala }
2816d1a5c838SRamaswamy Tummala 
2817d1a5c838SRamaswamy Tummala /*
2818d1a5c838SRamaswamy Tummala  * IOCTL implementation to get the list of HCAs
2819d1a5c838SRamaswamy Tummala  */
2820d1a5c838SRamaswamy Tummala static int
ibnex_ctl_get_hca_list(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)2821d1a5c838SRamaswamy Tummala ibnex_ctl_get_hca_list(dev_t dev, int cmd, intptr_t arg, int mode,
2822d1a5c838SRamaswamy Tummala     cred_t *credp, int *rvalp)
2823d1a5c838SRamaswamy Tummala {
2824d1a5c838SRamaswamy Tummala 	ibnex_ctl_get_hca_list_t hca_list;
2825d1a5c838SRamaswamy Tummala 	int		rv = 0;
2826d1a5c838SRamaswamy Tummala 	uint_t		*in_nhcasp;
2827d1a5c838SRamaswamy Tummala 	uint_t		nhcas, n;
2828d1a5c838SRamaswamy Tummala 	ib_guid_t	*hca_guids;
2829d1a5c838SRamaswamy Tummala 
2830d1a5c838SRamaswamy Tummala 	IBTF_DPRINTF_L4("ibnex", "\tctl_get_hca_list: cmd=%x, arg=%p, "
2831d1a5c838SRamaswamy Tummala 	    "mode=%x, cred=%p, rval=%p, dev=0x%x", cmd, arg, mode, credp,
2832d1a5c838SRamaswamy Tummala 	    rvalp, dev);
2833d1a5c838SRamaswamy Tummala 
2834d1a5c838SRamaswamy Tummala #ifdef	_MULTI_DATAMODEL
2835d1a5c838SRamaswamy Tummala 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
2836d1a5c838SRamaswamy Tummala 		ibnex_ctl_get_hca_list_32_t hca_list_32;
2837d1a5c838SRamaswamy Tummala 
2838d1a5c838SRamaswamy Tummala 		if (ddi_copyin((void *)arg, &hca_list_32,
2839d1a5c838SRamaswamy Tummala 		    sizeof (ibnex_ctl_get_hca_list_32_t), mode) != 0) {
2840d1a5c838SRamaswamy Tummala 			IBTF_DPRINTF_L2("ibnex",
2841d1a5c838SRamaswamy Tummala 			    "\tctl_get_hca_list: ddi_copyin err 1");
2842d1a5c838SRamaswamy Tummala 			return (EFAULT);
2843d1a5c838SRamaswamy Tummala 		}
2844d1a5c838SRamaswamy Tummala 
2845d1a5c838SRamaswamy Tummala 		hca_list.hca_guids_alloc_sz = hca_list_32.hca_guids_alloc_sz;
2846d1a5c838SRamaswamy Tummala 		hca_list.hca_guids =
2847d1a5c838SRamaswamy Tummala 		    (ib_guid_t *)(uintptr_t)hca_list_32.hca_guids;
2848d1a5c838SRamaswamy Tummala 		in_nhcasp = &((ibnex_ctl_get_hca_list_32_t *)arg)->nhcas;
2849d1a5c838SRamaswamy Tummala 	} else
2850d1a5c838SRamaswamy Tummala #endif
2851d1a5c838SRamaswamy Tummala 	{
2852d1a5c838SRamaswamy Tummala 		if (ddi_copyin((void *)arg, &hca_list,
2853d1a5c838SRamaswamy Tummala 		    sizeof (ibnex_ctl_get_hca_list_t), mode) != 0) {
2854d1a5c838SRamaswamy Tummala 			IBTF_DPRINTF_L2("ibnex",
2855d1a5c838SRamaswamy Tummala 			    "\tctl_get_hca_list: ddi_copyin err 2");
2856d1a5c838SRamaswamy Tummala 			return (EFAULT);
2857d1a5c838SRamaswamy Tummala 		}
2858d1a5c838SRamaswamy Tummala 
2859d1a5c838SRamaswamy Tummala 		in_nhcasp = &((ibnex_ctl_get_hca_list_t *)arg)->nhcas;
2860d1a5c838SRamaswamy Tummala 	}
2861d1a5c838SRamaswamy Tummala 
2862d1a5c838SRamaswamy Tummala 	nhcas = ibt_get_hca_list(&hca_guids);
2863d1a5c838SRamaswamy Tummala 
2864d1a5c838SRamaswamy Tummala 	/* copy number of hcas to user space */
2865d1a5c838SRamaswamy Tummala 	if (ddi_copyout(&nhcas, in_nhcasp, sizeof (uint_t), mode) != 0) {
2866d1a5c838SRamaswamy Tummala 		IBTF_DPRINTF_L2("ibnex",
2867d1a5c838SRamaswamy Tummala 		    "\tctl_get_hca_list: ddi_copyout err 1");
2868d1a5c838SRamaswamy Tummala 		rv = EFAULT;
2869d1a5c838SRamaswamy Tummala 		goto out;
2870d1a5c838SRamaswamy Tummala 	}
2871d1a5c838SRamaswamy Tummala 
2872d1a5c838SRamaswamy Tummala 	n = MIN(nhcas, hca_list.hca_guids_alloc_sz);
2873d1a5c838SRamaswamy Tummala 	if (n == 0)
2874d1a5c838SRamaswamy Tummala 		goto out;
2875d1a5c838SRamaswamy Tummala 
2876d1a5c838SRamaswamy Tummala 	/* copy HCA guids to user space */
2877d1a5c838SRamaswamy Tummala 	if (ddi_copyout(hca_guids, hca_list.hca_guids,
2878d1a5c838SRamaswamy Tummala 	    n * sizeof (ib_guid_t), mode) != 0) {
2879d1a5c838SRamaswamy Tummala 		IBTF_DPRINTF_L2("ibnex",
2880d1a5c838SRamaswamy Tummala 		    "\tctl_get_hca_list: ddi_copyout err 2");
2881d1a5c838SRamaswamy Tummala 		rv = EFAULT;
2882d1a5c838SRamaswamy Tummala 	}
2883d1a5c838SRamaswamy Tummala 
2884d1a5c838SRamaswamy Tummala out:
2885d1a5c838SRamaswamy Tummala 	if (nhcas > 0)
2886d1a5c838SRamaswamy Tummala 		ibt_free_hca_list(hca_guids, nhcas);
2887d1a5c838SRamaswamy Tummala 
2888d1a5c838SRamaswamy Tummala 	return (rv);
2889d1a5c838SRamaswamy Tummala }
2890d1a5c838SRamaswamy Tummala 
2891e8174f4eSRamaswamy Tummala #define	IBNEX_CTL_CP_HCA_INFO(x, y, driver_name, instance, device_path, \
2892e8174f4eSRamaswamy Tummala     device_path_alloc_sz, device_path_len)				\
2893e8174f4eSRamaswamy Tummala {									\
2894e8174f4eSRamaswamy Tummala 	(x)->hca_node_guid		= (y)->hca_node_guid;		\
2895e8174f4eSRamaswamy Tummala 	(x)->hca_si_guid		= (y)->hca_si_guid;		\
2896e8174f4eSRamaswamy Tummala 	(x)->hca_nports			= (y)->hca_nports;		\
2897e8174f4eSRamaswamy Tummala 	(x)->hca_flags			= (y)->hca_flags;		\
2898e8174f4eSRamaswamy Tummala 	(x)->hca_flags2			= (y)->hca_flags2;		\
2899e8174f4eSRamaswamy Tummala 	(x)->hca_vendor_id		= (y)->hca_vendor_id;		\
2900e8174f4eSRamaswamy Tummala 	(x)->hca_device_id		= (y)->hca_device_id;		\
2901e8174f4eSRamaswamy Tummala 	(x)->hca_version_id		= (y)->hca_version_id;		\
2902e8174f4eSRamaswamy Tummala 	(x)->hca_max_chans		= (y)->hca_max_chans;		\
2903e8174f4eSRamaswamy Tummala 	(x)->hca_max_chan_sz		= (y)->hca_max_chan_sz;		\
2904e8174f4eSRamaswamy Tummala 	(x)->hca_max_sgl		= (y)->hca_max_sgl;		\
2905e8174f4eSRamaswamy Tummala 	(x)->hca_max_cq			= (y)->hca_max_cq;		\
2906e8174f4eSRamaswamy Tummala 	(x)->hca_max_cq_sz		= (y)->hca_max_cq_sz;		\
2907e8174f4eSRamaswamy Tummala 	(x)->hca_page_sz		= (y)->hca_page_sz;		\
2908e8174f4eSRamaswamy Tummala 	(x)->hca_max_memr		= (y)->hca_max_memr;		\
2909e8174f4eSRamaswamy Tummala 	(x)->hca_max_memr_len		= (y)->hca_max_memr_len;	\
2910e8174f4eSRamaswamy Tummala 	(x)->hca_max_mem_win		= (y)->hca_max_mem_win;		\
2911e8174f4eSRamaswamy Tummala 	(x)->hca_max_rsc		= (y)->hca_max_rsc;		\
2912e8174f4eSRamaswamy Tummala 	(x)->hca_max_rdma_in_chan	= (y)->hca_max_rdma_in_chan;	\
2913e8174f4eSRamaswamy Tummala 	(x)->hca_max_rdma_out_chan	= (y)->hca_max_rdma_out_chan;	\
2914e8174f4eSRamaswamy Tummala 	(x)->hca_max_ipv6_chan		= (y)->hca_max_ipv6_chan;	\
2915bf8d275aSToomas Soome 	(x)->hca_max_ether_chan		= (y)->hca_max_ether_chan;	\
2916e8174f4eSRamaswamy Tummala 	(x)->hca_max_mcg_chans		= (y)->hca_max_mcg_chans;	\
2917e8174f4eSRamaswamy Tummala 	(x)->hca_max_mcg		= (y)->hca_max_mcg;		\
2918e8174f4eSRamaswamy Tummala 	(x)->hca_max_chan_per_mcg	= (y)->hca_max_chan_per_mcg;	\
2919e8174f4eSRamaswamy Tummala 	(x)->hca_max_partitions		= (y)->hca_max_partitions;	\
2920e8174f4eSRamaswamy Tummala 	(x)->hca_local_ack_delay	= (y)->hca_local_ack_delay;	\
2921e8174f4eSRamaswamy Tummala 	(x)->hca_max_port_sgid_tbl_sz	= (y)->hca_max_port_sgid_tbl_sz; \
2922e8174f4eSRamaswamy Tummala 	(x)->hca_max_port_pkey_tbl_sz	= (y)->hca_max_port_pkey_tbl_sz; \
2923e8174f4eSRamaswamy Tummala 	(x)->hca_max_pd			= (y)->hca_max_pd;		\
2924e8174f4eSRamaswamy Tummala 	(x)->hca_max_ud_dest		= (y)->hca_max_ud_dest;		\
2925e8174f4eSRamaswamy Tummala 	(x)->hca_max_srqs		= (y)->hca_max_srqs;		\
2926e8174f4eSRamaswamy Tummala 	(x)->hca_max_srqs_sz		= (y)->hca_max_srqs_sz;		\
2927e8174f4eSRamaswamy Tummala 	(x)->hca_max_srq_sgl		= (y)->hca_max_srq_sgl;		\
2928e8174f4eSRamaswamy Tummala 	(x)->hca_max_cq_handlers	= (y)->hca_max_cq_handlers;	\
2929e8174f4eSRamaswamy Tummala 	(x)->hca_reserved_lkey		= (y)->hca_reserved_lkey;	\
2930e8174f4eSRamaswamy Tummala 	(x)->hca_max_fmrs		= (y)->hca_max_fmrs;		\
2931e8174f4eSRamaswamy Tummala 	(x)->hca_max_lso_size		= (y)->hca_max_lso_size;	\
2932e8174f4eSRamaswamy Tummala 	(x)->hca_max_lso_hdr_size	= (y)->hca_max_lso_hdr_size;	\
2933e8174f4eSRamaswamy Tummala 	(x)->hca_max_inline_size	= (y)->hca_max_inline_size;	\
2934e8174f4eSRamaswamy Tummala 	(x)->hca_max_cq_mod_count	= (y)->hca_max_cq_mod_count;	\
2935e8174f4eSRamaswamy Tummala 	(x)->hca_max_cq_mod_usec	= (y)->hca_max_cq_mod_usec;	\
2936e8174f4eSRamaswamy Tummala 	(x)->hca_fw_major_version	= (y)->hca_fw_major_version;	\
2937e8174f4eSRamaswamy Tummala 	(x)->hca_fw_minor_version	= (y)->hca_fw_minor_version;	\
2938e8174f4eSRamaswamy Tummala 	(x)->hca_fw_micro_version	= (y)->hca_fw_micro_version;	\
2939e8174f4eSRamaswamy Tummala 	(x)->hca_ud_send_inline_sz	= (y)->hca_ud_send_inline_sz;	\
2940e8174f4eSRamaswamy Tummala 	(x)->hca_conn_send_inline_sz	= (y)->hca_conn_send_inline_sz;	\
2941e8174f4eSRamaswamy Tummala 	(x)->hca_conn_rdmaw_inline_overhead =				\
2942e8174f4eSRamaswamy Tummala 	    (y)->hca_conn_rdmaw_inline_overhead;			\
2943e8174f4eSRamaswamy Tummala 	(x)->hca_recv_sgl_sz		= (y)->hca_recv_sgl_sz;		\
2944e8174f4eSRamaswamy Tummala 	(x)->hca_ud_send_sgl_sz		= (y)->hca_ud_send_sgl_sz;	\
2945e8174f4eSRamaswamy Tummala 	(x)->hca_conn_send_sgl_sz	= (y)->hca_conn_send_sgl_sz;	\
2946e8174f4eSRamaswamy Tummala 	(x)->hca_conn_rdma_sgl_overhead = (y)->hca_conn_rdma_sgl_overhead; \
2947e8174f4eSRamaswamy Tummala 									\
2948e8174f4eSRamaswamy Tummala 	(void) strlcpy((x)->hca_driver_name, (driver_name),		\
2949e8174f4eSRamaswamy Tummala 	    MAX_HCA_DRVNAME_LEN);					\
2950e8174f4eSRamaswamy Tummala 	(x)->hca_driver_instance	= (instance);			\
2951e8174f4eSRamaswamy Tummala 									\
2952bf8d275aSToomas Soome 	(x)->hca_device_path		= (device_path);		\
2953e8174f4eSRamaswamy Tummala 	(x)->hca_device_path_len	= (device_path_len);		\
2954e8174f4eSRamaswamy Tummala }
2955e8174f4eSRamaswamy Tummala 
2956d1a5c838SRamaswamy Tummala /*
2957d1a5c838SRamaswamy Tummala  * IOCTL implementation to query HCA attributes
2958d1a5c838SRamaswamy Tummala  */
2959d1a5c838SRamaswamy Tummala static int
ibnex_ctl_query_hca(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)2960d1a5c838SRamaswamy Tummala ibnex_ctl_query_hca(dev_t dev, int cmd, intptr_t arg, int mode,
2961d1a5c838SRamaswamy Tummala     cred_t *credp, int *rvalp)
2962d1a5c838SRamaswamy Tummala {
2963d1a5c838SRamaswamy Tummala 	int			rv = 0;
2964e8174f4eSRamaswamy Tummala 	ibnex_ctl_query_hca_t	*query_hca = NULL;
2965bf8d275aSToomas Soome #ifdef	_MULTI_DATAMODEL
2966e8174f4eSRamaswamy Tummala 	ibnex_ctl_query_hca_32_t *query_hca_32 = NULL;
2967bf8d275aSToomas Soome #endif
2968e8174f4eSRamaswamy Tummala 	ibt_hca_attr_t		*hca_attr = NULL;
2969d1a5c838SRamaswamy Tummala 	char			driver_name[MAX_HCA_DRVNAME_LEN];
2970d1a5c838SRamaswamy Tummala 	int			instance;
2971e8174f4eSRamaswamy Tummala 	ib_guid_t		hca_guid;
2972e8174f4eSRamaswamy Tummala 	char			*device_path;
2973e8174f4eSRamaswamy Tummala 	uint_t			device_path_alloc_sz, hca_device_path_len;
2974e8174f4eSRamaswamy Tummala 	char			*hca_device_path = NULL;
2975bf8d275aSToomas Soome 	uint_t			model;
2976d1a5c838SRamaswamy Tummala 
2977d1a5c838SRamaswamy Tummala 	IBTF_DPRINTF_L4("ibnex", "\tctl_query_hca: cmd=%x, arg=%p, "
2978d1a5c838SRamaswamy Tummala 	    "mode=%x, cred=%p, rval=%p, dev=0x%x", cmd, arg, mode, credp,
2979d1a5c838SRamaswamy Tummala 	    rvalp, dev);
2980d1a5c838SRamaswamy Tummala 
2981bf8d275aSToomas Soome 	switch (model = ddi_model_convert_from(mode & FMODELS)) {
2982e8174f4eSRamaswamy Tummala #ifdef	_MULTI_DATAMODEL
2983bf8d275aSToomas Soome 	case DDI_MODEL_ILP32:
2984e8174f4eSRamaswamy Tummala 		query_hca_32 = kmem_zalloc(
2985e8174f4eSRamaswamy Tummala 		    sizeof (ibnex_ctl_query_hca_32_t), KM_SLEEP);
2986d1a5c838SRamaswamy Tummala 
2987e8174f4eSRamaswamy Tummala 		if (ddi_copyin((void *)arg, query_hca_32,
2988e8174f4eSRamaswamy Tummala 		    sizeof (ibnex_ctl_query_hca_32_t), mode) != 0) {
2989e8174f4eSRamaswamy Tummala 			IBTF_DPRINTF_L2("ibnex",
2990e8174f4eSRamaswamy Tummala 			    "\tctl_query_hca: ddi_copyin err 1");
2991e8174f4eSRamaswamy Tummala 			rv = EFAULT;
2992e8174f4eSRamaswamy Tummala 			goto out;
2993e8174f4eSRamaswamy Tummala 		}
2994d1a5c838SRamaswamy Tummala 
2995e8174f4eSRamaswamy Tummala 		hca_guid = query_hca_32->hca_guid;
2996e8174f4eSRamaswamy Tummala 		device_path = (char *)(uintptr_t)query_hca_32->hca_device_path;
2997e8174f4eSRamaswamy Tummala 		device_path_alloc_sz = query_hca_32->hca_device_path_alloc_sz;
2998bf8d275aSToomas Soome 		break;
2999e8174f4eSRamaswamy Tummala #endif
3000bf8d275aSToomas Soome 	default:
3001e8174f4eSRamaswamy Tummala 		query_hca = kmem_zalloc(sizeof (ibnex_ctl_query_hca_t),
3002e8174f4eSRamaswamy Tummala 		    KM_SLEEP);
3003e8174f4eSRamaswamy Tummala 
3004e8174f4eSRamaswamy Tummala 		if (ddi_copyin((void *)arg, query_hca,
3005e8174f4eSRamaswamy Tummala 		    sizeof (ibnex_ctl_query_hca_t), mode) != 0) {
3006e8174f4eSRamaswamy Tummala 			IBTF_DPRINTF_L2("ibnex",
3007e8174f4eSRamaswamy Tummala 			    "\tctl_query_hca: ddi_copyin err 2");
3008e8174f4eSRamaswamy Tummala 			rv = EFAULT;
3009e8174f4eSRamaswamy Tummala 			goto out;
3010e8174f4eSRamaswamy Tummala 		}
3011e8174f4eSRamaswamy Tummala 
3012e8174f4eSRamaswamy Tummala 		hca_guid = query_hca->hca_guid;
3013e8174f4eSRamaswamy Tummala 		device_path = query_hca->hca_device_path;
3014e8174f4eSRamaswamy Tummala 		device_path_alloc_sz = query_hca->hca_device_path_alloc_sz;
3015bf8d275aSToomas Soome 		break;
3016d1a5c838SRamaswamy Tummala 	}
3017d1a5c838SRamaswamy Tummala 
3018e8174f4eSRamaswamy Tummala 	hca_attr = kmem_zalloc(sizeof (ibt_hca_attr_t), KM_SLEEP);
3019e8174f4eSRamaswamy Tummala 	hca_device_path = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
3020e8174f4eSRamaswamy Tummala 
3021e8174f4eSRamaswamy Tummala 	if (ibtl_ibnex_query_hca_byguid(hca_guid, hca_attr,
3022e8174f4eSRamaswamy Tummala 	    driver_name, sizeof (driver_name), &instance, hca_device_path)
3023e8174f4eSRamaswamy Tummala 	    != IBT_SUCCESS) {
3024d1a5c838SRamaswamy Tummala 		rv = ENXIO;
3025d1a5c838SRamaswamy Tummala 		goto out;
3026d1a5c838SRamaswamy Tummala 	}
3027d1a5c838SRamaswamy Tummala 
3028e8174f4eSRamaswamy Tummala 	hca_device_path_len = strlen(hca_device_path) + 1;
3029e8174f4eSRamaswamy Tummala 
3030bf8d275aSToomas Soome 	switch (model) {
3031bf8d275aSToomas Soome 		char		*device_path64;
3032e8174f4eSRamaswamy Tummala #ifdef	_MULTI_DATAMODEL
3033bf8d275aSToomas Soome 		caddr32_t	device_path32;
3034bf8d275aSToomas Soome 	case DDI_MODEL_ILP32:
3035bf8d275aSToomas Soome 
3036bf8d275aSToomas Soome 		if (device_path_alloc_sz >= hca_device_path_len)
3037bf8d275aSToomas Soome 			device_path32 = (uintptr_t)device_path;
3038bf8d275aSToomas Soome 		else
3039bf8d275aSToomas Soome 			device_path32 = (uintptr_t)NULL;
3040e8174f4eSRamaswamy Tummala 
3041e8174f4eSRamaswamy Tummala 		IBNEX_CTL_CP_HCA_INFO(&query_hca_32->hca_info, hca_attr,
3042bf8d275aSToomas Soome 		    driver_name, instance, device_path32,
3043e8174f4eSRamaswamy Tummala 		    device_path_alloc_sz, hca_device_path_len);
3044e8174f4eSRamaswamy Tummala 
3045e8174f4eSRamaswamy Tummala 		/* copy hca information to the user space */
3046e8174f4eSRamaswamy Tummala 		if (ddi_copyout(&query_hca_32->hca_info,
3047e8174f4eSRamaswamy Tummala 		    &((ibnex_ctl_query_hca_32_t *)arg)->hca_info,
3048e8174f4eSRamaswamy Tummala 		    sizeof (ibnex_ctl_hca_info_32_t), mode) != 0) {
3049e8174f4eSRamaswamy Tummala 			IBTF_DPRINTF_L2("ibnex",
3050e8174f4eSRamaswamy Tummala 			    "\tctl_query_hca: ddi_copyout err 1");
3051e8174f4eSRamaswamy Tummala 			rv = EFAULT;
3052e8174f4eSRamaswamy Tummala 			goto out;
3053e8174f4eSRamaswamy Tummala 		}
3054bf8d275aSToomas Soome 		break;
3055e8174f4eSRamaswamy Tummala #endif
3056bf8d275aSToomas Soome 	default:
3057bf8d275aSToomas Soome 		if (device_path_alloc_sz >= hca_device_path_len)
3058bf8d275aSToomas Soome 			device_path64 = device_path;
3059bf8d275aSToomas Soome 		else
3060bf8d275aSToomas Soome 			device_path64 = NULL;
3061bf8d275aSToomas Soome 
3062e8174f4eSRamaswamy Tummala 		IBNEX_CTL_CP_HCA_INFO(&query_hca->hca_info, hca_attr,
3063bf8d275aSToomas Soome 		    driver_name, instance, device_path64,
3064e8174f4eSRamaswamy Tummala 		    device_path_alloc_sz, hca_device_path_len);
3065e8174f4eSRamaswamy Tummala 
3066e8174f4eSRamaswamy Tummala 		/* copy hca information to the user space */
3067e8174f4eSRamaswamy Tummala 		if (ddi_copyout(&query_hca->hca_info,
3068e8174f4eSRamaswamy Tummala 		    &((ibnex_ctl_query_hca_t *)arg)->hca_info,
3069e8174f4eSRamaswamy Tummala 		    sizeof (ibnex_ctl_hca_info_t), mode) != 0) {
3070e8174f4eSRamaswamy Tummala 			IBTF_DPRINTF_L2("ibnex",
3071e8174f4eSRamaswamy Tummala 			    "\tctl_query_hca: ddi_copyout err 2");
3072e8174f4eSRamaswamy Tummala 			rv = EFAULT;
3073e8174f4eSRamaswamy Tummala 			goto out;
3074e8174f4eSRamaswamy Tummala 		}
3075bf8d275aSToomas Soome 		break;
3076e8174f4eSRamaswamy Tummala 	}
3077e8174f4eSRamaswamy Tummala 
3078e8174f4eSRamaswamy Tummala 	if (device_path_alloc_sz >= hca_device_path_len) {
3079e8174f4eSRamaswamy Tummala 		if (ddi_copyout(hca_device_path,
3080e8174f4eSRamaswamy Tummala 		    device_path,
3081e8174f4eSRamaswamy Tummala 		    hca_device_path_len, mode) != 0) {
3082e8174f4eSRamaswamy Tummala 			IBTF_DPRINTF_L2("ibnex", "\tctl_query_hca: "
3083e8174f4eSRamaswamy Tummala 			    "ddi_copyout err copying device path");
3084e8174f4eSRamaswamy Tummala 			rv = EFAULT;
3085e8174f4eSRamaswamy Tummala 		}
3086d1a5c838SRamaswamy Tummala 	}
3087d1a5c838SRamaswamy Tummala 
3088d1a5c838SRamaswamy Tummala out:
3089e8174f4eSRamaswamy Tummala 	if (query_hca)
3090e8174f4eSRamaswamy Tummala 		kmem_free(query_hca, sizeof (ibnex_ctl_query_hca_t));
3091bf8d275aSToomas Soome #ifdef	_MULTI_DATAMODEL
3092e8174f4eSRamaswamy Tummala 	if (query_hca_32)
3093e8174f4eSRamaswamy Tummala 		kmem_free(query_hca_32, sizeof (ibnex_ctl_query_hca_32_t));
3094bf8d275aSToomas Soome #endif
3095e8174f4eSRamaswamy Tummala 	if (hca_attr)
3096e8174f4eSRamaswamy Tummala 		kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
3097e8174f4eSRamaswamy Tummala 	if (hca_device_path)
3098e8174f4eSRamaswamy Tummala 		kmem_free(hca_device_path, MAXPATHLEN);
3099e8174f4eSRamaswamy Tummala 
3100d1a5c838SRamaswamy Tummala 	return (rv);
3101d1a5c838SRamaswamy Tummala }
3102d1a5c838SRamaswamy Tummala 
3103d1a5c838SRamaswamy Tummala #define	IBNEX_CTL_CP_PORT_INFO(x, y, sgid_tbl, pkey_tbl)	\
3104d1a5c838SRamaswamy Tummala {								\
3105d1a5c838SRamaswamy Tummala 	(x)->p_lid		= (y)->p_opaque1;		\
3106d1a5c838SRamaswamy Tummala 	(x)->p_qkey_violations	= (y)->p_qkey_violations;	\
3107d1a5c838SRamaswamy Tummala 	(x)->p_pkey_violations	= (y)->p_pkey_violations;	\
3108d1a5c838SRamaswamy Tummala 	(x)->p_sm_sl		= (y)->p_sm_sl;			\
3109d1a5c838SRamaswamy Tummala 	(x)->p_phys_state	= (y)->p_phys_state;		\
3110d1a5c838SRamaswamy Tummala 	(x)->p_sm_lid		= (y)->p_sm_lid;		\
3111d1a5c838SRamaswamy Tummala 	(x)->p_linkstate	= (y)->p_linkstate;		\
3112d1a5c838SRamaswamy Tummala 	(x)->p_port_num		= (y)->p_port_num;		\
3113d1a5c838SRamaswamy Tummala 	(x)->p_width_supported	= (y)->p_width_supported;	\
3114d1a5c838SRamaswamy Tummala 	(x)->p_width_enabled	= (y)->p_width_enabled;		\
3115d1a5c838SRamaswamy Tummala 	(x)->p_width_active	= (y)->p_width_active;		\
3116d1a5c838SRamaswamy Tummala 	(x)->p_mtu		= (y)->p_mtu;			\
3117d1a5c838SRamaswamy Tummala 	(x)->p_lmc		= (y)->p_lmc;			\
3118d1a5c838SRamaswamy Tummala 	(x)->p_speed_supported	= (y)->p_speed_supported;	\
3119d1a5c838SRamaswamy Tummala 	(x)->p_speed_enabled	= (y)->p_speed_enabled;		\
3120d1a5c838SRamaswamy Tummala 	(x)->p_speed_active	= (y)->p_speed_active;		\
3121d1a5c838SRamaswamy Tummala 	(x)->p_sgid_tbl		= (sgid_tbl);			\
3122d1a5c838SRamaswamy Tummala 	(x)->p_sgid_tbl_sz	= (y)->p_sgid_tbl_sz;		\
3123d1a5c838SRamaswamy Tummala 	(x)->p_pkey_tbl		= (pkey_tbl);			\
3124d1a5c838SRamaswamy Tummala 	(x)->p_pkey_tbl_sz	= (y)->p_pkey_tbl_sz;		\
3125d1a5c838SRamaswamy Tummala 	(x)->p_def_pkey_ix	= (y)->p_def_pkey_ix;		\
3126d1a5c838SRamaswamy Tummala 	(x)->p_max_vl		= (y)->p_max_vl;		\
3127d1a5c838SRamaswamy Tummala 	(x)->p_init_type_reply	= (y)->p_init_type_reply;	\
3128d1a5c838SRamaswamy Tummala 	(x)->p_subnet_timeout	= (y)->p_subnet_timeout;	\
3129d1a5c838SRamaswamy Tummala 	(x)->p_capabilities	= (y)->p_capabilities;		\
3130d1a5c838SRamaswamy Tummala 	(x)->p_msg_sz		= (y)->p_msg_sz;		\
3131d1a5c838SRamaswamy Tummala }
3132d1a5c838SRamaswamy Tummala 
3133d1a5c838SRamaswamy Tummala /*
3134d1a5c838SRamaswamy Tummala  * IOCTL implementation to query HCA port attributes
3135d1a5c838SRamaswamy Tummala  */
3136d1a5c838SRamaswamy Tummala static int
ibnex_ctl_query_hca_port(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)3137d1a5c838SRamaswamy Tummala ibnex_ctl_query_hca_port(dev_t dev, int cmd, intptr_t arg, int mode,
3138d1a5c838SRamaswamy Tummala     cred_t *credp, int *rvalp)
3139d1a5c838SRamaswamy Tummala {
3140d1a5c838SRamaswamy Tummala 	ibt_hca_portinfo_t		*ibt_pi;
3141d1a5c838SRamaswamy Tummala 	uint_t				nports;
3142d1a5c838SRamaswamy Tummala 	uint_t				size = 0;
3143d1a5c838SRamaswamy Tummala 	int				rv = 0;
3144d1a5c838SRamaswamy Tummala 	ibnex_ctl_query_hca_port_t	*query_hca_port = NULL;
3145d1a5c838SRamaswamy Tummala 	ibnex_ctl_query_hca_port_32_t	*query_hca_port_32 = NULL;
3146d1a5c838SRamaswamy Tummala 	uint_t				sgid_tbl_sz;
3147d1a5c838SRamaswamy Tummala 	uint16_t			pkey_tbl_sz;
3148d080a1d7SRamaswamy Tummala 	ibt_hca_attr_t			hca_attr;
3149d1a5c838SRamaswamy Tummala 
3150d1a5c838SRamaswamy Tummala 	IBTF_DPRINTF_L4("ibnex", "\tctl_query_hca_port: cmd=%x, arg=%p, "
3151d1a5c838SRamaswamy Tummala 	    "mode=%x, cred=%p, rval=%p, dev=0x%x", cmd, arg, mode, credp,
3152d1a5c838SRamaswamy Tummala 	    rvalp, dev);
3153d1a5c838SRamaswamy Tummala 
3154d1a5c838SRamaswamy Tummala 	query_hca_port = kmem_zalloc(sizeof (ibnex_ctl_query_hca_port_t),
3155d1a5c838SRamaswamy Tummala 	    KM_SLEEP);
3156d1a5c838SRamaswamy Tummala 
3157d1a5c838SRamaswamy Tummala #ifdef	_MULTI_DATAMODEL
3158d1a5c838SRamaswamy Tummala 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
3159d1a5c838SRamaswamy Tummala 		query_hca_port_32 = kmem_zalloc(
3160d1a5c838SRamaswamy Tummala 		    sizeof (ibnex_ctl_query_hca_port_32_t), KM_SLEEP);
3161d1a5c838SRamaswamy Tummala 
3162d1a5c838SRamaswamy Tummala 		if (ddi_copyin((void *)arg, query_hca_port_32,
3163d1a5c838SRamaswamy Tummala 		    sizeof (ibnex_ctl_query_hca_port_32_t), mode) != 0) {
3164d1a5c838SRamaswamy Tummala 			IBTF_DPRINTF_L2("ibnex",
3165e8174f4eSRamaswamy Tummala 			    "\tctl_query_hca_port: ddi_copyin err 1");
3166d1a5c838SRamaswamy Tummala 			rv = EFAULT;
3167d1a5c838SRamaswamy Tummala 			goto out;
3168d1a5c838SRamaswamy Tummala 		}
3169d1a5c838SRamaswamy Tummala 
3170d1a5c838SRamaswamy Tummala 		query_hca_port->hca_guid = query_hca_port_32->hca_guid;
3171d1a5c838SRamaswamy Tummala 		query_hca_port->port_num = query_hca_port_32->port_num;
3172d1a5c838SRamaswamy Tummala 
3173d1a5c838SRamaswamy Tummala 		query_hca_port->sgid_tbl =
3174d1a5c838SRamaswamy Tummala 		    (ib_gid_t *)(uintptr_t)query_hca_port_32->sgid_tbl;
3175d1a5c838SRamaswamy Tummala 		query_hca_port->sgid_tbl_alloc_sz =
3176d1a5c838SRamaswamy Tummala 		    query_hca_port_32->sgid_tbl_alloc_sz;
3177d1a5c838SRamaswamy Tummala 
3178d1a5c838SRamaswamy Tummala 		query_hca_port->pkey_tbl =
3179d1a5c838SRamaswamy Tummala 		    (ib_pkey_t *)(uintptr_t)query_hca_port_32->pkey_tbl;
3180d1a5c838SRamaswamy Tummala 		query_hca_port->pkey_tbl_alloc_sz =
3181d1a5c838SRamaswamy Tummala 		    query_hca_port_32->pkey_tbl_alloc_sz;
3182d1a5c838SRamaswamy Tummala 
3183d1a5c838SRamaswamy Tummala 	} else
3184d1a5c838SRamaswamy Tummala #endif
3185d1a5c838SRamaswamy Tummala 	{
3186d1a5c838SRamaswamy Tummala 		if (ddi_copyin((void *)arg, query_hca_port,
3187d1a5c838SRamaswamy Tummala 		    sizeof (ibnex_ctl_query_hca_port_t), mode) != 0) {
3188d1a5c838SRamaswamy Tummala 			IBTF_DPRINTF_L2("ibnex",
3189d1a5c838SRamaswamy Tummala 			    "\tctl_query_hca_port: ddi_copyin err 2");
3190d1a5c838SRamaswamy Tummala 			rv = EFAULT;
3191d1a5c838SRamaswamy Tummala 			goto out;
3192d1a5c838SRamaswamy Tummala 		}
3193d1a5c838SRamaswamy Tummala 	}
3194d1a5c838SRamaswamy Tummala 
3195d080a1d7SRamaswamy Tummala 	if (ibt_query_hca_byguid(query_hca_port->hca_guid, &hca_attr) !=
3196d080a1d7SRamaswamy Tummala 	    IBT_SUCCESS) {
3197d080a1d7SRamaswamy Tummala 		rv = ENXIO;
3198d080a1d7SRamaswamy Tummala 		goto out;
3199d080a1d7SRamaswamy Tummala 	}
3200d080a1d7SRamaswamy Tummala 
3201d080a1d7SRamaswamy Tummala 	if (query_hca_port->port_num == 0 ||
3202d080a1d7SRamaswamy Tummala 	    query_hca_port->port_num > hca_attr.hca_nports) {
3203d080a1d7SRamaswamy Tummala 		rv = ENOENT;
3204d1a5c838SRamaswamy Tummala 		goto out;
3205d1a5c838SRamaswamy Tummala 	}
3206d1a5c838SRamaswamy Tummala 
3207d1a5c838SRamaswamy Tummala 	/*
3208d1a5c838SRamaswamy Tummala 	 * Query hca port attributes and copy them to the user space.
3209d1a5c838SRamaswamy Tummala 	 */
3210d1a5c838SRamaswamy Tummala 
3211d1a5c838SRamaswamy Tummala 	if (ibt_query_hca_ports_byguid(query_hca_port->hca_guid,
3212d1a5c838SRamaswamy Tummala 	    query_hca_port->port_num, &ibt_pi, &nports, &size) != IBT_SUCCESS) {
3213d080a1d7SRamaswamy Tummala 		rv = ENXIO;
3214d1a5c838SRamaswamy Tummala 		goto out;
3215d1a5c838SRamaswamy Tummala 	}
3216d1a5c838SRamaswamy Tummala 
3217d1a5c838SRamaswamy Tummala 	sgid_tbl_sz = MIN(query_hca_port->sgid_tbl_alloc_sz,
3218d1a5c838SRamaswamy Tummala 	    ibt_pi->p_sgid_tbl_sz);
3219d1a5c838SRamaswamy Tummala 
3220d1a5c838SRamaswamy Tummala 	pkey_tbl_sz = MIN(query_hca_port->pkey_tbl_alloc_sz,
3221d1a5c838SRamaswamy Tummala 	    ibt_pi->p_pkey_tbl_sz);
3222d1a5c838SRamaswamy Tummala 
3223d1a5c838SRamaswamy Tummala #ifdef	_MULTI_DATAMODEL
3224d1a5c838SRamaswamy Tummala 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
3225d1a5c838SRamaswamy Tummala 		IBNEX_CTL_CP_PORT_INFO(
3226d1a5c838SRamaswamy Tummala 		    &query_hca_port_32->port_info, ibt_pi,
3227d1a5c838SRamaswamy Tummala 		    query_hca_port_32->sgid_tbl, query_hca_port_32->pkey_tbl);
3228d1a5c838SRamaswamy Tummala 
3229d1a5c838SRamaswamy Tummala 		if (ddi_copyout(&query_hca_port_32->port_info,
3230d1a5c838SRamaswamy Tummala 		    &((ibnex_ctl_query_hca_port_32_t *)arg)->port_info,
3231d1a5c838SRamaswamy Tummala 		    sizeof (ibnex_ctl_hca_port_info_32_t), mode) != 0 ||
3232d1a5c838SRamaswamy Tummala 
3233d1a5c838SRamaswamy Tummala 		    ddi_copyout(ibt_pi->p_sgid_tbl,
3234d1a5c838SRamaswamy Tummala 		    query_hca_port->sgid_tbl,
3235d1a5c838SRamaswamy Tummala 		    sgid_tbl_sz * sizeof (ib_gid_t), mode) != 0 ||
3236d1a5c838SRamaswamy Tummala 
3237d1a5c838SRamaswamy Tummala 		    ddi_copyout(ibt_pi->p_pkey_tbl,
3238d1a5c838SRamaswamy Tummala 		    query_hca_port->pkey_tbl,
3239d1a5c838SRamaswamy Tummala 		    pkey_tbl_sz * sizeof (ib_pkey_t), mode) != 0) {
3240d1a5c838SRamaswamy Tummala 
3241d1a5c838SRamaswamy Tummala 			IBTF_DPRINTF_L2("ibnex",
3242d1a5c838SRamaswamy Tummala 			    "\tctl_query_hca_port: ddi_copyout err 2");
3243d1a5c838SRamaswamy Tummala 			rv = EFAULT;
3244d1a5c838SRamaswamy Tummala 			goto out;
3245d1a5c838SRamaswamy Tummala 		}
3246d1a5c838SRamaswamy Tummala 	} else
3247d1a5c838SRamaswamy Tummala #endif
3248d1a5c838SRamaswamy Tummala 	{
3249d1a5c838SRamaswamy Tummala 		IBNEX_CTL_CP_PORT_INFO(
3250d1a5c838SRamaswamy Tummala 		    &query_hca_port->port_info, ibt_pi,
3251d1a5c838SRamaswamy Tummala 		    query_hca_port->sgid_tbl, query_hca_port->pkey_tbl);
3252d1a5c838SRamaswamy Tummala 
3253d1a5c838SRamaswamy Tummala 		if (ddi_copyout(&query_hca_port->port_info,
3254d1a5c838SRamaswamy Tummala 		    &((ibnex_ctl_query_hca_port_t *)arg)->port_info,
3255d1a5c838SRamaswamy Tummala 		    sizeof (ibnex_ctl_hca_port_info_t), mode) != 0 ||
3256d1a5c838SRamaswamy Tummala 
3257d1a5c838SRamaswamy Tummala 		    ddi_copyout(ibt_pi->p_sgid_tbl,
3258d1a5c838SRamaswamy Tummala 		    query_hca_port->sgid_tbl,
3259d1a5c838SRamaswamy Tummala 		    sgid_tbl_sz * sizeof (ib_gid_t), mode) != 0 ||
3260d1a5c838SRamaswamy Tummala 
3261d1a5c838SRamaswamy Tummala 		    ddi_copyout(ibt_pi->p_pkey_tbl,
3262d1a5c838SRamaswamy Tummala 		    query_hca_port->pkey_tbl,
3263d1a5c838SRamaswamy Tummala 		    pkey_tbl_sz * sizeof (ib_pkey_t), mode) != 0) {
3264d1a5c838SRamaswamy Tummala 
3265d1a5c838SRamaswamy Tummala 			IBTF_DPRINTF_L2("ibnex",
3266d1a5c838SRamaswamy Tummala 			    "\tctl_query_hca_port: ddi_copyout err 2");
3267d1a5c838SRamaswamy Tummala 			rv = EFAULT;
3268d1a5c838SRamaswamy Tummala 			goto out;
3269d1a5c838SRamaswamy Tummala 		}
3270d1a5c838SRamaswamy Tummala 	}
3271d1a5c838SRamaswamy Tummala 
3272d1a5c838SRamaswamy Tummala out:
3273d1a5c838SRamaswamy Tummala 	if (size > 0)
3274d1a5c838SRamaswamy Tummala 		ibt_free_portinfo(ibt_pi, size);
3275d1a5c838SRamaswamy Tummala 
3276d1a5c838SRamaswamy Tummala 	if (query_hca_port)
3277d1a5c838SRamaswamy Tummala 		kmem_free(query_hca_port, sizeof (ibnex_ctl_query_hca_port_t));
3278d1a5c838SRamaswamy Tummala 
3279d1a5c838SRamaswamy Tummala 	if (query_hca_port_32)
3280d1a5c838SRamaswamy Tummala 		kmem_free(query_hca_port_32,
3281d1a5c838SRamaswamy Tummala 		    sizeof (ibnex_ctl_query_hca_port_32_t));
3282d1a5c838SRamaswamy Tummala 	return (rv);
3283d1a5c838SRamaswamy Tummala }
3284