Пример #1
0
static int
vnex_attach(device_t dev)
{
    struct vnex_devinfo  *vndi;
    struct vnex_softc    *sc;
    device_t              cdev;
    phandle_t             node;
    mde_cookie_t          rootnode, *listp = NULL;
    int                   i, listsz, num_nodes, num_devices;
    md_t                 *mdp;


    node = ofw_bus_get_node(dev);
    if (node == -1)
        panic("%s: ofw_bus_get_node failed.", __func__);

    sc = device_get_softc(dev);
    sc->sc_intr_rman.rm_type = RMAN_ARRAY;
    sc->sc_intr_rman.rm_descr = "Interrupts";
    sc->sc_mem_rman.rm_type = RMAN_ARRAY;
    sc->sc_mem_rman.rm_descr = "Device Memory";
    if (rman_init(&sc->sc_intr_rman) != 0 ||
            rman_init(&sc->sc_mem_rman) != 0 ||
            rman_manage_region(&sc->sc_intr_rman, 0, IV_MAX - 1) != 0 ||
            rman_manage_region(&sc->sc_mem_rman, 0ULL, ~0ULL) != 0)
        panic("%s: failed to set up rmans.", __func__);

    if ((mdp = md_get()) == NULL)
        return (ENXIO);

    num_nodes = md_node_count(mdp);
    listsz = num_nodes * sizeof(mde_cookie_t);
    listp = (mde_cookie_t *)malloc(listsz, M_DEVBUF, M_WAITOK);
    rootnode = md_root_node(mdp);

    /*
     * scan the machine description for virtual devices
     */
    num_devices = md_scan_dag(mdp, rootnode,
                              md_find_name(mdp, "virtual-device"),
                              md_find_name(mdp, "fwd"), listp);

    for (i = 0; i < num_devices; i++) {
        if ((vndi = vnex_setup_dinfo(dev, listp[i])) == NULL)
            continue;

        cdev = device_add_child(dev, NULL, -1);
        if (cdev == NULL) {
            device_printf(dev, "<%s>: device_add_child failed\n",
                          vndi->vndi_mbdinfo.mbd_name);
            vnex_destroy_dinfo(vndi);
            continue;
        }
        device_set_ivars(cdev, vndi);
    }
    bus_generic_attach(dev);
    free(listp, M_DEVBUF);

    return (0);
}
Пример #2
0
/*
 * Failed to allocate the list : Return value -1
 * md_scan_dag API failed      : Return the result from md_scan_dag API
 */
int
md_alloc_scan_dag(md_t *ptr,
	mde_cookie_t startnode,
	char *node_name,
	char *dag,
	mde_cookie_t **list)
{
	int res;
	md_impl_t *mdp = (md_impl_t *)ptr;

	*list = (mde_cookie_t *)mdp->allocp(sizeof (mde_cookie_t) *
	    mdp->node_count);
	if (*list == NULL)
		return (-1);

	res = md_scan_dag(ptr, startnode,
	    md_find_name(ptr, node_name),
	    md_find_name(ptr, dag), *list);

	/*
	 * If md_scan_dag API returned 0 or -1 then free the buffer
	 * and return -1 to indicate the error from this API.
	 */
	if (res < 1) {
		md_free_scan_dag(ptr, list);
		*list = NULL;
	}

	return (res);
}
Пример #3
0
/*
 * Extract from the PRI the processor, strand and their fru identity
 */
int
cpu_mdesc_init(topo_mod_t *mod, md_info_t *chip)
{
	int rc = -1;
	md_t *mdp;
	ssize_t bufsiz = 0;
	uint64_t *bufp;
	ldom_hdl_t *lhp;
	uint32_t type = 0;

	/* get the PRI/MD */
	if ((lhp = ldom_init(cpu_alloc, cpu_free)) == NULL) {
		topo_mod_dprintf(mod, "ldom_init() failed\n");
		return (topo_mod_seterrno(mod, EMOD_NOMEM));
	}

	(void) ldom_get_type(lhp, &type);
	if ((type & LDOM_TYPE_CONTROL) != 0) {
		bufsiz = ldom_get_core_md(lhp, &bufp);
	} else {
		bufsiz = ldom_get_local_md(lhp, &bufp);
	}
	if (bufsiz <= 0) {
		topo_mod_dprintf(mod, "failed to get the PRI/MD\n");
		ldom_fini(lhp);
		return (-1);
	}

	if ((mdp = md_init_intern(bufp, cpu_alloc, cpu_free)) == NULL ||
	    md_node_count(mdp) <= 0) {
		cpu_free(bufp, (size_t)bufsiz);
		ldom_fini(lhp);
		return (-1);
	}

	/*
	 * N1 MD contains cpu nodes while N2 MD contains component nodes.
	 */
	if (md_find_name(mdp, MD_STR_COMPONENT) != MDE_INVAL_STR_COOKIE) {
		rc = cpu_n2_mdesc_init(mod, mdp, chip);
	} else if (md_find_name(mdp, MD_STR_CPU) != MDE_INVAL_STR_COOKIE) {
		rc =  cpu_n1_mdesc_init(mod, mdp, chip);
	} else {
		topo_mod_dprintf(mod, "Unsupported PRI/MD\n");
		rc = -1;
	}

	cpu_free(bufp, (size_t)bufsiz);
	(void) md_fini(mdp);
	ldom_fini(lhp);

	return (rc);
}
Пример #4
0
int
md_get_prop_str(md_t *ptr, mde_cookie_t node, char *namep, char **strp)
{
	mde_str_cookie_t prop_name;
	md_impl_t	*mdp;
	mde_cookie_t	elem;

	mdp = (md_impl_t *)ptr;

	if (node == MDE_INVAL_ELEM_COOKIE) {
		return (-1);
	}

	prop_name = md_find_name(ptr, namep);
	if (prop_name == MDE_INVAL_STR_COOKIE) {
		return (-1);
	}

	elem = md_find_node_prop(mdp, node, prop_name, MDET_PROP_STR);

	if (elem != MDE_INVAL_ELEM_COOKIE) {
		md_element_t *mdep;
		mdep = &(mdp->mdep[(int)elem]);

		*strp = (char *)(mdp->datap+
			MDE_PROP_DATA_OFFSET(mdep));
		return (0);
	}

	return (-1);	/* no such property name */
}
Пример #5
0
int
md_get_prop_val(md_t *ptr, mde_cookie_t node, char *namep, uint64_t *valp)
{
	mde_str_cookie_t prop_name;
	md_impl_t	*mdp;
	mde_cookie_t	elem;

	mdp = (md_impl_t *)ptr;

	if (node == MDE_INVAL_ELEM_COOKIE) {
		return (-1);
	}

	prop_name = md_find_name(ptr, namep);
	if (prop_name == MDE_INVAL_STR_COOKIE) {
		return (-1);
	}

	elem = md_find_node_prop(mdp, node, prop_name, MDET_PROP_VAL);

	if (elem != MDE_INVAL_ELEM_COOKIE) {
		md_element_t *mdep;
		mdep = &(mdp->mdep[(int)elem]);

		*valp = MDE_PROP_VALUE(mdep);
		return (0);
	}

	return (-1);	/* no such property name */
}
int
md_vdev_find_node(device_t dev, mde_cookie_t *valp)
{
	uint64_t              cfg_handle;
	mde_cookie_t          rootnode, node, *listp = NULL;
	int                   i, listsz, num_nodes, num_devices, error;
	md_t                 *mdp;

	cfg_handle = mdesc_bus_get_handle(dev);

	error = EINVAL;

	if ((mdp = md_get()) == NULL) 
		return (ENXIO);

	num_nodes = md_node_count(mdp);
	listsz = num_nodes * sizeof(mde_cookie_t);
	listp = (mde_cookie_t *)malloc(listsz, M_DEVBUF, M_WAITOK);
	rootnode = md_root_node(mdp);
	node = error = 0;

	num_devices = md_scan_dag(mdp, rootnode, 
				  md_find_name(mdp, "virtual-device"),
				  md_find_name(mdp, "fwd"), listp);
	
	if (num_devices == 0) {
		error = ENOENT;
		goto done;
	}
		
	for (i = 0; i < num_devices; i++) {
		uint64_t thandle;

		node = listp[i];
		md_get_prop_val(mdp, node, "cfg-handle", &thandle);
		if (thandle == cfg_handle) {
			*valp = node;
			break;
		}
	}

done:
	md_put(mdp);

	return (error);
}
Пример #7
0
static int
i_vldc_get_port_channel(md_t *mdp, mde_cookie_t node, uint64_t *ldc_id)
{
	int num_nodes, nchan;
	size_t listsz;
	mde_cookie_t *listp;

	/*
	 * Find the channel-endpoint node(s) (which should be under this
	 * port node) which contain the channel id(s).
	 */
	if ((num_nodes = md_node_count(mdp)) <= 0) {
		cmn_err(CE_NOTE, "?i_vldc_get_port_channel: invalid number of "
		    "channel-endpoint nodes found (%d)", num_nodes);
		return (-1);
	}

	/* allocate space for node list */
	listsz = num_nodes * sizeof (mde_cookie_t);
	listp = kmem_alloc(listsz, KM_SLEEP);

	nchan = md_scan_dag(mdp, node, md_find_name(mdp, "channel-endpoint"),
	    md_find_name(mdp, "fwd"), listp);

	if (nchan <= 0) {
		cmn_err(CE_NOTE, "?i_vldc_get_port_channel: no channel-endpoint"
		    " nodes found");
		kmem_free(listp, listsz);
		return (-1);
	}

	D2("i_vldc_get_port_channel: %d channel-endpoint nodes found", nchan);

	/* use property from first node found */
	if (md_get_prop_val(mdp, listp[0], "id", ldc_id)) {
		cmn_err(CE_NOTE, "?i_vldc_get_port_channel: channel-endpoint "
		    "has no 'id' property");
		kmem_free(listp, listsz);
		return (-1);
	}

	kmem_free(listp, listsz);

	return (0);
}
Пример #8
0
static void
init_domaining_capabilities(md_t *mdp, mde_cookie_t *listp)
{
	mde_cookie_t	rootnode;
	int		num_nodes;
	uint64_t	val = 0;

	rootnode = md_root_node(mdp);
	ASSERT(rootnode != MDE_INVAL_ELEM_COOKIE);

	num_nodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "platform"),
	    md_find_name(mdp, "fwd"), listp);

	/* should only be one platform node */
	ASSERT(num_nodes == 1);

	if (md_get_prop_val(mdp, *listp, "domaining-enabled", &val) != 0) {
		/*
		 * The property is not present. This implies
		 * that the firmware does not support domaining
		 * features.
		 */
		MDP(("'domaining-enabled' property not present\n"));

		domaining_capabilities = 0;
		return;
	}

	domaining_capabilities = DOMAINING_SUPPORTED;

	if (val == 1) {
		if (force_domaining_disabled) {
			MDP(("domaining manually disabled\n"));
		} else {
			domaining_capabilities |= DOMAINING_ENABLED;
		}
	}

	MDP(("domaining_capabilities= 0x%x\n", domaining_capabilities));
}
Пример #9
0
static mde_cookie_t
mdeg_find_start_node(md_t *md, mdeg_node_spec_t *nspec)
{
	mde_cookie_t		*nodesp;
	mde_str_cookie_t	nname;
	mde_str_cookie_t	aname;
	int			nnodes;
	int			idx;

	if ((md == NULL) || (nspec == NULL))
		return (MDE_INVAL_ELEM_COOKIE);

	nname = md_find_name(md, nspec->namep);
	aname = md_find_name(md, "fwd");

	nnodes = md_scan_dag(md, NULL, nname, aname, NULL);
	if (nnodes == 0)
		return (MDE_INVAL_ELEM_COOKIE);

	nodesp = kmem_alloc(sizeof (mde_cookie_t) * nnodes, KM_SLEEP);

	(void) md_scan_dag(md, NULL, nname, aname, nodesp);

	for (idx = 0; idx < nnodes; idx++) {

		if (mdeg_node_spec_match(md, nodesp[idx], nspec)) {
			mde_cookie_t res = nodesp[idx];

			kmem_free(nodesp, sizeof (mde_cookie_t) * nnodes);
			return (res);
		}
	}

	kmem_free(nodesp, sizeof (mde_cookie_t) * nnodes);
	return (MDE_INVAL_ELEM_COOKIE);
}
Пример #10
0
/* ARGSUSED */
static int
pi_enum(topo_mod_t *mod, tnode_t *t_parent, const char *name,
    topo_instance_t min, topo_instance_t max, void *pi_private, void *data)
{
	int		result;
	int		idx;
	int		num_components;
	size_t		csize;
	hrtime_t	starttime;

	pi_enum_t	pi;

	mde_cookie_t	*components;
	mde_str_cookie_t arc_cookie;
	mde_str_cookie_t component_cookie;

	/* Begin enumeration */
	starttime = gethrtime();
	topo_mod_dprintf(mod, "enumeration starting.\n");

	/* Initialize the walker */
	result = pi_walker_init(mod);
	if (result != 0) {
		(void) topo_mod_seterrno(mod, EMOD_UKNOWN_ENUM);
		return (-1);
	}

	/* Open a connection to the LDOM PRI */
	bzero(&pi, sizeof (pi_enum_t));
	result = pi_ldompri_open(mod, &pi);
	if (result != 0) {
		pi_walker_fini(mod);
		topo_mod_dprintf(mod, "could not open LDOM PRI\n");
		(void) topo_mod_seterrno(mod, EMOD_UKNOWN_ENUM);
		return (-1);
	}
	pi.mod = mod;

	/*
	 * Find the top of the components graph in the PRI using the machine
	 * description library.
	 */
	num_components = pi_find_mdenodes(mod, pi.mdp, MDE_INVAL_ELEM_COOKIE,
	    MD_STR_COMPONENTS, MD_STR_FWD, &components, &csize);
	if (num_components < 0 || components == NULL) {
		/* No nodes were found */
		pi_walker_fini(mod);
		topo_mod_dprintf(mod, "could not find components in PRI\n");
		(void) topo_mod_seterrno(mod, EMOD_UKNOWN_ENUM);
		return (-1);
	}

	/*
	 * There should be a single components node.  But scan all of the
	 * results just in case a future machine has multiple hierarchies
	 * for some unknown reason.
	 *
	 * We continue to walk components nodes until they are all exhausted
	 * and do not stop if a node cannot be enumerated.  Instead, we
	 * enumerate what we can and return a partial-enumeration error if
	 * there is a problem.
	 */
	topo_mod_dprintf(mod, "enumerating %d components hierarchies\n",
	    num_components);

	component_cookie = md_find_name(pi.mdp, MD_STR_COMPONENT);
	arc_cookie	 = md_find_name(pi.mdp, MD_STR_FWD);
	result = 0;
	for (idx = 0; idx < num_components; idx++) {
		int	skip;

		/*
		 * We have found a component hierarchy to process.  First,
		 * make sure we are not supposed to skip the graph.
		 */
		skip = pi_skip_node(mod, pi.mdp, components[idx]);
		if (skip == 0) {
			/*
			 * We have found a components node.  Find the top-
			 * level nodes and create a topology tree from them.
			 */
			result = pi_enum_components(&pi, t_parent, name,
			    components[idx], component_cookie, arc_cookie);
		}
	}
	topo_mod_free(mod, components, csize);

	/* Close our connection to the PRI */
	pi_ldompri_close(mod, &pi);

	/* Clean up after the walker */
	pi_walker_fini(mod);

	/* Complete enumeration */
	topo_mod_dprintf(mod, "enumeration complete in %lld ms.\n",
	    ((gethrtime() - starttime)/MICROSEC));

	/* All done */
	return (result);
}
Пример #11
0
/*
 * Routine used to setup a newly inserted CPU in preparation for starting
 * it running code.
 */
int
mp_cpu_configure(int cpuid)
{
	md_t		*mdp;
	mde_cookie_t	rootnode, cpunode = MDE_INVAL_ELEM_COOKIE;
	int		listsz, i;
	mde_cookie_t	*listp = NULL;
	int		num_nodes;
	uint64_t	cpuid_prop;
	cpu_t		*cpu;
	processorid_t	id;

	ASSERT(MUTEX_HELD(&cpu_lock));

	if ((mdp = md_get_handle()) == NULL)
		return (ENODEV);

	rootnode = md_root_node(mdp);

	ASSERT(rootnode != MDE_INVAL_ELEM_COOKIE);

	num_nodes = md_node_count(mdp);

	ASSERT(num_nodes > 0);

	listsz = num_nodes * sizeof (mde_cookie_t);
	listp = kmem_zalloc(listsz, KM_SLEEP);

	num_nodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "cpu"),
	    md_find_name(mdp, "fwd"), listp);

	if (num_nodes < 0)
		return (ENODEV);

	for (i = 0; i < num_nodes; i++) {
		if (md_get_prop_val(mdp, listp[i], "id", &cpuid_prop))
			break;
		if (cpuid_prop == (uint64_t)cpuid) {
			cpunode = listp[i];
			break;
		}
	}

	if (cpunode == MDE_INVAL_ELEM_COOKIE)
		return (ENODEV);

	kmem_free(listp, listsz);

	mpo_cpu_add(mdp, cpuid);

	/*
	 * Note: uses cpu_lock to protect cpunodes
	 * which will be modified inside of fill_cpu and
	 * setup_exec_unit_mappings.
	 */
	fill_cpu(mdp, cpunode);

	/*
	 * Adding a CPU may cause the execution unit sharing
	 * relationships to change. Update the mappings in
	 * the cpunode structures.
	 */
	setup_chip_mappings(mdp);
	setup_exec_unit_mappings(mdp);

	/* propagate the updated mappings to the CPU structures */
	for (id = 0; id < NCPU; id++) {
		if ((cpu = cpu_get(id)) == NULL)
			continue;

		cpu_map_exec_units(cpu);
	}

	(void) md_fini_handle(mdp);

	if ((i = setup_cpu_common(cpuid)) != 0) {
		(void) cleanup_cpu_common(cpuid);
		return (i);
	}

	return (0);
}
Пример #12
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);
}
Пример #13
0
/*
 * Exported interface to register a LDC endpoint with
 * the channel nexus
 */
static int
cnex_reg_chan(dev_info_t *dip, uint64_t id, ldc_dev_t devclass)
{
	int		idx;
	cnex_ldc_t	*cldcp;
	cnex_ldc_t	*new_cldcp;
	int		listsz, num_nodes, num_channels;
	md_t		*mdp = NULL;
	mde_cookie_t	rootnode, *listp = NULL;
	uint64_t	tmp_id;
	uint64_t	rxino = (uint64_t)-1;
	uint64_t	txino = (uint64_t)-1;
	cnex_soft_state_t *cnex_ssp;
	int		status, instance;
	dev_info_t	*chan_dip = NULL;

	/* Get device instance and structure */
	instance = ddi_get_instance(dip);
	cnex_ssp = ddi_get_soft_state(cnex_state, instance);

	/* Check to see if channel is already registered */
	mutex_enter(&cnex_ssp->clist_lock);
	cldcp = cnex_ssp->clist;
	while (cldcp) {
		if (cldcp->id == id) {
			DWARN("cnex_reg_chan: channel 0x%llx exists\n", id);
			mutex_exit(&cnex_ssp->clist_lock);
			return (EINVAL);
		}
		cldcp = cldcp->next;
	}
	mutex_exit(&cnex_ssp->clist_lock);

	/* Get the Tx/Rx inos from the MD */
	if ((mdp = md_get_handle()) == NULL) {
		DWARN("cnex_reg_chan: cannot init MD\n");
		return (ENXIO);
	}
	num_nodes = md_node_count(mdp);
	ASSERT(num_nodes > 0);

	listsz = num_nodes * sizeof (mde_cookie_t);
	listp = (mde_cookie_t *)kmem_zalloc(listsz, KM_SLEEP);

	rootnode = md_root_node(mdp);

	/* search for all channel_endpoint nodes */
	num_channels = md_scan_dag(mdp, rootnode,
	    md_find_name(mdp, "channel-endpoint"),
	    md_find_name(mdp, "fwd"), listp);
	if (num_channels <= 0) {
		DWARN("cnex_reg_chan: invalid channel id\n");
		kmem_free(listp, listsz);
		(void) md_fini_handle(mdp);
		return (EINVAL);
	}

	for (idx = 0; idx < num_channels; idx++) {

		/* Get the channel ID */
		status = md_get_prop_val(mdp, listp[idx], "id", &tmp_id);
		if (status) {
			DWARN("cnex_reg_chan: cannot read LDC ID\n");
			kmem_free(listp, listsz);
			(void) md_fini_handle(mdp);
			return (ENXIO);
		}
		if (tmp_id != id)
			continue;

		/* Get the Tx and Rx ino */
		status = md_get_prop_val(mdp, listp[idx], "tx-ino", &txino);
		if (status) {
			DWARN("cnex_reg_chan: cannot read Tx ino\n");
			kmem_free(listp, listsz);
			(void) md_fini_handle(mdp);
			return (ENXIO);
		}
		status = md_get_prop_val(mdp, listp[idx], "rx-ino", &rxino);
		if (status) {
			DWARN("cnex_reg_chan: cannot read Rx ino\n");
			kmem_free(listp, listsz);
			(void) md_fini_handle(mdp);
			return (ENXIO);
		}
		chan_dip = cnex_find_chan_dip(dip, id, mdp, listp[idx]);
		ASSERT(chan_dip != NULL);
	}
	kmem_free(listp, listsz);
	(void) md_fini_handle(mdp);

	/*
	 * check to see if we looped through the list of channel IDs without
	 * matching one (i.e. an 'ino' has not been initialised).
	 */
	if ((rxino == -1) || (txino == -1)) {
		DERR("cnex_reg_chan: no ID matching '%llx' in MD\n", id);
		return (ENOENT);
	}

	/* Allocate a new channel structure */
	new_cldcp = kmem_zalloc(sizeof (*new_cldcp), KM_SLEEP);

	/* Initialize the channel */
	mutex_init(&new_cldcp->lock, NULL, MUTEX_DRIVER, NULL);

	new_cldcp->id = id;
	new_cldcp->tx.ino = txino;
	new_cldcp->rx.ino = rxino;
	new_cldcp->devclass = devclass;
	new_cldcp->tx.weight = CNEX_TX_INTR_WEIGHT;
	new_cldcp->rx.weight = cnex_class_weight(devclass);
	new_cldcp->dip = chan_dip;

	/*
	 * Add channel to nexus channel list.
	 * Check again to see if channel is already registered since
	 * clist_lock was dropped above.
	 */
	mutex_enter(&cnex_ssp->clist_lock);
	cldcp = cnex_ssp->clist;
	while (cldcp) {
		if (cldcp->id == id) {
			DWARN("cnex_reg_chan: channel 0x%llx exists\n", id);
			mutex_exit(&cnex_ssp->clist_lock);
			mutex_destroy(&new_cldcp->lock);
			kmem_free(new_cldcp, sizeof (*new_cldcp));
			return (EINVAL);
		}
		cldcp = cldcp->next;
	}
	new_cldcp->next = cnex_ssp->clist;
	cnex_ssp->clist = new_cldcp;
	mutex_exit(&cnex_ssp->clist_lock);

	return (0);
}
Пример #14
0
/*
 * cnex_find_chan_dip -- Find the dip of a device that is corresponding
 * 	to the specific channel. Below are the details on how the dip
 *	is derived.
 *
 *	- In the MD, the cfg-handle is expected to be unique for
 *	  virtual-device nodes that have the same 'name' property value.
 *	  This value is expected to be the same as that of "reg" property
 *	  of the corresponding OBP device node.
 *
 *	- The value of the 'name' property of a virtual-device node
 *	  in the MD is expected to be the same for the corresponding
 *	  OBP device node.
 *
 *	- Find the virtual-device node corresponding to a channel-endpoint
 *	  by walking backwards. Then obtain the values for the 'name' and
 *	  'cfg-handle' properties.
 *
 *	- Walk all the children of the cnex, find a matching dip which
 *	  has the same 'name' and 'reg' property values.
 *
 *	- The channels that have no corresponding device driver are
 *	  treated as if they  correspond to the cnex driver,
 *	  that is, return cnex dip for them. This means, the
 *	  cnex acts as an umbrella device driver. Note, this is
 *	  for 'intrstat' statistics purposes only. As a result of this,
 *	  the 'intrstat' shows cnex as the device that is servicing the
 *	  interrupts corresponding to these channels.
 *
 *	  For now, only one such case is known, that is, the channels that
 *	  are used by the "domain-services".
 */
static dev_info_t *
cnex_find_chan_dip(dev_info_t *dip, uint64_t chan_id,
    md_t *mdp, mde_cookie_t mde)
{
	int listsz;
	int num_nodes;
	int num_devs;
	uint64_t cfghdl;
	char *md_name;
	mde_cookie_t *listp;
	dev_info_t *cdip = NULL;

	num_nodes = md_node_count(mdp);
	ASSERT(num_nodes > 0);
	listsz = num_nodes * sizeof (mde_cookie_t);
	listp = (mde_cookie_t *)kmem_zalloc(listsz, KM_SLEEP);

	num_devs = md_scan_dag(mdp, mde, md_find_name(mdp, "virtual-device"),
	    md_find_name(mdp, "back"), listp);
	ASSERT(num_devs <= 1);
	if (num_devs <= 0) {
		DWARN("cnex_find_chan_dip:channel(0x%llx): "
		    "No virtual-device found\n", chan_id);
		goto fdip_exit;
	}
	if (md_get_prop_str(mdp, listp[0], "name", &md_name) != 0) {
		DWARN("cnex_find_chan_dip:channel(0x%llx): "
		    "name property not found\n", chan_id);
		goto fdip_exit;
	}

	D1("cnex_find_chan_dip: channel(0x%llx): virtual-device "
	    "name property value = %s\n", chan_id, md_name);

	if (md_get_prop_val(mdp, listp[0], "cfg-handle", &cfghdl) != 0) {
		DWARN("cnex_find_chan_dip:channel(0x%llx): virtual-device's "
		    "cfg-handle property not found\n", chan_id);
		goto fdip_exit;
	}

	D1("cnex_find_chan_dip:channel(0x%llx): virtual-device cfg-handle "
	    " property value = 0x%x\n", chan_id, cfghdl);

	for (cdip = ddi_get_child(dip); cdip != NULL;
	    cdip = ddi_get_next_sibling(cdip)) {

		int *cnex_regspec;
		uint32_t reglen;
		char	*dev_name;

		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, cdip,
		    DDI_PROP_DONTPASS, "name",
		    &dev_name) != DDI_PROP_SUCCESS) {
			DWARN("cnex_find_chan_dip: name property not"
			    " found for dip(0x%p)\n", cdip);
			continue;
		}
		if (strcmp(md_name, dev_name) != 0) {
			ddi_prop_free(dev_name);
			continue;
		}
		ddi_prop_free(dev_name);
		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
		    DDI_PROP_DONTPASS, "reg",
		    &cnex_regspec, &reglen) != DDI_SUCCESS) {
			DWARN("cnex_find_chan_dip: reg property not"
			    " found for dip(0x%p)\n", cdip);
			continue;
		}
		if (*cnex_regspec == cfghdl) {
			D1("cnex_find_chan_dip:channel(0x%llx): found "
			    "dip(0x%p) drvname=%s\n", chan_id, cdip,
			    ddi_driver_name(cdip));
			ddi_prop_free(cnex_regspec);
			break;
		}
		ddi_prop_free(cnex_regspec);
	}

fdip_exit:
	if (cdip == NULL) {
		/*
		 * If a virtual-device node exists but no dip found,
		 * then for now print a DEBUG error message only.
		 */
		if (num_devs > 0) {
			DERR("cnex_find_chan_dip:channel(0x%llx): "
			    "No device found\n", chan_id);
		}

		/* If no dip was found, return cnex device's dip. */
		cdip = dip;
	}

	kmem_free(listp, listsz);
	D1("cnex_find_chan_dip:channel(0x%llx): returning dip=0x%p\n",
	    chan_id, cdip);
	return (cdip);
}
Пример #15
0
/*
 * Send a notification to a client immediately after it registers.
 * The result_t is a list of all the nodes that match their specified
 * nodes of interest, all returned on the added list. This serves
 * as a base of reference to the client. All future MD updates are
 * relative to this list.
 */
static int
mdeg_notify_client_reg(mdeg_clnt_t *clnt)
{
	md_t			*mdp = NULL;
	mde_str_cookie_t	nname;
	mde_str_cookie_t	aname;
	mde_cookie_t		startnode;
	int			nnodes;
	int			nodechk;
	mde_cookie_t		*listp = NULL;
	mdeg_result_t		*mdeg_res = NULL;
	int			rv = MDEG_SUCCESS;

	mutex_enter(&mdeg.lock);

	/*
	 * Handle the special case where the node specification
	 * is NULL. In this case, call the client callback without
	 * any results. All processing is left to the client.
	 */
	if (clnt->pspec == NULL) {
		/* call the client callback */
		(*clnt->cb)(clnt->cb_arg, NULL);
		goto done;
	}

	if ((mdp = md_get_handle()) == NULL) {
		cmn_err(CE_WARN, "unable to retrieve current MD");
		rv = MDEG_FAILURE;
		goto done;
	}

	startnode = mdeg_find_start_node(mdp, clnt->pspec);
	if (startnode == MDE_INVAL_ELEM_COOKIE) {
		/* not much we can do */
		cmn_err(CE_WARN, "unable to match node specifier");
		rv = MDEG_FAILURE;
		goto done;
	}

	/*
	 * Use zalloc to provide correct default values for the
	 * unused removed, match_prev, and match_curr lists.
	 */
	mdeg_res = kmem_zalloc(sizeof (mdeg_result_t), KM_SLEEP);

	nname = md_find_name(mdp, clnt->nmatch->namep);
	aname = md_find_name(mdp, "fwd");

	nnodes = md_scan_dag(mdp, startnode, nname, aname, NULL);

	if (nnodes == 0) {
		MDEG_DBG("mdeg_notify_client_reg: no nodes of interest\n");
		rv = MDEG_SUCCESS;
		goto done;
	} else if (nnodes == -1) {
		MDEG_DBG("error scanning DAG\n");
		rv = MDEG_FAILURE;
		goto done;
	}

	MDEG_DBG("mdeg_notify_client_reg: %d node%s of interest\n",
	    nnodes, (nnodes == 1) ? "" : "s");

	/* get the list of nodes of interest */
	listp = kmem_alloc(sizeof (mde_cookie_t) * nnodes, KM_SLEEP);
	nodechk = md_scan_dag(mdp, startnode, nname, aname, listp);

	ASSERT(nodechk == nnodes);

	mdeg_res->added.mdp = mdp;
	mdeg_res->added.mdep = listp;
	mdeg_res->added.nelem = nnodes;

	/* call the client callback */
	(*clnt->cb)(clnt->cb_arg, mdeg_res);

done:
	mutex_exit(&mdeg.lock);

	if (mdp)
		(void) md_fini_handle(mdp);

	if (listp)
		kmem_free(listp, sizeof (mde_cookie_t) * nnodes);

	if (mdeg_res)
		kmem_free(mdeg_res, sizeof (mdeg_result_t));

	return (rv);
}
Пример #16
0
int
add_cpu_prop(picl_nodehdl_t node, void *args)
{
	mde_cookie_t *cpulistp;
	mde_cookie_t *cachelistp;
	mde_cookie_t *tlblistp;
	int x, num_nodes;
	int ncpus, ncaches, ntlbs;
	int status;
	int reg_prop[SUN4V_CPU_REGSIZE], cpuid;
	uint64_t int_value;

	status = ptree_get_propval_by_name(node, OBP_REG, reg_prop,
	    sizeof (reg_prop));
	if (status != PICL_SUCCESS) {
		return (PICL_WALK_TERMINATE);
	}

	cpuid = CFGHDL_TO_CPUID(reg_prop[0]);

	/*
	 * Allocate space for our searches.
	 */

	num_nodes = md_node_count(mdp);

	cpulistp = (mde_cookie_t *) alloca(sizeof (mde_cookie_t) *num_nodes);
	if (cpulistp == NULL) {
		return (PICL_WALK_TERMINATE);
	}

	cachelistp = (mde_cookie_t *) alloca(sizeof (mde_cookie_t) *num_nodes);
	if (cachelistp == NULL) {
		return (PICL_WALK_TERMINATE);
	}

	tlblistp = (mde_cookie_t *) alloca(sizeof (mde_cookie_t) *num_nodes);
	if (tlblistp == NULL) {
		return (PICL_WALK_TERMINATE);
	}

	/*
	 * Starting at the root node, scan the "fwd" dag for
	 * all the cpus in this description.
	 */

	ncpus = md_scan_dag(mdp, rootnode, md_find_name(mdp, "cpu"),
	    md_find_name(mdp, "fwd"), cpulistp);

	if (ncpus < 0) {
		return (PICL_WALK_TERMINATE);
	}

	/*
	 * Create PD cpus with a few select properties
	 */

	for (x = 0; x < ncpus; x++) {
		if (md_get_prop_val(mdp, cpulistp[x], "id", &int_value)) {
			continue;
		}

		if (int_value != cpuid)
			continue;

		add_md_prop(node, sizeof (int_value), "cpuid", &int_value,
			PICL_PTYPE_INT);

		add_md_prop(node, sizeof (int_value), "portid", &int_value,
		    PICL_PTYPE_INT);

		/* get caches for CPU */
		ncaches = md_scan_dag(mdp, cpulistp[x],
		    md_find_name(mdp, "cache"),
		    md_find_name(mdp, "fwd"),
		    cachelistp);

		add_cache_props(node, cachelistp, ncaches);

		/* get tlbs for CPU */
		ntlbs = md_scan_dag(mdp, cpulistp[x],
		    md_find_name(mdp, "tlb"),
		    md_find_name(mdp, "fwd"),
		    tlblistp);

		add_tlb_props(node, tlblistp, ntlbs);
	}

	return (PICL_WALK_CONTINUE);
}
Пример #17
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);
}
Пример #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);
}
Пример #19
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);
}