/*ARGSUSED*/ static int ASRU_set(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp, const char *tpnm) { topo_mod_t *mp; nvlist_t *fmri; char *dnpath, *path, *fpath, *nm; int d, e, f; /* * If this topology node represents a function of device, * set the ASRU to a dev scheme FMRI based on the value of * di_devfs_path(). If that path is NULL, set the ASRU to * be the resource describing this topology node. If this * isn't a function, inherit any ASRU from the parent. */ mp = did_mod(pd); nm = topo_node_name(tn); if ((strcmp(nm, PCI_BUS) == 0 && did_gettnode(pd) && strcmp(topo_node_name(did_gettnode(pd)), HOSTBRIDGE) == 0) || strcmp(nm, PCI_FUNCTION) == 0 || strcmp(nm, PCIEX_FUNCTION) == 0 || strcmp(nm, PCIEX_ROOT) == 0) { if ((dnpath = di_devfs_path(did_dinode(pd))) != NULL) { /* * Dup the path, dev_path_fix() may replace it and * dev_path_fix() wouldn't know to use * di_devfs_path_free() */ if ((path = topo_mod_strdup(mp, dnpath)) == NULL) { di_devfs_path_free(dnpath); return (topo_mod_seterrno(mp, EMOD_NOMEM)); } di_devfs_path_free(dnpath); did_BDF(pd, NULL, &d, &f); if ((fpath = dev_path_fix(mp, path, d, f)) == NULL) return (topo_mod_seterrno(mp, EMOD_NOMEM)); fmri = topo_mod_devfmri(mp, FM_DEV_SCHEME_VERSION, fpath, NULL); if (fmri == NULL) { topo_mod_dprintf(mp, "dev:///%s fmri creation failed.\n", fpath); topo_mod_strfree(mp, fpath); return (-1); } topo_mod_strfree(mp, fpath); } else { topo_mod_dprintf(mp, "NULL di_devfs_path.\n"); if (topo_prop_get_fmri(tn, TOPO_PGROUP_PROTOCOL, TOPO_PROP_RESOURCE, &fmri, &e) < 0) return (topo_mod_seterrno(mp, e)); } if (topo_node_asru_set(tn, fmri, 0, &e) < 0) { nvlist_free(fmri); return (topo_mod_seterrno(mp, e)); } nvlist_free(fmri); return (0); } (void) topo_node_asru_set(tn, NULL, 0, &e); return (0); }
static int mptsas_led_mode(topo_mod_t *mod, tnode_t *node, topo_version_t vers, nvlist_t *in, nvlist_t **nvout) { int err, ret = 0; tnode_t *pnode = topo_node_parent(node); uint32_t type, ledmode = 0; nvlist_t *pargs, *nvl; char *driver = NULL, *devctl = NULL; uint32_t enclosure, slot; uint8_t mptsas_led; boolean_t set; if (vers > TOPO_METH_MPTSAS_LED_MODE_VERSION) return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW)); if (topo_prop_get_string(pnode, TOPO_PGROUP_BINDING, TOPO_BINDING_DRIVER, &driver, &err) != 0 || strcmp("mpt_sas", driver) != 0) { topo_mod_dprintf(mod, "%s: Facility driver was not mpt_sas", __func__); ret = topo_mod_seterrno(mod, EMOD_NVL_INVAL); goto out; } if (topo_prop_get_uint32(node, TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE, &type, &err) != 0) { topo_mod_dprintf(mod, "%s: Failed to lookup %s property " "(%s)", __func__, TOPO_FACILITY_TYPE, topo_strerror(err)); return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); } switch (type) { case (TOPO_LED_TYPE_SERVICE): mptsas_led = MPTSAS_LEDCTL_LED_FAIL; break; case (TOPO_LED_TYPE_LOCATE): mptsas_led = MPTSAS_LEDCTL_LED_IDENT; break; case (TOPO_LED_TYPE_OK2RM): mptsas_led = MPTSAS_LEDCTL_LED_OK2RM; break; default: topo_mod_dprintf(mod, "%s: Invalid LED type: 0x%x\n", __func__, type); return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); } if (topo_prop_get_string(pnode, TOPO_PGROUP_BINDING, TOPO_BINDING_DEVCTL, &devctl, &err) != 0 || topo_prop_get_uint32(pnode, TOPO_PGROUP_BINDING, TOPO_BINDING_ENCLOSURE, &enclosure, &err) != 0 || topo_prop_get_uint32(pnode, TOPO_PGROUP_BINDING, TOPO_BINDING_SLOT, &slot, &err) != 0) { topo_mod_dprintf(mod, "%s: Facility was missing mpt_sas binding" " properties\n", __func__); ret = topo_mod_seterrno(mod, EMOD_NVL_INVAL); goto out; } if ((nvlist_lookup_nvlist(in, TOPO_PROP_PARGS, &pargs) == 0) && nvlist_exists(pargs, TOPO_PROP_VAL_VAL)) { /* * Set the LED mode */ set = B_TRUE; if ((ret = nvlist_lookup_uint32(pargs, TOPO_PROP_VAL_VAL, &ledmode)) != 0) { topo_mod_dprintf(mod, "%s: Failed to lookup %s nvpair " "(%s)\n", __func__, TOPO_PROP_VAL_VAL, strerror(ret)); ret = topo_mod_seterrno(mod, EMOD_NVL_INVAL); goto out; } topo_mod_dprintf(mod, "%s: Setting LED mode to %s\n", __func__, ledmode ? "ON" : "OFF"); } else { /* * Get the LED mode */ set = B_FALSE; topo_mod_dprintf(mod, "%s: Getting LED mode\n", __func__); } if (do_led_control(mod, devctl, enclosure, slot, mptsas_led, &ledmode, set) != 0) { topo_mod_dprintf(mod, "%s: do_led_control failed", __func__); ret = topo_mod_seterrno(mod, EMOD_UNKNOWN); goto out; } if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 || nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, TOPO_LED_MODE) != 0 || nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_UINT32) != 0 || nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, ledmode) != 0) { topo_mod_dprintf(mod, "%s: Failed to allocate 'out' nvlist\n", __func__); nvlist_free(nvl); ret = topo_mod_seterrno(mod, EMOD_NOMEM); goto out; } *nvout = nvl; out: if (driver != NULL) topo_mod_strfree(mod, driver); if (devctl != NULL) topo_mod_strfree(mod, devctl); return (ret); }
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 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)); }
/* * Calculate the authority information for a node. Inherit the data if * possible, but always create an appropriate property group. */ int x86pi_set_auth(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri, tnode_t *t_parent, tnode_t *t_node) { int result; int err; int is_chassis = 0; int chassis_instance = 0; nvlist_t *auth; char *val = NULL; char *prod = NULL; char *psn = NULL; char *csn = NULL; char *server = NULL; char *f = "x86pi_set_auth"; if (mod == NULL || t_parent == NULL || t_node == NULL) { return (-1); } result = topo_pgroup_create(t_node, &auth_pgroup, &err); if (result != 0 && err != ETOPO_PROP_DEFD) { /* * We failed to create the property group and it was not * already defined. Set the err code and return failure. */ (void) topo_mod_seterrno(mod, err); return (-1); } /* Get the authority information already available from the parent */ auth = topo_mod_auth(mod, t_parent); /* Determnine if this is a chassis node and set it's instance */ if ((strlen(hcfmri->hc_name) == strlen(CHASSIS)) && strncmp(hcfmri->hc_name, CHASSIS, strlen(CHASSIS)) == 0) { is_chassis = 1; chassis_instance = hcfmri->instance; } /* * Set the authority data, inheriting it if possible, but creating it * if necessary. */ /* product-id */ result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT, &err); if (result != 0 && err != ETOPO_PROP_DEFD) { result = nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT, &prod); if (result != 0 || prod == NULL) { /* * No product information in the parent node or auth * list. Use the product information in the hcfrmi * struct. */ prod = (char *)hcfmri->product; if (prod == NULL) { topo_mod_dprintf(mod, "%s: product name not " "found for %s node\n", f, hcfmri->hc_name); } } /* * We continue even if the product information is not available * to enumerate as much as possible. */ if (prod != NULL) { result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT, TOPO_PROP_IMMUTABLE, prod, &err); if (result != 0) { /* Preserve the error and continue */ (void) topo_mod_seterrno(mod, err); topo_mod_dprintf(mod, "%s: failed to set " "property %s (%d) : %s\n", f, FM_FMRI_AUTH_PRODUCT, err, topo_strerror(err)); } } } /* product-sn */ result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT_SN, &err); if (result != 0 && err != ETOPO_PROP_DEFD) { result = nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT_SN, &psn); if (result != 0 || psn == NULL) { /* * No product-sn information in the parent node or auth * list. */ topo_mod_dprintf(mod, "%s: psn not found\n", f); } else { /* * We continue even if the product-sn information is * not available to enumerate as much as possible. */ result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT_SN, TOPO_PROP_IMMUTABLE, psn, &err); if (result != 0) { /* Preserve the error and continue */ (void) topo_mod_seterrno(mod, err); topo_mod_dprintf(mod, "%s: failed to " "set property %s (%d) : %s\n", f, FM_FMRI_AUTH_PRODUCT_SN, err, topo_strerror(err)); } } } /* chassis-id */ if (is_chassis == 0 || (is_chassis == 1 && chassis_instance == 0)) { /* either not a chassis node, or chassis #0 */ result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS, &err); } else { /* chassis 'n' in a >1 chassis system */ result = err = -1; } if (result != 0 && err != ETOPO_PROP_DEFD) { if (is_chassis == 0) { result = nvlist_lookup_string(auth, FM_FMRI_AUTH_CHASSIS, &csn); if (result != 0 || csn == NULL) { /* * No chassis information in the parent * node or auth list. */ topo_mod_dprintf(mod, "%s: csn name not found\n", f); } } else { /* * So as not to blindly set the chassis-id to * chassis #0's serial number. */ csn = val = topo_mod_strdup(mod, hcfmri->serial_number); } /* * We continue even if the chassis information is not available * to enumerate as much as possible. */ if (csn != NULL) { if (is_chassis == 1) result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS, TOPO_PROP_MUTABLE, csn, &err); else result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS, TOPO_PROP_IMMUTABLE, csn, &err); if (result != 0) { /* Preserve the error and continue */ (void) topo_mod_seterrno(mod, err); topo_mod_dprintf(mod, "%s: failed to " "set property %s (%d) : %s\n", f, FM_FMRI_AUTH_CHASSIS, err, topo_strerror(err)); } } if (val != NULL) { topo_mod_strfree(mod, val); val = NULL; } } /* server-id */ result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_SERVER, &err); if (result != 0 && err != ETOPO_PROP_DEFD) { result = nvlist_lookup_string(auth, FM_FMRI_AUTH_SERVER, &server); if (result != 0 || server == NULL) { /* * No server information in the parent node or auth * list. Find the server information in hostname. */ server = val = x86pi_get_serverid(mod); if (server == NULL) { topo_mod_dprintf(mod, "%s: server " "name not found for %s node\n", f, hcfmri->hc_name); } } /* * We continue even if the server information is not available * to enumerate as much as possible. */ if (server != NULL) { result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_SERVER, TOPO_PROP_IMMUTABLE, server, &err); if (result != 0) { /* Preserve the error and continue */ (void) topo_mod_seterrno(mod, err); topo_mod_dprintf(mod, "%s: failed to " "set property %s (%d) : %s\n", f, FM_FMRI_AUTH_SERVER, err, topo_strerror(err)); } } if (val != NULL) topo_mod_strfree(mod, val); } nvlist_free(auth); return (0); }
static int create_chip(topo_mod_t *mod, tnode_t *pnode, topo_instance_t min, topo_instance_t max, nvlist_t *cpu, nvlist_t *auth, int mc_offchip) { tnode_t *chip; nvlist_t *fmri = NULL; int err, perr, nerr = 0; int32_t chipid, procnodeid, procnodes_per_pkg; const char *vendor; int32_t family, model; boolean_t create_mc = B_FALSE; uint16_t smbios_id; /* * /dev/fm will export the chipid based on SMBIOS' ordering * of Type-4 structures, if SMBIOS meets FMA needs */ err = nvlist_lookup_pairs(cpu, 0, FM_PHYSCPU_INFO_CHIP_ID, DATA_TYPE_INT32, &chipid, FM_PHYSCPU_INFO_NPROCNODES, DATA_TYPE_INT32, &procnodes_per_pkg, FM_PHYSCPU_INFO_PROCNODE_ID, DATA_TYPE_INT32, &procnodeid, FM_PHYSCPU_INFO_VENDOR_ID, DATA_TYPE_STRING, &vendor, FM_PHYSCPU_INFO_FAMILY, DATA_TYPE_INT32, &family, FM_PHYSCPU_INFO_MODEL, DATA_TYPE_INT32, &model, NULL); if (err) { whinge(mod, NULL, "create_chip: lookup failed: %s\n", strerror(err)); return (-1); } if (chipid < min || chipid > max) return (-1); if (FM_AWARE_SMBIOS(mod)) { if ((err = nvlist_lookup_uint16(cpu, FM_PHYSCPU_INFO_SMBIOS_ID, &smbios_id)) != 0) { whinge(mod, NULL, "create_chip: lookup smbios_id failed" ": enumerating x86pi & chip topology, but" " no Chip properties from SMBIOS" " - err msg : %s\n", strerror(err)); /* * Lets reset the module specific * data to NULL, overriding any * SMBIOS capability encoded earlier. * This will fail all subsequent * FM_AWARE_SMBIOS checks. */ topo_mod_setspecific(mod, NULL); } } if ((chip = topo_node_lookup(pnode, CHIP_NODE_NAME, chipid)) == NULL) { if ((chip = create_node(mod, pnode, auth, CHIP_NODE_NAME, chipid, smbios_id)) == NULL) return (-1); /* * Do not register XML map methods if SMBIOS can provide * serial, part, revision & label */ if (!FM_AWARE_SMBIOS(mod)) { if (topo_method_register(mod, chip, chip_methods) < 0) whinge(mod, &nerr, "create_chip: " "topo_method_register failed\n"); } (void) topo_pgroup_create(chip, &chip_pgroup, &err); nerr -= add_nvlist_strprop(mod, chip, cpu, PGNAME(CHIP), CHIP_VENDOR_ID, NULL); nerr -= add_nvlist_longprops(mod, chip, cpu, PGNAME(CHIP), NULL, CHIP_FAMILY, CHIP_MODEL, CHIP_STEPPING, NULL); if (FM_AWARE_SMBIOS(mod)) { int fru = 0; char *serial = NULL; char *part = NULL; char *rev = NULL; char *label; fru = chip_fru_smbios_get(mod, smbios_id); /* * Chip is not a FRU, set the FRU fmri of parent node */ if (topo_node_resource(chip, &fmri, &perr) != 0) whinge(mod, &nerr, "create_chip: " "topo_node_resource failed\n"); if (!fru) { (void) topo_node_fru_set(chip, NULL, 0, &perr); label = NULL; } else { label = (char *)chip_label_smbios_get(mod, pnode, smbios_id, NULL); if (topo_node_fru_set(chip, fmri, 0, &perr) != 0) { whinge(mod, NULL, "create_chip: " "topo_node_fru_set failed\n"); perr = 0; } } perr += nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID, &serial); perr += nvlist_lookup_string(fmri, FM_FMRI_HC_PART, &part); perr += nvlist_lookup_string(fmri, FM_FMRI_HC_REVISION, &rev); if (perr != 0) { whinge(mod, NULL, "create_chip: nvlist_lookup_string" "failed\n"); perr = 0; } perr += topo_prop_set_string(chip, PGNAME(CHIP), FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr); perr += topo_prop_set_string(chip, PGNAME(CHIP), FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr); perr += topo_prop_set_string(chip, PGNAME(CHIP), FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr); if (perr != 0) whinge(mod, NULL, "create_chip: topo_prop_set_string" "failed\n"); nvlist_free(fmri); if (topo_node_label_set(chip, label, &perr) == -1) { whinge(mod, NULL, "create_chip: " "topo_node_label_set failed\n"); } topo_mod_strfree(mod, label); } else { if (topo_node_resource(chip, &fmri, &err) == -1) { whinge(mod, &nerr, "create_chip: " "topo_node_resource failed\n"); } else { (void) topo_node_fru_set(chip, fmri, 0, &perr); nvlist_free(fmri); } } if (topo_method_register(mod, chip, strands_retire_methods) < 0) whinge(mod, &nerr, "create_chip: " "topo_method_register failed\n"); if (topo_node_range_create(mod, chip, CORE_NODE_NAME, 0, 255)) return (-1); if (strcmp(vendor, "AuthenticAMD") == 0) { if (topo_node_range_create(mod, chip, MCT_NODE_NAME, 0, 255)) return (-1); } create_mc = B_TRUE; } if (FM_AWARE_SMBIOS(mod)) { int status = 0; /* * STATUS * CPU Socket Populated * CPU Socket Unpopulated * Populated : Enabled * Populated : Disabled by BIOS (Setup) * Populated : Disabled by BIOS (Error) * Populated : Idle * * Enumerate core & strand only for Populated : Enabled * Enumerate Off-Chip Memory Controller only for * Populated : Enabled */ status = chip_status_smbios_get(mod, (id_t)smbios_id); if (!status) { whinge(mod, NULL, "create_chip: " "CPU Socket is not populated or is disabled\n"); return (0); } } err = create_core(mod, chip, cpu, auth, smbios_id); /* * Create memory-controller node under a chip for architectures * that may have on-chip memory-controller(s). * If SMBIOS meets FMA needs, when Multi-Chip-Module is * addressed, mc instances should be derived from SMBIOS */ if (strcmp(vendor, "AuthenticAMD") == 0) { amd_mc_create(mod, smbios_id, chip, MCT_NODE_NAME, auth, procnodeid, procnodes_per_pkg, family, model, &nerr); } else if (create_mc && !mc_offchip) onchip_mc_create(mod, smbios_id, chip, MCT_NODE_NAME, auth); return (err == 0 && nerr == 0 ? 0 : -1); }
int platform_pci_fru(topo_mod_t *mod, tnode_t *node, nvlist_t *in, nvlist_t **out) { int err = 0; uint64_t ptr; did_t *dp, *pdp; tnode_t *pnode; char *nm, *plat, *pp, **cp; char *label; int found_t1plat = 0; uchar_t *loc; int locsiz; topo_mod_dprintf(mod, "entering platform_pci_fru\n"); if (topo_prop_get_string(node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT, &plat, &err) < 0) { (void) topo_mod_seterrno(mod, err); return (-1); } /* Delete the "SUNW," */ pp = strchr(plat, ','); if (pp == NULL) pp = plat; else ++pp; /* Is this an UltraSPARC-T1 platform? */ cp = usT1_plats; while ((*cp != NULL) && (found_t1plat == 0)) { if (strcmp(pp, *cp) == 0) found_t1plat = 1; cp++; } topo_mod_strfree(mod, plat); /* * On UltraSPARC-T1 systems, use the legacy hc scheme on * the adapter slots to ensure ALOM on the SP can interpret * the FRU correctly. For everything else, follow the normal * code flow */ if (found_t1plat) { *out = NULL; nm = topo_node_name(node); if (strcmp(nm, PCI_DEVICE) != 0 && strcmp(nm, PCIEX_DEVICE) != 0 && strcmp(nm, PCIEX_BUS) != 0) return (0); if (nvlist_lookup_uint64(in, "nv1", &ptr) != 0) { topo_mod_dprintf(mod, "label method argument " "not found.\n"); return (-1); } dp = (did_t *)(uintptr_t)ptr; pnode = did_gettnode(dp); pdp = did_find(mod, topo_node_getspecific(pnode)); /* * Is there a slotname associated with the device? */ if ((label = pci_slot_label_lookup(mod, pnode, dp, pdp)) != NULL) { nvlist_t *rnvl; char buf[PATH_MAX]; (void) snprintf(buf, PATH_MAX, "hc:///component=%s", label); if (topo_mod_str2nvl(mod, buf, &rnvl) < 0) return (-1); *out = rnvl; } return (0); } else if (di_bytes_get(mod, topo_node_getspecific(node), PI_PROP_CHASSIS_LOCATION_NAME, &locsiz, &loc) == 0 && locsiz > 0) { /* * We have crossed a FRU boundary and need to find the parent * node with this location and set our FMRI to that value. */ return (platform_pci_fru_location(mod, node, loc, locsiz)); } else { return (pci_fru_compute(mod, node, in, out)); } }
static int amd_dimm_create(topo_mod_t *mod, uint16_t chip_smbid, tnode_t *pnode, const char *name, nvlist_t *mc, nvlist_t *auth) { int i, err, nerr = 0; int perr = 0; nvpair_t *nvp; tnode_t *dimmnode; nvlist_t *fmri, **dimmarr = NULL; uint64_t num; uint_t ndimm; id_t smbid; const char *serial; const char *part; const char *rev; if (nvlist_lookup_nvlist_array(mc, "dimmlist", &dimmarr, &ndimm) != 0) { whinge(mod, NULL, "amd_dimm_create: dimmlist lookup failed\n"); return (-1); } if (ndimm == 0) return (0); /* no dimms present on this node */ if (topo_node_range_create(mod, pnode, name, 0, MAX_DIMMNUM) < 0) { whinge(mod, NULL, "amd_dimm_create: range create failed\n"); return (-1); } for (i = 0; i < ndimm; i++) { if (nvlist_lookup_uint64(dimmarr[i], "num", &num) != 0) { whinge(mod, &nerr, "amd_dimm_create: dimm num property " "missing\n"); continue; } if (mkrsrc(mod, pnode, name, num, auth, &fmri) < 0) { whinge(mod, &nerr, "amd_dimm_create: mkrsrc failed\n"); continue; } if (FM_AWARE_SMBIOS(mod)) { smbid = memnode_to_smbiosid(mod, chip_smbid, DIMM_NODE_NAME, i, NULL); serial = chip_serial_smbios_get(mod, smbid); part = chip_part_smbios_get(mod, smbid); rev = chip_rev_smbios_get(mod, smbid); perr += nvlist_add_string(fmri, FM_FMRI_HC_SERIAL_ID, serial); perr += nvlist_add_string(fmri, FM_FMRI_HC_PART, part); perr += nvlist_add_string(fmri, FM_FMRI_HC_REVISION, rev); if (perr != 0) whinge(mod, NULL, "amd_dimm_create:" "nvlist_add_string failed\n"); } if ((dimmnode = topo_node_bind(mod, pnode, name, num, fmri)) == NULL) { nvlist_free(fmri); whinge(mod, &nerr, "amd_dimm_create: node bind " "failed\n"); continue; } if (!FM_AWARE_SMBIOS(mod)) if (topo_method_register(mod, dimmnode, dimm_methods) < 0) whinge(mod, &nerr, "amd_dimm_create: " "topo_method_register failed"); (void) topo_pgroup_create(dimmnode, &dimm_pgroup, &err); if (FM_AWARE_SMBIOS(mod)) { char *label; nvlist_free(fmri); (void) topo_node_resource(dimmnode, &fmri, &err); label = (char *)chip_label_smbios_get(mod, pnode, smbid, NULL); if (topo_node_label_set(dimmnode, label, &perr) == -1) topo_mod_dprintf(mod, "Failed" "to set label\n"); topo_mod_strfree(mod, label); (void) topo_prop_set_string(dimmnode, PGNAME(DIMM), FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &err); (void) topo_prop_set_string(dimmnode, PGNAME(DIMM), FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &err); (void) topo_prop_set_string(dimmnode, PGNAME(DIMM), FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &err); } (void) topo_node_asru_set(dimmnode, fmri, 0, &err); (void) topo_node_fru_set(dimmnode, fmri, 0, &err); nvlist_free(fmri); for (nvp = nvlist_next_nvpair(dimmarr[i], NULL); nvp != NULL; nvp = nvlist_next_nvpair(dimmarr[i], nvp)) { if (nvpair_type(nvp) == DATA_TYPE_UINT64_ARRAY && strcmp(nvpair_name(nvp), "csnums") == 0 || nvpair_type(nvp) == DATA_TYPE_STRING_ARRAY && strcmp(nvpair_name(nvp), "csnames") == 0) continue; /* used in amd_rank_create() */ nerr += nvprop_add(mod, nvp, PGNAME(DIMM), dimmnode); } nerr += amd_rank_create(mod, dimmnode, dimmarr[i], auth); } return (nerr == 0 ? 0 : -1); }
/* * 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 tnode_t * mb_tnode_create(topo_mod_t *mod, tnode_t *parent, const char *name, topo_instance_t i, void *priv) { nvlist_t *fmri; tnode_t *ntn; char *serial = NULL, *part = NULL; char *psn = NULL, *csn = NULL, *pstr = NULL; nvlist_t *auth = topo_mod_auth(mod, parent); /* * Get Product Serial Number, Chassis ID, MB Serial Number and * Part Number from PRI. */ (void) mb_get_pri_info(mod, &serial, &part, &csn, &psn); if (nvlist_lookup_string(auth, FM_FMRI_AUTH_CHASSIS, &pstr) != 0 && csn != NULL) { if (nvlist_add_string(auth, FM_FMRI_AUTH_CHASSIS, csn) != 0) { topo_mod_dprintf(mod, "failed to add chassis to auth"); nvlist_free(auth); return (NULL); } } if (nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT_SN, &pstr) != 0 && psn != NULL) { if (nvlist_add_string(auth, FM_FMRI_AUTH_PRODUCT_SN, psn) != 0) { topo_mod_dprintf(mod, "failed to add product-sn to auth"); nvlist_free(auth); return (NULL); } } fmri = topo_mod_hcfmri(mod, NULL, FM_HC_SCHEME_VERSION, name, i, NULL, auth, part, NULL, serial); topo_mod_strfree(mod, serial); topo_mod_strfree(mod, part); topo_mod_strfree(mod, csn); topo_mod_strfree(mod, psn); if (fmri == NULL) { topo_mod_dprintf(mod, "Unable to make nvlist for %s bind: %s.\n", name, topo_mod_errmsg(mod)); nvlist_free(auth); return (NULL); } ntn = topo_node_bind(mod, parent, name, i, fmri); if (ntn == NULL) { topo_mod_dprintf(mod, "topo_node_bind (%s%d/%s%d) failed: %s\n", topo_node_name(parent), topo_node_instance(parent), name, i, topo_strerror(topo_mod_errno(mod))); nvlist_free(auth); nvlist_free(fmri); return (NULL); } mb_prop_set(ntn, auth); nvlist_free(auth); nvlist_free(fmri); topo_node_setspecific(ntn, priv); return (ntn); }
/*ARGSUSED*/ static int amd_generic_mc_create(topo_mod_t *mod, uint16_t smbid, tnode_t *cnode, tnode_t *mcnode, int family, int model, nvlist_t *auth) { int chan, cs; /* * Elsewhere we have already returned for families less than 0xf. * This "generic" topology is adequate for all of family 0xf and * for revisions A to E of family 0x10 (for the list of models * in each revision, refer to usr/src/uts/i86pc/os/cpuid_subr.c). * We cover all family 0x10 models, till model 10. */ if (family > 0x10 || (family == 0x10 && model > 10)) return (1); if (topo_node_range_create(mod, mcnode, CHAN_NODE_NAME, 0, MAX_CHANNUM) < 0) { whinge(mod, NULL, "amd_generic_mc_create: range create for " "channels failed\n"); return (-1); } for (chan = 0; chan <= MAX_CHANNUM; chan++) { tnode_t *chnode; nvlist_t *fmri; int err; if (mkrsrc(mod, mcnode, CHAN_NODE_NAME, chan, auth, &fmri) != 0) { whinge(mod, NULL, "amd_generic_mc_create: mkrsrc " "failed\n"); return (-1); } if ((chnode = topo_node_bind(mod, mcnode, CHAN_NODE_NAME, chan, fmri)) == NULL) { nvlist_free(fmri); whinge(mod, NULL, "amd_generic_mc_create: node " "bind failed\n"); return (-1); } nvlist_free(fmri); (void) topo_pgroup_create(chnode, &chan_pgroup, &err); (void) topo_prop_set_string(chnode, PGNAME(CHAN), "channel", TOPO_PROP_IMMUTABLE, chan == 0 ? "A" : "B", &err); if (FM_AWARE_SMBIOS(mod)) { if (topo_node_label_set(chnode, NULL, &err) == -1) whinge(mod, NULL, "amd_generic_mc_create: " "topo_node_label_set\n"); if (topo_node_fru_set(chnode, NULL, 0, &err) != 0) whinge(mod, NULL, "amd_generic_mc_create: " "topo_node_fru_set failed\n"); } if (topo_node_range_create(mod, chnode, CS_NODE_NAME, 0, MAX_CSNUM) < 0) { whinge(mod, NULL, "amd_generic_mc_create: " "range create for cs failed\n"); return (-1); } for (cs = 0; cs <= MAX_CSNUM; cs++) { tnode_t *csnode; if (mkrsrc(mod, chnode, CS_NODE_NAME, cs, auth, &fmri) != 0) { whinge(mod, NULL, "amd_generic_mc_create: " "mkrsrc for cs failed\n"); return (-1); } if ((csnode = topo_node_bind(mod, chnode, CS_NODE_NAME, cs, fmri)) == NULL) { nvlist_free(fmri); whinge(mod, NULL, "amd_generic_mc_create: " "bind for cs failed\n"); return (-1); } /* * Dynamic ASRU for page faults within a chip-select. * The topology does not represent pages (there are * too many) so when a page is faulted we generate * an ASRU to represent the individual page. * If SMBIOS meets FMA needs, derive labels & serials * for DIMMS and apply to chip-select nodes. * If deriving from SMBIOS, skip IPMI */ if (FM_AWARE_SMBIOS(mod)) { if (topo_method_register(mod, csnode, x86pi_gen_cs_methods) < 0) whinge(mod, NULL, "amd_generic_mc_create: " "method registration failed\n"); } else { if (topo_method_register(mod, csnode, gen_cs_methods) < 0) whinge(mod, NULL, "amd_generic_mc_create: method" "registration failed\n"); } (void) topo_node_asru_set(csnode, fmri, TOPO_ASRU_COMPUTE, &err); nvlist_free(fmri); /* * If SMBIOS meets FMA needs, set DIMM as the FRU for * the chip-select node. Use the channel & chip-select * numbers to get the DIMM instance. * Send via inst : dram channel number * Receive via inst : dimm instance */ if (FM_AWARE_SMBIOS(mod)) { int inst; id_t dimm_smbid; const char *serial; const char *part; const char *rev; char *label; (void) topo_pgroup_create(csnode, &cs_pgroup, &err); inst = chan; dimm_smbid = memnode_to_smbiosid(mod, smbid, CS_NODE_NAME, cs, &inst); serial = chip_serial_smbios_get(mod, dimm_smbid); part = chip_part_smbios_get(mod, dimm_smbid); rev = chip_rev_smbios_get(mod, dimm_smbid); label = (char *)chip_label_smbios_get(mod, chnode, dimm_smbid, NULL); (void) topo_prop_set_string(csnode, PGNAME(CS), FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &err); (void) topo_prop_set_string(csnode, PGNAME(CS), FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &err); (void) topo_prop_set_string(csnode, PGNAME(CS), FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &err); /* * We apply DIMM labels to chip-select nodes, * FRU for chip-selects should be DIMMs, and * we do not derive dimm nodes for Family 0x10 * so FRU fmri is NULL, but FRU Labels are set, * the FRU labels point to the DIMM. */ (void) topo_node_label_set(csnode, label, &err); topo_mod_strfree(mod, label); } } } return (0); }
/*ARGSUSED*/ static int sw_fmri_nvl2str(topo_mod_t *mod, tnode_t *node, topo_version_t version, nvlist_t *nvl, nvlist_t **out) { nvlist_t *object, *site = NULL, *anvl = NULL; char *file, *func, *token; uint8_t scheme_version; char *path, *root; nvlist_t *fmristr; size_t buflen = 0; int linevalid = 0; char *buf = NULL; ssize_t size = 0; char linebuf[32]; int64_t line; int pass; int err; if (version > TOPO_METH_NVL2STR_VERSION) return (topo_mod_seterrno(mod, EMOD_VER_NEW)); if (nvlist_lookup_uint8(nvl, FM_VERSION, &scheme_version) != 0 || scheme_version > FM_SW_SCHEME_VERSION) return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); /* Get authority, if present */ err = nvlist_lookup_nvlist(nvl, FM_FMRI_AUTHORITY, &anvl); if (err != 0 && err != ENOENT) return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); /* * The 'object' nvlist is required. It must include the path, * but the root is optional. */ if (nvlist_lookup_nvlist(nvl, FM_FMRI_SW_OBJ, &object) != 0 || !lookup_string(object, FM_FMRI_SW_OBJ_PATH, &path, B_TRUE) || !lookup_string(object, FM_FMRI_SW_OBJ_ROOT, &root, B_FALSE)) return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); /* The 'site' nvlist is optional */ file = func = token = NULL; linevalid = 0; if ((err = nvlist_lookup_nvlist(nvl, FM_FMRI_SW_SITE, &site)) == 0) { /* * Prefer 'token' to file/func/line */ if (lookup_string(site, FM_FMRI_SW_SITE_TOKEN, &token, B_FALSE) <= 0) { /* * If no token then try file, func, line - but * func and line are meaningless without file. */ if (lookup_string(site, FM_FMRI_SW_SITE_FILE, &file, B_FALSE) == 1) { (void) lookup_string(site, FM_FMRI_SW_SITE_FUNC, &func, B_FALSE); if (nvlist_lookup_int64(site, FM_FMRI_SW_SITE_LINE, &line) == 0) linevalid = 1; } } } else if (err != ENOENT) { return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); } /* On the first pass buf is NULL and size and buflen are 0 */ pass = 1; again: /* * sw://[<authority>]/ * [:root=<object.root] * :path=<object.path> * [#<fragment-identifier>] * * <fragment-identifier> is one of * * :token=<site.token> * or * :file=<site.file>[:func=<site.func>][:line=<site.line>] */ /* sw:// */ topo_fmristr_build(&size, buf, buflen, FM_FMRI_SCHEME_SW, NULL, "://"); /* authority, if any */ if (anvl != NULL) { nvpair_t *apair; char *aname, *aval; for (apair = nvlist_next_nvpair(anvl, NULL); apair != NULL; apair = nvlist_next_nvpair(anvl, apair)) { if (nvpair_type(apair) != DATA_TYPE_STRING || nvpair_value_string(apair, &aval) != 0) continue; aname = nvpair_name(apair); topo_fmristr_build(&size, buf, buflen, ":", NULL, NULL); topo_fmristr_build(&size, buf, buflen, "=", aname, aval); } } /* separating slash */ topo_fmristr_build(&size, buf, buflen, "/", NULL, NULL); /* :root=... */ if (root) { topo_fmristr_build(&size, buf, buflen, root, ":" FM_FMRI_SW_OBJ_ROOT "=", NULL); } /* :path=... */ topo_fmristr_build(&size, buf, buflen, path, ":" FM_FMRI_SW_OBJ_PATH "=", NULL); if (token) { /* #:token=... */ topo_fmristr_build(&size, buf, buflen, token, "#:" FM_FMRI_SW_SITE_TOKEN "=", NULL); } else if (file) { /* #:file=... */ topo_fmristr_build(&size, buf, buflen, file, "#:" FM_FMRI_SW_SITE_FILE "=", NULL); /* :func=... */ if (func) { topo_fmristr_build(&size, buf, buflen, func, ":" FM_FMRI_SW_SITE_FUNC "=", NULL); } /* :line=... */ if (linevalid) { if (pass == 1) (void) snprintf(linebuf, sizeof (linebuf), "%lld", line); topo_fmristr_build(&size, buf, buflen, linebuf, ":" FM_FMRI_SW_SITE_LINE "=", NULL); } } if (buf == NULL) { if ((buf = topo_mod_alloc(mod, size + 1)) == NULL) return (topo_mod_seterrno(mod, EMOD_NOMEM)); buflen = size + 1; size = 0; pass = 2; goto again; } /* * Construct the nvlist to return as the result. */ if (topo_mod_nvalloc(mod, &fmristr, NV_UNIQUE_NAME) != 0) { topo_mod_strfree(mod, buf); return (topo_mod_seterrno(mod, EMOD_NOMEM)); } if (nvlist_add_string(fmristr, "fmri-string", buf) != 0) { topo_mod_strfree(mod, buf); nvlist_free(fmristr); return (topo_mod_seterrno(mod, EMOD_NOMEM)); } topo_mod_strfree(mod, buf); *out = fmristr; return (0); }
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; } }
tnode_t * x86pi_gen_chassis(topo_mod_t *mod, tnode_t *t_parent, int smb_id, int instance) { int rv; smbios_info_t ip; smbios_chassis_t ch; x86pi_hcfmri_t ch_hcfmri; tnode_t *ch_node; char *f = "x86pi_gen_chassis"; smbios_hdl_t *shp; shp = topo_mod_smbios(mod); if (shp == NULL) { topo_mod_dprintf(mod, "%s: failed to load SMBIOS\n", f); return (NULL); } /* init fmri struct */ bzero(&ch_hcfmri, sizeof (x86pi_hcfmri_t)); /* grab SMBIOS strings */ rv = smbios_info_common(shp, smb_id, &ip); if (rv != 0) { return (NULL); } /* grab SMBIOS type 3 struct */ rv = smbios_info_chassis(shp, smb_id, &ch); if (rv != 0) { return (NULL); } /* populate string entries */ ch_hcfmri.serial_number = x86pi_cleanup_smbios_str(mod, ip.smbi_serial, 0); ch_hcfmri.version = x86pi_cleanup_smbios_str(mod, ip.smbi_version, 0); ch_hcfmri.manufacturer = x86pi_cleanup_smbios_str(mod, ip.smbi_manufacturer, 0); /* set hc_name and instance */ ch_hcfmri.hc_name = topo_mod_strdup(mod, "chassis"); ch_hcfmri.instance = instance; topo_mod_dprintf(mod, "%s: instance (%d)\n", f, ch_hcfmri.instance); topo_mod_dprintf(mod, "%s: hc name (%s)\n", f, ch_hcfmri.hc_name); topo_mod_dprintf(mod, "%s: Serial Number (%s)\n", f, ch_hcfmri.serial_number); topo_mod_dprintf(mod, "%s: Version (%s)\n", f, ch_hcfmri.version); topo_mod_dprintf(mod, "%s: Manufacturer (%s)\n", f, ch_hcfmri.manufacturer); /* create topo node */ if (!instance) { /* First Chassis SMBIOS Record is Chassis topo instance 0 */ rv = x86pi_enum_generic(mod, &ch_hcfmri, t_parent, NULL, &ch_node, 0); } else { rv = x86pi_enum_generic(mod, &ch_hcfmri, t_parent, t_parent, &ch_node, 0); } if (rv != 0) { topo_mod_dprintf(mod, "%s: failed to create %d tnode\n", f, instance); return (NULL); } /* free up strings */ if (ch_hcfmri.serial_number != NULL) { topo_mod_strfree(mod, (char *)ch_hcfmri.serial_number); } if (ch_hcfmri.version != NULL) { topo_mod_strfree(mod, (char *)ch_hcfmri.version); } if (ch_hcfmri.manufacturer != NULL) { topo_mod_strfree(mod, (char *)ch_hcfmri.manufacturer); } if (ch_hcfmri.hc_name != NULL) { topo_mod_strfree(mod, (char *)ch_hcfmri.hc_name); } return (ch_node); }
static int create_strand(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu, nvlist_t *auth, uint16_t chip_smbiosid) { tnode_t *strand; int32_t strandid, cpuid; int err, perr, nerr = 0; nvlist_t *fmri; char *serial = NULL; char *part = NULL; char *rev = NULL; if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_STRAND_ID, &strandid)) != 0) { whinge(mod, NULL, "create_strand: lookup strand_id failed: " "%s\n", strerror(err)); return (-1); } if ((strand = topo_node_lookup(pnode, STRAND_NODE_NAME, strandid)) != NULL) { whinge(mod, NULL, "create_strand: duplicate tuple found\n"); return (-1); } if ((strand = create_node(mod, pnode, auth, STRAND_NODE_NAME, strandid, chip_smbiosid)) == NULL) return (-1); /* * Inherit FRU from core node, in native use cpu scheme ASRU, * in xpv, use hc scheme ASRU. */ (void) topo_node_fru_set(strand, NULL, 0, &perr); /* * From the inherited FRU, extract the Serial * number(if SMBIOS donates) and set it in the ASRU */ if (FM_AWARE_SMBIOS(mod)) { char *val = NULL; if (topo_prop_get_fmri(strand, TOPO_PGROUP_PROTOCOL, TOPO_PROP_RESOURCE, &fmri, &err) != 0) whinge(mod, NULL, "create_strand: topo_prop_get_fmri failed\n"); if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID, &val) != 0) whinge(mod, NULL, "create_strand: nvlist_lookup_string failed: \n"); else serial = topo_mod_strdup(mod, val); nvlist_free(fmri); } if (is_xpv()) { if (topo_node_resource(strand, &fmri, &err) == -1) { whinge(mod, &nerr, "create_strand: " "topo_node_resource failed\n"); } else { if (FM_AWARE_SMBIOS(mod)) (void) nvlist_add_string(fmri, FM_FMRI_HC_SERIAL_ID, serial); (void) topo_node_asru_set(strand, fmri, 0, &err); nvlist_free(fmri); } } else { if (nvlist_lookup_int32(cpu, STRAND_CPU_ID, &cpuid) != 0) { whinge(mod, &nerr, "create_strand: lookup cpuid " "failed\n"); } else { if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0)) != NULL) { (void) topo_node_asru_set(strand, fmri, 0, &err); nvlist_free(fmri); } else { whinge(mod, &nerr, "create_strand: " "cpu_fmri_create() failed\n"); } } } if (topo_method_register(mod, strand, strands_retire_methods) < 0) whinge(mod, &nerr, "create_strand: " "topo_method_register failed\n"); (void) topo_pgroup_create(strand, &strand_pgroup, &err); nerr -= add_nvlist_longprops(mod, strand, cpu, PGNAME(STRAND), NULL, STRAND_CHIP_ID, STRAND_PROCNODE_ID, STRAND_CORE_ID, STRAND_CPU_ID, NULL); if (FM_AWARE_SMBIOS(mod)) { (void) topo_node_label_set(strand, NULL, &perr); if (topo_node_resource(strand, &fmri, &perr) != 0) { whinge(mod, &nerr, "create_strand: " "topo_node_resource failed\n"); perr = 0; } perr += nvlist_lookup_string(fmri, FM_FMRI_HC_PART, &part); perr += nvlist_lookup_string(fmri, FM_FMRI_HC_REVISION, &rev); if (perr != 0) { whinge(mod, NULL, "create_strand: nvlist_lookup_string failed\n"); perr = 0; } perr += topo_prop_set_string(strand, PGNAME(STRAND), FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr); perr += topo_prop_set_string(strand, PGNAME(STRAND), FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr); perr += topo_prop_set_string(strand, PGNAME(STRAND), FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr); if (perr != 0) whinge(mod, NULL, "create_strand: topo_prop_set_string" "failed\n"); nvlist_free(fmri); topo_mod_strfree(mod, serial); } return (err == 0 && nerr == 0 ? 0 : -1); }
/* * Set the properties of the disk node, from dev_di_node_t data. * Properties include: * group: protocol properties: resource, asru, label, fru * group: authority properties: product-id, chasis-id, server-id * group: io properties: devfs-path, devid * group: storage properties: * - logical-disk, disk-model, disk-manufacturer, serial-number * - firmware-revision, capacity-in-bytes * * NOTE: the io and storage groups won't be present if the dnode passed in is * NULL. This happens when a disk is found through ses, but is not enumerated * in the devinfo tree. */ static int disk_set_props(topo_mod_t *mod, tnode_t *parent, tnode_t *dtn, dev_di_node_t *dnode) { nvlist_t *asru = NULL, *drive_attrs; char *label = NULL; nvlist_t *fmri = NULL; dm_descriptor_t drive_descr = NULL; uint32_t rpm; int err; /* pull the label property down from our parent 'bay' node */ if (topo_node_label(parent, &label, &err) != 0) { topo_mod_dprintf(mod, "disk_set_props: " "label error %s\n", topo_strerror(err)); goto error; } if (topo_node_label_set(dtn, label, &err) != 0) { topo_mod_dprintf(mod, "disk_set_props: " "label_set error %s\n", topo_strerror(err)); goto error; } /* get the resource fmri, and use it as the fru */ if (topo_node_resource(dtn, &fmri, &err) != 0) { topo_mod_dprintf(mod, "disk_set_props: " "resource error: %s\n", topo_strerror(err)); goto error; } if (topo_node_fru_set(dtn, fmri, 0, &err) != 0) { topo_mod_dprintf(mod, "disk_set_props: " "fru_set error: %s\n", topo_strerror(err)); goto error; } /* create/set the authority group */ if ((topo_pgroup_create(dtn, &disk_auth_pgroup, &err) != 0) && (err != ETOPO_PROP_DEFD)) { topo_mod_dprintf(mod, "disk_set_props: " "create disk_auth error %s\n", topo_strerror(err)); goto error; } /* create the storage group */ if (topo_pgroup_create(dtn, &storage_pgroup, &err) != 0) { topo_mod_dprintf(mod, "disk_set_props: " "create storage error %s\n", topo_strerror(err)); goto error; } /* no dnode was found for this disk - skip the io and storage groups */ if (dnode == NULL) { err = 0; goto out; } /* form and set the asru */ if ((asru = topo_mod_devfmri(mod, FM_DEV_SCHEME_VERSION, dnode->ddn_dpath, dnode->ddn_devid)) == NULL) { err = ETOPO_FMRI_UNKNOWN; topo_mod_dprintf(mod, "disk_set_props: " "asru error %s\n", topo_strerror(err)); goto error; } if (topo_node_asru_set(dtn, asru, 0, &err) != 0) { topo_mod_dprintf(mod, "disk_set_props: " "asru_set error %s\n", topo_strerror(err)); goto error; } /* create/set the devfs-path and devid in the io group */ if (topo_pgroup_create(dtn, &io_pgroup, &err) != 0) { topo_mod_dprintf(mod, "disk_set_props: " "create io error %s\n", topo_strerror(err)); goto error; } if (topo_prop_set_string(dtn, TOPO_PGROUP_IO, TOPO_IO_DEV_PATH, TOPO_PROP_IMMUTABLE, dnode->ddn_dpath, &err) != 0) { topo_mod_dprintf(mod, "disk_set_props: " "set dev error %s\n", topo_strerror(err)); goto error; } if (dnode->ddn_devid && topo_prop_set_string(dtn, TOPO_PGROUP_IO, TOPO_IO_DEVID, TOPO_PROP_IMMUTABLE, dnode->ddn_devid, &err) != 0) { topo_mod_dprintf(mod, "disk_set_props: " "set devid error %s\n", topo_strerror(err)); goto error; } if (dnode->ddn_ppath_count != 0 && topo_prop_set_string_array(dtn, TOPO_PGROUP_IO, TOPO_IO_PHYS_PATH, TOPO_PROP_IMMUTABLE, (const char **)dnode->ddn_ppath, dnode->ddn_ppath_count, &err) != 0) { topo_mod_dprintf(mod, "disk_set_props: " "set phys-path error %s\n", topo_strerror(err)); goto error; } /* set the storage group public /dev name */ if (dnode->ddn_lpath != NULL && topo_prop_set_string(dtn, TOPO_PGROUP_STORAGE, TOPO_STORAGE_LOGICAL_DISK_NAME, TOPO_PROP_IMMUTABLE, dnode->ddn_lpath, &err) != 0) { topo_mod_dprintf(mod, "disk_set_props: " "set disk_name error %s\n", topo_strerror(err)); goto error; } /* populate other misc storage group properties */ if (dnode->ddn_mfg && (topo_prop_set_string(dtn, TOPO_PGROUP_STORAGE, TOPO_STORAGE_MANUFACTURER, TOPO_PROP_IMMUTABLE, dnode->ddn_mfg, &err) != 0)) { topo_mod_dprintf(mod, "disk_set_props: " "set mfg error %s\n", topo_strerror(err)); goto error; } if (dnode->ddn_model && (topo_prop_set_string(dtn, TOPO_PGROUP_STORAGE, TOPO_STORAGE_MODEL, TOPO_PROP_IMMUTABLE, dnode->ddn_model, &err) != 0)) { topo_mod_dprintf(mod, "disk_set_props: " "set model error %s\n", topo_strerror(err)); goto error; } if (dnode->ddn_serial && (topo_prop_set_string(dtn, TOPO_PGROUP_STORAGE, TOPO_STORAGE_SERIAL_NUM, TOPO_PROP_IMMUTABLE, dnode->ddn_serial, &err) != 0)) { topo_mod_dprintf(mod, "disk_set_props: " "set serial error %s\n", topo_strerror(err)); goto error; } if (dnode->ddn_firm && (topo_prop_set_string(dtn, TOPO_PGROUP_STORAGE, TOPO_STORAGE_FIRMWARE_REV, TOPO_PROP_IMMUTABLE, dnode->ddn_firm, &err) != 0)) { topo_mod_dprintf(mod, "disk_set_props: " "set firm error %s\n", topo_strerror(err)); goto error; } if (dnode->ddn_cap && (topo_prop_set_string(dtn, TOPO_PGROUP_STORAGE, TOPO_STORAGE_CAPACITY, TOPO_PROP_IMMUTABLE, dnode->ddn_cap, &err) != 0)) { topo_mod_dprintf(mod, "disk_set_props: " "set cap error %s\n", topo_strerror(err)); goto error; } if (dnode->ddn_devid == NULL || (drive_descr = dm_get_descriptor_by_name(DM_DRIVE, dnode->ddn_devid, &err)) == NULL || (drive_attrs = dm_get_attributes(drive_descr, &err)) == NULL) goto out; if (nvlist_lookup_boolean(drive_attrs, DM_SOLIDSTATE) == 0 || nvlist_lookup_uint32(drive_attrs, DM_RPM, &rpm) != 0) goto out; if (topo_prop_set_uint32(dtn, TOPO_PGROUP_STORAGE, TOPO_STORAGE_RPM, TOPO_PROP_IMMUTABLE, rpm, &err) != 0) { topo_mod_dprintf(mod, "disk_set_props: " "set rpm error %s\n", topo_strerror(err)); dm_free_descriptor(drive_descr); goto error; } err = 0; out: if (drive_descr != NULL) dm_free_descriptor(drive_descr); nvlist_free(fmri); if (label) topo_mod_strfree(mod, label); nvlist_free(asru); return (err); error: err = topo_mod_seterrno(mod, err); goto out; }
static int create_core(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu, nvlist_t *auth, uint16_t chip_smbiosid) { tnode_t *core; int32_t coreid, cpuid; int err, perr, nerr = 0; nvlist_t *fmri; char *serial = NULL; char *part = NULL; char *rev = NULL; if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_CORE_ID, &coreid)) != 0) { whinge(mod, NULL, "create_core: lookup core_id failed: %s\n", strerror(err)); return (-1); } if ((core = topo_node_lookup(pnode, CORE_NODE_NAME, coreid)) == NULL) { if ((core = create_node(mod, pnode, auth, CORE_NODE_NAME, coreid, chip_smbiosid)) == NULL) return (-1); /* * Inherit FRU from the chip node, for native, we use hc * scheme ASRU for the core node. */ (void) topo_node_fru_set(core, NULL, 0, &perr); /* * From the inherited FRU, extract the Serial * number if SMBIOS donates and set it in the ASRU */ if (FM_AWARE_SMBIOS(mod)) { char *val = NULL; if (topo_node_resource(core, &fmri, &err) != 0) whinge(mod, NULL, "create_core: topo_prop_get_fmri failed\n"); if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID, &val) != 0) whinge(mod, NULL, "create_core:" "nvlist_lookup_string failed\n"); else serial = topo_mod_strdup(mod, val); nvlist_free(fmri); } if (is_xpv()) { if (topo_node_resource(core, &fmri, &err) == -1) { whinge(mod, &nerr, "create_core: " "topo_node_resource failed\n"); } else { if (FM_AWARE_SMBIOS(mod)) (void) nvlist_add_string(fmri, FM_FMRI_HC_SERIAL_ID, serial); (void) topo_node_asru_set(core, fmri, 0, &err); nvlist_free(fmri); } } if (topo_method_register(mod, core, strands_retire_methods) < 0) whinge(mod, &nerr, "create_core: " "topo_method_register failed\n"); (void) topo_pgroup_create(core, &core_pgroup, &err); nerr -= add_nvlist_longprops(mod, core, cpu, PGNAME(CORE), NULL, CORE_CHIP_ID, CORE_PROCNODE_ID, NULL); if (topo_node_range_create(mod, core, STRAND_NODE_NAME, 0, 255) != 0) return (-1); } if (!is_xpv()) { /* * In native mode, we're in favor of cpu scheme ASRU for * printing reason. More work needs to be done to support * multi-strand cpu: the ASRU will be a list of cpuid then. */ if (nvlist_lookup_int32(cpu, STRAND_CPU_ID, &cpuid) != 0) { whinge(mod, &nerr, "create_core: lookup cpuid " "failed\n"); } else { if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0)) != NULL) { (void) topo_node_asru_set(core, fmri, 0, &err); nvlist_free(fmri); } else { whinge(mod, &nerr, "create_core: " "cpu_fmri_create() failed\n"); } } } if (FM_AWARE_SMBIOS(mod)) { (void) topo_node_label_set(core, NULL, &perr); if (topo_node_resource(core, &fmri, &perr) != 0) { whinge(mod, &nerr, "create_core: " "topo_node_resource failed\n"); perr = 0; } perr += nvlist_lookup_string(fmri, FM_FMRI_HC_PART, &part); perr += nvlist_lookup_string(fmri, FM_FMRI_HC_REVISION, &rev); if (perr != 0) { whinge(mod, NULL, "create_core: nvlist_lookup_string failed\n"); perr = 0; } perr += topo_prop_set_string(core, PGNAME(CORE), FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr); perr += topo_prop_set_string(core, PGNAME(CORE), FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr); perr += topo_prop_set_string(core, PGNAME(CORE), FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr); if (perr != 0) whinge(mod, NULL, "create_core: topo_prop_set_string" "failed\n"); nvlist_free(fmri); topo_mod_strfree(mod, serial); } err = create_strand(mod, core, cpu, auth, chip_smbiosid); return (err == 0 && nerr == 0 ? 0 : -1); }
/* create the disk topo node */ static int disk_tnode_create(topo_mod_t *mod, tnode_t *parent, dev_di_node_t *dnode, const char *name, topo_instance_t i, tnode_t **rval) { int len; nvlist_t *fmri; tnode_t *dtn; char *part = NULL; nvlist_t *auth; char *mfg, *model, *firm, *serial; *rval = NULL; if (dnode != NULL) { mfg = topo_mod_clean_str(mod, dnode->ddn_mfg); model = topo_mod_clean_str(mod, dnode->ddn_model); firm = topo_mod_clean_str(mod, dnode->ddn_firm); serial = topo_mod_clean_str(mod, dnode->ddn_serial); } else { mfg = model = firm = serial = NULL; } /* form 'part=' of fmri as "<mfg>-<model>" */ if (mfg != NULL && model != NULL) { len = strlen(mfg) + 1 + strlen(model) + 1; if ((part = topo_mod_alloc(mod, len)) != NULL) (void) snprintf(part, len, "%s-%s", mfg, model); } auth = topo_mod_auth(mod, parent); fmri = topo_mod_hcfmri(mod, parent, FM_HC_SCHEME_VERSION, name, i, NULL, auth, part ? part : model, firm, serial); nvlist_free(auth); topo_mod_strfree(mod, part); topo_mod_strfree(mod, mfg); topo_mod_strfree(mod, model); topo_mod_strfree(mod, firm); topo_mod_strfree(mod, serial); if (fmri == NULL) { topo_mod_dprintf(mod, "disk_tnode_create: " "hcfmri (%s%d/%s%d) error %s\n", topo_node_name(parent), topo_node_instance(parent), name, i, topo_strerror(topo_mod_errno(mod))); return (-1); } if ((dtn = topo_node_bind(mod, parent, name, i, fmri)) == NULL) { if (topo_mod_errno(mod) == EMOD_NODE_BOUND) { /* * if disk 0 is already there then we're done */ nvlist_free(fmri); return (0); } topo_mod_dprintf(mod, "disk_tnode_create: " "bind (%s%d/%s%d) error %s\n", topo_node_name(parent), topo_node_instance(parent), name, i, topo_strerror(topo_mod_errno(mod))); nvlist_free(fmri); return (-1); } nvlist_free(fmri); /* add the properties of the disk */ if (disk_set_props(mod, parent, dtn, dnode) != 0) { topo_mod_dprintf(mod, "disk_tnode_create: " "disk_set_props (%s%d/%s%d) error %s\n", topo_node_name(parent), topo_node_instance(parent), name, i, topo_strerror(topo_mod_errno(mod))); topo_node_unbind(dtn); return (-1); } if (dnode->ddn_devid != NULL && disk_add_temp_sensor(mod, dtn, dnode->ddn_devid) != 0) { topo_mod_dprintf(mod, "disk_tnode_create: failed to create " "temperature sensor node on bay=%d/disk=0", topo_node_instance(parent)); } *rval = dtn; return (0); }
/* * For each visited cpu node, call the callback function with its ASRU. */ static int cpu_walker(topo_mod_t *mod, tnode_t *node, void *pdata) { struct cpu_walk_data *swdp = pdata; nvlist_t *asru; int err, rc; /* * Terminate the walk if we reach start-node's sibling */ if (node != swdp->parent && topo_node_parent(node) == topo_node_parent(swdp->parent)) return (TOPO_WALK_TERMINATE); if (strcmp(topo_node_name(node), CPU) != 0 && strcmp(topo_node_name(node), STRAND) != 0) return (TOPO_WALK_NEXT); if (topo_node_asru(node, &asru, NULL, &err) != 0) { swdp->fail++; return (TOPO_WALK_NEXT); } rc = swdp->func(swdp->lhp, asru); /* * The "offline" and "online" counter are only useful for the "status" * callback. */ if (rc == P_OFFLINE || rc == P_FAULTED) { swdp->offline++; err = 0; } else if (rc == P_ONLINE) { swdp->online++; err = 0; } else { swdp->fail++; err = errno; } /* dump out status info if debug is turned on. */ if (getenv("TOPOCHIPDBG") != NULL || getenv("TOPOSUN4VPIDBG") != NULL) { const char *op; char *fmristr = NULL; if (swdp->func == ldom_fmri_retire) op = "retire"; else if (swdp->func == ldom_fmri_unretire) op = "unretire"; else if (swdp->func == ldom_fmri_status) op = "check status"; else op = "unknown op"; (void) topo_mod_nvl2str(mod, asru, &fmristr); topo_mod_dprintf(mod, "%s cpu (%s): rc = %d, err = %s\n", op, fmristr == NULL ? "unknown fmri" : fmristr, rc, strerror(err)); if (fmristr != NULL) topo_mod_strfree(mod, fmristr); } nvlist_free(asru); return (TOPO_WALK_NEXT); }
static int xaui_label_set(topo_mod_t *mod, tnode_t *node, topo_instance_t n, void *priv) { const char *label = NULL; char *plat, *pp; int err; int i, p; (void) xaui_get_pri_label(mod, n, priv, (char **)&label); if (label == NULL) { topo_mod_dprintf(mod, "no PRI node for label\n"); if (Phyxaui_Names == NULL) return (-1); if (topo_prop_get_string(node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT, &plat, &err) < 0) { return (topo_mod_seterrno(mod, err)); } /* * Trim SUNW, from the platform name */ pp = strchr(plat, ','); if (pp == NULL) pp = plat; else ++pp; for (p = 0; p < Phyxaui_Names->psn_nplats; p++) { if (strcmp(Phyxaui_Names->psn_names[p].pnm_platform, pp) != 0) continue; for (i = 0; i < Phyxaui_Names->psn_names[p].pnm_nnames; i++) { physnm_t ps; ps = Phyxaui_Names->psn_names[p].pnm_names[i]; if (ps.ps_num == n) { label = ps.ps_label; break; } } break; } topo_mod_strfree(mod, plat); } if (label != NULL) { if (topo_prop_set_string(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_LABEL, TOPO_PROP_IMMUTABLE, label, &err) != 0) { if (freeprilabel == 1) { topo_mod_strfree(mod, (char *)label); } return (topo_mod_seterrno(mod, err)); } if (freeprilabel == 1) { topo_mod_strfree(mod, (char *)label); } } return (0); }