xref: /onnv-gate/usr/src/lib/fm/topo/modules/sun4v/sun4vpi/pi_defer.c (revision 11583:24344dea001d)
17205Ssd77468 /*
27205Ssd77468  * CDDL HEADER START
37205Ssd77468  *
47205Ssd77468  * The contents of this file are subject to the terms of the
57205Ssd77468  * Common Development and Distribution License (the "License").
67205Ssd77468  * You may not use this file except in compliance with the License.
77205Ssd77468  *
87205Ssd77468  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97205Ssd77468  * or http://www.opensolaris.org/os/licensing.
107205Ssd77468  * See the License for the specific language governing permissions
117205Ssd77468  * and limitations under the License.
127205Ssd77468  *
137205Ssd77468  * When distributing Covered Code, include this CDDL HEADER in each
147205Ssd77468  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157205Ssd77468  * If applicable, add the following below this CDDL HEADER, with the
167205Ssd77468  * fields enclosed by brackets "[]" replaced with your own identifying
177205Ssd77468  * information: Portions Copyright [yyyy] [name of copyright owner]
187205Ssd77468  *
197205Ssd77468  * CDDL HEADER END
207205Ssd77468  */
217205Ssd77468 
227205Ssd77468 /*
23*11583SSurya.Prakki@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
247205Ssd77468  * Use is subject to license terms.
257205Ssd77468  */
267205Ssd77468 
277205Ssd77468 /*
287205Ssd77468  * Some topology creation routines may need to defer completing enumeration
297205Ssd77468  * until after the entire PRI graph has been visited.  This file includes
307205Ssd77468  * the interfaces necessary to permit these routines to do this in a general
317205Ssd77468  * way.
327205Ssd77468  */
337205Ssd77468 
347205Ssd77468 #include <sys/types.h>
357205Ssd77468 #include <sys/time.h>
367205Ssd77468 #include <stddef.h>
377205Ssd77468 #include <inttypes.h>
387205Ssd77468 #include <strings.h>
397205Ssd77468 #include <string.h>
407205Ssd77468 #include <libuutil.h>
417205Ssd77468 #include <libnvpair.h>
427205Ssd77468 #include <sys/mdesc.h>
437205Ssd77468 #include <fm/topo_mod.h>
447205Ssd77468 #include <fm/topo_hc.h>
457205Ssd77468 #include "pi_impl.h"
467205Ssd77468 
4710665STom.Pothier@Sun.COM static uu_list_pool_t	*defer_pool = NULL;
4810665STom.Pothier@Sun.COM static uu_list_t	*defer_list = NULL;
497205Ssd77468 
507205Ssd77468 struct pi_defernode_s {
517205Ssd77468 	uu_list_node_t	defer_node;
527205Ssd77468 
537205Ssd77468 	mde_cookie_t	mde_node;	/* MDE node index */
547205Ssd77468 	tnode_t		*t_parent;	/* Parent topology node */
557205Ssd77468 	tnode_t		*t_node;	/* Topo node associated with MDE node */
567205Ssd77468 	void		*private;	/* Private data for defer routine */
577205Ssd77468 
587205Ssd77468 	pi_deferenum_fn_t *func;	/* Defered enumeration routine */
597205Ssd77468 };
607205Ssd77468 typedef struct pi_defernode_s pi_defernode_t;
617205Ssd77468 
627205Ssd77468 /* Routines to handle the list of topology parents and mde_nodes */
637205Ssd77468 static int  pi_deferlist_create(topo_mod_t *);
647205Ssd77468 static int  pi_deferlist_compare(const void *, const void *, void *);
657205Ssd77468 
667205Ssd77468 
677205Ssd77468 /*
687205Ssd77468  * Add a new routine to the list of deferred enumeration routines
697205Ssd77468  */
707205Ssd77468 int
pi_defer_add(topo_mod_t * mod,mde_cookie_t mde_node,tnode_t * t_parent,tnode_t * t_node,pi_deferenum_fn_t func,void * private)717205Ssd77468 pi_defer_add(topo_mod_t *mod, mde_cookie_t mde_node, tnode_t *t_parent,
727205Ssd77468     tnode_t *t_node, pi_deferenum_fn_t func, void *private)
737205Ssd77468 {
747205Ssd77468 	int		result;
757205Ssd77468 	uu_list_index_t	idx;
767205Ssd77468 	pi_defernode_t	*dnp;
777205Ssd77468 
787205Ssd77468 	if (defer_list == NULL) {
797205Ssd77468 		result = pi_deferlist_create(mod);
807205Ssd77468 		if (result != 0) {
817205Ssd77468 			return (result);
827205Ssd77468 		}
837205Ssd77468 	}
847205Ssd77468 
857205Ssd77468 	/*
867205Ssd77468 	 * Create a data structure to store information about the node for
877205Ssd77468 	 * which to defer enumeration.  The defer_pool is created by the
887205Ssd77468 	 * list creation routine, above.
897205Ssd77468 	 */
907205Ssd77468 	dnp = topo_mod_zalloc(mod, sizeof (pi_defernode_t));
917205Ssd77468 	if (dnp == NULL) {
92*11583SSurya.Prakki@Sun.COM 		(void) topo_mod_seterrno(mod, EMOD_NOMEM);
937205Ssd77468 		return (-1);
947205Ssd77468 	}
957205Ssd77468 	uu_list_node_init(dnp, &(dnp->defer_node), defer_pool);
967205Ssd77468 
977205Ssd77468 	dnp->mde_node	= mde_node;
987205Ssd77468 	dnp->t_parent	= t_parent;
997205Ssd77468 	dnp->t_node	= t_node;
1007205Ssd77468 	dnp->private	= private;
1017205Ssd77468 	dnp->func	= func;
1027205Ssd77468 
1037205Ssd77468 	(void) uu_list_find(defer_list, dnp, NULL, &idx);
1047205Ssd77468 	uu_list_insert(defer_list, dnp, idx);
1057205Ssd77468 
1067205Ssd77468 	return (0);
1077205Ssd77468 }
1087205Ssd77468 
1097205Ssd77468 
1107205Ssd77468 /*
1117205Ssd77468  * Execute the list of deferred enumeration routines, destroying the list as
1127205Ssd77468  * we go.
1137205Ssd77468  */
1147205Ssd77468 int
pi_defer_exec(topo_mod_t * mod,md_t * mdp)1157205Ssd77468 pi_defer_exec(topo_mod_t *mod, md_t *mdp)
1167205Ssd77468 {
1177205Ssd77468 	int		result;
1187205Ssd77468 
1197205Ssd77468 	void		*dvp;
1207205Ssd77468 	pi_defernode_t	*dp;
1217205Ssd77468 	topo_instance_t	inst;
1227205Ssd77468 	mde_cookie_t	mde_node;
1237205Ssd77468 	tnode_t		*t_parent;
1247205Ssd77468 	tnode_t		*t_node;
1257205Ssd77468 	void		*private;
1267205Ssd77468 	char		*hc_name;
1277205Ssd77468 
1287205Ssd77468 	pi_deferenum_fn_t *func;
1297205Ssd77468 
1307205Ssd77468 	topo_mod_dprintf(mod, "beginning deferred enumerator execution\n");
1317205Ssd77468 	if (defer_list == NULL) {
1327205Ssd77468 		topo_mod_dprintf(mod, "no deferred enumerators.  done.\n");
1337205Ssd77468 		return (0);
1347205Ssd77468 	}
1357205Ssd77468 
1367205Ssd77468 	while ((dvp = uu_list_first(defer_list)) != NULL) {
1377205Ssd77468 		/* Extract the necessary information from the defernode_t */
1387205Ssd77468 		dp = (pi_defernode_t *)dvp;
1397205Ssd77468 		mde_node = dp->mde_node;
1407205Ssd77468 		t_parent = dp->t_parent;
1417205Ssd77468 		t_node   = dp->t_node;
1427205Ssd77468 		private  = dp->private;
1437205Ssd77468 		func	 = dp->func;
1447205Ssd77468 
1457205Ssd77468 		/*
1467205Ssd77468 		 * Remove the element from the list.  Once we are done calling
1477205Ssd77468 		 * the routine we do not need it any more.
1487205Ssd77468 		 */
1497205Ssd77468 		uu_list_remove(defer_list, dvp);
1507205Ssd77468 		uu_list_node_fini(dp, &(dp->defer_node), defer_pool);
1517205Ssd77468 		topo_mod_free(mod, dp, sizeof (pi_defernode_t));
1527205Ssd77468 
1537205Ssd77468 		/* Get the instance value from the mde node */
1547205Ssd77468 		if (pi_get_instance(mod, mdp, mde_node, &inst) != 0) {
1557205Ssd77468 			topo_mod_dprintf(mod, "deferred node_0x%llx invalid\n",
1567205Ssd77468 			    (uint64_t)mde_node);
1577205Ssd77468 
1587205Ssd77468 			/* Move on to the next node */
159*11583SSurya.Prakki@Sun.COM 			(void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM);
1607205Ssd77468 			continue;
1617205Ssd77468 		}
1627205Ssd77468 
1637205Ssd77468 		/* Get the hc name from the mde node */
1647205Ssd77468 		hc_name = pi_get_topo_hc_name(mod, mdp, mde_node);
1657205Ssd77468 		if (hc_name == NULL) {
1667205Ssd77468 			topo_mod_dprintf(mod,
1677205Ssd77468 			    "deferred node_0x%llx has invalid NULL hc_name\n",
1687205Ssd77468 			    (uint64_t)mde_node);
1697205Ssd77468 
1707205Ssd77468 			/* Move on to the next node */
171*11583SSurya.Prakki@Sun.COM 			(void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM);
1727205Ssd77468 			continue;
1737205Ssd77468 		}
1747205Ssd77468 		topo_mod_dprintf(mod,
1757205Ssd77468 		    "calling deferred enumerator for node_0x%llx\n",
1767205Ssd77468 		    (uint64_t)mde_node);
1777205Ssd77468 
1787205Ssd77468 		/* Call the deferred enumeration function */
1797205Ssd77468 		result = (func)(mod, mdp, mde_node, inst, t_parent, hc_name,
1807205Ssd77468 		    t_node, private);
1817205Ssd77468 		if (result != 0) {
1827205Ssd77468 			topo_mod_dprintf(mod,
1837205Ssd77468 			    "deferred enumeration for node_0x%llx failed\n",
1847205Ssd77468 			    (uint64_t)mde_node);
185*11583SSurya.Prakki@Sun.COM 			(void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM);
1867205Ssd77468 		}
1877205Ssd77468 
1887205Ssd77468 		/* Clean up from the deferred call */
1897205Ssd77468 		topo_mod_strfree(mod, hc_name);
1907205Ssd77468 	}
1917205Ssd77468 	topo_mod_dprintf(mod, "deferred enumeration completed.\n");
1927205Ssd77468 
1937205Ssd77468 	uu_list_destroy(defer_list);
1947205Ssd77468 	uu_list_pool_destroy(defer_pool);
19510665STom.Pothier@Sun.COM 	defer_list = NULL;
19610665STom.Pothier@Sun.COM 	defer_pool = NULL;
1977205Ssd77468 
1987205Ssd77468 	return (0);
1997205Ssd77468 }
2007205Ssd77468 
2017205Ssd77468 
2027205Ssd77468 static int
pi_deferlist_create(topo_mod_t * mod)2037205Ssd77468 pi_deferlist_create(topo_mod_t *mod)
2047205Ssd77468 {
2057205Ssd77468 	/* Initialize the uutil list structure */
2067205Ssd77468 	defer_pool = uu_list_pool_create("pi_defer_pool",
2077205Ssd77468 	    sizeof (pi_defernode_t), offsetof(pi_defernode_t, defer_node),
2087205Ssd77468 	    pi_deferlist_compare, 0);
2097205Ssd77468 	if (defer_pool == NULL) {
210*11583SSurya.Prakki@Sun.COM 		(void) topo_mod_seterrno(mod, EMOD_NOMEM);
2117205Ssd77468 		return (-1);
2127205Ssd77468 	}
2137205Ssd77468 	defer_list = uu_list_create(defer_pool, NULL, 0);
2147205Ssd77468 	if (defer_list == NULL) {
2157205Ssd77468 		uu_list_pool_destroy(defer_pool);
21610665STom.Pothier@Sun.COM 		defer_pool = NULL;
217*11583SSurya.Prakki@Sun.COM 		(void) topo_mod_seterrno(mod, EMOD_NOMEM);
2187205Ssd77468 		return (-1);
2197205Ssd77468 	}
2207205Ssd77468 
2217205Ssd77468 	return (0);
2227205Ssd77468 }
2237205Ssd77468 
2247205Ssd77468 
2257205Ssd77468 /* ARGSUSED */
2267205Ssd77468 static int
pi_deferlist_compare(const void * l_arg,const void * r_arg,void * private)2277205Ssd77468 pi_deferlist_compare(const void *l_arg, const void *r_arg, void *private)
2287205Ssd77468 {
2297205Ssd77468 	pi_defernode_t	*lp = (pi_defernode_t *)l_arg;
2307205Ssd77468 	pi_defernode_t	*rp = (pi_defernode_t *)r_arg;
2317205Ssd77468 
2327205Ssd77468 	if (lp->func != rp->func) {
2337205Ssd77468 		return (1);
2347205Ssd77468 	}
2357205Ssd77468 	if (lp->t_parent != rp->t_parent) {
2367205Ssd77468 		return (-1);
2377205Ssd77468 	}
2387205Ssd77468 	return (0);
2397205Ssd77468 }
240