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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
/* * 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); }