Example #1
0
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);
}
Example #2
0
/*
 * dev_for_hostbridge() -- For hostbridges we truncate the devfs path
 * after the first element in the bus address.
 */
static char *
dev_for_hostbridge(topo_mod_t *mp, char *path)
{
	char *lastslash;
	char *newpath;
	char *comma;
	int plen;

	plen = strlen(path) + 1;

	/*
	 * We only care about the last component of the dev path. If
	 * we don't find a slash, something is weird.
	 */
	lastslash = strrchr(path, '/');
	assert(lastslash != NULL);

	/*
	 * Find the comma in the last component component@x,y, and
	 * truncate the comma and any following number.
	 */
	comma = strchr(lastslash, ',');
	assert(comma != NULL);

	*comma = '\0';
	if ((newpath = topo_mod_strdup(mp, path)) == NULL) {
		topo_mod_free(mp, path, plen);
		return (NULL);
	}

	*comma = ',';
	topo_mod_free(mp, path, plen);
	return (newpath);
}
Example #3
0
/* di_devlink callback for dev_di_node_add */
static int
disk_devlink_callback(di_devlink_t dl, void *arg)
{
	disk_cbdata_t	*cbp = (disk_cbdata_t *)arg;
	topo_mod_t	*mod = cbp->dcb_mod;
	dev_di_node_t	*dnode = cbp->dcb_dnode;
	const char	*devpath;
	char		*ctds, *slice;

	devpath = di_devlink_path(dl);
	if ((dnode == NULL) || (devpath == NULL))
		return (DI_WALK_TERMINATE);

	/* trim the slice off the public name */
	if (((ctds = strrchr(devpath, '/')) != NULL) &&
	    ((slice = strchr(ctds, 's')) != NULL))
		*slice = '\0';

	/* Establish the public /dev name (no slice) */
	dnode->ddn_lpath = topo_mod_strdup(mod, ctds ? ctds + 1 : devpath);

	if (ctds && slice)
		*slice = 's';
	return (DI_WALK_TERMINATE);
}
Example #4
0
did_t *
split_bus_address(did_hash_t *dhash, di_node_t dp, uint_t baseaddr,
    uint_t bussep, int minbrd, int maxbrd, int *brd, int *br, int *bus,
    di_prom_handle_t promtree, topo_mod_t *mod)
{
	uint_t bc, ac;
	char *comma;
	char *bac;
	char *ba;
	int e;

	if ((ba = di_bus_addr(dp)) == NULL ||
	    (bac = topo_mod_strdup(mod, ba)) == NULL)
		return (NULL);

	topo_mod_dprintf(mod,
	    "Transcribing %s into board, bus, etc.\n", bac);

	if ((comma = strchr(bac, ',')) == NULL) {
		topo_mod_strfree(mod, bac);
		return (NULL);
	}
	*comma = '\0';
	bc = strtonum(mod, bac, &e);
	*comma = ',';
	if (e < 0) {
		topo_mod_dprintf(mod,
		    "Trouble interpreting %s before comma.\n", bac);
		topo_mod_strfree(mod, bac);
		return (NULL);
	}
	ac = strtonum(mod, comma + 1, &e);
	if (e < 0) {
		topo_mod_dprintf(mod,
		    "Trouble interpreting %s after comma.\n", bac);
		topo_mod_strfree(mod, bac);
		return (NULL);
	}
	topo_mod_strfree(mod, bac);

	*brd = ((bc - baseaddr) / bussep) + minbrd;
	*br = (bc - baseaddr) % bussep;
	*bus = ((ac == IOB_BUSADDR1) ? 0 : 1);
	if (*brd < minbrd || *brd > maxbrd || (*br != 0 && *br != 1) ||
	    (ac != IOB_BUSADDR1 && ac != IOB_BUSADDR2)) {
		topo_mod_dprintf(mod, "Trouble with transcription\n");
		topo_mod_dprintf(mod, "brd=%d br=%d bus=%d bc=%x ac=%x\n",
		    *brd, *br, *bus, bc, ac);
		return (NULL);
	}
	return (did_create(dhash, dp, *brd, *br, NO_RC, *bus, promtree));
}
Example #5
0
int
topo_node_range_create(topo_mod_t *mod, tnode_t *pnode, const char *name,
    topo_instance_t min, topo_instance_t max)
{
	topo_nodehash_t *nhp;

	topo_node_lock(pnode);

	assert((pnode->tn_state & TOPO_NODE_BOUND) ||
	    (pnode->tn_state & TOPO_NODE_ROOT));

	for (nhp = topo_list_next(&pnode->tn_children); nhp != NULL;
	    nhp = topo_list_next(nhp)) {
		if (strcmp(nhp->th_name, name) == 0)
			return (node_create_seterror(mod, pnode, NULL,
			    ETOPO_NODE_DUP));
	}

	if (min < 0 || max < min)
		return (node_create_seterror(mod, pnode, NULL,
		    ETOPO_NODE_INVAL));

	if ((nhp = topo_mod_zalloc(mod, sizeof (topo_nodehash_t))) == NULL)
		return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM));

	if ((nhp->th_name = topo_mod_strdup(mod, name)) == NULL)
		return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM));

	nhp->th_arrlen = max - min + 1;

	if ((nhp->th_nodearr = topo_mod_zalloc(mod,
	    nhp->th_arrlen * sizeof (tnode_t *))) == NULL)
		return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM));

	nhp->th_range.tr_min = min;
	nhp->th_range.tr_max = max;
	nhp->th_enum = mod;
	topo_mod_hold(mod);

	/*
	 * Add these nodes to parent child list
	 */
	topo_list_append(&pnode->tn_children, nhp);
	topo_node_unlock(pnode);

	topo_dprintf(TOPO_DBG_MOD, "created node range %s[%d-%d]\n", name,
	    min, max);

	return (0);
}
Example #6
0
tf_info_t *
tf_info_new(topo_mod_t *mp, xmlDocPtr doc, xmlChar *scheme)
{
	tf_info_t *r;

	if ((r = topo_mod_zalloc(mp, sizeof (tf_info_t))) == NULL)
		return (NULL);
	r->tf_flags = TF_LIVE;
	if ((r->tf_scheme = topo_mod_strdup(mp, (char *)scheme)) == NULL) {
		tf_info_free(mp, r);
		return (NULL);
	}
	r->tf_xdoc = doc;
	return (r);
}
Example #7
0
/*
 * Manufacturing strings can contain characters that are invalid for use in hc
 * authority names.  This trims leading and trailing whitespace, and
 * substitutes any characters known to be bad.
 */
char *
disk_auth_clean(topo_mod_t *mod, const char *str)
{
	char *buf, *p;

	if (str == NULL)
		return (NULL);

	if ((buf = topo_mod_strdup(mod, str)) == NULL)
		return (NULL);

	while ((p = strpbrk(buf, " :=")) != NULL)
		*p = '-';

	return (buf);
}
Example #8
0
const char *
x86pi_cleanup_smbios_str(topo_mod_t *mod, const char *begin, int str_type)
{
	char buf[MAXNAMELEN];
	const char *end, *cp;
	char *pp;
	char c;
	int i;

	end = begin + strlen(begin);

	while (begin < end && isspace(*begin))
		begin++;
	while (begin < end && isspace(*(end - 1)))
		end--;

	if (begin >= end)
		return (NULL);

	cp = begin;
	for (i = 0; i < MAXNAMELEN - 1; i++) {
		if (cp >= end)
			break;
		c = *cp;
		if (str_type == LABEL) {
			if (!isprint(c))
				buf[i] = '-';
			else
				buf[i] = c;
		} else {
			if (c == ':' || c == '=' || c == '/' ||
			    isspace(c) || !isprint(c))
				buf[i] = '-';
			else
				buf[i] = c;
		}
		cp++;
	}
	buf[i] = 0;

	pp = topo_mod_strdup(mod, buf);

	if (str_type == LABEL)
		topo_mod_strfree(mod, (char *)begin);

	return (pp);
}
Example #9
0
tf_rdata_t *
tf_rdata_new(topo_mod_t *mp, tf_info_t *xinfo, xmlNodePtr n, tnode_t *troot)
{
	tf_rdata_t *r;
	uint64_t ui;
	xmlChar *name = NULL;

	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "new rdata\n");
	if ((r = topo_mod_zalloc(mp, sizeof (tf_rdata_t))) == NULL) {
		(void) topo_mod_seterrno(mp, ETOPO_NOMEM);
		return (NULL);
	}
	r->rd_pn = troot;
	if ((name = xmlGetProp(n, (xmlChar *)Name)) == NULL) {
		(void) topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
		goto rdata_nogood;
	}
	if ((r->rd_name = topo_mod_strdup(mp, (char *)name)) == NULL) {
		(void) topo_mod_seterrno(mp, ETOPO_NOMEM);
		goto rdata_nogood;
	}
	if (xmlattr_to_int(mp, n, Min, &ui) < 0)
		goto rdata_nogood;
	r->rd_min = (int)ui;
	if (xmlattr_to_int(mp, n, Max, &ui) < 0)
		goto rdata_nogood;
	r->rd_max = (int)ui;
	if (r->rd_min < 0 || r->rd_max < 0 || r->rd_max < r->rd_min) {
		(void) topo_mod_seterrno(mp, ETOPO_PRSR_BADRNG);
		goto rdata_nogood;
	}
	r->rd_finfo = xinfo;
	r->rd_mod = mp;

	if (topo_xml_range_process(mp, n, r) < 0)
		goto rdata_nogood;

	xmlFree(name);
	return (r);

rdata_nogood:
	if (name != NULL)
		xmlFree(name);
	tf_rdata_free(mp, r);
	return (NULL);
}
Example #10
0
/*
 * Get the server hostname (the ID as far as the topo authority is
 * concerned) from sysinfo and return a copy to the caller.
 *
 * The string must be freed with topo_mod_strfree()
 */
char *
x86pi_get_serverid(topo_mod_t *mod)
{
	int result;
	char hostname[MAXNAMELEN];

	topo_mod_dprintf(mod, "x86pi_get_serverid\n");

	result = sysinfo(SI_HOSTNAME, hostname, sizeof (hostname));
	/* Everything is freed up and it's time to return the platform-id */
	if (result == -1) {
		return (NULL);
	}
	topo_mod_dprintf(mod, "x86pi_get_serverid: hostname = %s\n", hostname);

	return (topo_mod_strdup(mod, hostname));
}
Example #11
0
ttree_t *
topo_tree_create(topo_hdl_t *thp, topo_mod_t *mod, const char *scheme)
{
    ttree_t *tp;
    tnode_t *rp;

    if ((tp = topo_mod_zalloc(mod, sizeof (ttree_t))) == NULL)
        return (set_create_error(thp, NULL, ETOPO_NOMEM));

    tp->tt_mod = mod;

    if ((tp->tt_scheme = topo_mod_strdup(mod, scheme)) == NULL)
        return (set_create_error(thp, tp, ETOPO_NOMEM));

    /*
     * Initialize a private walker for internal use
     */
    if ((tp->tt_walk = topo_mod_zalloc(mod, sizeof (topo_walk_t))) == NULL)
        return (set_create_error(thp, tp, ETOPO_NOMEM));

    /*
     * Create the root of this tree: LINKED but never BOUND
     */
    if ((rp = topo_mod_zalloc(mod, sizeof (tnode_t))) == NULL)
        return (set_create_error(thp, tp, 0)); /* th_errno set */

    rp->tn_state = TOPO_NODE_ROOT | TOPO_NODE_INIT;
    rp->tn_name = tp->tt_scheme;
    rp->tn_instance = 0;
    rp->tn_enum = mod;
    rp->tn_hdl = thp;

    topo_node_hold(rp);

    tp->tt_walk->tw_root = rp;
    tp->tt_walk->tw_thp = thp;

    topo_mod_hold(mod); /* released when root node destroyed */

    tp->tt_root = rp;

    return (tp);
}
Example #12
0
/*
 * Remove the 3 character device name (pci/niu) from devfs path.
 */
static char *
xaui_trans_str(topo_mod_t *mod, char *dn, char *p, size_t buf_len)
{
	int i = 0;
	int j = 0;
	char buf[MAXPATHLEN];

	topo_mod_dprintf(mod, "xaui_trans_str: dev path(%s) dev name(%s)\n",
	    dn, p);
	do {
		/* strip out either "pci" or "niu" */
		if (dn[i] == p[0] && dn[i + 1] == p[1] && dn[i + 2] == p[2])
			i += 3;
		else
			buf[j++] = dn[i++];
	} while (i < buf_len);

	topo_mod_dprintf(mod, "xaui_trans_str: return(%s)\n", buf);
	return (topo_mod_strdup(mod, (char *)buf));
}
Example #13
0
/*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);
}
Example #14
0
static int
create_core(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu,
    nvlist_t *auth, uint16_t chip_smbiosid)
{
	tnode_t *core;
	int32_t coreid, cpuid;
	int err, perr, nerr = 0;
	nvlist_t *fmri;
	char *serial = NULL;
	char *part = NULL;
	char *rev = NULL;

	if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_CORE_ID, &coreid))
	    != 0) {
		whinge(mod, NULL, "create_core: lookup core_id failed: %s\n",
		    strerror(err));
		return (-1);
	}
	if ((core = topo_node_lookup(pnode, CORE_NODE_NAME, coreid)) == NULL) {
		if ((core = create_node(mod, pnode, auth, CORE_NODE_NAME,
		    coreid, chip_smbiosid)) == NULL)
			return (-1);

		/*
		 * Inherit FRU from the chip node, for native, we use hc
		 * scheme ASRU for the core node.
		 */
		(void) topo_node_fru_set(core, NULL, 0, &perr);
		/*
		 * From the inherited FRU, extract the Serial
		 * number if SMBIOS donates and set it in the ASRU
		 */
		if (FM_AWARE_SMBIOS(mod)) {
			char *val = NULL;

			if (topo_node_resource(core, &fmri, &err) != 0)
				whinge(mod, NULL,
				    "create_core: topo_prop_get_fmri failed\n");
			if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID,
			    &val) != 0)
				whinge(mod, NULL, "create_core:"
				    "nvlist_lookup_string failed\n");
			else
				serial = topo_mod_strdup(mod, val);
			nvlist_free(fmri);
		}
		if (is_xpv()) {
			if (topo_node_resource(core, &fmri, &err) == -1) {
				whinge(mod, &nerr, "create_core: "
				    "topo_node_resource failed\n");
			} else {
				if (FM_AWARE_SMBIOS(mod))
					(void) nvlist_add_string(fmri,
					    FM_FMRI_HC_SERIAL_ID, serial);
				(void) topo_node_asru_set(core, fmri, 0, &err);
				nvlist_free(fmri);
			}
		}
		if (topo_method_register(mod, core, strands_retire_methods) < 0)
			whinge(mod, &nerr, "create_core: "
			    "topo_method_register failed\n");

		(void) topo_pgroup_create(core, &core_pgroup, &err);
		nerr -= add_nvlist_longprops(mod, core, cpu, PGNAME(CORE), NULL,
		    CORE_CHIP_ID, CORE_PROCNODE_ID, NULL);

		if (topo_node_range_create(mod, core, STRAND_NODE_NAME,
		    0, 255) != 0)
			return (-1);
	}

	if (!is_xpv()) {
		/*
		 * In native mode, we're in favor of cpu scheme ASRU for
		 * printing reason.  More work needs to be done to support
		 * multi-strand cpu: the ASRU will be a list of cpuid then.
		 */
		if (nvlist_lookup_int32(cpu, STRAND_CPU_ID, &cpuid) != 0) {
			whinge(mod, &nerr, "create_core: lookup cpuid "
			    "failed\n");
		} else {
			if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0))
			    != NULL) {
				(void) topo_node_asru_set(core, fmri, 0, &err);
				nvlist_free(fmri);
			} else {
				whinge(mod, &nerr, "create_core: "
				    "cpu_fmri_create() failed\n");
			}
		}
	}

	if (FM_AWARE_SMBIOS(mod)) {
		(void) topo_node_label_set(core, NULL, &perr);

		if (topo_node_resource(core, &fmri, &perr) != 0) {
			whinge(mod, &nerr, "create_core: "
			    "topo_node_resource failed\n");
			perr = 0;
		}

		perr += nvlist_lookup_string(fmri,
		    FM_FMRI_HC_PART, &part);
		perr += nvlist_lookup_string(fmri,
		    FM_FMRI_HC_REVISION, &rev);

		if (perr != 0) {
			whinge(mod, NULL,
			    "create_core: nvlist_lookup_string failed\n");
			perr = 0;
		}

		perr += topo_prop_set_string(core, PGNAME(CORE),
		    FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr);
		perr += topo_prop_set_string(core, PGNAME(CORE),
		    FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr);
		perr += topo_prop_set_string(core, PGNAME(CORE),
		    FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr);

		if (perr != 0)
			whinge(mod, NULL, "create_core: topo_prop_set_string"
			    "failed\n");

		nvlist_free(fmri);
		topo_mod_strfree(mod, serial);
	}

	err = create_strand(mod, core, cpu, auth, chip_smbiosid);

	return (err == 0 && nerr == 0 ? 0 : -1);
}
Example #15
0
static int
create_strand(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu,
    nvlist_t *auth, uint16_t chip_smbiosid)
{
	tnode_t *strand;
	int32_t strandid, cpuid;
	int err, perr, nerr = 0;
	nvlist_t *fmri;
	char *serial = NULL;
	char *part = NULL;
	char *rev = NULL;

	if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_STRAND_ID,
	    &strandid)) != 0) {
		whinge(mod, NULL, "create_strand: lookup strand_id failed: "
		    "%s\n", strerror(err));
		return (-1);
	}

	if ((strand = topo_node_lookup(pnode, STRAND_NODE_NAME, strandid))
	    != NULL) {
		whinge(mod, NULL, "create_strand: duplicate tuple found\n");
		return (-1);
	}

	if ((strand = create_node(mod, pnode, auth, STRAND_NODE_NAME,
	    strandid, chip_smbiosid)) == NULL)
		return (-1);

	/*
	 * Inherit FRU from core node, in native use cpu scheme ASRU,
	 * in xpv, use hc scheme ASRU.
	 */
	(void) topo_node_fru_set(strand, NULL, 0, &perr);
	/*
	 * From the inherited FRU, extract the Serial
	 * number(if SMBIOS donates) and set it in the ASRU
	 */
	if (FM_AWARE_SMBIOS(mod)) {
		char *val = NULL;

		if (topo_prop_get_fmri(strand, TOPO_PGROUP_PROTOCOL,
		    TOPO_PROP_RESOURCE, &fmri, &err) != 0)
			whinge(mod, NULL,
			    "create_strand: topo_prop_get_fmri failed\n");
		if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID, &val) != 0)
			whinge(mod, NULL,
			    "create_strand: nvlist_lookup_string failed: \n");
		else
			serial = topo_mod_strdup(mod, val);
		nvlist_free(fmri);
	}
	if (is_xpv()) {
		if (topo_node_resource(strand, &fmri, &err) == -1) {
			whinge(mod, &nerr, "create_strand: "
			    "topo_node_resource failed\n");
		} else {
			if (FM_AWARE_SMBIOS(mod))
				(void) nvlist_add_string(fmri,
				    FM_FMRI_HC_SERIAL_ID, serial);
			(void) topo_node_asru_set(strand, fmri, 0, &err);
			nvlist_free(fmri);
		}
	} else {
		if (nvlist_lookup_int32(cpu, STRAND_CPU_ID, &cpuid) != 0) {
			whinge(mod, &nerr, "create_strand: lookup cpuid "
			    "failed\n");
		} else {
			if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0))
			    != NULL) {
				(void) topo_node_asru_set(strand, fmri,
				    0, &err);
				nvlist_free(fmri);
			} else {
				whinge(mod, &nerr, "create_strand: "
				    "cpu_fmri_create() failed\n");
			}
		}
	}

	if (topo_method_register(mod, strand, strands_retire_methods) < 0)
		whinge(mod, &nerr, "create_strand: "
		    "topo_method_register failed\n");

	(void) topo_pgroup_create(strand, &strand_pgroup, &err);
	nerr -= add_nvlist_longprops(mod, strand, cpu, PGNAME(STRAND), NULL,
	    STRAND_CHIP_ID, STRAND_PROCNODE_ID, STRAND_CORE_ID, STRAND_CPU_ID,
	    NULL);

	if (FM_AWARE_SMBIOS(mod)) {
		(void) topo_node_label_set(strand, NULL, &perr);

		if (topo_node_resource(strand, &fmri, &perr) != 0) {
			whinge(mod, &nerr, "create_strand: "
			    "topo_node_resource failed\n");
			perr = 0;
		}

		perr += nvlist_lookup_string(fmri,
		    FM_FMRI_HC_PART, &part);
		perr += nvlist_lookup_string(fmri,
		    FM_FMRI_HC_REVISION, &rev);

		if (perr != 0) {
			whinge(mod, NULL,
			    "create_strand: nvlist_lookup_string failed\n");
			perr = 0;
		}

		perr += topo_prop_set_string(strand, PGNAME(STRAND),
		    FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr);
		perr += topo_prop_set_string(strand, PGNAME(STRAND),
		    FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr);
		perr += topo_prop_set_string(strand, PGNAME(STRAND),
		    FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr);

		if (perr != 0)
			whinge(mod, NULL, "create_strand: topo_prop_set_string"
			    "failed\n");

		nvlist_free(fmri);
		topo_mod_strfree(mod, serial);
	}

	return (err == 0 && nerr == 0 ? 0 : -1);
}
Example #16
0
/*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);
}
Example #17
0
tnode_t *
x86pi_gen_chassis(topo_mod_t *mod, tnode_t *t_parent, int smb_id, int instance)
{
	int			rv;
	smbios_info_t		ip;
	smbios_chassis_t	ch;
	x86pi_hcfmri_t		ch_hcfmri;
	tnode_t			*ch_node;
	char			*f = "x86pi_gen_chassis";
	smbios_hdl_t		*shp;

	shp = topo_mod_smbios(mod);
	if (shp == NULL) {
		topo_mod_dprintf(mod, "%s: failed to load SMBIOS\n", f);
		return (NULL);
	}

	/* init fmri struct */
	bzero(&ch_hcfmri, sizeof (x86pi_hcfmri_t));

	/* grab SMBIOS strings */
	rv = smbios_info_common(shp, smb_id, &ip);
	if (rv != 0) {
		return (NULL);
	}

	/* grab SMBIOS type 3 struct */
	rv = smbios_info_chassis(shp, smb_id, &ch);
	if (rv != 0) {
		return (NULL);
	}

	/* populate string entries */
	ch_hcfmri.serial_number = x86pi_cleanup_smbios_str(mod,
	    ip.smbi_serial, 0);
	ch_hcfmri.version = x86pi_cleanup_smbios_str(mod, ip.smbi_version, 0);
	ch_hcfmri.manufacturer = x86pi_cleanup_smbios_str(mod,
	    ip.smbi_manufacturer, 0);

	/* set hc_name and instance */
	ch_hcfmri.hc_name = topo_mod_strdup(mod, "chassis");
	ch_hcfmri.instance = instance;

	topo_mod_dprintf(mod, "%s: instance (%d)\n", f, ch_hcfmri.instance);
	topo_mod_dprintf(mod, "%s: hc name (%s)\n", f, ch_hcfmri.hc_name);
	topo_mod_dprintf(mod, "%s: Serial Number (%s)\n",
	    f, ch_hcfmri.serial_number);
	topo_mod_dprintf(mod, "%s: Version (%s)\n", f, ch_hcfmri.version);
	topo_mod_dprintf(mod, "%s: Manufacturer (%s)\n",
	    f, ch_hcfmri.manufacturer);

	/* create topo node */
	if (!instance) {
		/* First Chassis SMBIOS Record is Chassis topo instance 0 */
		rv = x86pi_enum_generic(mod, &ch_hcfmri, t_parent, NULL,
		    &ch_node, 0);
	} else {
		rv = x86pi_enum_generic(mod, &ch_hcfmri, t_parent, t_parent,
		    &ch_node, 0);
	}
	if (rv != 0) {
		topo_mod_dprintf(mod, "%s: failed to create %d tnode\n", f,
		    instance);
		return (NULL);
	}

	/* free up strings */
	if (ch_hcfmri.serial_number != NULL) {
		topo_mod_strfree(mod, (char *)ch_hcfmri.serial_number);
	}
	if (ch_hcfmri.version != NULL) {
		topo_mod_strfree(mod, (char *)ch_hcfmri.version);
	}
	if (ch_hcfmri.manufacturer != NULL) {
		topo_mod_strfree(mod, (char *)ch_hcfmri.manufacturer);
	}
	if (ch_hcfmri.hc_name != NULL) {
		topo_mod_strfree(mod, (char *)ch_hcfmri.hc_name);
	}

	return (ch_node);
}
Example #18
0
static int
cpu_n2_mdesc_init(topo_mod_t *mod, md_t *mdp, md_info_t *chip)
{
	mde_cookie_t *list1p, *list2p;
	md_cpumap_t *mcmp;
	md_proc_t *procp;
	md_fru_t *frup;
	int i, j, cnt;
	int procid_flag = 0;
	int nnode, ncomp, nproc, ncpu;
	char *str = NULL;
	uint64_t x, sn;
	char *strserial, *end;

	nnode = md_node_count(mdp);
	list1p = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * nnode);

	/* Count the number of processors and strands */
	ncomp = md_scan_dag(mdp,
	    MDE_INVAL_ELEM_COOKIE,
	    md_find_name(mdp, MD_STR_COMPONENT),
	    md_find_name(mdp, "fwd"),
	    list1p);
	if (ncomp <= 0) {
		topo_mod_dprintf(mod, "Component nodes not found\n");
		topo_mod_free(mod, list1p, sizeof (mde_cookie_t) * nnode);
		return (-1);
	}
	for (i = 0, nproc = 0, ncpu = 0; i < ncomp; i++) {
		if (md_get_prop_str(mdp, list1p[i], MD_STR_TYPE, &str) == 0 &&
		    str != NULL && strcmp(str, MD_STR_PROCESSOR) == 0) {
			nproc++;
			/* check if the physical id exists */
			if (md_get_prop_val(mdp, list1p[i], MD_STR_ID, &x)
			    == 0) {
				procid_flag = 1;
			}
		}
		if (md_get_prop_str(mdp, list1p[i], MD_STR_TYPE, &str) == 0 &&
		    str && strcmp(str, MD_STR_STRAND) == 0) {
			ncpu++;
		}
	}
	topo_mod_dprintf(mod, "Found %d procs and %d strands\n", nproc, ncpu);
	if (nproc == 0 || ncpu == 0) {
		topo_mod_free(mod, list1p, sizeof (mde_cookie_t) * nnode);
		return (-1);
	}

	/* Alloc processors and strand entries */
	list2p = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * 2 * ncpu);
	chip->nprocs = nproc;
	chip->procs = topo_mod_zalloc(mod, nproc * sizeof (md_proc_t));
	chip->ncpus = ncpu;
	chip->cpus = topo_mod_zalloc(mod, ncpu * sizeof (md_cpumap_t));

	/* Visit each processor node */
	procp = chip->procs;
	mcmp = chip->cpus;
	for (i = 0, nproc = 0, ncpu = 0; i < ncomp; i++) {
		if (md_get_prop_str(mdp, list1p[i], MD_STR_TYPE, &str) < 0 ||
		    str == NULL || strcmp(str, MD_STR_PROCESSOR))
			continue;
		if (md_get_prop_val(mdp, list1p[i], MD_STR_SERIAL, &sn) < 0) {
			if (md_get_prop_str(mdp, list1p[i], MD_STR_SERIAL,
			    &strserial) < 0) {
				topo_mod_dprintf(mod,
				    "Failed to get the serial number of"
				    "proc[%d]\n", nproc);
				continue;
			} else {
				sn = (uint64_t)strtoull(strserial, &end, 16);
				if (strserial == end) {
					topo_mod_dprintf(mod,
					    "Failed to convert the serial "
					    "string to serial int of "
					    "proc[%d]\n", nproc);
					continue;
				}
			}
		}
		procp->serialno = sn;

		/* Assign physical proc id */
		procp->id = -1;
		if (procid_flag) {
			if (md_get_prop_val(mdp, list1p[i], MD_STR_ID, &x)
			    == 0) {
				procp->id = x;
			}
		} else {
			procp->id = nproc;
		}
		topo_mod_dprintf(mod, "proc %d: sn=%llx, id=%d\n", nproc,
		    procp->serialno, procp->id);

		/* Get all the strands below this proc */
		cnt = md_scan_dag(mdp,
		    list1p[i],
		    md_find_name(mdp, MD_STR_COMPONENT),
		    md_find_name(mdp, "fwd"),
		    list2p);
		topo_mod_dprintf(mod, "proc[%llx]: Found %d fwd components\n",
		    sn, cnt);
		if (cnt <= 0) {
			nproc++;
			procp++;
			continue;
		}
		for (j = 0; j < cnt; j++) {
			/* Consider only the strand nodes */
			if (md_get_prop_str(mdp, list2p[j], MD_STR_TYPE, &str)
			    < 0 || str == NULL || strcmp(str, MD_STR_STRAND))
				continue;

			if (md_get_prop_val(mdp, list2p[j], MD_STR_ID, &x) < 0)
				x = (uint64_t)-1; /* invalid value */
			mcmp->cpumap_id = x;

			if (md_get_prop_val(mdp, list2p[j], MD_STR_PID, &x) < 0)
				x = mcmp->cpumap_id;
			mcmp->cpumap_pid = x;

			mcmp->cpumap_serialno = sn;
			mcmp->cpumap_chipidx = nproc;
			ncpu++;
			mcmp++;
		}

		/*
		 * To get the fru of this proc, follow the back arc up to
		 * find the first node whose fru field is set
		 */
		cnt = md_scan_dag(mdp,
		    list1p[i],
		    md_find_name(mdp, MD_STR_COMPONENT),
		    md_find_name(mdp, "back"),
		    list2p);
		topo_mod_dprintf(mod, "proc[%d]: Found %d back components\n",
		    nproc, cnt);
		if (cnt <= 0) {
			nproc++;
			procp++;
			continue;
		}
		for (j = 0; j < cnt; j++) {
			/* test the fru field which must be positive number */
			if ((md_get_prop_val(mdp, list2p[j], MD_STR_FRU, &x)
			    == 0) && x > 0)
				break;
		}
		if (j < cnt) {
			/* Found the FRU node, get the fru identity */
			topo_mod_dprintf(mod, "proc[%d] sn=%llx has a fru %d\n",
			    nproc, procp->serialno, j);
			frup = topo_mod_zalloc(mod, sizeof (md_fru_t));
			procp->fru = frup;
			if (!md_get_prop_str(mdp, list2p[j], MD_STR_NAC, &str))
				frup->nac = topo_mod_strdup(mod, str);
			else
				frup->nac = topo_mod_strdup(mod, MD_FRU_DEF);
			if (!md_get_prop_str(mdp, list2p[j], MD_STR_PART, &str))
				frup->part = topo_mod_strdup(mod, str);
			if (!md_get_prop_str(mdp, list2p[j], MD_STR_SERIAL,
			    &str))
				frup->serial = topo_mod_strdup(mod, str);
			if (!md_get_prop_str(mdp, list2p[j], MD_STR_DASH, &str))
				frup->dash = topo_mod_strdup(mod, str);
		} else {
			topo_mod_dprintf(mod, "proc[%d] sn=%llx has no fru\n",
			    i, procp->serialno);
		}

		nproc++;
		procp++;
	} /* for i */

	topo_mod_free(mod, list1p, sizeof (mde_cookie_t) * nnode);
	topo_mod_free(mod, list2p, sizeof (mde_cookie_t) * 2*chip->ncpus);

	return (0);
}
Example #19
0
/*
 * Request the SAS address of the disk (if any) attached to this mpt_sas
 * instance at (Enclosure Number, Slot Number).  The function returns
 * -1 on error and sets errno to ENOENT _only_ if the /devices node
 * (*devctl) does not exist.
 */
static int
get_sas_address(topo_mod_t *mod, char *devctl, uint32_t enclosure,
    uint32_t slot, char **sas_address)
{
	int ret = -1, en = ENXIO;
	int fd, i;
	mptsas_get_disk_info_t gdi;
	mptsas_disk_info_t *di;
	size_t disz;

	bzero(&gdi, sizeof (gdi));

	if ((fd = open(devctl, O_RDWR)) == -1) {
		en = errno;
		topo_mod_dprintf(mod, "could not open '%s' for ioctl: %s\n",
		    devctl, strerror(errno));
		errno = en;
		return (-1);
	}

	if (ioctl(fd, MPTIOCTL_GET_DISK_INFO, &gdi) == -1) {
		if (errno != ENOENT)
			en = errno;
		topo_mod_dprintf(mod, "ioctl 1 on '%s' failed: %s\n", devctl,
		    strerror(errno));
		goto out;
	}

	gdi.DiskInfoArraySize = disz = sizeof (mptsas_disk_info_t) *
	    gdi.DiskCount;
	gdi.PtrDiskInfoArray = di = topo_mod_alloc(mod, disz);
	if (di == NULL) {
		topo_mod_dprintf(mod, "memory allocation failed\n");
		en = ENOMEM;
		goto out;
	}

	if (ioctl(fd, MPTIOCTL_GET_DISK_INFO, &gdi) == -1) {
		if (errno != ENOENT)
			en = errno;
		topo_mod_dprintf(mod, "ioctl 2 on '%s' failed: %s\n", devctl,
		    strerror(errno));
		topo_mod_free(mod, di, disz);
		goto out;
	}

	for (i = 0; i < gdi.DiskCount; i++) {
		if (di[i].Enclosure == enclosure && di[i].Slot == slot) {
			char sas[17]; /* 16 hex digits and NUL */
			(void) snprintf(sas, 17, "%llx", di[i].SasAddress);
			topo_mod_dprintf(mod, "found mpt_sas disk (%d/%d) "
			    "with adddress %s\n", enclosure, slot, sas);
			*sas_address = topo_mod_strdup(mod, sas);
			en = ret = 0;
			break;
		}
	}

	topo_mod_free(mod, di, disz);
out:
	(void) close(fd);
	errno = en;
	return (ret);
}
Example #20
0
static int
mb_get_pri_info(topo_mod_t *mod, char **serialp, char **partp, char **csnp,
    char **psnp)
{
	char isa[MAXNAMELEN];
	md_t *mdp;
	mde_cookie_t *listp;
	uint64_t *bufp;
	ssize_t bufsize = 0;
	int  nfrus, num_nodes, i;
	char *pstr = NULL;
	char *sn, *pn, *dn, *csn, *psn;
	uint32_t type = 0;
	ldom_hdl_t *lhp;

	lhp = ldom_init(mb_topo_alloc, mb_topo_free);
	if (lhp == NULL) {
		topo_mod_dprintf(mod, "ldom_init failed\n");
		return (-1);
	}

	(void) sysinfo(SI_MACHINE, isa, MAXNAMELEN);
	if (strcmp(isa, "sun4v") != 0) {
		topo_mod_dprintf(mod, "not sun4v architecture%s\n",
		    isa);
		ldom_fini(lhp);
		return (-1);
	}

	(void) ldom_get_type(lhp, &type);
	if ((type & LDOM_TYPE_CONTROL) != 0) {
		bufsize = ldom_get_core_md(lhp, &bufp);
	} else {
		bufsize = ldom_get_local_md(lhp, &bufp);
	}
	if (bufsize < 1) {
		topo_mod_dprintf(mod, "Failed to get the pri/md (bufsize=%d)\n",
		    bufsize);
		ldom_fini(lhp);
		return (-1);
	}
	topo_mod_dprintf(mod, "pri/md bufsize=%d\n", bufsize);

	if ((mdp = md_init_intern(bufp, mb_topo_alloc, mb_topo_free)) == NULL ||
	    (num_nodes = md_node_count(mdp)) < 1) {
		topo_mod_dprintf(mod, "md_init_intern error\n");
		mb_topo_free(bufp, (size_t)bufsize);
		ldom_fini(lhp);
		return (-1);
	}
	topo_mod_dprintf(mod, "num_nodes=%d\n", num_nodes);

	if ((listp = (mde_cookie_t *)mb_topo_alloc(
	    sizeof (mde_cookie_t) * num_nodes)) == NULL) {
		topo_mod_dprintf(mod, "alloc listp error\n");
		mb_topo_free(bufp, (size_t)bufsize);
		(void) md_fini(mdp);
		ldom_fini(lhp);
		return (-1);
	}

	nfrus = md_scan_dag(mdp, MDE_INVAL_ELEM_COOKIE,
	    md_find_name(mdp, "component"),
	    md_find_name(mdp, "fwd"), listp);
	if (nfrus <= 0) {
		topo_mod_dprintf(mod, "error: nfrus=%d\n", nfrus);
		mb_topo_free(listp, sizeof (mde_cookie_t) * num_nodes);
		mb_topo_free(bufp, (size_t)bufsize);
		(void) md_fini(mdp);
		ldom_fini(lhp);
		return (-1);
	}
	topo_mod_dprintf(mod, "nfrus=%d\n", nfrus);

	sn = pn = dn = psn = csn = NULL;

	for (i = 0; i < nfrus; i++) {
		if (md_get_prop_str(mdp, listp[i], "type", &pstr) == 0) {
			/* systemboard/motherboard component */
			if (strcmp("systemboard", pstr) == 0) {
				if (md_get_prop_str(mdp, listp[i],
				    "serial_number", &sn) < 0)
					sn = NULL;
				if (md_get_prop_str(mdp, listp[i],
				    "part_number", &pn) < 0)
					pn = NULL;
				if (md_get_prop_str(mdp, listp[i],
				    "dash_number", &dn) < 0)
					dn = NULL;
			} else if (strcmp("product", pstr) == 0) {
				if (md_get_prop_str(mdp, listp[i],
				    "serial_number", &psn) < 0)
					psn = NULL;
			}
		}
		/* redefined access method for chassis serial number */
		if (md_get_prop_str(mdp, listp[i], "nac", &pstr) == 0) {
			if (strcmp("SYS", pstr) == 0) {
				if (md_get_prop_str(mdp, listp[i],
				    "serial_number", &csn) < 0)
					csn = NULL;
			}
		}
	}

	*serialp = topo_mod_strdup(mod, sn);

	i = (pn ? strlen(pn) : 0) + (dn ? strlen(dn) : 0) + 1;
	pstr = mb_topo_alloc(i);
	(void) snprintf(pstr, i, "%s%s", pn ? pn : "", dn ? dn : "");
	*partp = topo_mod_strdup(mod, pstr);
	mb_topo_free(pstr, i);

	*csnp = topo_mod_strdup(mod, csn);
	*psnp = topo_mod_strdup(mod, psn);

	mb_topo_free(listp, sizeof (mde_cookie_t) * num_nodes);
	mb_topo_free(bufp, (size_t)bufsize);
	(void) md_fini(mdp);
	ldom_fini(lhp);

	return (0);
}
Example #21
0
/*
 * Calculate the authority information for a node.  Inherit the data if
 * possible, but always create an appropriate property group.
 */
int
x86pi_set_auth(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri, tnode_t *t_parent,
    tnode_t *t_node)
{
	int 		result;
	int		err;
	int		is_chassis = 0;
	int		chassis_instance = 0;
	nvlist_t	*auth;
	char		*val = NULL;
	char		*prod = NULL;
	char		*psn = NULL;
	char		*csn = NULL;
	char		*server = NULL;
	char		*f = "x86pi_set_auth";

	if (mod == NULL || t_parent == NULL || t_node == NULL) {
		return (-1);
	}

	result = topo_pgroup_create(t_node, &auth_pgroup, &err);
	if (result != 0 && err != ETOPO_PROP_DEFD) {
		/*
		 * We failed to create the property group and it was not
		 * already defined.  Set the err code and return failure.
		 */
		(void) topo_mod_seterrno(mod, err);
		return (-1);
	}

	/* Get the authority information already available from the parent */
	auth = topo_mod_auth(mod, t_parent);

	/* Determnine if this is a chassis node and set it's instance */
	if ((strlen(hcfmri->hc_name) == strlen(CHASSIS)) &&
	    strncmp(hcfmri->hc_name, CHASSIS, strlen(CHASSIS)) == 0) {
		is_chassis = 1;
		chassis_instance = hcfmri->instance;
	}

	/*
	 * Set the authority data, inheriting it if possible, but creating it
	 * if necessary.
	 */

	/* product-id */
	result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
	    FM_FMRI_AUTH_PRODUCT, &err);
	if (result != 0 && err != ETOPO_PROP_DEFD) {
		result = nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT,
		    &prod);
		if (result != 0 || prod == NULL) {
			/*
			 * No product information in the parent node or auth
			 * list. Use the product information in the hcfrmi
			 * struct.
			 */
			prod = (char *)hcfmri->product;
			if (prod == NULL) {
				topo_mod_dprintf(mod, "%s: product name not "
				    "found for %s node\n", f, hcfmri->hc_name);
			}
		}

		/*
		 * We continue even if the product information is not available
		 * to enumerate as much as possible.
		 */
		if (prod != NULL) {
			result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY,
			    FM_FMRI_AUTH_PRODUCT, TOPO_PROP_IMMUTABLE, prod,
			    &err);
			if (result != 0) {
				/* Preserve the error and continue */
				(void) topo_mod_seterrno(mod, err);
				topo_mod_dprintf(mod, "%s: failed to set "
				    "property %s (%d) : %s\n", f,
				    FM_FMRI_AUTH_PRODUCT, err,
				    topo_strerror(err));
			}
		}
	}

	/* product-sn */
	result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
	    FM_FMRI_AUTH_PRODUCT_SN, &err);
	if (result != 0 && err != ETOPO_PROP_DEFD) {
		result = nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT_SN,
		    &psn);
		if (result != 0 || psn == NULL) {
			/*
			 * No product-sn information in the parent node or auth
			 * list.
			 */
			topo_mod_dprintf(mod, "%s: psn not found\n", f);
		} else {
			/*
			 * We continue even if the product-sn information is
			 * not available to enumerate as much as possible.
			 */
			result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY,
			    FM_FMRI_AUTH_PRODUCT_SN, TOPO_PROP_IMMUTABLE, psn,
			    &err);
			if (result != 0) {
				/* Preserve the error and continue */
				(void) topo_mod_seterrno(mod, err);
				topo_mod_dprintf(mod, "%s: failed to "
				    "set property %s (%d) : %s\n", f,
				    FM_FMRI_AUTH_PRODUCT_SN, err,
				    topo_strerror(err));
			}
		}
	}

	/* chassis-id */
	if (is_chassis == 0 || (is_chassis == 1 && chassis_instance == 0)) {
		/* either not a chassis node, or chassis #0 */
		result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
		    FM_FMRI_AUTH_CHASSIS, &err);
	} else {
		/* chassis 'n' in a >1 chassis system */
		result = err = -1;
	}
	if (result != 0 && err != ETOPO_PROP_DEFD) {
		if (is_chassis == 0) {
			result = nvlist_lookup_string(auth,
			    FM_FMRI_AUTH_CHASSIS, &csn);
			if (result != 0 || csn == NULL) {
				/*
				 * No chassis information in the parent
				 * node or auth list.
				 */
				topo_mod_dprintf(mod,
				    "%s: csn name not found\n", f);
			}
		} else {
			/*
			 * So as not to blindly set the chassis-id to
			 * chassis #0's serial number.
			 */
			csn = val = topo_mod_strdup(mod, hcfmri->serial_number);
		}

		/*
		 * We continue even if the chassis information is not available
		 * to enumerate as much as possible.
		 */
		if (csn != NULL) {
			if (is_chassis == 1)
				result = topo_prop_set_string(t_node,
				    FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS,
				    TOPO_PROP_MUTABLE, csn, &err);
			else
				result = topo_prop_set_string(t_node,
				    FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS,
				    TOPO_PROP_IMMUTABLE, csn, &err);

			if (result != 0) {
				/* Preserve the error and continue */
				(void) topo_mod_seterrno(mod, err);
				topo_mod_dprintf(mod, "%s: failed to "
				    "set property %s (%d) : %s\n", f,
				    FM_FMRI_AUTH_CHASSIS, err,
				    topo_strerror(err));
			}
		}

		if (val != NULL) {
			topo_mod_strfree(mod, val);
			val = NULL;
		}
	}

	/* server-id */
	result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
	    FM_FMRI_AUTH_SERVER, &err);
	if (result != 0 && err != ETOPO_PROP_DEFD) {
		result = nvlist_lookup_string(auth, FM_FMRI_AUTH_SERVER,
		    &server);
		if (result != 0 || server == NULL) {
			/*
			 * No server information in the parent node or auth
			 * list.  Find the server information in hostname.
			 */
			server = val = x86pi_get_serverid(mod);
			if (server == NULL) {
				topo_mod_dprintf(mod, "%s: server "
				    "name not found for %s node\n", f,
				    hcfmri->hc_name);
			}
		}

		/*
		 * We continue even if the server information is not available
		 * to enumerate as much as possible.
		 */
		if (server != NULL) {
			result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY,
			    FM_FMRI_AUTH_SERVER, TOPO_PROP_IMMUTABLE, server,
			    &err);
			if (result != 0) {
				/* Preserve the error and continue */
				(void) topo_mod_seterrno(mod, err);
				topo_mod_dprintf(mod, "%s: failed to "
				    "set property %s (%d) : %s\n", f,
				    FM_FMRI_AUTH_SERVER, err,
				    topo_strerror(err));
			}
		}

		if (val != NULL)
			topo_mod_strfree(mod, val);
	}

	nvlist_free(auth);

	return (0);
}
Example #22
0
static int
dev_di_node_add(di_node_t node, char *devid, disk_cbdata_t *cbp)
{
	topo_mod_t	*mod = cbp->dcb_mod;
	dev_di_node_t	*dnode;
	di_path_t	pnode;
	char		*path;
	int		mlen;
	char		*minorpath;
	char		*extn = ":a";
	char		*s;
	int64_t		*nblocksp;
	uint64_t	nblocks;
	int		*dblksizep;
	uint_t		dblksize;
	char		lentry[MAXPATHLEN];
	int		pathcount;
	int		*inq_dtype, itype;
	int		i;

	if (devid) {
		/*
		 * Check for list duplicate using devid search.
		 * Note if there is no devid, then we can end up with duplicates
		 * in the list, but this doesn't do any harm.
		 */
		for (dnode = topo_list_next(cbp->dcb_list);
		    dnode != NULL; dnode = topo_list_next(dnode)) {
			if (dnode->ddn_devid &&
			    devid_str_compare(dnode->ddn_devid, devid) == 0) {
				topo_mod_dprintf(mod, "dev_di_node_add: "
				    "already there %s\n", devid);
				return (0);
			}
		}
	}

	if ((dnode = topo_mod_zalloc(mod, sizeof (dev_di_node_t))) == NULL)
		return (-1);

	if (devid) {
		/* Establish the devid. */
		dnode->ddn_devid = topo_mod_strdup(mod, devid);
		if (dnode->ddn_devid == NULL)
			goto error;
	}

	/* Establish the devinfo dpath */
	if ((path = di_devfs_path(node)) == NULL) {
		(void) topo_mod_seterrno(mod, errno);
		goto error;
	}

	dnode->ddn_dpath = topo_mod_strdup(mod, path);
	di_devfs_path_free(path);
	if (dnode->ddn_dpath == NULL)
		goto error;

	/*
	 * Establish the physical ppath and target ports. If the device is
	 * non-mpxio then dpath and ppath are the same, and the target port is a
	 * property of the device node.
	 *
	 * If dpath is a client node under scsi_vhci, then iterate over all
	 * paths and get their physical paths and target port properrties.
	 * di_path_client_next_path call below will
	 * return non-NULL, and ppath is set to the physical path to the first
	 * pathinfo node.
	 *
	 * NOTE: It is possible to get a generic.vs.non-generic path
	 * for di_devfs_path.vs.di_path_devfs_path like:
	 *    xml: /pci@7b,0/pci1022,7458@11/pci1000,3060@2/sd@2,0
	 *  pnode: /pci@7b,0/pci1022,7458@11/pci1000,3060@2/disk@2,0
	 * To resolve this issue disk_declare_path() needs to use the
	 * special di_devfs_path_match() interface.
	 */
	pathcount = 0;
	pnode = NULL;
	while ((pnode = di_path_client_next_path(node, pnode)) != NULL) {
		pathcount++;
	}

	if (pathcount == 0) {
		if ((dnode->ddn_ppath =
		    topo_mod_zalloc(mod, sizeof (char *))) == NULL)
			goto error;

		dnode->ddn_ppath_count = 1;
		if ((dnode->ddn_ppath[0] = topo_mod_strdup(mod,
		    dnode->ddn_dpath)) == NULL)
			goto error;

		if ((dnode->ddn_target_port = topo_mod_zalloc(mod,
		    sizeof (char *))) == NULL)
			goto error;

		if ((dnode->ddn_attached_port = topo_mod_zalloc(mod,
		    sizeof (char *))) == NULL)
			goto error;

		if ((dnode->ddn_bridge_port = topo_mod_zalloc(mod,
		    sizeof (char *))) == NULL)
			goto error;

		/* There should be only one target port for a devinfo node. */
		if ((di_prop_lookup_strings(DDI_DEV_T_ANY, node,
		    SCSI_ADDR_PROP_TARGET_PORT, &s)) == 1) {
			if ((dnode->ddn_target_port[0] =
			    topo_mod_strdup(mod,
			    scsi_wwnstr_skip_ua_prefix(s))) ==
			    NULL)
				goto error;
		}

		if ((di_prop_lookup_strings(DDI_DEV_T_ANY, node,
		    SCSI_ADDR_PROP_ATTACHED_PORT, &s)) == 1) {
			/* There should be one attached port if any. */
			if ((dnode->ddn_attached_port[0] =
			    topo_mod_strdup(mod,
			    scsi_wwnstr_skip_ua_prefix(s))) ==
			    NULL)
				goto error;
		}

		if ((di_prop_lookup_strings(DDI_DEV_T_ANY, node,
		    SCSI_ADDR_PROP_BRIDGE_PORT, &s)) == 1) {
			/* There should be one bridge port if any. */
			if ((dnode->ddn_bridge_port[0] =
			    topo_mod_strdup(mod,
			    scsi_wwnstr_skip_ua_prefix(s))) ==
			    NULL)
				goto error;
		}

	} else {
		/* processing a scsi_vhci device. */
		if ((dnode->ddn_ppath = topo_mod_zalloc(mod,
		    pathcount * sizeof (char *))) == NULL)
			goto error;

		dnode->ddn_ppath_count = pathcount;

		if ((dnode->ddn_target_port = topo_mod_zalloc(mod,
		    pathcount * sizeof (char *))) == NULL)
			goto error;

		if ((dnode->ddn_attached_port = topo_mod_zalloc(mod,
		    pathcount * sizeof (char *))) == NULL)
			goto error;

		if ((dnode->ddn_bridge_port = topo_mod_zalloc(mod,
		    pathcount * sizeof (char *))) == NULL)
			goto error;

		pnode = NULL;
		pathcount = 0;
		while ((pnode = di_path_client_next_path(node,
		    pnode)) != NULL) {
			if ((path = di_path_devfs_path(pnode)) == NULL) {
				(void) topo_mod_seterrno(mod, errno);
				goto error;
			}

			dnode->ddn_ppath[pathcount] =
			    topo_mod_strdup(mod, path);
			di_devfs_path_free(path);
			if (dnode->ddn_ppath[pathcount] == NULL)
				goto error;

			if ((di_path_prop_lookup_strings(pnode,
			    SCSI_ADDR_PROP_TARGET_PORT, &s)) == 1) {
				if ((dnode->ddn_target_port[pathcount] =
				    topo_mod_strdup(mod,
				    scsi_wwnstr_skip_ua_prefix(s))) ==
				    NULL)
					goto error;
			}

			if ((di_path_prop_lookup_strings(pnode,
			    SCSI_ADDR_PROP_ATTACHED_PORT, &s)) == 1) {
				if ((dnode->ddn_attached_port[pathcount] =
				    topo_mod_strdup(mod,
				    scsi_wwnstr_skip_ua_prefix(s))) ==
				    NULL)
					goto error;
			}

			if ((di_path_prop_lookup_strings(pnode,
			    SCSI_ADDR_PROP_BRIDGE_PORT, &s)) == 1) {
				if ((dnode->ddn_bridge_port[pathcount] =
				    topo_mod_strdup(mod,
				    scsi_wwnstr_skip_ua_prefix(s))) ==
				    NULL)
					goto error;
			}

			pathcount++;
		}
	}

	/*
	 * Find the public /dev name for a disk by adding a minor name and using
	 * di_devlink interface for reverse translation (use devinfo path).
	 */
	if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "inquiry-device-type",
	    &inq_dtype) > 0) {
		dnode->ddn_dtype = *inq_dtype;
		itype = (*inq_dtype) & DTYPE_MASK;
		if (itype == DTYPE_DIRECT) {
			mlen = strlen(dnode->ddn_dpath) + strlen(extn) + 1;
			if ((minorpath = topo_mod_alloc(mod, mlen)) == NULL)
				goto error;
			(void) snprintf(minorpath, mlen, "%s%s",
			    dnode->ddn_dpath, extn);
			cbp->dcb_dnode = dnode;
			(void) di_devlink_walk(cbp->dcb_devhdl, "^dsk/",
			    minorpath, DI_PRIMARY_LINK, cbp,
			    disk_devlink_callback);
			topo_mod_free(mod, minorpath, mlen);
			if (dnode->ddn_lpath == NULL) {
				topo_mod_dprintf(mod, "dev_di_node_add: "
				    "failed to determine logical path");
			}
		}
	} else {
		dnode->ddn_dtype = DTYPE_UNKNOWN;
	}

	/* cache various bits of optional information about the device. */
	if (di_prop_lookup_strings(DDI_DEV_T_ANY, node,
	    INQUIRY_VENDOR_ID, &s) > 0) {
		if ((dnode->ddn_mfg = disk_trim_whitespace(mod, s)) == NULL)
			goto error;
	}
	if (di_prop_lookup_strings(DDI_DEV_T_ANY, node,
	    INQUIRY_PRODUCT_ID, &s) > 0) {
		if ((dnode->ddn_model = disk_trim_whitespace(mod, s)) == NULL)
			goto error;
	}
	if (di_prop_lookup_strings(DDI_DEV_T_ANY, node,
	    INQUIRY_REVISION_ID, &s) > 0) {
		if ((dnode->ddn_firm = disk_trim_whitespace(mod, s)) == NULL)
			goto error;
	}
	if (di_prop_lookup_strings(DDI_DEV_T_ANY, node,
	    INQUIRY_SERIAL_NO, &s) > 0) {
		if ((dnode->ddn_serial = disk_trim_whitespace(mod, s)) == NULL)
			goto error;
	}
	if (di_prop_lookup_int64(DDI_DEV_T_ANY, node,
	    "device-nblocks", &nblocksp) > 0) {
		nblocks = (uint64_t)*nblocksp;
		/*
		 * To save kernel memory, the driver may not define
		 * "device-dblksize" when its value is default DEV_BSIZE.
		 */
		if (di_prop_lookup_ints(DDI_DEV_T_ANY, node,
		    "device-dblksize", &dblksizep) > 0)
			dblksize = (uint_t)*dblksizep;
		else
			dblksize = DEV_BSIZE;		/* default value */
		(void) snprintf(lentry, sizeof (lentry),
		    "%" PRIu64, nblocks * dblksize);
		if ((dnode->ddn_cap = topo_mod_strdup(mod, lentry)) == NULL)
			goto error;
	}

	topo_mod_dprintf(mod, "dev_di_node_add: "
	    "adding %s\n", devid ? dnode->ddn_devid : "NULL devid");
	topo_mod_dprintf(mod, "                  "
	    "       %s\n", dnode->ddn_dpath);
	for (i = 0; i < dnode->ddn_ppath_count; i++) {
		topo_mod_dprintf(mod, "                  "
		    "       %s\n", dnode->ddn_ppath[i]);
	}
	topo_list_append(cbp->dcb_list, dnode);
	return (0);

error:
	dev_di_node_free(mod, dnode);
	return (-1);
}
Example #23
0
static int
xaui_get_pri_label(topo_mod_t *mod, topo_instance_t n, void *priv,
    char **labelp)
{
	ldom_hdl_t *hdlp;
	uint32_t type = 0;
	ssize_t bufsize = 0;
	uint64_t *bufp;
	md_t *mdp;
	int num_nodes, ncomp;
	mde_cookie_t *listp;
	char *pstr = NULL;
	int i;
	char *path;

	/* Get device path minus the device names */
	path = xaui_get_path(mod, priv, n);
	if (path == NULL) {
		topo_mod_dprintf(mod, "can't get path\n");
		return (-1);
	}

	hdlp = ldom_init(xaui_topo_alloc, xaui_topo_free);
	if (hdlp == NULL) {
		topo_mod_dprintf(mod, "ldom_init failed\n");
		return (-1);
	}

	(void) ldom_get_type(hdlp, &type);
	if ((type & LDOM_TYPE_CONTROL) != 0) {
		bufsize = ldom_get_core_md(hdlp, &bufp);
	} else {
		bufsize = ldom_get_local_md(hdlp, &bufp);
	}
	if (bufsize < 1) {
		topo_mod_dprintf(mod, "failed to get pri/md (%d)\n", bufsize);
		ldom_fini(hdlp);
		return (-1);
	}

	if ((mdp = md_init_intern(bufp, xaui_topo_alloc, xaui_topo_free)) ==
	    NULL || (num_nodes = md_node_count(mdp)) < 1) {
		topo_mod_dprintf(mod, "md_init_intern failed\n");
		xaui_topo_free(bufp, (size_t)bufsize);
		ldom_fini(hdlp);
		return (-1);
	}

	if ((listp = (mde_cookie_t *)xaui_topo_alloc(
	    sizeof (mde_cookie_t) * num_nodes)) == NULL) {
		topo_mod_dprintf(mod, "can't alloc listp\n");
		xaui_topo_free(bufp, (size_t)bufsize);
		(void) md_fini(mdp);
		ldom_fini(hdlp);
		return (-1);
	}

	ncomp = md_scan_dag(mdp, MDE_INVAL_ELEM_COOKIE,
	    md_find_name(mdp, "component"),
	    md_find_name(mdp, "fwd"), listp);
	if (ncomp <= 0) {
		topo_mod_dprintf(mod, "no component nodes found\n");
		xaui_topo_free(listp, sizeof (mde_cookie_t) * num_nodes);
		xaui_topo_free(bufp, (size_t)bufsize);
		(void) md_fini(mdp);
		ldom_fini(hdlp);
		return (-1);
	}
	topo_mod_dprintf(mod, "number of comps (%d)\n", ncomp);

	for (i = 0; i < ncomp; i++) {
		/*
		 * Look for type == "io", topo-hc-name == "xaui";
		 * match "path" md property.
		 */
		if ((md_get_prop_str(mdp, listp[i], "type", &pstr) == 0) &&
		    (pstr != NULL) &&
		    (strncmp(pstr, "io", strlen(pstr)) == 0) &&
		    (md_get_prop_str(mdp, listp[i], "topo-hc-name", &pstr)
		    == 0) && (pstr != NULL) &&
		    (strncmp(pstr, "xaui", strlen(pstr)) == 0) &&
		    (md_get_prop_str(mdp, listp[i], "path", &pstr) == 0) &&
		    (pstr != NULL)) {
			/* check node path */
			if (strncmp(pstr, path, sizeof (path)) == 0) {
				/* this is the node, grab the label */
				if (md_get_prop_str(mdp, listp[i], "nac",
				    &pstr) == 0) {
					*labelp = topo_mod_strdup(mod, pstr);
					/* need to free this later */
					freeprilabel = 1;
					break;
				}
			}
		}
	}

	xaui_topo_free(listp, sizeof (mde_cookie_t) * num_nodes);
	xaui_topo_free(bufp, (size_t)bufsize);
	(void) md_fini(mdp);
	ldom_fini(hdlp);

	if (path != NULL) {
		xaui_topo_free(path, strlen(path) + 1);
	}
	return (0);
}