19e86db79SHyon Kim /*
29e86db79SHyon Kim  * CDDL HEADER START
39e86db79SHyon Kim  *
49e86db79SHyon Kim  * The contents of this file are subject to the terms of the
59e86db79SHyon Kim  * Common Development and Distribution License (the "License").
69e86db79SHyon Kim  * You may not use this file except in compliance with the License.
79e86db79SHyon Kim  *
89e86db79SHyon Kim  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99e86db79SHyon Kim  * or http://www.opensolaris.org/os/licensing.
109e86db79SHyon Kim  * See the License for the specific language governing permissions
119e86db79SHyon Kim  * and limitations under the License.
129e86db79SHyon Kim  *
139e86db79SHyon Kim  * When distributing Covered Code, include this CDDL HEADER in each
149e86db79SHyon Kim  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159e86db79SHyon Kim  * If applicable, add the following below this CDDL HEADER, with the
169e86db79SHyon Kim  * fields enclosed by brackets "[]" replaced with your own identifying
179e86db79SHyon Kim  * information: Portions Copyright [yyyy] [name of copyright owner]
189e86db79SHyon Kim  *
199e86db79SHyon Kim  * CDDL HEADER END
209e86db79SHyon Kim  */
219e86db79SHyon Kim 
229e86db79SHyon Kim /*
239e86db79SHyon Kim  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
249e86db79SHyon Kim  * Use is subject to license terms.
259e86db79SHyon Kim  */
26*00f453f4SRob Johnston /*
27*00f453f4SRob Johnston  * Copyright 2019 Joyent, Inc.
28*00f453f4SRob Johnston  */
299e86db79SHyon Kim 
309e86db79SHyon Kim #include    <sun_sas.h>
319e86db79SHyon Kim 
329e86db79SHyon Kim /*
339e86db79SHyon Kim  * Discover an HBA node with  matching path.
349e86db79SHyon Kim  * The di_node_t argument should be the root of the device tree.
359e86db79SHyon Kim  * This routine assumes the locks have been taken
369e86db79SHyon Kim  */
379e86db79SHyon Kim static int
find_matching_hba(di_node_t node,void * arg)389e86db79SHyon Kim find_matching_hba(di_node_t node, void *arg)
399e86db79SHyon Kim {
409e86db79SHyon Kim 	int *propData, rval;
419e86db79SHyon Kim 	walkarg_t *wa = (walkarg_t *)arg;
429e86db79SHyon Kim 	char	*devpath, fulldevpath[MAXPATHLEN];
439e86db79SHyon Kim 
449e86db79SHyon Kim 	/* Skip stub(instance -1) nodes */
459e86db79SHyon Kim 	if (IS_STUB_NODE(node)) {
469e86db79SHyon Kim 		return (DI_WALK_CONTINUE);
479e86db79SHyon Kim 	}
489e86db79SHyon Kim 
499e86db79SHyon Kim 	rval = di_prop_lookup_ints(DDI_DEV_T_ANY, node,
509e86db79SHyon Kim 	    "sm-hba-supported", &propData);
519e86db79SHyon Kim 	if (rval < 0) {
529e86db79SHyon Kim 		return (DI_WALK_CONTINUE);
539e86db79SHyon Kim 	} else {
549e86db79SHyon Kim 		if ((devpath = di_devfs_path(node)) == NULL) {
559e86db79SHyon Kim 			/* still continue to see if there is matching one. */
569e86db79SHyon Kim 			return (DI_WALK_CONTINUE);
579e86db79SHyon Kim 		}
589e86db79SHyon Kim 		(void) snprintf(fulldevpath, MAXPATHLEN, "%s%s", DEVICES_DIR,
599e86db79SHyon Kim 		    devpath);
609e86db79SHyon Kim 
619e86db79SHyon Kim 		if ((strstr(fulldevpath, wa->devpath)) != NULL) {
62*00f453f4SRob Johnston 			*wa->flag = B_TRUE;
639e86db79SHyon Kim 			/* Found a node. No need to walk any more. */
649e86db79SHyon Kim 			di_devfs_path_free(devpath);
659e86db79SHyon Kim 			return (DI_WALK_TERMINATE);
669e86db79SHyon Kim 		}
679e86db79SHyon Kim 		di_devfs_path_free(devpath);
689e86db79SHyon Kim 	}
699e86db79SHyon Kim 
709e86db79SHyon Kim 	return (DI_WALK_CONTINUE);
719e86db79SHyon Kim }
729e86db79SHyon Kim 
739e86db79SHyon Kim /*
749e86db79SHyon Kim  * Refreshes information about an HBA
759e86db79SHyon Kim  *
769e86db79SHyon Kim  * Note: This routine holds the locks in write mode
779e86db79SHyon Kim  *       during most of the processing, and as such, will cause
789e86db79SHyon Kim  *	 all other threads to block on entry into the library
799e86db79SHyon Kim  *	 until the refresh is complete.  An optimization would be
809e86db79SHyon Kim  *       to put fine-grain locking in for the open_handle structures.
819e86db79SHyon Kim  */
829e86db79SHyon Kim void
Sun_sasRefreshAdapterConfiguration()839e86db79SHyon Kim Sun_sasRefreshAdapterConfiguration()
849e86db79SHyon Kim {
859e86db79SHyon Kim 	const char		    ROUTINE[] =
869e86db79SHyon Kim 	    "Sun_sasRefreshAdapterConfiguration";
879e86db79SHyon Kim 	struct sun_sas_hba	    *hba_ptr;
889e86db79SHyon Kim 	di_node_t		    root;
899e86db79SHyon Kim 	hrtime_t		    start;
909e86db79SHyon Kim 	hrtime_t		    end;
919e86db79SHyon Kim 	double			    duration;
929e86db79SHyon Kim 	walkarg_t		    wa;
939e86db79SHyon Kim 
949e86db79SHyon Kim 	/*
959e86db79SHyon Kim 	 * We're going to be tweaking a lot of global lists, so write
969e86db79SHyon Kim 	 * lock them.
979e86db79SHyon Kim 	 */
989e86db79SHyon Kim 	lock(&all_hbas_lock);
999e86db79SHyon Kim 	lock(&open_handles_lock);
1009e86db79SHyon Kim 
1019e86db79SHyon Kim 	start = gethrtime();
1029e86db79SHyon Kim 	/* Grab device tree */
1039e86db79SHyon Kim 	if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL) {
1049e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
1059e86db79SHyon Kim 		    "Unable to load device tree for reason \"%s\"",
1069e86db79SHyon Kim 		    strerror(errno));
1079e86db79SHyon Kim 		unlock(&open_handles_lock);
1089e86db79SHyon Kim 		unlock(&all_hbas_lock);
1099e86db79SHyon Kim 		return;
1109e86db79SHyon Kim 	}
1119e86db79SHyon Kim 
1129e86db79SHyon Kim 	end = gethrtime();
1139e86db79SHyon Kim 	duration = end - start;
1149e86db79SHyon Kim 	duration /= HR_SECOND;
1159e86db79SHyon Kim 	log(LOG_DEBUG, ROUTINE, "Device tree init took "
1169e86db79SHyon Kim 	    "%.6f seconds", duration);
1179e86db79SHyon Kim 
1189e86db79SHyon Kim 	for (hba_ptr = global_hba_head; hba_ptr != NULL;
1199e86db79SHyon Kim 	    hba_ptr = hba_ptr->next) {
1209e86db79SHyon Kim 		wa.devpath = hba_ptr->device_path;
1219e86db79SHyon Kim 		wa.flag = (boolean_t *)calloc(1, sizeof (boolean_t));
1229e86db79SHyon Kim 		*wa.flag = B_FALSE;
1239e86db79SHyon Kim 
1249e86db79SHyon Kim 		if (di_walk_node(root, DI_WALK_SIBFIRST, &wa,
1259e86db79SHyon Kim 		    find_matching_hba) != 0) {
1269e86db79SHyon Kim 			log(LOG_DEBUG, ROUTINE, "di_walk_node failed.");
1279e86db79SHyon Kim 			unlock(&open_handles_lock);
1289e86db79SHyon Kim 			unlock(&all_hbas_lock);
1299e86db79SHyon Kim 			S_FREE(wa.flag);
1309e86db79SHyon Kim 			di_fini(root);
1319e86db79SHyon Kim 			return;
1329e86db79SHyon Kim 		}
1339e86db79SHyon Kim 
1349e86db79SHyon Kim 		if (*wa.flag == B_FALSE) {
1359e86db79SHyon Kim 			/*
1369e86db79SHyon Kim 			 * Keep the HBA as it is including open handles
1379e86db79SHyon Kim 			 * per the SM-HBA standards. Just mark it as invalid.
1389e86db79SHyon Kim 			 */
1399e86db79SHyon Kim 			log(LOG_DEBUG, ROUTINE, "No matching HBA found. %s",
1409e86db79SHyon Kim 			    hba_ptr->device_path);
1419e86db79SHyon Kim 			hba_ptr->invalid = B_TRUE;
1429e86db79SHyon Kim 		}
1439e86db79SHyon Kim 		S_FREE(wa.flag);
1449e86db79SHyon Kim 	}
1459e86db79SHyon Kim 
1469e86db79SHyon Kim 	/*
1479e86db79SHyon Kim 	 * Now we marked missing HBA(s). Redisoover hbas to refresh
1489e86db79SHyon Kim 	 * or add any new adapter to the hba list.
1499e86db79SHyon Kim 	 * Simply call devtree_get_all_hbas().
1509e86db79SHyon Kim 	 */
1519e86db79SHyon Kim 	if (devtree_get_all_hbas(root) != HBA_STATUS_OK) {
1529e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE, "devtree_get_all_hbas failed.");
1539e86db79SHyon Kim 	}
1549e86db79SHyon Kim 	di_fini(root);
1559e86db79SHyon Kim 
1569e86db79SHyon Kim 	unlock(&open_handles_lock);
1579e86db79SHyon Kim 	unlock(&all_hbas_lock);
1589e86db79SHyon Kim }
159