xref: /onnv-gate/usr/src/uts/intel/io/devfm_machdep.c (revision 10947:2ecbb0a4d189)
17532SSean.Ye@Sun.COM /*
27532SSean.Ye@Sun.COM  * CDDL HEADER START
37532SSean.Ye@Sun.COM  *
47532SSean.Ye@Sun.COM  * The contents of this file are subject to the terms of the
57532SSean.Ye@Sun.COM  * Common Development and Distribution License (the "License").
67532SSean.Ye@Sun.COM  * You may not use this file except in compliance with the License.
77532SSean.Ye@Sun.COM  *
87532SSean.Ye@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97532SSean.Ye@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107532SSean.Ye@Sun.COM  * See the License for the specific language governing permissions
117532SSean.Ye@Sun.COM  * and limitations under the License.
127532SSean.Ye@Sun.COM  *
137532SSean.Ye@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147532SSean.Ye@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157532SSean.Ye@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167532SSean.Ye@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177532SSean.Ye@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187532SSean.Ye@Sun.COM  *
197532SSean.Ye@Sun.COM  * CDDL HEADER END
207532SSean.Ye@Sun.COM  */
217532SSean.Ye@Sun.COM /*
2210942STom.Pothier@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237532SSean.Ye@Sun.COM  * Use is subject to license terms.
247532SSean.Ye@Sun.COM  */
257532SSean.Ye@Sun.COM 
267532SSean.Ye@Sun.COM #include <sys/stat.h>
277532SSean.Ye@Sun.COM #include <sys/types.h>
287532SSean.Ye@Sun.COM #include <sys/time.h>
297532SSean.Ye@Sun.COM 
307532SSean.Ye@Sun.COM #include <sys/fm/protocol.h>
3110942STom.Pothier@Sun.COM #include <sys/fm/smb/fmsmb.h>
327532SSean.Ye@Sun.COM #include <sys/devfm.h>
337532SSean.Ye@Sun.COM 
347532SSean.Ye@Sun.COM #include <sys/cpu_module.h>
357532SSean.Ye@Sun.COM 
367532SSean.Ye@Sun.COM #define	ANY_ID		(uint_t)-1
377532SSean.Ye@Sun.COM 
387532SSean.Ye@Sun.COM /*
397532SSean.Ye@Sun.COM  * INIT_HDLS is the initial size of cmi_hdl_t array.  We fill the array
407532SSean.Ye@Sun.COM  * during cmi_hdl_walk, if the array overflows, we will reallocate
417532SSean.Ye@Sun.COM  * a new array twice the size of the old one.
427532SSean.Ye@Sun.COM  */
437532SSean.Ye@Sun.COM #define	INIT_HDLS	16
447532SSean.Ye@Sun.COM 
457532SSean.Ye@Sun.COM typedef struct fm_cmi_walk_t
467532SSean.Ye@Sun.COM {
477532SSean.Ye@Sun.COM 	uint_t	chipid;		/* chipid to match during walk */
487532SSean.Ye@Sun.COM 	uint_t	coreid;		/* coreid to match */
497532SSean.Ye@Sun.COM 	uint_t	strandid;	/* strandid to match */
507532SSean.Ye@Sun.COM 	int	(*cbfunc)(cmi_hdl_t, void *, void *);  	/* callback function */
517532SSean.Ye@Sun.COM 	cmi_hdl_t *hdls;	/* allocated array to save the handles */
527532SSean.Ye@Sun.COM 	int	nhdl_max;	/* allocated array size */
537532SSean.Ye@Sun.COM 	int	nhdl;		/* handles saved */
547532SSean.Ye@Sun.COM } fm_cmi_walk_t;
557532SSean.Ye@Sun.COM 
5610942STom.Pothier@Sun.COM extern int x86gentopo_legacy;
5710942STom.Pothier@Sun.COM 
587532SSean.Ye@Sun.COM int
fm_get_paddr(nvlist_t * nvl,uint64_t * paddr)597532SSean.Ye@Sun.COM fm_get_paddr(nvlist_t *nvl, uint64_t *paddr)
607532SSean.Ye@Sun.COM {
617532SSean.Ye@Sun.COM 	uint8_t version;
627532SSean.Ye@Sun.COM 	uint64_t pa;
637532SSean.Ye@Sun.COM 	char *scheme;
647532SSean.Ye@Sun.COM 	int err;
657532SSean.Ye@Sun.COM 
667532SSean.Ye@Sun.COM 	/* Verify FMRI scheme name and version number */
677532SSean.Ye@Sun.COM 	if ((nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &scheme) != 0) ||
687532SSean.Ye@Sun.COM 	    (strcmp(scheme, FM_FMRI_SCHEME_HC) != 0) ||
697532SSean.Ye@Sun.COM 	    (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0) ||
707532SSean.Ye@Sun.COM 	    version > FM_HC_SCHEME_VERSION) {
717532SSean.Ye@Sun.COM 		return (EINVAL);
727532SSean.Ye@Sun.COM 	}
737532SSean.Ye@Sun.COM 
747532SSean.Ye@Sun.COM 	if ((err = cmi_mc_unumtopa(NULL, nvl, &pa)) != CMI_SUCCESS &&
757532SSean.Ye@Sun.COM 	    err != CMIERR_MC_PARTIALUNUMTOPA)
767532SSean.Ye@Sun.COM 		return (EINVAL);
777532SSean.Ye@Sun.COM 
787532SSean.Ye@Sun.COM 	*paddr = pa;
797532SSean.Ye@Sun.COM 	return (0);
807532SSean.Ye@Sun.COM }
817532SSean.Ye@Sun.COM 
827532SSean.Ye@Sun.COM /*
837532SSean.Ye@Sun.COM  * Routines for cmi handles walk.
847532SSean.Ye@Sun.COM  */
857532SSean.Ye@Sun.COM 
867532SSean.Ye@Sun.COM static void
walk_init(fm_cmi_walk_t * wp,uint_t chipid,uint_t coreid,uint_t strandid,int (* cbfunc)(cmi_hdl_t,void *,void *))877532SSean.Ye@Sun.COM walk_init(fm_cmi_walk_t *wp, uint_t chipid, uint_t coreid, uint_t strandid,
887532SSean.Ye@Sun.COM     int (*cbfunc)(cmi_hdl_t, void *, void *))
897532SSean.Ye@Sun.COM {
907532SSean.Ye@Sun.COM 	wp->chipid = chipid;
917532SSean.Ye@Sun.COM 	wp->coreid = coreid;
927532SSean.Ye@Sun.COM 	wp->strandid = strandid;
937532SSean.Ye@Sun.COM 	/*
947532SSean.Ye@Sun.COM 	 * If callback is not set, we allocate an array to save the
957532SSean.Ye@Sun.COM 	 * cmi handles.
967532SSean.Ye@Sun.COM 	 */
977532SSean.Ye@Sun.COM 	if ((wp->cbfunc = cbfunc) == NULL) {
987532SSean.Ye@Sun.COM 		wp->hdls = kmem_alloc(sizeof (cmi_hdl_t) * INIT_HDLS, KM_SLEEP);
997532SSean.Ye@Sun.COM 		wp->nhdl_max = INIT_HDLS;
1007532SSean.Ye@Sun.COM 		wp->nhdl = 0;
1017532SSean.Ye@Sun.COM 	}
1027532SSean.Ye@Sun.COM }
1037532SSean.Ye@Sun.COM 
1047532SSean.Ye@Sun.COM static void
walk_fini(fm_cmi_walk_t * wp)1057532SSean.Ye@Sun.COM walk_fini(fm_cmi_walk_t *wp)
1067532SSean.Ye@Sun.COM {
1077532SSean.Ye@Sun.COM 	if (wp->cbfunc == NULL)
1087532SSean.Ye@Sun.COM 		kmem_free(wp->hdls, sizeof (cmi_hdl_t) * wp->nhdl_max);
1097532SSean.Ye@Sun.COM }
1107532SSean.Ye@Sun.COM 
1117532SSean.Ye@Sun.COM static int
select_cmi_hdl(cmi_hdl_t hdl,void * arg1,void * arg2,void * arg3)1127532SSean.Ye@Sun.COM select_cmi_hdl(cmi_hdl_t hdl, void *arg1, void *arg2, void *arg3)
1137532SSean.Ye@Sun.COM {
1147532SSean.Ye@Sun.COM 	fm_cmi_walk_t *wp = (fm_cmi_walk_t *)arg1;
1157532SSean.Ye@Sun.COM 
1167532SSean.Ye@Sun.COM 	if (wp->chipid != ANY_ID && wp->chipid != cmi_hdl_chipid(hdl))
1177532SSean.Ye@Sun.COM 		return (CMI_HDL_WALK_NEXT);
1187532SSean.Ye@Sun.COM 	if (wp->coreid != ANY_ID && wp->coreid != cmi_hdl_coreid(hdl))
1197532SSean.Ye@Sun.COM 		return (CMI_HDL_WALK_NEXT);
1207532SSean.Ye@Sun.COM 	if (wp->strandid != ANY_ID && wp->strandid != cmi_hdl_strandid(hdl))
1217532SSean.Ye@Sun.COM 		return (CMI_HDL_WALK_NEXT);
1227532SSean.Ye@Sun.COM 
1237532SSean.Ye@Sun.COM 	/*
1247532SSean.Ye@Sun.COM 	 * Call the callback function if any exists, otherwise we hold a
1257532SSean.Ye@Sun.COM 	 * reference of the handle and push it to preallocated array.
1267532SSean.Ye@Sun.COM 	 * If the allocated array is going to overflow, reallocate a
1277532SSean.Ye@Sun.COM 	 * bigger one to replace it.
1287532SSean.Ye@Sun.COM 	 */
1297532SSean.Ye@Sun.COM 	if (wp->cbfunc != NULL)
1307532SSean.Ye@Sun.COM 		return (wp->cbfunc(hdl, arg2, arg3));
1317532SSean.Ye@Sun.COM 
1327532SSean.Ye@Sun.COM 	if (wp->nhdl == wp->nhdl_max) {
1337532SSean.Ye@Sun.COM 		size_t sz = sizeof (cmi_hdl_t) * wp->nhdl_max;
1347532SSean.Ye@Sun.COM 		cmi_hdl_t *newarray = kmem_alloc(sz << 1, KM_SLEEP);
1357532SSean.Ye@Sun.COM 
1367532SSean.Ye@Sun.COM 		bcopy(wp->hdls, newarray, sz);
1377532SSean.Ye@Sun.COM 		kmem_free(wp->hdls, sz);
1387532SSean.Ye@Sun.COM 		wp->hdls = newarray;
1397532SSean.Ye@Sun.COM 		wp->nhdl_max <<= 1;
1407532SSean.Ye@Sun.COM 	}
1417532SSean.Ye@Sun.COM 
1427532SSean.Ye@Sun.COM 	cmi_hdl_hold(hdl);
1437532SSean.Ye@Sun.COM 	wp->hdls[wp->nhdl++] = hdl;
1447532SSean.Ye@Sun.COM 
1457532SSean.Ye@Sun.COM 	return (CMI_HDL_WALK_NEXT);
1467532SSean.Ye@Sun.COM }
1477532SSean.Ye@Sun.COM 
1487532SSean.Ye@Sun.COM static void
populate_cpu(nvlist_t ** nvlp,cmi_hdl_t hdl)1497532SSean.Ye@Sun.COM populate_cpu(nvlist_t **nvlp, cmi_hdl_t hdl)
1507532SSean.Ye@Sun.COM {
15110942STom.Pothier@Sun.COM 	uint_t	fm_chipid;
15210942STom.Pothier@Sun.COM 	uint16_t smbios_id;
15310942STom.Pothier@Sun.COM 
1547532SSean.Ye@Sun.COM 	(void) nvlist_alloc(nvlp, NV_UNIQUE_NAME, KM_SLEEP);
15510942STom.Pothier@Sun.COM 
15610942STom.Pothier@Sun.COM 	/*
15710942STom.Pothier@Sun.COM 	 * If SMBIOS satisfies FMA Topology needs, gather
15810942STom.Pothier@Sun.COM 	 * more information on the chip's physical roots
15910942STom.Pothier@Sun.COM 	 * like /chassis=x/motherboard=y/cpuboard=z and
16010942STom.Pothier@Sun.COM 	 * set the chip_id to match the SMBIOS' Type 4
16110942STom.Pothier@Sun.COM 	 * ordering & this has to match the ereport's chip
16210942STom.Pothier@Sun.COM 	 * resource instance derived off of SMBIOS.
16310942STom.Pothier@Sun.COM 	 * Multi-Chip-Module support should set the chipid
16410942STom.Pothier@Sun.COM 	 * in terms of the processor package rather than
16510942STom.Pothier@Sun.COM 	 * the die/node in the processor package, for FM.
16610942STom.Pothier@Sun.COM 	 */
16710942STom.Pothier@Sun.COM 
16810942STom.Pothier@Sun.COM 	if (!x86gentopo_legacy) {
16910942STom.Pothier@Sun.COM 		smbios_id = cmi_hdl_smbiosid(hdl);
17010942STom.Pothier@Sun.COM 		fm_chipid = cmi_hdl_smb_chipid(hdl);
17110942STom.Pothier@Sun.COM 		(void) nvlist_add_nvlist(*nvlp, FM_PHYSCPU_INFO_CHIP_ROOTS,
17210942STom.Pothier@Sun.COM 		    cmi_hdl_smb_bboard(hdl));
17310942STom.Pothier@Sun.COM 		(void) nvlist_add_uint16(*nvlp, FM_PHYSCPU_INFO_SMBIOS_ID,
17410942STom.Pothier@Sun.COM 		    (uint16_t)smbios_id);
17510942STom.Pothier@Sun.COM 	} else
17610942STom.Pothier@Sun.COM 		fm_chipid = cmi_hdl_chipid(hdl);
17710942STom.Pothier@Sun.COM 
1787532SSean.Ye@Sun.COM 	fm_payload_set(*nvlp,
1797532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_VENDOR_ID, DATA_TYPE_STRING,
1807532SSean.Ye@Sun.COM 	    cmi_hdl_vendorstr(hdl),
1817532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_FAMILY, DATA_TYPE_INT32,
1827532SSean.Ye@Sun.COM 	    (int32_t)cmi_hdl_family(hdl),
1837532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_MODEL, DATA_TYPE_INT32,
1847532SSean.Ye@Sun.COM 	    (int32_t)cmi_hdl_model(hdl),
1857532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_STEPPING, DATA_TYPE_INT32,
1867532SSean.Ye@Sun.COM 	    (int32_t)cmi_hdl_stepping(hdl),
1877532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_CHIP_ID, DATA_TYPE_INT32,
18810942STom.Pothier@Sun.COM 	    (int32_t)fm_chipid,
189*10947SSrihari.Venkatesan@Sun.COM 	    FM_PHYSCPU_INFO_NPROCNODES, DATA_TYPE_INT32,
190*10947SSrihari.Venkatesan@Sun.COM 	    (int32_t)cmi_hdl_procnodes_per_pkg(hdl),
191*10947SSrihari.Venkatesan@Sun.COM 	    FM_PHYSCPU_INFO_PROCNODE_ID, DATA_TYPE_INT32,
192*10947SSrihari.Venkatesan@Sun.COM 	    (int32_t)cmi_hdl_procnodeid(hdl),
1937532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_CORE_ID, DATA_TYPE_INT32,
1947532SSean.Ye@Sun.COM 	    (int32_t)cmi_hdl_coreid(hdl),
1957532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_STRAND_ID, DATA_TYPE_INT32,
1967532SSean.Ye@Sun.COM 	    (int32_t)cmi_hdl_strandid(hdl),
19710942STom.Pothier@Sun.COM 	    FM_PHYSCPU_INFO_STRAND_APICID, DATA_TYPE_INT32,
19810942STom.Pothier@Sun.COM 	    (int32_t)cmi_hdl_strand_apicid(hdl),
1997532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_CHIP_REV, DATA_TYPE_STRING,
2007532SSean.Ye@Sun.COM 	    cmi_hdl_chiprevstr(hdl),
2017532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_SOCKET_TYPE, DATA_TYPE_UINT32,
2027532SSean.Ye@Sun.COM 	    (uint32_t)cmi_hdl_getsockettype(hdl),
2037532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_CPU_ID, DATA_TYPE_INT32,
2047532SSean.Ye@Sun.COM 	    (int32_t)cmi_hdl_logical_id(hdl),
2057532SSean.Ye@Sun.COM 	    NULL);
2067532SSean.Ye@Sun.COM }
2077532SSean.Ye@Sun.COM 
2087532SSean.Ye@Sun.COM /*ARGSUSED*/
2097532SSean.Ye@Sun.COM int
fm_ioctl_physcpu_info(int cmd,nvlist_t * invl,nvlist_t ** onvlp)2107532SSean.Ye@Sun.COM fm_ioctl_physcpu_info(int cmd, nvlist_t *invl, nvlist_t **onvlp)
2117532SSean.Ye@Sun.COM {
2127532SSean.Ye@Sun.COM 	nvlist_t **cpus, *nvl;
2137532SSean.Ye@Sun.COM 	int i, err;
2147532SSean.Ye@Sun.COM 	fm_cmi_walk_t wk;
2157532SSean.Ye@Sun.COM 
2167532SSean.Ye@Sun.COM 	/*
2177532SSean.Ye@Sun.COM 	 * Do a walk to save all the cmi handles in the array.
2187532SSean.Ye@Sun.COM 	 */
2197532SSean.Ye@Sun.COM 	walk_init(&wk, ANY_ID, ANY_ID, ANY_ID, NULL);
2207532SSean.Ye@Sun.COM 	cmi_hdl_walk(select_cmi_hdl, &wk, NULL, NULL);
2217532SSean.Ye@Sun.COM 
2227532SSean.Ye@Sun.COM 	if (wk.nhdl == 0) {
2237532SSean.Ye@Sun.COM 		walk_fini(&wk);
2247532SSean.Ye@Sun.COM 		return (ENOENT);
2257532SSean.Ye@Sun.COM 	}
2267532SSean.Ye@Sun.COM 
2277532SSean.Ye@Sun.COM 	cpus = kmem_alloc(sizeof (nvlist_t *) * wk.nhdl, KM_SLEEP);
2287532SSean.Ye@Sun.COM 	for (i = 0; i < wk.nhdl; i++) {
2297532SSean.Ye@Sun.COM 		populate_cpu(cpus + i, wk.hdls[i]);
2307532SSean.Ye@Sun.COM 		cmi_hdl_rele(wk.hdls[i]);
2317532SSean.Ye@Sun.COM 	}
2327532SSean.Ye@Sun.COM 
2337532SSean.Ye@Sun.COM 	walk_fini(&wk);
2347532SSean.Ye@Sun.COM 
2357532SSean.Ye@Sun.COM 	(void) nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
2367532SSean.Ye@Sun.COM 	err = nvlist_add_nvlist_array(nvl, FM_PHYSCPU_INFO_CPUS,
2377532SSean.Ye@Sun.COM 	    cpus, wk.nhdl);
2387532SSean.Ye@Sun.COM 
2397532SSean.Ye@Sun.COM 	for (i = 0; i < wk.nhdl; i++)
2407532SSean.Ye@Sun.COM 		nvlist_free(cpus[i]);
2417532SSean.Ye@Sun.COM 	kmem_free(cpus, sizeof (nvlist_t *) * wk.nhdl);
2427532SSean.Ye@Sun.COM 
2437532SSean.Ye@Sun.COM 	if (err != 0) {
2447532SSean.Ye@Sun.COM 		nvlist_free(nvl);
2457532SSean.Ye@Sun.COM 		return (err);
2467532SSean.Ye@Sun.COM 	}
2477532SSean.Ye@Sun.COM 
2487532SSean.Ye@Sun.COM 	*onvlp = nvl;
2497532SSean.Ye@Sun.COM 	return (0);
2507532SSean.Ye@Sun.COM }
2517532SSean.Ye@Sun.COM 
2527532SSean.Ye@Sun.COM int
fm_ioctl_cpu_retire(int cmd,nvlist_t * invl,nvlist_t ** onvlp)2537532SSean.Ye@Sun.COM fm_ioctl_cpu_retire(int cmd, nvlist_t *invl, nvlist_t **onvlp)
2547532SSean.Ye@Sun.COM {
2557532SSean.Ye@Sun.COM 	int32_t chipid, coreid, strandid;
2567532SSean.Ye@Sun.COM 	int rc, new_status, old_status;
2577532SSean.Ye@Sun.COM 	cmi_hdl_t hdl;
2587532SSean.Ye@Sun.COM 	nvlist_t *nvl;
2597532SSean.Ye@Sun.COM 
2607532SSean.Ye@Sun.COM 	switch (cmd) {
2617532SSean.Ye@Sun.COM 	case FM_IOC_CPU_RETIRE:
2627532SSean.Ye@Sun.COM 		new_status = P_FAULTED;
2637532SSean.Ye@Sun.COM 		break;
2647532SSean.Ye@Sun.COM 	case FM_IOC_CPU_STATUS:
2657532SSean.Ye@Sun.COM 		new_status = P_STATUS;
2667532SSean.Ye@Sun.COM 		break;
2677532SSean.Ye@Sun.COM 	case FM_IOC_CPU_UNRETIRE:
2687532SSean.Ye@Sun.COM 		new_status = P_ONLINE;
2697532SSean.Ye@Sun.COM 		break;
2707532SSean.Ye@Sun.COM 	default:
2717532SSean.Ye@Sun.COM 		return (ENOTTY);
2727532SSean.Ye@Sun.COM 	}
2737532SSean.Ye@Sun.COM 
2747532SSean.Ye@Sun.COM 	if (nvlist_lookup_int32(invl, FM_CPU_RETIRE_CHIP_ID, &chipid) != 0 ||
2757532SSean.Ye@Sun.COM 	    nvlist_lookup_int32(invl, FM_CPU_RETIRE_CORE_ID, &coreid) != 0 ||
2767532SSean.Ye@Sun.COM 	    nvlist_lookup_int32(invl, FM_CPU_RETIRE_STRAND_ID, &strandid) != 0)
2777532SSean.Ye@Sun.COM 		return (EINVAL);
2787532SSean.Ye@Sun.COM 
2797532SSean.Ye@Sun.COM 	hdl = cmi_hdl_lookup(CMI_HDL_NEUTRAL, chipid, coreid, strandid);
2807532SSean.Ye@Sun.COM 	if (hdl == NULL)
2817532SSean.Ye@Sun.COM 		return (EINVAL);
2827532SSean.Ye@Sun.COM 
2837532SSean.Ye@Sun.COM 	rc = cmi_hdl_online(hdl, new_status, &old_status);
2847532SSean.Ye@Sun.COM 	cmi_hdl_rele(hdl);
2857532SSean.Ye@Sun.COM 
2867532SSean.Ye@Sun.COM 	if (rc == 0) {
2877532SSean.Ye@Sun.COM 		(void) nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
2887532SSean.Ye@Sun.COM 		(void) nvlist_add_int32(nvl, FM_CPU_RETIRE_OLDSTATUS,
2897532SSean.Ye@Sun.COM 		    old_status);
2907532SSean.Ye@Sun.COM 		*onvlp = nvl;
2917532SSean.Ye@Sun.COM 	}
2927532SSean.Ye@Sun.COM 
2937532SSean.Ye@Sun.COM 	return (rc);
2947532SSean.Ye@Sun.COM }
29510942STom.Pothier@Sun.COM 
29610942STom.Pothier@Sun.COM /*
29710942STom.Pothier@Sun.COM  * Retrun the value of x86gentopo_legacy variable as an nvpair.
29810942STom.Pothier@Sun.COM  *
29910942STom.Pothier@Sun.COM  * The caller is responsible for freeing the nvlist.
30010942STom.Pothier@Sun.COM  */
30110942STom.Pothier@Sun.COM /* ARGSUSED */
30210942STom.Pothier@Sun.COM int
fm_ioctl_gentopo_legacy(int cmd,nvlist_t * invl,nvlist_t ** onvlp)30310942STom.Pothier@Sun.COM fm_ioctl_gentopo_legacy(int cmd, nvlist_t *invl, nvlist_t **onvlp)
30410942STom.Pothier@Sun.COM {
30510942STom.Pothier@Sun.COM 	nvlist_t *nvl;
30610942STom.Pothier@Sun.COM 
30710942STom.Pothier@Sun.COM 	if (cmd != FM_IOC_GENTOPO_LEGACY) {
30810942STom.Pothier@Sun.COM 		return (ENOTTY);
30910942STom.Pothier@Sun.COM 	}
31010942STom.Pothier@Sun.COM 
31110942STom.Pothier@Sun.COM 	/*
31210942STom.Pothier@Sun.COM 	 * Inform the caller of the intentions of the ereport generators to
31310942STom.Pothier@Sun.COM 	 * generate either a "generic" or "legacy" x86 topology.
31410942STom.Pothier@Sun.COM 	 */
31510942STom.Pothier@Sun.COM 
31610942STom.Pothier@Sun.COM 	(void) nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
31710942STom.Pothier@Sun.COM 	(void) nvlist_add_int32(nvl, FM_GENTOPO_LEGACY, x86gentopo_legacy);
31810942STom.Pothier@Sun.COM 	*onvlp = nvl;
31910942STom.Pothier@Sun.COM 
32010942STom.Pothier@Sun.COM 	return (0);
32110942STom.Pothier@Sun.COM }
322