Exemplo n.º 1
0
int
md_vdev_find_val(device_t dev, char *namep, uint64_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);

	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) 
			break;
	}

	md_get_prop_val(mdp, node, namep, valp);
done:
	free(listp, M_DEVBUF);
	md_put(mdp);

	return (error);
}
Exemplo n.º 2
0
static void
add_tlb_props(picl_nodehdl_t node, mde_cookie_t *tlblistp, int ntlbs)
{
	int i;
	uint64_t int_value;
	uint8_t *type;
	char str[MAXSTRLEN];
	char property[MAXSTRLEN];
	char tlb_str[MAXSTRLEN];
	int type_size, str_size, total_size, type_flag;

	for (i = 0; i < ntlbs; i++) {
		if (md_get_prop_data(mdp, tlblistp[i], "type", &type,
			&type_size)) {
			return;
		}

		total_size = type_flag = 0;

		while (total_size < type_size) {
			str_size = strlen((char *)type + total_size) + 1;
			(void) strncpy(str, (char *)type + total_size,
			    sizeof (str));
			if (strncmp(str, "instn", sizeof (str)) == 0)
				type_flag |= ICACHE_FLAG;
			if (strncmp(str, "data", sizeof (str)) == 0)
				type_flag |= DCACHE_FLAG;
			total_size += str_size;
		}

		switch (type_flag) {
		case 1:
			(void) snprintf(tlb_str, sizeof (tlb_str),
			    "itlb");
			break;
		case 2:
			(void) snprintf(tlb_str, sizeof (tlb_str),
			    "dtlb");
			break;
		default:
			(void) snprintf(tlb_str, sizeof (tlb_str),
			    "Not a known cache type");
		}

		if (!(md_get_prop_val(mdp, tlblistp[i], "entries",
			&int_value))) {
			(void) snprintf(property, sizeof (property),
			    "%s-entries", tlb_str);
			add_md_prop(node, sizeof (int_value), property,
			    &int_value, PICL_PTYPE_INT);
		}
	}
}
Exemplo n.º 3
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);
}
Exemplo n.º 4
0
static boolean_t
mdeg_node_spec_match(md_t *md, mde_cookie_t node, mdeg_node_spec_t *nspec)
{
	mdeg_prop_spec_t	*prop;

	ASSERT(md && nspec);
	ASSERT(node != MDE_INVAL_ELEM_COOKIE);

	prop = nspec->specp;

	while (prop->type != MDET_LIST_END) {

		switch (prop->type) {
		case MDET_PROP_VAL: {
			uint64_t val;

			if (md_get_prop_val(md, node, prop->namep, &val) != 0)
				return (B_FALSE);

			if (prop->ps_val != val)
				return (B_FALSE);

			break;
		}
		case MDET_PROP_STR: {
			char	*str;

			if (md_get_prop_str(md, node, prop->namep, &str) != 0)
				return (B_FALSE);

			if (strcmp(prop->ps_str, str) != 0)
				return (B_FALSE);

			break;
		}

		default:
			return (B_FALSE);
		}

		prop++;
	}

	return (B_TRUE);
}
Exemplo n.º 5
0
int
mdesc_bus_gen_setup_devinfo(struct mdesc_bus_devinfo *mbd, mde_cookie_t node)
{
	md_t *mdp;
	
        if (mbd == NULL)
                return (ENOMEM);
	
	mdp = md_get();
	
        /* The 'name' property is considered mandatory. */
        if ((md_get_prop_alloc(mdp, node, "name", MDET_PROP_STR, (uint8_t **)&mbd->mbd_name)) == -1)
                return (EINVAL);
        md_get_prop_alloc(mdp, node, "compatible", MDET_PROP_DAT, (uint8_t **)&mbd->mbd_compat);
        md_get_prop_alloc(mdp, node, "device-type", MDET_PROP_STR, (uint8_t **)&mbd->mbd_type);
        md_get_prop_val(mdp, node, "cfg-handle", &mbd->mbd_handle);

	md_put(mdp);
        return (0);
}
Exemplo n.º 6
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));
}
Exemplo n.º 7
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);
}
Exemplo n.º 8
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);
}
Exemplo n.º 9
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);
}
Exemplo n.º 10
0
/* add a vldc port */
static int
i_vldc_add_port(vldc_t *vldcp, md_t *mdp, mde_cookie_t node)
{
	vldc_port_t	*vport;
	char		*sname;
	uint64_t	portno;
	int		vldc_inst;
	minor_t		minor;
	int		minor_idx;
	boolean_t	new_minor;
	int		rv;

	ASSERT(MUTEX_HELD(&vldcp->lock));

	/* read in the port's id property */
	if (md_get_prop_val(mdp, node, "id", &portno)) {
		cmn_err(CE_NOTE, "?i_vldc_add_port: node 0x%lx of added "
		    "list has no 'id' property", node);
		return (MDEG_FAILURE);
	}

	if (portno >= VLDC_MAX_PORTS) {
		cmn_err(CE_NOTE, "?i_vldc_add_port: found port number (%lu) "
		    "larger than maximum supported number of ports", portno);
		return (MDEG_FAILURE);
	}

	vport = &(vldcp->port[portno]);

	if (vport->minorp != NULL) {
		cmn_err(CE_NOTE, "?i_vldc_add_port: trying to add a port (%lu)"
		    " which is already bound", portno);
		return (MDEG_FAILURE);
	}

	vport->number = portno;

	/* get all channels for this device (currently only one) */
	if (i_vldc_get_port_channel(mdp, node, &vport->ldc_id) == -1) {
		return (MDEG_FAILURE);
	}

	/* set the default MTU */
	vport->mtu = VLDC_DEFAULT_MTU;

	/* get the service being exported by this port */
	if (md_get_prop_str(mdp, node, "vldc-svc-name", &sname)) {
		cmn_err(CE_NOTE, "?i_vldc_add_port: vdevice has no "
		    "'vldc-svc-name' property");
		return (MDEG_FAILURE);
	}

	/* minor number look up */
	for (minor_idx = 0; minor_idx < vldcp->minors_assigned;
	    minor_idx++) {
		if (strcmp(vldcp->minor_tbl[minor_idx].sname, sname) == 0) {
			/* found previously assigned minor number */
			break;
		}
	}

	new_minor = B_FALSE;
	if (minor_idx == vldcp->minors_assigned) {
		/* end of lookup - assign new minor number */
		if (vldcp->minors_assigned == VLDC_MAX_MINORS) {
			cmn_err(CE_NOTE, "?i_vldc_add_port: too many minor "
			    "nodes (%d)", minor_idx);
			return (MDEG_FAILURE);
		}

		(void) strlcpy(vldcp->minor_tbl[minor_idx].sname,
		    sname, MAXPATHLEN);

		vldcp->minors_assigned++;
		new_minor = B_TRUE;
	}

	if (vldcp->minor_tbl[minor_idx].portno != VLDC_INVALID_PORTNO) {
		cmn_err(CE_NOTE, "?i_vldc_add_port: trying to add a port (%lu)"
		    " which has a minor number in use by port (%u)",
		    portno, vldcp->minor_tbl[minor_idx].portno);
		return (MDEG_FAILURE);
	}

	vldc_inst = ddi_get_instance(vldcp->dip);

	vport->inst = vldc_inst;
	vport->minorp = &vldcp->minor_tbl[minor_idx];
	vldcp->minor_tbl[minor_idx].portno = portno;
	vldcp->minor_tbl[minor_idx].in_use = 0;

	D1("i_vldc_add_port: vldc@%d:%d  mtu=%d, ldc=%ld, service=%s\n",
	    vport->inst, vport->number, vport->mtu, vport->ldc_id, sname);

	/*
	 * Create a minor node. The minor number is
	 * (vldc_inst << VLDC_INST_SHIFT) | minor_idx
	 */
	minor = (vldc_inst << VLDC_INST_SHIFT) | (minor_idx);

	rv = ddi_create_minor_node(vldcp->dip, sname, S_IFCHR,
	    minor, DDI_NT_SERIAL, 0);

	if (rv != DDI_SUCCESS) {
		cmn_err(CE_NOTE, "?i_vldc_add_port: failed to create minor"
		    "node (%u), err = %d", minor, rv);
		vldcp->minor_tbl[minor_idx].portno = VLDC_INVALID_PORTNO;
		if (new_minor) {
			vldcp->minors_assigned--;
		}
		return (MDEG_FAILURE);
	}

	/*
	 * The port is now bound to a minor node and is initially in the
	 * closed state.
	 */
	vport->status = VLDC_PORT_CLOSED;

	D1("i_vldc_add_port: port %lu initialized\n", portno);

	return (MDEG_SUCCESS);
}
Exemplo n.º 11
0
/* mdeg callback */
static int
i_vldc_mdeg_cb(void *cb_argp, mdeg_result_t *resp)
{
	vldc_t		*vldcp;
	int		idx;
	uint64_t	portno;
	int		rv;
	md_t		*mdp;
	mde_cookie_t	node;

	if (resp == NULL) {
		D1("i_vldc_mdeg_cb: no result returned\n");
		return (MDEG_FAILURE);
	}

	vldcp = (vldc_t *)cb_argp;

	mutex_enter(&vldcp->lock);
	if (vldcp->detaching == B_TRUE) {
		D1("i_vldc_mdeg_cb: detach in progress\n");
		mutex_exit(&vldcp->lock);
		return (MDEG_FAILURE);
	}

	D1("i_vldc_mdeg_cb: added=%d, removed=%d, matched=%d\n",
	    resp->added.nelem, resp->removed.nelem, resp->match_prev.nelem);

	/* process added ports */
	for (idx = 0; idx < resp->added.nelem; idx++) {
		mdp = resp->added.mdp;
		node = resp->added.mdep[idx];

		D1("i_vldc_mdeg_cb: processing added node 0x%lx\n", node);

		/* attempt to add a port */
		if ((rv = i_vldc_add_port(vldcp, mdp, node)) != MDEG_SUCCESS) {
			cmn_err(CE_NOTE, "?i_vldc_mdeg_cb: unable to add port, "
			    "err = %d", rv);
		}
	}

	/* process removed ports */
	for (idx = 0; idx < resp->removed.nelem; idx++) {
		mdp = resp->removed.mdp;
		node = resp->removed.mdep[idx];

		D1("i_vldc_mdeg_cb: processing removed node 0x%lx\n", node);

		/* read in the port's id property */
		if (md_get_prop_val(mdp, node, "id", &portno)) {
			cmn_err(CE_NOTE, "?i_vldc_mdeg_cb: node 0x%lx of "
			    "removed list has no 'id' property", node);
			continue;
		}

		/* attempt to remove a port */
		if ((rv = i_vldc_remove_port(vldcp, portno)) != 0) {
			cmn_err(CE_NOTE, "?i_vldc_mdeg_cb: unable to remove "
			    "port %lu, err %d", portno, rv);
		}
	}

	/*
	 * Currently no support for updating already active ports. So, ignore
	 * the match_curr and match_prev arrays for now.
	 */

	mutex_exit(&vldcp->lock);

	return (MDEG_SUCCESS);
}
Exemplo n.º 12
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);
}
Exemplo n.º 13
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);
}
Exemplo n.º 14
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);
}
Exemplo n.º 15
0
static void
add_cache_props(picl_nodehdl_t node, mde_cookie_t *cachelistp, int ncaches)
{
	int i;
	uint64_t int_value;
	uint8_t *type;
	char str[MAXSTRLEN];
	char property[MAXSTRLEN];
	char cache_str[MAXSTRLEN];
	int type_size, str_size, total_size, type_flag;

	for (i = 0; i < ncaches; i++) {
		if (md_get_prop_data(mdp, cachelistp[i], "type", &type,
			&type_size)) {
			return;
		}

		if (md_get_prop_val(mdp, cachelistp[i], "level", &int_value)) {
			return;
		}

		total_size = type_flag = 0;

		while (total_size < type_size) {
			str_size = strlen((char *)type + total_size) + 1;
			(void) strncpy(str, (char *)type + total_size,
			    sizeof (str));
			if (strncmp(str, "instn", sizeof (str)) == 0)
				type_flag |= ICACHE_FLAG;
			if (strncmp(str, "data", sizeof (str)) == 0)
				type_flag |= DCACHE_FLAG;
			total_size += str_size;
		}

		switch (type_flag) {
		case 1:
			(void) snprintf(cache_str, sizeof (cache_str),
			    "l%d-icache", (int)int_value);
			break;
		case 2:
			(void) snprintf(cache_str, sizeof (cache_str),
			    "l%d-dcache", (int)int_value);
			break;
		case 3:
			(void) snprintf(cache_str, sizeof (cache_str),
			    "l%d-cache", (int)int_value);
			break;
		default:
			(void) snprintf(cache_str, sizeof (cache_str),
			    "Not a known cache type");
		}

		if (!(md_get_prop_val(mdp, cachelistp[i], "associativity",
			&int_value))) {
			(void) snprintf(property, sizeof (property),
			    "%s-associativity", cache_str);
			add_md_prop(node, sizeof (int_value), property,
			    &int_value, PICL_PTYPE_INT);
		}

		if (!(md_get_prop_val(mdp, cachelistp[i], "size",
			&int_value))) {
			(void) snprintf(property, sizeof (property), "%s-size",
			    cache_str);
			add_md_prop(node, sizeof (int_value), property,
			    &int_value, PICL_PTYPE_INT);
		}

		if (!(md_get_prop_val(mdp, cachelistp[i], "line-size",
			&int_value))) {
			(void) snprintf(property, sizeof (property),
			    "%s-line-size", cache_str);
			add_md_prop(node, sizeof (int_value), property,
			    &int_value, PICL_PTYPE_INT);
		}
	}
}