Example #1
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 #2
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 #3
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 #4
0
tf_idata_t *
tf_idata_new(topo_mod_t *mp, topo_instance_t i, tnode_t *tn)
{
	tf_idata_t *r;

	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "new idata %d\n", i);
	if ((r = topo_mod_zalloc(mp, sizeof (tf_idata_t))) == NULL)
		return (NULL);
	r->ti_tn = tn;
	r->ti_i = i;
	return (r);
}
Example #5
0
tf_pad_t *
tf_pad_new(topo_mod_t *mp, int pcnt, int dcnt)
{
	tf_pad_t *r;

	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "new pad p=%d, d=%d\n",
	    pcnt, dcnt);
	if ((r = topo_mod_zalloc(mp, sizeof (tf_pad_t))) == NULL)
		return (NULL);
	r->tpad_pgcnt = pcnt;
	r->tpad_dcnt = dcnt;
	return (r);
}
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
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 #8
0
tnode_t *
topo_node_bind(topo_mod_t *mod, tnode_t *pnode, const char *name,
    topo_instance_t inst, nvlist_t *fmri, void *priv)
{
	int h, err;
	tnode_t *node;
	topo_nodehash_t *nhp;

	topo_node_lock(pnode);
	for (nhp = topo_list_next(&pnode->tn_children); nhp != NULL;
	    nhp = topo_list_next(nhp)) {
		if (strcmp(nhp->th_name, name) == 0) {

			if (inst > nhp->th_range.tr_max ||
			    inst < nhp->th_range.tr_min)
				return (node_bind_seterror(mod, pnode, NULL,
				    ETOPO_NODE_INVAL));

			h = topo_node_hash(nhp, inst);
			if (nhp->th_nodearr[h] != NULL)
				return (node_bind_seterror(mod, pnode, NULL,
				    ETOPO_NODE_BOUND));
			else
				break;

		}
	}

	if (nhp == NULL)
		return (node_bind_seterror(mod, pnode, NULL, ETOPO_NODE_NOENT));

	if ((node = topo_mod_zalloc(mod, sizeof (tnode_t))) == NULL)
		return (node_bind_seterror(mod, pnode, NULL, ETOPO_NOMEM));

	(void) pthread_mutex_init(&node->tn_lock, NULL);

	node->tn_enum = mod;
	node->tn_hdl = mod->tm_hdl;
	node->tn_parent = pnode;
	node->tn_name = nhp->th_name;
	node->tn_instance = inst;
	node->tn_phash = nhp;
	node->tn_refs = 0;

	/* Ref count module that bound this node */
	topo_mod_hold(mod);

	if (fmri == NULL)
		return (node_bind_seterror(mod, pnode, node, ETOPO_NODE_INVAL));

	if (topo_pgroup_create(node, TOPO_PGROUP_PROTOCOL,
	    TOPO_STABILITY_PRIVATE, &err) < 0)
		return (node_bind_seterror(mod, pnode, node, err));

	if (topo_prop_set_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_RESOURCE,
	    TOPO_PROP_SET_ONCE, fmri, &err) < 0)
		return (node_bind_seterror(mod, pnode, node, err));

	topo_dprintf(TOPO_DBG_MOD, "node bound %s=%d\n", node->tn_name,
	    node->tn_instance);

	node->tn_state |= TOPO_NODE_BOUND;
	node->tn_priv = priv;

	topo_node_hold(node);
	nhp->th_nodearr[h] = node;
	++pnode->tn_refs;
	topo_node_unlock(pnode);

	if (topo_pgroup_create(node, TOPO_PGROUP_SYSTEM,
	    TOPO_STABILITY_PRIVATE, &err) == 0) {
		(void) topo_prop_inherit(node, TOPO_PGROUP_SYSTEM,
		    TOPO_PROP_PLATFORM, &err);
		(void) topo_prop_inherit(node, TOPO_PGROUP_SYSTEM,
		    TOPO_PROP_ISA, &err);
		(void) topo_prop_inherit(node, TOPO_PGROUP_SYSTEM,
		    TOPO_PROP_MACHINE, &err);
	}

	return (node);
}
Example #9
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 #10
0
static int
cpu_n1_mdesc_init(topo_mod_t *mod, md_t *mdp, md_info_t *chip)
{
	mde_cookie_t *listp;
	md_cpumap_t *mcmp;
	int i, num_nodes, idx;
	uint64_t x;

	num_nodes = md_node_count(mdp);
	listp = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * num_nodes);

	chip->ncpus = md_scan_dag(mdp,
	    MDE_INVAL_ELEM_COOKIE,
	    md_find_name(mdp, "cpu"),
	    md_find_name(mdp, "fwd"),
	    listp);
	topo_mod_dprintf(mod, "Found %d cpus\n", chip->ncpus);

	chip->cpus = topo_mod_zalloc(mod, chip->ncpus * sizeof (md_cpumap_t));
	chip->nprocs = chip->ncpus;
	chip->procs = topo_mod_zalloc(mod, chip->nprocs * sizeof (md_proc_t));

	for (idx = 0, mcmp = chip->cpus; idx < chip->ncpus; idx++, mcmp++) {

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

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

		mcmp->cpumap_serialno = 0;
		mcmp->cpumap_chipidx = -1;
		if (md_get_prop_val(mdp, listp[idx], MD_STR_CPU_SERIAL,
		    &mcmp->cpumap_serialno) < 0) {
			continue;
		}
		if (mcmp->cpumap_serialno == 0) {
			continue;
		}

		/*
		 * This PRI/MD has no indentity info. of the FRU and no
		 * physical proc id.
		 * Find if there is already an existing processor entry
		 * Assign procid based on the order found during reading
		 */
		for (i = 0; i < chip->nprocs &&
		    chip->procs[i].serialno != 0; i++) {
			if (mcmp->cpumap_serialno == chip->procs[i].serialno) {
				break;
			}
		}
		if (i < chip->nprocs) {
			mcmp->cpumap_chipidx = i;
			if (chip->procs[i].serialno == 0) {
				chip->procs[i].id = i;
				chip->procs[i].serialno = mcmp->cpumap_serialno;
				topo_mod_dprintf(mod,
				    "chip[%d] serial is %llx\n",
				    i, chip->procs[i].serialno);
			}
		}

	}

	topo_mod_free(mod, listp, sizeof (mde_cookie_t) * num_nodes);

	return (0);
}
Example #11
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 #12
0
/*
 * This routined is called once for each mde node of type 'components'.  It
 * initiates enumeration of the graph starting with with this node.
 */
static int
pi_enum_components(pi_enum_t *pip, tnode_t *t_parent, const char *hc_name,
    mde_cookie_t mde_node, mde_str_cookie_t component_cookie,
    mde_str_cookie_t arc_cookie)
{
	int		result;

	int		num_arcs;
	mde_cookie_t	*arcp;
	size_t		arcsize;
	int		arcidx;

	topo_mod_t	*mod = pip->mod;
	md_t		*mdp = pip->mdp;

	if (t_parent == NULL) {
		topo_mod_dprintf(mod,
		    "walker failed to create node range with a NULL parent\n");
		(void) topo_mod_seterrno(mod, EMOD_METHOD_INVAL);
		return (-1);
	}

	/* Determine how many children the given node has */
	num_arcs = md_get_prop_arcs(mdp, mde_node, MD_STR_FWD, NULL, 0);
	if (num_arcs == 0) {
		/*
		 * This components node has no children and is not a topo
		 * node itself, so set partial enumeration and return.
		 */
		(void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM);
		return (0);
	}
	topo_mod_dprintf(mod, "node_0x%llx has %d children\n",
	    (uint64_t)mde_node, num_arcs);

	/* Get the indexes for all the child nodes and put them in an array */
	arcsize = sizeof (mde_cookie_t) * num_arcs;
	arcp = topo_mod_zalloc(mod, arcsize);
	if (arcp == NULL) {
		topo_mod_dprintf(mod, "out of memory\n");
		(void) topo_mod_seterrno(mod, EMOD_NOMEM);
		return (-1);
	}
	num_arcs = md_get_prop_arcs(mdp, mde_node, MD_STR_FWD, arcp,
	    arcsize);

	result = 0;
	for (arcidx = 0; arcidx < num_arcs; arcidx++) {
		/*
		 * Initiate walking the PRI graph starting with the current
		 * child of the components node.
		 */
		result = pi_walker(pip, t_parent, hc_name,
		    arcp[arcidx], component_cookie, arc_cookie);
		if (result != 0) {
			(void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM);
		}
	}
	topo_mod_free(mod, arcp, arcsize);

	/*
	 * We have now walked the entire PRI graph.  Execute any deferred
	 * enumeration routines that need all the nodes to be available.
	 */
	result = pi_defer_exec(mod, mdp);

	return (result);
}