コード例 #1
0
ファイル: fmtopo.c プロジェクト: CoryXie/opensolaris
static void
print_everstyle(tnode_t *node)
{
	char buf[PATH_MAX], numbuf[64];
	nvlist_t *fmri, **hcl;
	int i, err;
	uint_t n;

	if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL,
	    TOPO_PROP_RESOURCE, &fmri, &err) < 0) {
		(void) fprintf(stderr, "%s: failed to get fmri for %s=%d: %s\n",
		    g_pname, topo_node_name(node),
		    topo_node_instance(node), topo_strerror(err));
		return;
	}

	if (nvlist_lookup_nvlist_array(fmri, FM_FMRI_HC_LIST, &hcl, &n) != 0) {
		(void) fprintf(stderr, "%s: failed to find %s for %s=%d\n",
		    g_pname, FM_FMRI_HC_LIST, topo_node_name(node),
		    topo_node_instance(node));
		nvlist_free(fmri);
		return;
	}

	buf[0] = '\0';

	for (i = 0; i < n; i++) {
		char *name, *inst, *estr;
		ulong_t ul;

		if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name) != 0 ||
		    nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &inst) != 0) {
			(void) fprintf(stderr, "%s: failed to get "
			    "name-instance for %s=%d\n", g_pname,
			    topo_node_name(node), topo_node_instance(node));
			nvlist_free(fmri);
			return;
		}

		errno = 0;
		ul = strtoul(inst, &estr, 10);

		if (errno != 0 || estr == inst) {
			(void) fprintf(stderr, "%s: instance %s does not "
			    "convert to an unsigned integer\n", g_pname, inst);
		}

		(void) strlcat(buf, "/", sizeof (buf));
		(void) strlcat(buf, name, sizeof (buf));
		(void) snprintf(numbuf, sizeof (numbuf), "%u", ul);
		(void) strlcat(buf, numbuf, sizeof (buf));
	}
	nvlist_free(fmri);

	(void) printf("%s\n", buf);
}
コード例 #2
0
ファイル: did_props.c プロジェクト: NanXiao/illumos-joyent
/*ARGSUSED*/
static int
label_set(tnode_t *tn, did_t *pd,
    const char *dpnm, const char *tpgrp, const char *tpnm)
{
	topo_mod_t *mp;
	nvlist_t *in, *out;
	char *label;
	int err;

	mp = did_mod(pd);
	/*
	 * If this is a PCIEX_BUS and its parent is a PCIEX_ROOT,
	 * check for a CPUBOARD predecessor.  If found, inherit its
	 * parent's Label.  Otherwise, continue with label set.
	 */
	if ((strcmp(topo_node_name(tn), PCIEX_BUS) == 0) &&
	    (strcmp(topo_node_name(topo_node_parent(tn)), PCIEX_ROOT) == 0)) {

		if (use_predecessor_label(mp, tn, CPUBOARD) == 0)
			return (0);
	}
	if (topo_mod_nvalloc(mp, &in, NV_UNIQUE_NAME) != 0)
		return (topo_mod_seterrno(mp, EMOD_FMRI_NVL));
	if (nvlist_add_uint64(in, TOPO_METH_LABEL_ARG_NVL, (uintptr_t)pd) !=
	    0) {
		nvlist_free(in);
		return (topo_mod_seterrno(mp, EMOD_NOMEM));
	}
	if (topo_method_invoke(tn,
	    TOPO_METH_LABEL, TOPO_METH_LABEL_VERSION, in, &out, &err) != 0) {
		nvlist_free(in);
		return (topo_mod_seterrno(mp, err));
	}
	nvlist_free(in);
	if (out != NULL &&
	    nvlist_lookup_string(out, TOPO_METH_LABEL_RET_STR, &label) == 0) {
		if (topo_prop_set_string(tn, TOPO_PGROUP_PROTOCOL,
		    TOPO_PROP_LABEL, TOPO_PROP_IMMUTABLE, label, &err) != 0) {
			nvlist_free(out);
			return (topo_mod_seterrno(mp, err));
		}
		nvlist_free(out);
	}
	return (0);
}
コード例 #3
0
ファイル: topo_method.c プロジェクト: NanXiao/illumos-joyent
int
topo_method_register(topo_mod_t *mod, tnode_t *node, const topo_method_t *mp)
{
	topo_imethod_t *imp;
	const topo_method_t *meth;

	/*
	 * Initialize module methods
	 */
	for (meth = &mp[0]; meth->tm_name != NULL; meth++) {

		topo_node_lock(node);
		if (topo_method_lookup(node, meth->tm_name) != NULL) {
			topo_node_unlock(node);
			continue;
		}

		if (meth->tm_stability < TOPO_STABILITY_INTERNAL ||
		    meth->tm_stability > TOPO_STABILITY_MAX ||
		    meth->tm_func == NULL)
			return (set_methregister_error(mod, node, NULL,
			    ETOPO_METHOD_INVAL));

		imp = topo_mod_zalloc(mod, sizeof (topo_imethod_t));
		if (imp == NULL)
			return (set_methregister_error(mod, node, imp,
			    ETOPO_METHOD_NOMEM));

		if ((imp->tim_name = topo_mod_strdup(mod, meth->tm_name))
		    == NULL)
			return (set_methregister_error(mod, node, imp,
			    ETOPO_METHOD_NOMEM));

		if ((imp->tim_desc = topo_mod_strdup(mod, meth->tm_desc))
		    == NULL)
			return (set_methregister_error(mod, node, imp,
			    ETOPO_METHOD_NOMEM));


		imp->tim_stability = meth->tm_stability;
		imp->tim_version = meth->tm_version;
		imp->tim_func = meth->tm_func;
		imp->tim_mod = mod;

		topo_list_append(&node->tn_methods, imp);
		topo_node_unlock(node);

		topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC,
		    "registered module %s method "
		    "%s for %s=%d\n", mod->tm_name, imp->tim_name,
		    topo_node_name(node), topo_node_instance(node));

	}

	return (0);
}
コード例 #4
0
ファイル: did_props.c プロジェクト: NanXiao/illumos-joyent
tnode_t *
find_predecessor(tnode_t *tn, char *mod_name)
{
	tnode_t *pnode = topo_node_parent(tn);

	while (pnode && (strcmp(topo_node_name(pnode), mod_name) != 0)) {
		pnode = topo_node_parent(pnode);
	}
	return (pnode);
}
コード例 #5
0
ファイル: ioboard.c プロジェクト: andreiw/polaris
static tnode_t *
iob_tnode_create(tnode_t *parent,
    const char *name, topo_instance_t i, void *priv, topo_mod_t *mod)
{
	topo_hdl_t *thp;
	nvlist_t *args, *fmri, *pfmri;
	tnode_t *ntn;
	int err;

	thp = topo_mod_handle(mod);

	if (topo_node_resource(parent, &pfmri, &err) < 0) {
		topo_mod_seterrno(mod, err);
		topo_mod_dprintf(mod,
		    "Unable to retrieve parent resource.\n");
		return (NULL);
	}
	if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0) {
		(void) topo_mod_seterrno(mod, EMOD_FMRI_NVL);
		nvlist_free(pfmri);
		return (NULL);
	}
	err = nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_PARENT, pfmri);
	if (err != 0) {
		nvlist_free(pfmri);
		nvlist_free(args);
		(void) topo_mod_seterrno(mod, EMOD_FMRI_NVL);
		return (NULL);
	}
	fmri = topo_fmri_create(thp, FM_FMRI_SCHEME_HC, name, i, args, &err);
	if (fmri == NULL) {
		topo_mod_dprintf(mod,
		    "Unable to make nvlist for %s bind.\n", name);
		return (NULL);
	}
	ntn = topo_node_bind(mod, parent, name, i, fmri, priv);
	if (ntn == NULL) {
		topo_mod_dprintf(mod,
		    "topo_node_bind (%s%d/%s%d) failed: %s\n",
		    topo_node_name(parent), topo_node_instance(parent),
		    name, i,
		    topo_strerror(topo_mod_errno(mod)));
		nvlist_free(fmri);
		return (NULL);
	}
	nvlist_free(fmri);
	if (topo_method_register(mod, ntn, Iob_methods) < 0) {
		topo_mod_dprintf(mod, "topo_method_register failed: %s\n",
		    topo_strerror(topo_mod_errno(mod)));
		topo_node_unbind(ntn);
		return (NULL);
	}
	return (ntn);
}
コード例 #6
0
ファイル: disk_lights.c プロジェクト: AlainODea/illumos-gate
static int
dl_fault_walk_outer(topo_hdl_t *thp, tnode_t *node, void *arg)
{
	disk_lights_t *dl = arg;
	dl_fault_walk_inner_t fwi;
	tnode_t *pnode;
	int err, has_fault;
	nvlist_t *fmri = NULL;

	bzero(&fwi, sizeof (fwi));

	/*
	 * We are only looking for DISK nodes in the topology that have a parent
	 * BAY.
	 */
	if (strcmp(DISK, topo_node_name(node)) != 0 ||
	    (pnode = topo_node_parent(node)) == NULL ||
	    strcmp(BAY, topo_node_name(pnode)) != 0) {
		return (TOPO_WALK_NEXT);
	}

	/*
	 * Check to see if the Resource this FMRI describes is Faulty:
	 */
	if (topo_node_resource(node, &fmri, &err) != 0)
		return (TOPO_WALK_NEXT);
	has_fault = fmd_nvl_fmri_has_fault(dl->dl_fmd, fmri,
	    FMD_HAS_FAULT_RESOURCE, NULL);
	nvlist_free(fmri);

	/*
	 * Walk the children of this BAY and flush out our fault status if
	 * we find an appropriate indicator node.
	 */
	fwi.fwi_name = "fail";
	fwi.fwi_mode = has_fault ? TOPO_LED_STATE_ON : TOPO_LED_STATE_OFF;
	(void) topo_node_child_walk(thp, pnode, dl_fault_walk_inner, &fwi,
	    &err);

	return (TOPO_WALK_NEXT);
}
コード例 #7
0
ファイル: topo_gather.c プロジェクト: alhazred/onarm
/*ARGSUSED*/
static int
gather_topo_cfg(topo_hdl_t *thp, tnode_t *node, void *arg)
{
	char *nodename = topo_node_name(node);
	if (strcmp(DISK, nodename) == 0)
		return (topo_add_disk(thp, node, (walk_diskmon_t *)arg)
		    ? TOPO_WALK_ERR : TOPO_WALK_NEXT);
	else if (strcmp(BAY, nodename) == 0)
		return (topo_add_bay(thp, node, (walk_diskmon_t *)arg)
		    ? TOPO_WALK_ERR : TOPO_WALK_NEXT);

	return (TOPO_WALK_NEXT);
}
コード例 #8
0
ファイル: topo_gather.c プロジェクト: andreiw/polaris
/*ARGSUSED*/
static int
gather_topo_cfg(topo_hdl_t *thp, tnode_t *node, void *arg)
{
	char *nodename = topo_node_name(node);
	if (strcmp(SATA_DISK, nodename) == 0)
		return (topo_add_disk(thp, node, (diskmon_t *)arg)
		    ? TOPO_WALK_ERR : TOPO_WALK_NEXT);
	else if (strcmp(SATA_PORT, nodename) == 0)
		return (topo_add_sata_port(thp, node, (diskmon_t *)arg)
		    ? TOPO_WALK_ERR : TOPO_WALK_NEXT);

	return (TOPO_WALK_NEXT);
}
コード例 #9
0
ファイル: hostbridge.c プロジェクト: NanXiao/illumos-joyent
static tnode_t *
hb_tnode_create(topo_mod_t *mod, tnode_t *parent,
    const char *name, topo_instance_t i, void *priv)
{
	int err;
	nvlist_t *fmri;
	tnode_t *ntn;
	nvlist_t *auth = topo_mod_auth(mod, parent);

	fmri = topo_mod_hcfmri(mod, parent, FM_HC_SCHEME_VERSION, name, i,
	    NULL, auth, NULL, NULL, NULL);
	nvlist_free(auth);
	if (fmri == NULL) {
		topo_mod_dprintf(mod,
		    "Unable to make nvlist for %s bind: %s.\n",
		    name, topo_mod_errmsg(mod));
		return (NULL);
	}

	ntn = topo_node_bind(mod, parent, name, i, fmri);
	if (ntn == NULL) {
		topo_mod_dprintf(mod,
		    "topo_node_bind (%s%d/%s%d) failed: %s\n",
		    topo_node_name(parent), topo_node_instance(parent),
		    name, i,
		    topo_strerror(topo_mod_errno(mod)));
		nvlist_free(fmri);
		return (NULL);
	}
	nvlist_free(fmri);
	topo_node_setspecific(ntn, priv);

	if (topo_pgroup_create(ntn, &hb_auth_pgroup, &err) == 0) {
		(void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
		    FM_FMRI_AUTH_PRODUCT, &err);
		(void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
		    FM_FMRI_AUTH_PRODUCT_SN, &err);
		(void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
		    FM_FMRI_AUTH_CHASSIS, &err);
		(void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
		    FM_FMRI_AUTH_SERVER, &err);
	}

	if (topo_method_register(mod, ntn, Hb_methods) < 0) {
		topo_mod_dprintf(mod, "topo_method_register failed: %s\n",
		    topo_strerror(topo_mod_errno(mod)));
		topo_node_unbind(ntn);
		return (NULL);
	}
	return (ntn);
}
コード例 #10
0
ファイル: chip_amd.c プロジェクト: bahamas10/openzfs
static int
amd_htconfig(topo_mod_t *mod, tnode_t *cnode, nvlist_t *htnvl)
{
	nvpair_t *nvp;
	int nerr = 0;

	if (strcmp(topo_node_name(cnode), CHIP_NODE_NAME) != 0) {
		whinge(mod, &nerr, "amd_htconfig: must pass a chip node!");
		return (-1);
	}

	for (nvp = nvlist_next_nvpair(htnvl, NULL); nvp != NULL;
	    nvp = nvlist_next_nvpair(htnvl, nvp)) {
		if (nvprop_add(mod, nvp, PGNAME(CHIP), cnode) != 0)
			nerr++;
	}

	return (nerr == 0 ? 0 : -1);
}
コード例 #11
0
ファイル: niu.c プロジェクト: NanXiao/illumos-joyent
static tnode_t *
niu_tnode_create(topo_mod_t *mod, tnode_t *parent,
    const char *name, topo_instance_t i, void *priv)
{
	int err;
	nvlist_t *fmri;
	tnode_t *ntn;
	nvlist_t *auth = topo_mod_auth(mod, parent);

	fmri = topo_mod_hcfmri(mod, parent, FM_HC_SCHEME_VERSION, name, i,
	    NULL, auth, NULL, NULL, NULL);
	nvlist_free(auth);

	if (fmri == NULL) {
		topo_mod_dprintf(mod,
		    "Unable to make nvlist for %s bind: %s.\n",
		    name, topo_mod_errmsg(mod));
		return (NULL);
	}

	ntn = topo_node_bind(mod, parent, name, i, fmri);
	if (ntn == NULL) {
		topo_mod_dprintf(mod,
		    "topo_node_bind (%s%d/%s%d) failed: %s\n",
		    topo_node_name(parent), topo_node_instance(parent),
		    name, i,
		    topo_strerror(topo_mod_errno(mod)));
		nvlist_free(fmri);
		return (NULL);
	}
	nvlist_free(fmri);
	topo_node_setspecific(ntn, priv);

	if (topo_pgroup_create(ntn, &io_pgroup, &err) == 0) {
		(void) devprop_set(ntn, priv, TOPO_PGROUP_IO, TOPO_IO_DEV, mod);
		(void) driverprop_set(ntn, priv, TOPO_PGROUP_IO, TOPO_IO_DRIVER,
		    mod);
		(void) moduleprop_set(ntn, priv, TOPO_PGROUP_IO, TOPO_IO_MODULE,
		    mod);
	}
	return (ntn);
}
コード例 #12
0
ファイル: topo_snap.c プロジェクト: drscream/illumos-joyent
/*ARGSUSED*/
static int
fac_walker(topo_hdl_t *thp, tnode_t *node, void *arg)
{
	int err;
	nvlist_t *out;

	if (topo_method_supported(node, TOPO_METH_FAC_ENUM, 0)) {
		/*
		 * If the facility enumeration method fails, note the failure,
		 * but continue on with the walk.
		 */
		if (topo_method_invoke(node, TOPO_METH_FAC_ENUM, 0, NULL, &out,
		    &err) != 0) {
			topo_dprintf(thp, TOPO_DBG_ERR,
			    "facility enumeration method failed on node %s=%d "
			    "(%s)\n", topo_node_name(node),
			    topo_node_instance(node), topo_strerror(err));
		}
	}
	return (TOPO_WALK_NEXT);
}
コード例 #13
0
ファイル: pci_i86pc.c プロジェクト: NanXiao/illumos-joyent
/*
 * Look for down-stream switch "4" on riser card. First find this node's parent.
 * If it is a pciexfn node and it has dev=4 and node 6 levels further up
 * from it has a physlot then return true.
 */
int
ba_is_4(topo_mod_t *mod, did_t *dp)
{
	tnode_t *ptp;
	did_t *pdp;
	int i, d;

	ptp = did_gettnode(dp);
	if (strcmp(topo_node_name(ptp), PCIEX_FUNCTION) != 0)
		return (0);
	pdp = did_find(mod, topo_node_getspecific(ptp));
	if (!pdp)
		return (0);
	did_BDF(pdp, NULL, &d, NULL);
	if (d != 4)
		return (0);

	for (i = 0; i < 6; i++)
		if ((ptp = topo_node_parent(ptp)) == NULL)
			return (0);
	pdp = did_find(mod, topo_node_getspecific(ptp));
	return (pdp && did_physlot_exists(pdp));
}
コード例 #14
0
ファイル: did_props.c プロジェクト: NanXiao/illumos-joyent
/*ARGSUSED*/
static int
DEVprop_set(tnode_t *tn, did_t *pd,
    const char *dpnm, const char *tpgrp, const char *tpnm)
{
	topo_mod_t *mp;
	char *dnpath;
	char *path, *fpath;
	int d, f;
	int err, e;

	mp = did_mod(pd);
	if ((dnpath = di_devfs_path(did_dinode(pd))) == NULL) {
		topo_mod_dprintf(mp, "NULL di_devfs_path.\n");
		return (topo_mod_seterrno(mp, ETOPO_PROP_NOENT));
	}
	if ((path = topo_mod_strdup(mp, dnpath)) == NULL) {
		di_devfs_path_free(dnpath);
		return (-1);
	}
	di_devfs_path_free(dnpath);

	/* The DEV path is modified for hostbridges */
	if (strcmp(topo_node_name(tn), HOSTBRIDGE) == 0) {
		fpath = dev_for_hostbridge(did_mod(pd), path);
	} else {
		did_BDF(pd, NULL, &d, &f);
		fpath = dev_path_fix(mp, path, d, f);
	}
	if (fpath == NULL)
		return (-1);
	e = topo_prop_set_string(tn,
	    tpgrp, tpnm, TOPO_PROP_IMMUTABLE, fpath, &err);
	topo_mod_strfree(mp, fpath);
	if (e != 0)
		return (topo_mod_seterrno(mp, err));
	return (0);
}
コード例 #15
0
ファイル: pci_sun4v.c プロジェクト: NanXiao/illumos-joyent
int
platform_pci_fru(topo_mod_t *mod, tnode_t *node, nvlist_t *in,
    nvlist_t **out)
{
	int err = 0;
	uint64_t ptr;
	did_t *dp, *pdp;
	tnode_t *pnode;
	char *nm, *plat, *pp, **cp;
	char *label;
	int found_t1plat = 0;
	uchar_t *loc;
	int locsiz;

	topo_mod_dprintf(mod, "entering platform_pci_fru\n");

	if (topo_prop_get_string(node, FM_FMRI_AUTHORITY,
	    FM_FMRI_AUTH_PRODUCT, &plat, &err) < 0) {
		(void) topo_mod_seterrno(mod, err);
		return (-1);
	}
	/* Delete the "SUNW," */
	pp = strchr(plat, ',');
	if (pp == NULL)
		pp = plat;
	else
		++pp;

	/* Is this an UltraSPARC-T1 platform? */
	cp = usT1_plats;
	while ((*cp != NULL) && (found_t1plat == 0)) {
		if (strcmp(pp, *cp) == 0)
			found_t1plat = 1;
		cp++;
	}

	topo_mod_strfree(mod, plat);

	/*
	 * On UltraSPARC-T1 systems, use the legacy hc scheme on
	 * the adapter slots to ensure ALOM on the SP can interpret
	 * the FRU correctly. For everything else, follow the normal
	 * code flow
	 */
	if (found_t1plat) {
		*out = NULL;
		nm = topo_node_name(node);
		if (strcmp(nm, PCI_DEVICE) != 0 &&
		    strcmp(nm, PCIEX_DEVICE) != 0 &&
		    strcmp(nm, PCIEX_BUS) != 0)
			return (0);

		if (nvlist_lookup_uint64(in, "nv1", &ptr) != 0) {
			topo_mod_dprintf(mod, "label method argument "
			    "not found.\n");
			return (-1);
		}
		dp = (did_t *)(uintptr_t)ptr;
		pnode = did_gettnode(dp);
		pdp = did_find(mod, topo_node_getspecific(pnode));

		/*
		 * Is there a slotname associated with the device?
		 */
		if ((label = pci_slot_label_lookup(mod, pnode, dp, pdp))
		    != NULL) {
			nvlist_t *rnvl;
			char buf[PATH_MAX];

			(void) snprintf(buf, PATH_MAX, "hc:///component=%s",
			    label);
			if (topo_mod_str2nvl(mod, buf, &rnvl) < 0)
				return (-1);
			*out = rnvl;
		}
		return (0);
	} else if (di_bytes_get(mod, topo_node_getspecific(node),
	    PI_PROP_CHASSIS_LOCATION_NAME, &locsiz, &loc) == 0 && locsiz > 0) {
		/*
		 * We have crossed a FRU boundary and need to find the parent
		 * node with this location and set our FMRI to that value.
		 */
		return (platform_pci_fru_location(mod, node, loc, locsiz));
	} else {
		return (pci_fru_compute(mod, node, in, out));
	}
}
コード例 #16
0
ファイル: did_props.c プロジェクト: NanXiao/illumos-joyent
/*ARGSUSED*/
static int
FRU_set(tnode_t *tn, did_t *pd,
    const char *dpnm, const char *tpgrp, const char *tpnm)
{
	topo_mod_t *mp;
	char *nm;
	int e = 0, err = 0;

	nm = topo_node_name(tn);
	mp = did_mod(pd);

	/*
	 * If this is a PCIEX_BUS and its parent is a PCIEX_ROOT,
	 * check for a CPUBOARD predecessor.  If found, inherit its
	 * parent's FRU.  Otherwise, continue with FRU set.
	 */
	if ((strcmp(nm, PCIEX_BUS) == 0) &&
	    (strcmp(topo_node_name(topo_node_parent(tn)), PCIEX_ROOT) == 0)) {

		if (use_predecessor_fru(tn, CPUBOARD) == 0)
			return (0);
	}
	/*
	 * If this topology node represents something other than an
	 * ioboard or a device that implements a slot, inherit the
	 * parent's FRU value.  If there is no label, inherit our
	 * parent's FRU value.  Otherwise, munge up an fmri based on
	 * the label.
	 */
	if (strcmp(nm, IOBOARD) != 0 && strcmp(nm, PCI_DEVICE) != 0 &&
	    strcmp(nm, PCIEX_DEVICE) != 0 && strcmp(nm, PCIEX_BUS) != 0) {
		(void) topo_node_fru_set(tn, NULL, 0, &e);
		return (0);
	}

	/*
	 * If ioboard, set fru fmri to hc fmri
	 */
	if (strcmp(nm, IOBOARD) == 0) {
		e = FRU_fmri_set(mp, tn);
		return (e);
	} else if (strcmp(nm, PCI_DEVICE) == 0 ||
	    strcmp(nm, PCIEX_DEVICE) == 0 || strcmp(nm, PCIEX_BUS) == 0) {
		nvlist_t *in, *out;

		mp = did_mod(pd);
		if (topo_mod_nvalloc(mp, &in, NV_UNIQUE_NAME) != 0)
			return (topo_mod_seterrno(mp, EMOD_FMRI_NVL));
		if (nvlist_add_uint64(in, "nv1", (uintptr_t)pd) != 0) {
			nvlist_free(in);
			return (topo_mod_seterrno(mp, EMOD_NOMEM));
		}
		if (topo_method_invoke(tn,
		    TOPO_METH_FRU_COMPUTE, TOPO_METH_FRU_COMPUTE_VERSION,
		    in, &out, &err) != 0) {
			nvlist_free(in);
			return (topo_mod_seterrno(mp, err));
		}
		nvlist_free(in);
		(void) topo_node_fru_set(tn, out, 0, &err);
		if (out != NULL)
			nvlist_free(out);
	} else
		(void) topo_node_fru_set(tn, NULL, 0, &err);

	return (0);
}
コード例 #17
0
ファイル: did_props.c プロジェクト: NanXiao/illumos-joyent
/*ARGSUSED*/
static int
ASRU_set(tnode_t *tn, did_t *pd,
    const char *dpnm, const char *tpgrp, const char *tpnm)
{
	topo_mod_t *mp;
	nvlist_t *fmri;
	char *dnpath, *path, *fpath, *nm;
	int d, e, f;

	/*
	 * If this topology node represents a function of device,
	 * set the ASRU to a dev scheme FMRI based on the value of
	 * di_devfs_path().  If that path is NULL, set the ASRU to
	 * be the resource describing this topology node.  If this
	 * isn't a function, inherit any ASRU from the parent.
	 */
	mp = did_mod(pd);
	nm = topo_node_name(tn);
	if ((strcmp(nm, PCI_BUS) == 0 && did_gettnode(pd) &&
	    strcmp(topo_node_name(did_gettnode(pd)), HOSTBRIDGE) == 0) ||
	    strcmp(nm, PCI_FUNCTION) == 0 || strcmp(nm, PCIEX_FUNCTION) == 0 ||
	    strcmp(nm, PCIEX_ROOT) == 0) {
		if ((dnpath = di_devfs_path(did_dinode(pd))) != NULL) {
			/*
			 * Dup the path, dev_path_fix() may replace it and
			 * dev_path_fix() wouldn't know to use
			 * di_devfs_path_free()
			 */
			if ((path = topo_mod_strdup(mp, dnpath)) == NULL) {
				di_devfs_path_free(dnpath);
				return (topo_mod_seterrno(mp, EMOD_NOMEM));
			}
			di_devfs_path_free(dnpath);
			did_BDF(pd, NULL, &d, &f);
			if ((fpath = dev_path_fix(mp, path, d, f)) == NULL)
				return (topo_mod_seterrno(mp, EMOD_NOMEM));

			fmri = topo_mod_devfmri(mp, FM_DEV_SCHEME_VERSION,
			    fpath, NULL);
			if (fmri == NULL) {
				topo_mod_dprintf(mp,
				    "dev:///%s fmri creation failed.\n", fpath);
				topo_mod_strfree(mp, fpath);
				return (-1);
			}
			topo_mod_strfree(mp, fpath);
		} else {
			topo_mod_dprintf(mp, "NULL di_devfs_path.\n");
			if (topo_prop_get_fmri(tn, TOPO_PGROUP_PROTOCOL,
			    TOPO_PROP_RESOURCE, &fmri, &e) < 0)
				return (topo_mod_seterrno(mp, e));
		}
		if (topo_node_asru_set(tn, fmri, 0, &e) < 0) {
			nvlist_free(fmri);
			return (topo_mod_seterrno(mp, e));
		}
		nvlist_free(fmri);
		return (0);
	}
	(void) topo_node_asru_set(tn, NULL, 0, &e);

	return (0);
}
コード例 #18
0
/*
 * Create a generic topo node based on the hcfmri strcuture passed in.
 */
int
x86pi_enum_generic(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri,
    tnode_t *t_bindparent, tnode_t *t_fmriparent, tnode_t **t_node, int flag)
{
	int		rv;
	int		err;
	nvlist_t	*out;
	nvlist_t	*fmri;
	nvlist_t	*auth;

	topo_mod_dprintf(mod, "%s adding entry for type (%s)\n",
	    _ENUM_NAME, hcfmri->hc_name);

	if (t_bindparent == NULL) {
		topo_mod_dprintf(mod,
		    "%s called with NULL parent for type %s\n",
		    _ENUM_NAME, hcfmri->hc_name);
		return (-1);
	}

	/* Create the FMRI for this node */
	auth = topo_mod_auth(mod, t_bindparent);
	fmri = topo_mod_hcfmri(mod, t_fmriparent, FM_HC_SCHEME_VERSION,
	    hcfmri->hc_name, hcfmri->instance, NULL, auth,
	    hcfmri->part_number, hcfmri->version, hcfmri->serial_number);

	nvlist_free(auth);

	if (fmri == NULL) {
		topo_mod_dprintf(mod,
		    "%s failed to create %s fmri : %s\n", _ENUM_NAME,
		    hcfmri->hc_name, topo_strerror(topo_mod_errno(mod)));
		return (-1);
	}

	rv = topo_node_range_create(mod, t_bindparent, hcfmri->hc_name, 0, 4);
	if (rv != 0 && topo_mod_errno(mod) != EMOD_NODE_DUP) {
		topo_mod_dprintf(mod, "%s range create failed for node %s\n",
		    _ENUM_NAME, hcfmri->hc_name);
	}

	/* Bind this node to the parent */
	*t_node = x86pi_node_bind(mod, t_bindparent, hcfmri, fmri, flag);
	nvlist_free(fmri);
	if (*t_node == NULL) {
		topo_mod_dprintf(mod,
		    "%s failed to bind %s node instance %d: %s\n",
		    _ENUM_NAME, hcfmri->hc_name, hcfmri->instance,
		    topo_strerror(topo_mod_errno(mod)));
		return (-1);
	}

	/* call IPMI facility provider to register fac methods */
	if (topo_mod_load(mod, _FAC_PROV, TOPO_VERSION) == NULL) {
		topo_mod_dprintf(mod,
		    "%s: Failed to load %s module: %s\n", _ENUM_NAME, _FAC_PROV,
		    topo_mod_errmsg(mod));
		return (-1);
	}

	rv = topo_mod_enumerate(mod, *t_node, _FAC_PROV, _FAC_PROV, 0, 0, NULL);
	if (rv != 0) {
		topo_mod_dprintf(mod,
		    "%s: %s failed: %s\n", _ENUM_NAME, _FAC_PROV,
		    topo_mod_errmsg(mod));
		return (-1);
	}

	/* invoke fac_prov_ipmi_enum method */
	if (topo_method_supported(*t_node, TOPO_METH_FAC_ENUM, 0)) {
		if (topo_method_invoke(*t_node, TOPO_METH_FAC_ENUM, 0, NULL,
		    &out, &err) != 0) {
			/* log the error and drive on */
			topo_mod_dprintf(mod,
			    "%s: TOPO_METH_FAC_ENUM failed\n", _ENUM_NAME);
		} else {
			fac_done = 1;
		}
	}

	topo_mod_dprintf(mod, "%s added (%s) node\n", _ENUM_NAME,
	    topo_node_name(*t_node));

	return (0);
}
コード例 #19
0
ファイル: disk_common.c プロジェクト: drscream/illumos-joyent
static int
disk_add_temp_sensor(topo_mod_t *mod, tnode_t *pnode, const char *devid)
{
	tnode_t *fnode;
	topo_pgroup_info_t pgi;
	nvlist_t *arg_nvl = NULL;
	int err;

	if ((fnode = topo_node_facbind(mod, pnode, "temp",
	    TOPO_FAC_TYPE_SENSOR)) == NULL) {
		topo_mod_dprintf(mod, "failed to bind facility node");
		/* errno set */
		return (-1);
	}

	/*
	 * Set props:
	 * - facility/sensor-class
	 * - facility/sensor-type
	 * - facility/units
	 */
	pgi.tpi_name = TOPO_PGROUP_FACILITY;
	pgi.tpi_namestab = TOPO_STABILITY_PRIVATE;
	pgi.tpi_datastab = TOPO_STABILITY_PRIVATE;
	pgi.tpi_version = 1;
	if (topo_pgroup_create(fnode, &pgi, &err) != 0) {
		if (err != ETOPO_PROP_DEFD) {
			topo_mod_dprintf(mod,  "pgroups create failure (%s)\n",
			    topo_strerror(err));
			/* errno set */
			goto err;
		}
	}
	if (topo_prop_set_string(fnode, TOPO_PGROUP_FACILITY,
	    TOPO_SENSOR_CLASS, TOPO_PROP_IMMUTABLE,
	    TOPO_SENSOR_CLASS_THRESHOLD, &err) != 0 ||
	    topo_prop_set_uint32(fnode, TOPO_PGROUP_FACILITY,
	    TOPO_FACILITY_TYPE, TOPO_PROP_IMMUTABLE, TOPO_SENSOR_TYPE_TEMP,
	    &err) != 0 ||
	    topo_prop_set_uint32(fnode, TOPO_PGROUP_FACILITY,
	    TOPO_SENSOR_UNITS, TOPO_PROP_IMMUTABLE,
	    TOPO_SENSOR_UNITS_DEGREES_C, &err) != 0) {
		topo_mod_dprintf(mod, "Failed to set props on facnode (%s)",
		    topo_strerror(err));
		/* errno set */
		goto err;
	}

	/*
	 * Register a property method for facility/reading
	 */
	if (topo_method_register(mod, fnode, disk_fac_methods) < 0) {
		topo_mod_dprintf(mod, "failed to register facility methods");
		goto err;
	}
	if (topo_mod_nvalloc(mod, &arg_nvl, NV_UNIQUE_NAME) < 0 ||
	    nvlist_add_string(arg_nvl, TOPO_IO_DEVID, devid) != 0) {
		topo_mod_dprintf(mod, "Failed build arg nvlist\n");
		(void) topo_mod_seterrno(mod, EMOD_NOMEM);
		goto err;
	}
	if (topo_prop_method_register(fnode, TOPO_PGROUP_FACILITY,
	    TOPO_SENSOR_READING, TOPO_TYPE_DOUBLE, "disk_temp_reading",
	    arg_nvl, &err) != 0) {
		topo_mod_dprintf(mod, "Failed to register %s propmeth "
		    "on fac node %s (%s)\n", TOPO_SENSOR_READING,
		    topo_node_name(fnode), topo_strerror(err));
		/* errno set */
		goto err;
	}
	nvlist_free(arg_nvl);
	return (0);
err:
	topo_node_unbind(fnode);
	nvlist_free(arg_nvl);
	return (-1);
}
コード例 #20
0
ファイル: pi_meth.c プロジェクト: NanXiao/illumos-joyent
/*
 * For each visited cpu node, call the callback function with its ASRU.
 */
static int
cpu_walker(topo_mod_t *mod, tnode_t *node, void *pdata)
{
	struct cpu_walk_data *swdp = pdata;
	nvlist_t *asru;
	int err, rc;

	/*
	 * Terminate the walk if we reach start-node's sibling
	 */
	if (node != swdp->parent &&
	    topo_node_parent(node) == topo_node_parent(swdp->parent))
		return (TOPO_WALK_TERMINATE);

	if (strcmp(topo_node_name(node), CPU) != 0 &&
	    strcmp(topo_node_name(node), STRAND) != 0)
		return (TOPO_WALK_NEXT);

	if (topo_node_asru(node, &asru, NULL, &err) != 0) {
		swdp->fail++;
		return (TOPO_WALK_NEXT);
	}

	rc = swdp->func(swdp->lhp, asru);

	/*
	 * The "offline" and "online" counter are only useful for the "status"
	 * callback.
	 */
	if (rc == P_OFFLINE || rc == P_FAULTED) {
		swdp->offline++;
		err = 0;
	} else if (rc == P_ONLINE) {
		swdp->online++;
		err = 0;
	} else {
		swdp->fail++;
		err = errno;
	}

	/* dump out status info if debug is turned on. */
	if (getenv("TOPOCHIPDBG") != NULL ||
	    getenv("TOPOSUN4VPIDBG") != NULL) {
		const char *op;
		char *fmristr = NULL;

		if (swdp->func == ldom_fmri_retire)
			op = "retire";
		else if (swdp->func == ldom_fmri_unretire)
			op = "unretire";
		else if (swdp->func == ldom_fmri_status)
			op = "check status";
		else
			op = "unknown op";

		(void) topo_mod_nvl2str(mod, asru, &fmristr);
		topo_mod_dprintf(mod, "%s cpu (%s): rc = %d, err = %s\n",
		    op, fmristr == NULL ? "unknown fmri" : fmristr,
		    rc, strerror(err));
		if (fmristr != NULL)
			topo_mod_strfree(mod, fmristr);
	}

	nvlist_free(asru);
	return (TOPO_WALK_NEXT);
}
コード例 #21
0
ファイル: pci_i86pc.c プロジェクト: NanXiao/illumos-joyent
/*ARGSUSED*/
int
parent_is_rc(topo_mod_t *mod, did_t *dp)
{
	return (strcmp(topo_node_name(did_gettnode(dp)), PCIEX_ROOT) == 0);
}
コード例 #22
0
ファイル: fmtopo.c プロジェクト: CoryXie/opensolaris
/*ARGSUSED*/
static int
walk_node(topo_hdl_t *thp, tnode_t *node, void *arg)
{
	int err;
	nvlist_t *nvl;
	nvlist_t *rsrc, *out;
	char *s;

	if (opt_e && strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0) {
		print_everstyle(node);
		return (TOPO_WALK_NEXT);
	}

	if (topo_node_resource(node, &rsrc, &err) < 0) {
		(void) fprintf(stderr, "%s: failed to get resource: "
		    "%s", g_pname, topo_strerror(err));
		return (TOPO_WALK_NEXT);
	}
	if (topo_fmri_nvl2str(thp, rsrc, &s, &err) < 0) {
		(void) fprintf(stderr, "%s: failed to convert "
		    "resource to FMRI string: %s", g_pname,
		    topo_strerror(err));
		nvlist_free(rsrc);
		return (TOPO_WALK_NEXT);
	}

	if (g_fmri != NULL && fnmatch(g_fmri, s, 0) != 0) {
		nvlist_free(rsrc);
		topo_hdl_strfree(thp, s);
		return (TOPO_WALK_NEXT);
	}

	print_node(thp, node, rsrc, s);
	topo_hdl_strfree(thp, s);
	nvlist_free(rsrc);

	if (opt_m != NULL) {
		if (topo_method_invoke(node, opt_m, 0, NULL, &out, &err) == 0) {
			nvlist_print(stdout, out);
			nvlist_free(out);
		} else if (err != ETOPO_METHOD_NOTSUP)
			(void) fprintf(stderr, "%s: method failed unexpectedly "
			    "on %s=%d (%s)\n", g_pname, topo_node_name(node),
			    topo_node_instance(node), topo_strerror(err));
	}

	if (opt_V || opt_all) {
		if ((nvl = topo_prop_getprops(node, &err)) == NULL) {
			(void) fprintf(stderr, "%s: failed to get "
			    "properties for %s=%d: %s\n", g_pname,
			    topo_node_name(node), topo_node_instance(node),
			    topo_strerror(err));
		} else {
			print_all_props(thp, node, nvl, ALL);
			nvlist_free(nvl);
		}
	} else if (pcnt > 0)
		print_props(thp, node);

	(void) printf("\n");

	return (TOPO_WALK_NEXT);
}
コード例 #23
0
ファイル: disk_common.c プロジェクト: drscream/illumos-joyent
/* create the disk topo node */
static int
disk_tnode_create(topo_mod_t *mod, tnode_t *parent,
    dev_di_node_t *dnode, const char *name, topo_instance_t i, tnode_t **rval)
{
	int		len;
	nvlist_t	*fmri;
	tnode_t		*dtn;
	char		*part = NULL;
	nvlist_t	*auth;
	char		*mfg, *model, *firm, *serial;

	*rval = NULL;
	if (dnode != NULL) {
		mfg = topo_mod_clean_str(mod, dnode->ddn_mfg);
		model = topo_mod_clean_str(mod, dnode->ddn_model);
		firm = topo_mod_clean_str(mod, dnode->ddn_firm);
		serial = topo_mod_clean_str(mod, dnode->ddn_serial);
	} else {
		mfg = model = firm = serial = NULL;
	}

	/* form 'part=' of fmri as "<mfg>-<model>" */
	if (mfg != NULL && model != NULL) {
		len = strlen(mfg) + 1 + strlen(model) + 1;
		if ((part = topo_mod_alloc(mod, len)) != NULL)
			(void) snprintf(part, len, "%s-%s",
			    mfg, model);
	}

	auth = topo_mod_auth(mod, parent);
	fmri = topo_mod_hcfmri(mod, parent, FM_HC_SCHEME_VERSION, name, i, NULL,
	    auth, part ? part : model, firm, serial);
	nvlist_free(auth);

	topo_mod_strfree(mod, part);
	topo_mod_strfree(mod, mfg);
	topo_mod_strfree(mod, model);
	topo_mod_strfree(mod, firm);
	topo_mod_strfree(mod, serial);

	if (fmri == NULL) {
		topo_mod_dprintf(mod, "disk_tnode_create: "
		    "hcfmri (%s%d/%s%d) error %s\n",
		    topo_node_name(parent), topo_node_instance(parent),
		    name, i, topo_strerror(topo_mod_errno(mod)));
		return (-1);
	}

	if ((dtn = topo_node_bind(mod, parent, name, i, fmri)) == NULL) {
		if (topo_mod_errno(mod) == EMOD_NODE_BOUND) {
			/*
			 * if disk 0 is already there then we're done
			 */
			nvlist_free(fmri);
			return (0);
		}
		topo_mod_dprintf(mod, "disk_tnode_create: "
		    "bind (%s%d/%s%d) error %s\n",
		    topo_node_name(parent), topo_node_instance(parent),
		    name, i, topo_strerror(topo_mod_errno(mod)));
		nvlist_free(fmri);
		return (-1);
	}
	nvlist_free(fmri);

	/* add the properties of the disk */
	if (disk_set_props(mod, parent, dtn, dnode) != 0) {
		topo_mod_dprintf(mod, "disk_tnode_create: "
		    "disk_set_props (%s%d/%s%d) error %s\n",
		    topo_node_name(parent), topo_node_instance(parent),
		    name, i, topo_strerror(topo_mod_errno(mod)));
		topo_node_unbind(dtn);
		return (-1);
	}

	if (dnode->ddn_devid != NULL &&
	    disk_add_temp_sensor(mod, dtn, dnode->ddn_devid) != 0) {
		topo_mod_dprintf(mod, "disk_tnode_create: failed to create "
		    "temperature sensor node on bay=%d/disk=0",
		    topo_node_instance(parent));
	}
	*rval = dtn;
	return (0);
}
コード例 #24
0
ファイル: motherboard.c プロジェクト: NanXiao/illumos-joyent
static tnode_t *
mb_tnode_create(topo_mod_t *mod, tnode_t *parent,
    const char *name, topo_instance_t i, void *priv)
{
	nvlist_t *fmri;
	tnode_t *ntn;
	char *serial = NULL, *part = NULL;
	char *psn = NULL, *csn = NULL, *pstr = NULL;
	nvlist_t *auth = topo_mod_auth(mod, parent);

	/*
	 * Get Product Serial Number, Chassis ID, MB Serial Number and
	 * Part Number from PRI.
	 */
	(void) mb_get_pri_info(mod, &serial, &part, &csn, &psn);

	if (nvlist_lookup_string(auth, FM_FMRI_AUTH_CHASSIS, &pstr) != 0 &&
	    csn != NULL) {
		if (nvlist_add_string(auth, FM_FMRI_AUTH_CHASSIS, csn) != 0) {
			topo_mod_dprintf(mod,
			    "failed to add chassis to auth");
			nvlist_free(auth);
			return (NULL);
		}
	}

	if (nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT_SN, &pstr) != 0 &&
	    psn != NULL) {
		if (nvlist_add_string(auth, FM_FMRI_AUTH_PRODUCT_SN, psn)
		    != 0) {
			topo_mod_dprintf(mod,
			    "failed to add product-sn to auth");
			nvlist_free(auth);
			return (NULL);
		}
	}

	fmri = topo_mod_hcfmri(mod, NULL, FM_HC_SCHEME_VERSION, name, i,
	    NULL, auth, part, NULL, serial);

	topo_mod_strfree(mod, serial);
	topo_mod_strfree(mod, part);
	topo_mod_strfree(mod, csn);
	topo_mod_strfree(mod, psn);

	if (fmri == NULL) {
		topo_mod_dprintf(mod,
		    "Unable to make nvlist for %s bind: %s.\n",
		    name, topo_mod_errmsg(mod));
		nvlist_free(auth);
		return (NULL);
	}

	ntn = topo_node_bind(mod, parent, name, i, fmri);
	if (ntn == NULL) {
		topo_mod_dprintf(mod,
		    "topo_node_bind (%s%d/%s%d) failed: %s\n",
		    topo_node_name(parent), topo_node_instance(parent),
		    name, i,
		    topo_strerror(topo_mod_errno(mod)));
		nvlist_free(auth);
		nvlist_free(fmri);
		return (NULL);
	}

	mb_prop_set(ntn, auth);

	nvlist_free(auth);
	nvlist_free(fmri);

	topo_node_setspecific(ntn, priv);

	return (ntn);
}
コード例 #25
0
ファイル: pi_meth.c プロジェクト: NanXiao/illumos-joyent
/* Topo Methods */
static int
mem_asru_compute(topo_mod_t *mod, tnode_t *node, topo_version_t version,
    nvlist_t *in, nvlist_t **out)
{
	nvlist_t *asru, *pargs, *args, *hcsp;
	int err;
	char *serial = NULL, *label = NULL;
	uint64_t pa, offset;

	if (version > TOPO_METH_ASRU_COMPUTE_VERSION)
		return (topo_mod_seterrno(mod, EMOD_VER_NEW));

	if (strcmp(topo_node_name(node), DIMM) != 0)
		return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));

	pargs = NULL;

	if (nvlist_lookup_nvlist(in, TOPO_PROP_PARGS, &pargs) == 0)
		(void) nvlist_lookup_string(pargs, FM_FMRI_HC_SERIAL_ID,
		    &serial);
	if (serial == NULL &&
	    nvlist_lookup_nvlist(in, TOPO_PROP_ARGS, &args) == 0)
		(void) nvlist_lookup_string(args, FM_FMRI_HC_SERIAL_ID,
		    &serial);

	(void) topo_node_label(node, &label, &err);

	asru = mem_fmri_create(mod, serial, label);

	if (label != NULL)
		topo_mod_strfree(mod, label);

	if (asru == NULL)
		return (topo_mod_seterrno(mod, EMOD_NOMEM));

	err = 0;

	/*
	 * For a memory page, 'in' includes an hc-specific member which
	 * specifies physaddr and/or offset. Set them in asru as well.
	 */
	if (pargs && nvlist_lookup_nvlist(pargs,
	    FM_FMRI_HC_SPECIFIC, &hcsp) == 0) {
		if (nvlist_lookup_uint64(hcsp,
		    FM_FMRI_HC_SPECIFIC_PHYSADDR, &pa) == 0)
			err += nvlist_add_uint64(asru, FM_FMRI_MEM_PHYSADDR,
			    pa);
		if (nvlist_lookup_uint64(hcsp,
		    FM_FMRI_HC_SPECIFIC_OFFSET, &offset) == 0)
			err += nvlist_add_uint64(asru, FM_FMRI_MEM_OFFSET,
			    offset);
	}


	if (err != 0 || topo_mod_nvalloc(mod, out, NV_UNIQUE_NAME) < 0) {
		nvlist_free(asru);
		return (topo_mod_seterrno(mod, EMOD_NOMEM));
	}

	err = nvlist_add_string(*out, TOPO_PROP_VAL_NAME, TOPO_PROP_ASRU);
	err |= nvlist_add_uint32(*out, TOPO_PROP_VAL_TYPE, TOPO_TYPE_FMRI);
	err |= nvlist_add_nvlist(*out, TOPO_PROP_VAL_VAL, asru);
	nvlist_free(asru);

	if (err != 0) {
		nvlist_free(*out);
		*out = NULL;
		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
	}

	return (0);
}
コード例 #26
0
ファイル: topo_method.c プロジェクト: NanXiao/illumos-joyent
/*ARGSUSED*/
int
topo_method_sensor_failure(topo_mod_t *mod, tnode_t *node,
    topo_version_t version, nvlist_t *in, nvlist_t **out)
{
	const char *name = topo_node_name(node);
	topo_faclist_t faclist, *fp;
	int err;
	nvlist_t *nvl, *props, *propval, *tmp;
	int ret = -1;
	uint32_t type, state, units;
	nvpair_t *elem;
	double reading;
	char *propname;
	boolean_t has_reading;
	struct sensor_errinfo seinfo;

	if (strcmp(name, PSU) != 0 && strcmp(name, FAN) != 0)
		return (topo_mod_seterrno(mod, ETOPO_METHOD_NOTSUP));

	if (topo_node_facility(mod->tm_hdl, node, TOPO_FAC_TYPE_SENSOR,
	    TOPO_FAC_TYPE_ANY, &faclist, &err) != 0)
		return (topo_mod_seterrno(mod, ETOPO_METHOD_NOTSUP));

	if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0)
		goto error;

	for (fp = topo_list_next(&faclist.tf_list); fp != NULL;
	    fp = topo_list_next(fp)) {
		if (topo_prop_getpgrp(fp->tf_node, TOPO_PGROUP_FACILITY,
		    &props, &err) != 0) {
			nvlist_free(nvl);
			goto error;
		}
		type = state = units = 0;
		reading = 0;
		has_reading = B_FALSE;

		elem = NULL;
		while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
			if (strcmp(nvpair_name(elem), TOPO_PROP_VAL) != 0 ||
			    nvpair_type(elem) != DATA_TYPE_NVLIST)
				continue;

			(void) nvpair_value_nvlist(elem, &propval);
			if (nvlist_lookup_string(propval,
			    TOPO_PROP_VAL_NAME, &propname) != 0)
				continue;

			if (strcmp(propname, TOPO_FACILITY_TYPE) == 0) {
				(void) nvlist_lookup_uint32(propval,
				    TOPO_PROP_VAL_VAL, &type);
			} else if (strcmp(propname, TOPO_SENSOR_STATE) == 0) {
				(void) nvlist_lookup_uint32(propval,
				    TOPO_PROP_VAL_VAL, &state);
			} else if (strcmp(propname, TOPO_SENSOR_UNITS) == 0) {
				(void) nvlist_lookup_uint32(propval,
				    TOPO_PROP_VAL_VAL, &units);
			} else if (strcmp(propname, TOPO_SENSOR_READING) == 0) {
				has_reading = B_TRUE;
				(void) nvlist_lookup_double(propval,
				    TOPO_PROP_VAL_VAL, &reading);
			}
		}

		if (topo_sensor_failed(type, state, &seinfo)) {
			tmp = NULL;
			if (topo_mod_nvalloc(mod, &tmp, NV_UNIQUE_NAME) != 0 ||
			    nvlist_add_uint32(tmp, TOPO_FACILITY_TYPE,
			    type) != 0 ||
			    nvlist_add_uint32(tmp, TOPO_SENSOR_STATE,
			    state) != 0 ||
			    nvlist_add_uint32(tmp, TOPO_SENSOR_UNITS,
			    units) != 0 ||
			    nvlist_add_boolean_value(tmp,
			    "nonrecov", seinfo.se_nonrecov) != 0 ||
			    nvlist_add_boolean_value(tmp,
			    "predictive", seinfo.se_predictive) != 0 ||
			    nvlist_add_uint32(tmp, "source",
			    seinfo.se_src) != 0 ||
			    (has_reading && nvlist_add_double(tmp,
			    TOPO_SENSOR_READING, reading) != 0) ||
			    nvlist_add_nvlist(nvl, topo_node_name(fp->tf_node),
			    tmp) != 0) {
				nvlist_free(props);
				nvlist_free(tmp);
				nvlist_free(nvl);
				ret = topo_mod_seterrno(mod,
				    ETOPO_METHOD_NOMEM);
				goto error;
			}

			nvlist_free(tmp);
		}

		nvlist_free(props);
	}

	*out = nvl;
	ret = 0;
error:
	while ((fp = topo_list_next(&faclist.tf_list)) != NULL) {
		topo_list_delete(&faclist.tf_list, fp);
		topo_mod_free(mod, fp, sizeof (topo_faclist_t));
	}
	return (ret);
}