xref: /onnv-gate/usr/src/lib/fm/topo/modules/sun4v/sun4vpi/pi_cpu.c (revision 8221:28cd31f237ad)
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 /*
237205Ssd77468  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247205Ssd77468  * Use is subject to license terms.
257205Ssd77468  */
267205Ssd77468 
277205Ssd77468 /*
287205Ssd77468  * Enumerate a CPU node
297205Ssd77468  */
307205Ssd77468 #include <sys/types.h>
317205Ssd77468 #include <strings.h>
327205Ssd77468 #include <sys/fm/protocol.h>
337205Ssd77468 #include <fm/topo_mod.h>
347205Ssd77468 #include <fm/topo_hc.h>
357205Ssd77468 #include "pi_impl.h"
367205Ssd77468 
377205Ssd77468 #define	_ENUM_NAME	"enum_cpu"
387205Ssd77468 
397205Ssd77468 typedef struct cpuwalk_s {
407205Ssd77468 	topo_mod_t	*mod;
417205Ssd77468 	char		*serial;
427205Ssd77468 } cpuwalk_t;
437205Ssd77468 
447205Ssd77468 static int pi_enum_cpu_serial(topo_mod_t *, md_t *, mde_cookie_t, char **);
457205Ssd77468 static int pi_enum_cpu_serial_cb(md_t *, mde_cookie_t, mde_cookie_t, void *);
467205Ssd77468 
477205Ssd77468 int
pi_enum_cpu(topo_mod_t * mod,md_t * mdp,mde_cookie_t mde_node,topo_instance_t inst,tnode_t * t_parent,const char * hc_name,tnode_t ** t_node)487205Ssd77468 pi_enum_cpu(topo_mod_t *mod, md_t *mdp, mde_cookie_t mde_node,
497205Ssd77468     topo_instance_t inst, tnode_t *t_parent, const char *hc_name,
507205Ssd77468     tnode_t **t_node)
517205Ssd77468 {
527205Ssd77468 	int		result;
537205Ssd77468 	int		err;
547205Ssd77468 	int		cpumask;
557205Ssd77468 	nvlist_t	*asru = NULL;
567205Ssd77468 	char		*serial = NULL;
577205Ssd77468 
587205Ssd77468 	*t_node = NULL;
597205Ssd77468 
607205Ssd77468 	/*
617205Ssd77468 	 * Create the basic topology node for the CPU using the generic
627205Ssd77468 	 * enumerator.
637205Ssd77468 	 */
647205Ssd77468 	result = pi_enum_generic_impl(mod, mdp, mde_node, inst, t_parent,
65*8221SSean.Ye@Sun.COM 	    t_parent, hc_name, _ENUM_NAME, t_node, 0);
667205Ssd77468 	if (result != 0) {
677205Ssd77468 		/* Error messages are printed by the generic routine */
687205Ssd77468 		return (result);
697205Ssd77468 	}
707205Ssd77468 
717205Ssd77468 	/*
72*8221SSean.Ye@Sun.COM 	 * If the hc_name is "chip" or "core", set asru to resource,
73*8221SSean.Ye@Sun.COM 	 * otherwise for "cpu" and "strand", set asru to CPU scheme FMRI.
747205Ssd77468 	 */
75*8221SSean.Ye@Sun.COM 	if (strcmp(hc_name, CHIP) == 0 || strcmp(hc_name, CORE) == 0) {
76*8221SSean.Ye@Sun.COM 		result = topo_node_resource(*t_node, &asru, &err);
77*8221SSean.Ye@Sun.COM 		if (result != 0) {
78*8221SSean.Ye@Sun.COM 			topo_mod_dprintf(mod,
79*8221SSean.Ye@Sun.COM 			    "%s node_0x%llx failed to get resource: %s\n",
80*8221SSean.Ye@Sun.COM 			    _ENUM_NAME, (uint64_t)mde_node, topo_strerror(err));
81*8221SSean.Ye@Sun.COM 			return (-1);
82*8221SSean.Ye@Sun.COM 		}
83*8221SSean.Ye@Sun.COM 	} else {
84*8221SSean.Ye@Sun.COM 		/*
85*8221SSean.Ye@Sun.COM 		 * Compute ASRU for "cpu" and "strand" node.
86*8221SSean.Ye@Sun.COM 		 * Get the parameters required to create an FMRI.  The cpumask
87*8221SSean.Ye@Sun.COM 		 * is on the chip itself and while it may be part of an ereport
88*8221SSean.Ye@Sun.COM 		 * payload is unavailable here, so we set it to zero.
89*8221SSean.Ye@Sun.COM 		 */
90*8221SSean.Ye@Sun.COM 		cpumask = 0;
917205Ssd77468 
92*8221SSean.Ye@Sun.COM 		/*
93*8221SSean.Ye@Sun.COM 		 * Find the serial number, which is on the "chip" node, not the
94*8221SSean.Ye@Sun.COM 		 * "cpu" node.
95*8221SSean.Ye@Sun.COM 		 */
96*8221SSean.Ye@Sun.COM 		result = pi_enum_cpu_serial(mod, mdp, mde_node, &serial);
97*8221SSean.Ye@Sun.COM 		if (result != 0 || serial == NULL) {
98*8221SSean.Ye@Sun.COM 			topo_mod_dprintf(mod,
99*8221SSean.Ye@Sun.COM 			    "%s node_0x%llx failed to find serial number.\n",
100*8221SSean.Ye@Sun.COM 			    _ENUM_NAME, (uint64_t)mde_node);
101*8221SSean.Ye@Sun.COM 			return (result);
102*8221SSean.Ye@Sun.COM 		}
103*8221SSean.Ye@Sun.COM 
104*8221SSean.Ye@Sun.COM 		/*
105*8221SSean.Ye@Sun.COM 		 * Create a CPU scheme FMRI and set it as the ASRU for the CPU
106*8221SSean.Ye@Sun.COM 		 * node
107*8221SSean.Ye@Sun.COM 		 */
108*8221SSean.Ye@Sun.COM 		asru = topo_mod_cpufmri(mod, FM_CPU_SCHEME_VERSION, inst,
109*8221SSean.Ye@Sun.COM 		    cpumask, serial);
110*8221SSean.Ye@Sun.COM 		topo_mod_strfree(mod, serial);
111*8221SSean.Ye@Sun.COM 		if (asru == NULL) {
112*8221SSean.Ye@Sun.COM 			topo_mod_dprintf(mod, "%s node_0x%llx failed to "
113*8221SSean.Ye@Sun.COM 			    "compute cpu scheme ASRU: %s\n",
114*8221SSean.Ye@Sun.COM 			    _ENUM_NAME, (uint64_t)mde_node,
115*8221SSean.Ye@Sun.COM 			    topo_strerror(topo_mod_errno(mod)));
116*8221SSean.Ye@Sun.COM 			return (-1);
117*8221SSean.Ye@Sun.COM 		}
1187205Ssd77468 	}
1197205Ssd77468 
1207205Ssd77468 	/* Set the ASRU on the node without flags (the 0) */
1217205Ssd77468 	result = topo_node_asru_set(*t_node, asru, 0, &err);
1227205Ssd77468 	nvlist_free(asru);
1237205Ssd77468 	if (result != 0) {
1247205Ssd77468 		topo_mod_dprintf(mod,
1257205Ssd77468 		    "%s node_0x%llx failed to set ASRU: %s\n", _ENUM_NAME,
1267205Ssd77468 		    (uint64_t)mde_node, topo_strerror(err));
1277205Ssd77468 		return (-1);
1287205Ssd77468 	}
1297205Ssd77468 
1307205Ssd77468 	return (0);
1317205Ssd77468 }
1327205Ssd77468 
1337205Ssd77468 
1347205Ssd77468 static int
pi_enum_cpu_serial(topo_mod_t * mod,md_t * mdp,mde_cookie_t mde_node,char ** serial)1357205Ssd77468 pi_enum_cpu_serial(topo_mod_t *mod, md_t *mdp, mde_cookie_t mde_node,
1367205Ssd77468     char **serial)
1377205Ssd77468 {
1387205Ssd77468 	int			result;
1397205Ssd77468 	cpuwalk_t		args;
1407205Ssd77468 	mde_str_cookie_t	component_cookie;
1417205Ssd77468 	mde_str_cookie_t	back_cookie;
1427205Ssd77468 
1437205Ssd77468 	args.mod = mod;
1447205Ssd77468 	args.serial = NULL;
1457205Ssd77468 
1467205Ssd77468 	/*
1477205Ssd77468 	 * Search backwards through the PRI graph, starting at the current
1487205Ssd77468 	 * strand (aka cpu) mde_node, and find the MD_STR_CHIP node.  This
1497205Ssd77468 	 * node has the serial number for the cpu.
1507205Ssd77468 	 */
1517205Ssd77468 	component_cookie = md_find_name(mdp, MD_STR_COMPONENT);
1527205Ssd77468 	back_cookie	 = md_find_name(mdp, MD_STR_BACK);
1537205Ssd77468 
1547205Ssd77468 	result = md_walk_dag(mdp, mde_node, component_cookie, back_cookie,
1557205Ssd77468 	    pi_enum_cpu_serial_cb, (void *)&args);
1567205Ssd77468 	*serial = args.serial;
1577205Ssd77468 
1587205Ssd77468 	return (result);
1597205Ssd77468 }
1607205Ssd77468 
1617205Ssd77468 
1627205Ssd77468 /*ARGSUSED*/
1637205Ssd77468 static int
pi_enum_cpu_serial_cb(md_t * mdp,mde_cookie_t mde_parent,mde_cookie_t mde_node,void * private)1647205Ssd77468 pi_enum_cpu_serial_cb(md_t *mdp, mde_cookie_t mde_parent,
1657205Ssd77468     mde_cookie_t mde_node, void *private)
1667205Ssd77468 {
1677205Ssd77468 	char		*hc_name;
1687205Ssd77468 	cpuwalk_t	*args = (cpuwalk_t *)private;
1697205Ssd77468 
1707205Ssd77468 	if (args == NULL) {
1717205Ssd77468 		return (MDE_WALK_ERROR);
1727205Ssd77468 	}
1737205Ssd77468 	args->serial = NULL;
1747205Ssd77468 
1757205Ssd77468 	hc_name = pi_get_topo_hc_name(args->mod, mdp, mde_node);
1767205Ssd77468 	if (hc_name != NULL && strcmp(hc_name, MD_STR_CHIP) == 0) {
1777205Ssd77468 		args->serial = pi_get_serial(args->mod, mdp, mde_node);
1787205Ssd77468 	}
1797205Ssd77468 	topo_mod_strfree(args->mod, hc_name);
1807205Ssd77468 
1817205Ssd77468 	return ((args->serial == NULL ? MDE_WALK_NEXT : MDE_WALK_DONE));
1827205Ssd77468 }
183