static void dev_di_node_free(topo_mod_t *mod, dev_di_node_t *dnode) { int i; /* free the stuff we point to */ if (dnode->ddn_devid) topo_mod_strfree(mod, dnode->ddn_devid); for (i = 0; i < dnode->ddn_ppath_count; i++) { /* topo_mod_strfree does NULL checking. */ topo_mod_strfree(mod, dnode->ddn_ppath[i]); topo_mod_strfree(mod, dnode->ddn_target_port[i]); topo_mod_strfree(mod, dnode->ddn_attached_port[i]); topo_mod_strfree(mod, dnode->ddn_bridge_port[i]); } topo_mod_free(mod, dnode->ddn_ppath, dnode->ddn_ppath_count * sizeof (char *)); topo_mod_free(mod, dnode->ddn_target_port, dnode->ddn_ppath_count * sizeof (char *)); topo_mod_free(mod, dnode->ddn_attached_port, dnode->ddn_ppath_count * sizeof (char *)); topo_mod_free(mod, dnode->ddn_bridge_port, dnode->ddn_ppath_count * sizeof (char *)); topo_mod_strfree(mod, dnode->ddn_dpath); topo_mod_strfree(mod, dnode->ddn_lpath); topo_mod_strfree(mod, dnode->ddn_mfg); topo_mod_strfree(mod, dnode->ddn_model); topo_mod_strfree(mod, dnode->ddn_serial); topo_mod_strfree(mod, dnode->ddn_firm); topo_mod_strfree(mod, dnode->ddn_cap); /* free self */ topo_mod_free(mod, dnode, sizeof (dev_di_node_t)); }
void topo_tree_destroy(ttree_t *tp) { topo_mod_t *mod; if (tp == NULL) return; mod = tp->tt_mod; if (tp->tt_walk != NULL) topo_mod_free(mod, tp->tt_walk, sizeof (topo_walk_t)); if (tp->tt_root != NULL) { assert(tp->tt_root->tn_refs == 1); topo_node_rele(tp->tt_root); } /* * Deallocate this last, because a pointer alias for tt_scheme * (stored in the root node's name field) may be used in * topo_node_rele(). */ if (tp->tt_scheme != NULL) topo_mod_strfree(mod, tp->tt_scheme); topo_mod_free(mod, tp, sizeof (ttree_t)); }
/* * dev_for_hostbridge() -- For hostbridges we truncate the devfs path * after the first element in the bus address. */ static char * dev_for_hostbridge(topo_mod_t *mp, char *path) { char *lastslash; char *newpath; char *comma; int plen; plen = strlen(path) + 1; /* * We only care about the last component of the dev path. If * we don't find a slash, something is weird. */ lastslash = strrchr(path, '/'); assert(lastslash != NULL); /* * Find the comma in the last component component@x,y, and * truncate the comma and any following number. */ comma = strchr(lastslash, ','); assert(comma != NULL); *comma = '\0'; if ((newpath = topo_mod_strdup(mp, path)) == NULL) { topo_mod_free(mp, path, plen); return (NULL); } *comma = ','; topo_mod_free(mp, path, plen); return (newpath); }
void cpu_mdesc_fini(topo_mod_t *mod, md_info_t *chip) { int i; md_proc_t *procp; md_fru_t *frup; if (chip->cpus != NULL) topo_mod_free(mod, chip->cpus, chip->ncpus * sizeof (md_cpumap_t)); if (chip->procs != NULL) { procp = chip->procs; for (i = 0; i < chip->nprocs; i++) { if ((frup = procp->fru) != NULL) { topo_mod_strfree(mod, frup->nac); topo_mod_strfree(mod, frup->serial); topo_mod_strfree(mod, frup->part); topo_mod_strfree(mod, frup->dash); topo_mod_free(mod, frup, sizeof (md_fru_t)); } procp++; } topo_mod_free(mod, chip->procs, chip->nprocs * sizeof (md_proc_t)); } }
void tf_pad_free(topo_mod_t *mp, tf_pad_t *p) { int n; if (p == NULL) return; if (p->tpad_pgs != NULL) { for (n = 0; n < p->tpad_pgcnt; n++) nvlist_free(p->tpad_pgs[n]); topo_mod_free(mp, p->tpad_pgs, p->tpad_pgcnt * sizeof (nvlist_t *)); } tf_rdata_free(mp, p->tpad_child); tf_rdata_free(mp, p->tpad_sibs); topo_mod_free(mp, p, sizeof (tf_pad_t)); }
void topo_method_unregister(topo_mod_t *mod, tnode_t *node, const char *name) { topo_imethod_t *mp; topo_node_lock(node); for (mp = topo_list_next(&node->tn_methods); mp != NULL; mp = topo_list_next(mp)) { if (strcmp(name, mp->tim_name) == 0) break; } if (mp == NULL) { topo_node_unlock(node); return; } topo_list_delete(&node->tn_methods, mp); topo_node_unlock(node); if (mp->tim_name != NULL) topo_mod_strfree(mod, mp->tim_name); if (mp->tim_desc != NULL) topo_mod_strfree(mod, mp->tim_desc); topo_mod_free(mod, mp, sizeof (topo_imethod_t)); }
/*ARGSUSED*/ static int maybe_di_chars_copy(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp, const char *tpnm) { topo_mod_t *mp; uchar_t *typbuf; char *tmpbuf; int sz = -1; int err, e; if (di_bytes_get(did_mod(pd), did_dinode(pd), dpnm, &sz, &typbuf) < 0) return (0); mp = did_mod(pd); if ((tmpbuf = topo_mod_alloc(mp, sz + 1)) == NULL) return (topo_mod_seterrno(mp, EMOD_NOMEM)); bcopy(typbuf, tmpbuf, sz); tmpbuf[sz] = 0; e = topo_prop_set_string(tn, tpgrp, tpnm, TOPO_PROP_IMMUTABLE, tmpbuf, &err); topo_mod_free(mp, tmpbuf, sz + 1); if (e != 0) return (topo_mod_seterrno(mp, err)); return (0); }
void tf_idata_free(topo_mod_t *mp, tf_idata_t *p) { if (p == NULL) return; tf_idata_free(mp, p->ti_next); tf_pad_free(mp, p->ti_pad); topo_mod_free(mp, p, sizeof (tf_idata_t)); }
static nvlist_t * amd_lookup_by_mcid(topo_mod_t *mod, topo_instance_t id) { mc_snapshot_info_t mcs; void *buf = NULL; uint8_t ver; nvlist_t *nvl = NULL; char path[64]; int fd, err; (void) snprintf(path, sizeof (path), "/dev/mc/mc%d", id); fd = open(path, O_RDONLY); if (fd == -1) { /* * Some v20z and v40z systems may have had the 3rd-party * NWSnps packagae installed which installs a /dev/mc * link. So try again via /devices. */ (void) snprintf(path, sizeof (path), "/devices/pci@0,0/pci1022,1102@%x,2:mc-amd", MC_AMD_DEV_OFFSET + id); fd = open(path, O_RDONLY); } if (fd == -1) return (NULL); /* do not whinge */ if (ioctl(fd, MC_IOC_SNAPSHOT_INFO, &mcs) == -1 || (buf = topo_mod_alloc(mod, mcs.mcs_size)) == NULL || ioctl(fd, MC_IOC_SNAPSHOT, buf) == -1) { whinge(mod, NULL, "mc failed to snapshot %s: %s\n", path, strerror(errno)); free(buf); (void) close(fd); return (NULL); } (void) close(fd); err = nvlist_unpack(buf, mcs.mcs_size, &nvl, 0); topo_mod_free(mod, buf, mcs.mcs_size); if (nvlist_lookup_uint8(nvl, MC_NVLIST_VERSTR, &ver) != 0) { whinge(mod, NULL, "mc nvlist is not versioned\n"); nvlist_free(nvl); return (NULL); } else if (ver != MC_NVLIST_VERS1) { whinge(mod, NULL, "mc nvlist version mismatch\n"); nvlist_free(nvl); return (NULL); } return (err ? NULL : nvl); }
void tf_edata_free(topo_mod_t *mp, tf_edata_t *p) { if (p == NULL) return; if (p->te_name != NULL) xmlFree(p->te_name); topo_mod_free(mp, p, sizeof (tf_edata_t)); }
void tf_info_free(topo_mod_t *mp, tf_info_t *p) { if (p->tf_xdoc != NULL) xmlFreeDoc(p->tf_xdoc); if (p->tf_scheme != NULL) topo_mod_strfree(mp, p->tf_scheme); tf_rdata_free(mp, p->tf_rd); topo_mod_free(mp, p, sizeof (tf_info_t)); }
void topo_node_range_destroy(tnode_t *pnode, const char *name) { int i; topo_nodehash_t *nhp; topo_mod_t *mod; 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) { break; } } if (nhp == NULL) { topo_node_unlock(pnode); return; } topo_list_delete(&pnode->tn_children, nhp); topo_node_unlock(pnode); /* * Should be an empty node range */ for (i = 0; i < nhp->th_arrlen; i++) { topo_node_unbind(nhp->th_nodearr[i]); } mod = nhp->th_enum; if (nhp->th_name != NULL) topo_mod_strfree(mod, nhp->th_name); if (nhp->th_nodearr != NULL) { topo_mod_free(mod, nhp->th_nodearr, nhp->th_arrlen * sizeof (tnode_t *)); } topo_mod_free(mod, nhp, sizeof (topo_nodehash_t)); topo_mod_rele(mod); }
static int node_create_seterror(topo_mod_t *mod, tnode_t *pnode, topo_nodehash_t *nhp, int err) { topo_node_unlock(pnode); topo_dprintf(TOPO_DBG_ERR, "unable to insert child:" "%s\n", topo_strerror(err)); if (nhp != NULL) { if (nhp->th_name != NULL) topo_mod_strfree(mod, nhp->th_name); if (nhp->th_nodearr != NULL) { topo_mod_free(mod, nhp->th_nodearr, nhp->th_arrlen * sizeof (tnode_t *)); } topo_mod_free(mod, nhp, sizeof (topo_nodehash_t)); } return (topo_mod_seterrno(mod, err)); }
void tf_rdata_free(topo_mod_t *mp, tf_rdata_t *p) { if (p == NULL) return; tf_rdata_free(mp, p->rd_next); if (p->rd_name != NULL) topo_mod_strfree(mp, p->rd_name); tf_edata_free(mp, p->rd_einfo); tf_idata_free(mp, p->rd_instances); tf_pad_free(mp, p->rd_pad); topo_mod_free(mp, p, sizeof (tf_rdata_t)); }
void topo_method_unregister_all(topo_mod_t *mod, tnode_t *node) { topo_imethod_t *mp; topo_node_lock(node); while ((mp = topo_list_next(&node->tn_methods)) != NULL) { topo_list_delete(&node->tn_methods, mp); if (mp->tim_name != NULL) topo_mod_strfree(mod, mp->tim_name); if (mp->tim_desc != NULL) topo_mod_strfree(mod, mp->tim_desc); topo_mod_free(mod, mp, sizeof (topo_imethod_t)); } topo_node_unlock(node); }
static topo_mod_t * hb_enumr_load(topo_mod_t *mp, tnode_t *parent) { topo_mod_t *rp = NULL; char *plat, *mach; char *hbpath; char *rootdir; int err; plat = mach = NULL; if (topo_prop_get_string(parent, TOPO_PGROUP_SYSTEM, TOPO_PROP_PLATFORM, &plat, &err) < 0) { (void) topo_mod_seterrno(mp, err); return (NULL); } if (topo_prop_get_string(parent, TOPO_PGROUP_SYSTEM, TOPO_PROP_MACHINE, &mach, &err) < 0) { (void) topo_mod_seterrno(mp, err); return (NULL); } hbpath = topo_mod_alloc(mp, PATH_MAX); rootdir = topo_mod_rootdir(mp); (void) snprintf(hbpath, PATH_MAX, PATH_TO_HB_ENUM, rootdir ? rootdir : "", plat); if ((rp = topo_mod_load(mp, hbpath)) == NULL) { topo_mod_dprintf(mp, "%s enumerator could not load %s.\n", IOBOARD, hbpath); (void) snprintf(hbpath, PATH_MAX, PATH_TO_HB_ENUM, rootdir ? rootdir : "", mach); if ((rp = topo_mod_load(mp, hbpath)) == NULL) { topo_mod_dprintf(mp, "%s enumerator could not load %s.\n", IOBOARD, hbpath); } } topo_mod_strfree(mp, plat); topo_mod_strfree(mp, mach); topo_mod_free(mp, hbpath, PATH_MAX); return (rp); }
static int rtld_fini(topo_mod_t *mod) { topo_rtld_t *rp = mod->tm_data; assert(mod != NULL); if (mod->tm_flags & TOPO_MOD_REG) { rp->rtld_fini(mod); if (mod->tm_flags & TOPO_MOD_REG) { topo_mod_unregister(mod); } } if (getenv("TOPONODLCLOSE") == NULL) (void) dlclose(rp->rtld_dlp); topo_mod_free(mod, rp, sizeof (topo_rtld_t)); return (0); }
static int set_methregister_error(topo_mod_t *mod, tnode_t *node, topo_imethod_t *mp, int err) { if (mp != NULL) { topo_list_delete(&node->tn_methods, mp); if (mp->tim_name != NULL) topo_mod_strfree(mod, mp->tim_name); if (mp->tim_desc != NULL) topo_mod_strfree(mod, mp->tim_desc); topo_mod_free(mod, mp, sizeof (topo_imethod_t)); } topo_node_unlock(node); topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR, "method registration failed for %s: %s\n", mod->tm_name, topo_strerror(err)); return (topo_mod_seterrno(mod, err)); }
static topo_mod_t * module_load(topo_mod_t *mp, tnode_t *parent, const char *name) { topo_mod_t *rp = NULL; char *plat, *mach; char *path; char *rootdir; int err; plat = mach = NULL; if (topo_prop_get_string(parent, TOPO_PGROUP_SYSTEM, TOPO_PROP_PLATFORM, &plat, &err) < 0) { (void) topo_mod_seterrno(mp, err); return (NULL); } if (topo_prop_get_string(parent, TOPO_PGROUP_SYSTEM, TOPO_PROP_MACHINE, &mach, &err) < 0) { (void) topo_mod_seterrno(mp, err); return (NULL); } path = topo_mod_alloc(mp, PATH_MAX); rootdir = topo_mod_rootdir(mp); (void) snprintf(path, PATH_MAX, PATH_TEMPLATE, rootdir ? rootdir : "", plat, name); if ((rp = topo_mod_load(mp, path)) == NULL) { topo_mod_dprintf(mp, "Unable to load %s.\n", path); (void) snprintf(path, PATH_MAX, PATH_TEMPLATE, rootdir ? rootdir : "", mach, name); if ((rp = topo_mod_load(mp, path)) == NULL) topo_mod_dprintf(mp, "Unable to load %s.\n", path); } topo_mod_strfree(mp, plat); topo_mod_strfree(mp, mach); topo_mod_free(mp, path, PATH_MAX); return (rp); }
static void topo_node_destroy(tnode_t *node) { int i; tnode_t *pnode = node->tn_parent; topo_nodehash_t *nhp; topo_mod_t *hmod, *mod = node->tn_enum; if (node == NULL) return; assert(node->tn_refs == 0); topo_dprintf(TOPO_DBG_TREE, "destroying node %s=%d\n", node->tn_name, node->tn_instance); /* * If not a root node, remove this node from the parent's node hash */ if (!(node->tn_state & TOPO_NODE_ROOT)) { topo_node_lock(pnode); nhp = node->tn_phash; for (i = 0; i < nhp->th_arrlen; i++) { if (node == nhp->th_nodearr[i]) { nhp->th_nodearr[i] = NULL; /* * Release hold on parent */ --pnode->tn_refs; if (pnode->tn_refs == 0) topo_node_destroy(pnode); } } topo_node_unlock(pnode); } topo_node_unlock(node); /* * Allow enumerator to clean-up private data and then release * ref count */ if (mod->tm_info->tmi_release != NULL) mod->tm_info->tmi_release(mod, node); topo_method_unregister_all(mod, node); /* * Destroy all node hash lists */ while ((nhp = topo_list_next(&node->tn_children)) != NULL) { for (i = 0; i < nhp->th_arrlen; i++) { assert(nhp->th_nodearr[i] == NULL); } hmod = nhp->th_enum; topo_mod_strfree(hmod, nhp->th_name); topo_mod_free(hmod, nhp->th_nodearr, nhp->th_arrlen * sizeof (tnode_t *)); topo_list_delete(&node->tn_children, nhp); topo_mod_free(hmod, nhp, sizeof (topo_nodehash_t)); topo_mod_rele(hmod); } /* * Destroy all property data structures, free the node and release * the module that created it */ topo_pgroup_destroy_all(node); topo_mod_free(mod, node, sizeof (tnode_t)); topo_mod_rele(mod); }
static void mb_topo_free(void *data, size_t size) { assert(mb_mod_hdl != NULL); topo_mod_free(mb_mod_hdl, data, size); }
/* ARGSUSED */ int x86pi_check_comp(topo_mod_t *mod) { int rv; int fd; int32_t legacy; nvlist_t *nvl = NULL; fm_ioc_data_t fid; char *ibuf = NULL, *obuf = NULL; size_t insz = 0, outsz = 0; char *f = "x86pi_check_comp"; smbios_hdl_t *shp; shp = topo_mod_smbios(mod); if (shp == NULL) return (X86PI_NONE); /* open /dev/fm */ fd = open("/dev/fm", O_RDONLY); if (fd < 0) { topo_mod_dprintf(mod, "%s: failed to open /dev/fm.\n", f); return (X86PI_NONE); } /* set up buffers and ioctl data structure */ outsz = FM_IOC_MAXBUFSZ; obuf = topo_mod_alloc(mod, outsz); if (obuf == NULL) { perror("umem_alloc"); return (X86PI_NONE); } fid.fid_version = 1; fid.fid_insz = insz; fid.fid_inbuf = ibuf; fid.fid_outsz = outsz; fid.fid_outbuf = obuf; /* send the ioctl to /dev/fm to retrieve legacy variable */ rv = ioctl(fd, FM_IOC_GENTOPO_LEGACY, &fid); if (rv < 0) { topo_mod_dprintf(mod, "%s: ioctl to /dev/fm failed", f); perror("fm_ioctl"); (void) close(fd); return (X86PI_NONE); } (void) close(fd); (void) nvlist_unpack(fid.fid_outbuf, fid.fid_outsz, &nvl, 0); (void) nvlist_lookup_int32(nvl, FM_GENTOPO_LEGACY, &legacy); nvlist_free(nvl); topo_mod_free(mod, obuf, outsz); if (legacy == 1) { /* legacy kernel variable set; will do the same */ return (X86PI_NONE); } /* legacy kernel variable not set; generic topo enum */ return (X86PI_FULL); }
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 void topo_snap_destroy(topo_hdl_t *thp) { int i; ttree_t *tp; topo_walk_t *twp; tnode_t *root; topo_nodehash_t *nhp; topo_mod_t *mod; for (tp = topo_list_next(&thp->th_trees); tp != NULL; tp = topo_list_next(tp)) { root = tp->tt_root; twp = tp->tt_walk; /* * Clean-up tree nodes from the bottom-up */ if ((twp->tw_node = topo_child_first(root)) != NULL) { twp->tw_cb = topo_walk_destroy; topo_node_hold(root); topo_node_hold(twp->tw_node); /* released at walk end */ (void) topo_walk_bottomup(twp, TOPO_WALK_CHILD); topo_node_rele(root); } /* * Tidy-up the root node */ while ((nhp = topo_list_next(&root->tn_children)) != NULL) { for (i = 0; i < nhp->th_arrlen; i++) { assert(nhp->th_nodearr[i] == NULL); } mod = nhp->th_enum; topo_mod_strfree(mod, nhp->th_name); topo_mod_free(mod, nhp->th_nodearr, nhp->th_arrlen * sizeof (tnode_t *)); topo_list_delete(&root->tn_children, nhp); topo_mod_free(mod, nhp, sizeof (topo_nodehash_t)); topo_mod_rele(mod); } } /* * Clean-up our cached devinfo and prom tree handles. */ if (thp->th_di != DI_NODE_NIL) { di_fini(thp->th_di); thp->th_di = DI_NODE_NIL; } if (thp->th_pi != DI_PROM_HANDLE_NIL) { di_prom_fini(thp->th_pi); thp->th_pi = DI_PROM_HANDLE_NIL; } if (thp->th_uuid != NULL) { topo_hdl_free(thp, thp->th_uuid, TOPO_UUID_SIZE); thp->th_uuid = NULL; } }
/* * Query the current disk status. If successful, the disk status is returned * as an nvlist consisting of at least the following members: * * protocol string Supported protocol (currently "scsi") * * status nvlist Arbitrary protocol-specific information * about the current state of the disk. * * faults nvlist A list of supported faults. Each * element of this list is a boolean value. * An element's existence indicates that * the drive supports detecting this fault, * and the value indicates the current * state of the fault. * * <fault-name> nvlist For each fault named in 'faults', a * nvlist describing protocol-specific * attributes of the fault. * * This method relies on the libdiskstatus library to query this information. */ static int disk_status(topo_mod_t *mod, tnode_t *nodep, topo_version_t vers, nvlist_t *in_nvl, nvlist_t **out_nvl) { disk_status_t *dsp; char *devpath, *fullpath; size_t pathlen; nvlist_t *status; int err; *out_nvl = NULL; if (vers != TOPO_METH_DISK_STATUS_VERSION) return (topo_mod_seterrno(mod, EMOD_VER_NEW)); /* * If the caller specifies the "path" parameter, then this indicates * that we should use this instead of deriving it from the topo node * itself. */ if (nvlist_lookup_string(in_nvl, "path", &fullpath) == 0) { devpath = NULL; } else { /* * Get the /devices path and attempt to open the disk status * handle. */ if (topo_prop_get_string(nodep, TOPO_PGROUP_IO, TOPO_IO_DEV_PATH, &devpath, &err) != 0) return (topo_mod_seterrno(mod, EMOD_METHOD_NOTSUP)); /* * Note that sizeof(string) includes the terminating NULL byte */ pathlen = strlen(devpath) + sizeof ("/devices") + sizeof (PHYS_EXTN) - 1; if ((fullpath = topo_mod_alloc(mod, pathlen)) == NULL) return (topo_mod_seterrno(mod, EMOD_NOMEM)); (void) snprintf(fullpath, pathlen, "/devices%s%s", devpath, PHYS_EXTN); topo_mod_strfree(mod, devpath); } if ((dsp = disk_status_open(fullpath, &err)) == NULL) { if (devpath) topo_mod_free(mod, fullpath, pathlen); return (topo_mod_seterrno(mod, err == EDS_NOMEM ? EMOD_NOMEM : EMOD_METHOD_NOTSUP)); } if (devpath) topo_mod_free(mod, fullpath, pathlen); if ((status = disk_status_get(dsp)) == NULL) { err = (disk_status_errno(dsp) == EDS_NOMEM ? EMOD_NOMEM : EMOD_METHOD_NOTSUP); disk_status_close(dsp); return (topo_mod_seterrno(mod, err)); } *out_nvl = status; disk_status_close(dsp); return (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); }
/* * Request the SAS address of the disk (if any) attached to this mpt_sas * instance at (Enclosure Number, Slot Number). The function returns * -1 on error and sets errno to ENOENT _only_ if the /devices node * (*devctl) does not exist. */ static int get_sas_address(topo_mod_t *mod, char *devctl, uint32_t enclosure, uint32_t slot, char **sas_address) { int ret = -1, en = ENXIO; int fd, i; mptsas_get_disk_info_t gdi; mptsas_disk_info_t *di; size_t disz; bzero(&gdi, sizeof (gdi)); if ((fd = open(devctl, O_RDWR)) == -1) { en = errno; topo_mod_dprintf(mod, "could not open '%s' for ioctl: %s\n", devctl, strerror(errno)); errno = en; return (-1); } if (ioctl(fd, MPTIOCTL_GET_DISK_INFO, &gdi) == -1) { if (errno != ENOENT) en = errno; topo_mod_dprintf(mod, "ioctl 1 on '%s' failed: %s\n", devctl, strerror(errno)); goto out; } gdi.DiskInfoArraySize = disz = sizeof (mptsas_disk_info_t) * gdi.DiskCount; gdi.PtrDiskInfoArray = di = topo_mod_alloc(mod, disz); if (di == NULL) { topo_mod_dprintf(mod, "memory allocation failed\n"); en = ENOMEM; goto out; } if (ioctl(fd, MPTIOCTL_GET_DISK_INFO, &gdi) == -1) { if (errno != ENOENT) en = errno; topo_mod_dprintf(mod, "ioctl 2 on '%s' failed: %s\n", devctl, strerror(errno)); topo_mod_free(mod, di, disz); goto out; } for (i = 0; i < gdi.DiskCount; i++) { if (di[i].Enclosure == enclosure && di[i].Slot == slot) { char sas[17]; /* 16 hex digits and NUL */ (void) snprintf(sas, 17, "%llx", di[i].SasAddress); topo_mod_dprintf(mod, "found mpt_sas disk (%d/%d) " "with adddress %s\n", enclosure, slot, sas); *sas_address = topo_mod_strdup(mod, sas); en = ret = 0; break; } } topo_mod_free(mod, di, disz); out: (void) close(fd); errno = en; return (ret); }
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); }
static void xaui_topo_free(void *data, size_t size) { assert(xaui_mod_hdl != NULL); topo_mod_free(xaui_mod_hdl, data, size); }
/*ARGSUSED*/ int topo_method_sensor_failure(topo_mod_t *mod, tnode_t *node, topo_version_t version, nvlist_t *in, nvlist_t **out) { const char *name = topo_node_name(node); topo_faclist_t faclist, *fp; int err; nvlist_t *nvl, *props, *propval, *tmp; int ret = -1; uint32_t type, state, units; nvpair_t *elem; double reading; char *propname; boolean_t has_reading; struct sensor_errinfo seinfo; if (strcmp(name, PSU) != 0 && strcmp(name, FAN) != 0) return (topo_mod_seterrno(mod, ETOPO_METHOD_NOTSUP)); if (topo_node_facility(mod->tm_hdl, node, TOPO_FAC_TYPE_SENSOR, TOPO_FAC_TYPE_ANY, &faclist, &err) != 0) return (topo_mod_seterrno(mod, ETOPO_METHOD_NOTSUP)); if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0) goto error; for (fp = topo_list_next(&faclist.tf_list); fp != NULL; fp = topo_list_next(fp)) { if (topo_prop_getpgrp(fp->tf_node, TOPO_PGROUP_FACILITY, &props, &err) != 0) { nvlist_free(nvl); goto error; } type = state = units = 0; reading = 0; has_reading = B_FALSE; elem = NULL; while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { if (strcmp(nvpair_name(elem), TOPO_PROP_VAL) != 0 || nvpair_type(elem) != DATA_TYPE_NVLIST) continue; (void) nvpair_value_nvlist(elem, &propval); if (nvlist_lookup_string(propval, TOPO_PROP_VAL_NAME, &propname) != 0) continue; if (strcmp(propname, TOPO_FACILITY_TYPE) == 0) { (void) nvlist_lookup_uint32(propval, TOPO_PROP_VAL_VAL, &type); } else if (strcmp(propname, TOPO_SENSOR_STATE) == 0) { (void) nvlist_lookup_uint32(propval, TOPO_PROP_VAL_VAL, &state); } else if (strcmp(propname, TOPO_SENSOR_UNITS) == 0) { (void) nvlist_lookup_uint32(propval, TOPO_PROP_VAL_VAL, &units); } else if (strcmp(propname, TOPO_SENSOR_READING) == 0) { has_reading = B_TRUE; (void) nvlist_lookup_double(propval, TOPO_PROP_VAL_VAL, &reading); } } if (topo_sensor_failed(type, state, &seinfo)) { tmp = NULL; if (topo_mod_nvalloc(mod, &tmp, NV_UNIQUE_NAME) != 0 || nvlist_add_uint32(tmp, TOPO_FACILITY_TYPE, type) != 0 || nvlist_add_uint32(tmp, TOPO_SENSOR_STATE, state) != 0 || nvlist_add_uint32(tmp, TOPO_SENSOR_UNITS, units) != 0 || nvlist_add_boolean_value(tmp, "nonrecov", seinfo.se_nonrecov) != 0 || nvlist_add_boolean_value(tmp, "predictive", seinfo.se_predictive) != 0 || nvlist_add_uint32(tmp, "source", seinfo.se_src) != 0 || (has_reading && nvlist_add_double(tmp, TOPO_SENSOR_READING, reading) != 0) || nvlist_add_nvlist(nvl, topo_node_name(fp->tf_node), tmp) != 0) { nvlist_free(props); nvlist_free(tmp); nvlist_free(nvl); ret = topo_mod_seterrno(mod, ETOPO_METHOD_NOMEM); goto error; } nvlist_free(tmp); } nvlist_free(props); } *out = nvl; ret = 0; error: while ((fp = topo_list_next(&faclist.tf_list)) != NULL) { topo_list_delete(&faclist.tf_list, fp); topo_mod_free(mod, fp, sizeof (topo_faclist_t)); } return (ret); }