static int amd_dramchan_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *auth) { tnode_t *chnode; nvlist_t *fmri; char *socket; int i, nchan; nvlist_t *pfmri = NULL; int err, nerr = 0; /* * We will enumerate the number of channels present even if only * channel A is in use (i.e., running in 64-bit mode). Only * the socket 754 package has a single channel. */ if (topo_prop_get_string(pnode, PGNAME(MCT), "socket", &socket, &err) == 0 && strcmp(socket, "Socket 754") == 0) nchan = 1; else nchan = 2; topo_mod_strfree(mod, socket); if (topo_node_range_create(mod, pnode, name, 0, nchan - 1) < 0) return (-1); (void) topo_node_fru(pnode, &pfmri, NULL, &err); for (i = 0; i < nchan; i++) { if (mkrsrc(mod, pnode, name, i, auth, &fmri) != 0) { whinge(mod, &nerr, "amd_dramchan_create: mkrsrc " "failed\n"); continue; } if ((chnode = topo_node_bind(mod, pnode, name, i, fmri)) == NULL) { nvlist_free(fmri); whinge(mod, &nerr, "amd_dramchan_create: node bind " "failed\n"); continue; } (void) topo_node_asru_set(chnode, fmri, 0, &err); if (pfmri) (void) topo_node_fru_set(chnode, pfmri, 0, &err); nvlist_free(fmri); (void) topo_pgroup_create(chnode, &chan_pgroup, &err); (void) topo_prop_set_string(chnode, PGNAME(CHAN), "channel", TOPO_PROP_IMMUTABLE, i == 0 ? "A" : "B", &err); } nvlist_free(pfmri); return (nerr == 0 ? 0 : -1); }
int disk_mptsas_find_disk(topo_mod_t *mod, tnode_t *baynode, char **sas_address) { char *devctl = NULL; uint32_t enclosure, slot; int err; char *elem, *lastp; int ret = -1; /* * Get the required properties from the node. These come from * the static XML mapping. */ if (topo_prop_get_string(baynode, TOPO_PGROUP_BINDING, TOPO_BINDING_DEVCTL, &devctl, &err) != 0 || topo_prop_get_uint32(baynode, TOPO_PGROUP_BINDING, TOPO_BINDING_ENCLOSURE, &enclosure, &err) != 0 || topo_prop_get_uint32(baynode, TOPO_PGROUP_BINDING, TOPO_BINDING_SLOT, &slot, &err) != 0) { if (devctl != NULL) topo_mod_strfree(mod, devctl); topo_mod_dprintf(mod, "bay node was missing mpt_sas binding " "properties\n"); return (-1); } /* * devctl is a (potentially) pipe-separated list of different device * paths to try. */ if ((elem = topo_mod_strsplit(mod, devctl, "|", &lastp)) != NULL) { boolean_t done = B_FALSE; do { topo_mod_dprintf(mod, "trying mpt_sas instance at %s\n", elem); ret = get_sas_address(mod, elem, enclosure, slot, sas_address); /* * Only try further devctl paths from the list if this * one was not found: */ if (ret == 0 || errno != ENOENT) { done = B_TRUE; } else { topo_mod_dprintf(mod, "instance not found\n"); } topo_mod_strfree(mod, elem); } while (!done && (elem = topo_mod_strsplit(mod, NULL, "|", &lastp)) != NULL); } topo_mod_strfree(mod, devctl); return (ret); }
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 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); }
int pcifn_enum(topo_mod_t *mp, tnode_t *parent) { char *ccstr; int rv = 0; int i, e; uint_t cc; topo_mod_t *child_mod; topo_mod_dprintf(mp, "Enumerating beneath pci(ex) function.\n"); /* * Extract the class code of the PCI function and make sure * it matches the type that the module cares about. */ if (topo_prop_get_string(parent, TOPO_PGROUP_PCI, TOPO_PROP_CLASS, &ccstr, &e) < 0) return (0); if (sscanf(ccstr, "%x", &cc) != 1) { topo_mod_strfree(mp, ccstr); return (0); } topo_mod_strfree(mp, ccstr); cc = cc >> 16; for (i = 0; i < Pcifn_enumerator_count; i++) { if (cc != Pcifn_enumerators[i].pfne_class) continue; child_mod = module_load(mp, parent, Pcifn_enumerators[i].pfne_modname); if (child_mod) { rv = module_run(mp, parent, &Pcifn_enumerators[i]) != 0 ? -1 : 0; topo_mod_unload(child_mod); } } return (rv); }
static int topo_add_bay(topo_hdl_t *thp, tnode_t *node, walk_diskmon_t *wdp) { diskmon_t *target_diskp = wdp->target; nvlist_t *nvlp = find_disk_monitor_private_pgroup(node); nvlist_t *prop_nvlp; nvpair_t *nvp = NULL; char *prop_name, *prop_value; #define PNAME_MAX 128 char pname[PNAME_MAX]; char msgbuf[MAX_CONF_MSG_LEN]; char *indicator_name, *indicator_action; char *indrule_states, *indrule_actions; int err = 0, i; conf_err_t conferr; boolean_t conf_failure = B_FALSE; char *unadj_physid = NULL; char physid[MAXPATHLEN]; char *label; nvlist_t *diskprops = NULL; char *cstr = NULL; indicator_t *indp = NULL; indrule_t *indrp = NULL; void *p; diskmon_t *diskp; void *ptr; /* No private properties -- just ignore the port */ if (nvlp == NULL) return (0); /* * Look for a diskmon based on this node's FMRI string. * Once a diskmon has been created, it's not re-created. This is * essential for the times when the tree-walk is called after a * disk is inserted (or removed) -- in that case, the disk node * handler simply updates the FRU information in the diskmon. */ if ((p = fmri2ptr(thp, node, &cstr, &err)) != NULL) { diskp = (diskmon_t *)p; /* * Delete the FRU information from the diskmon. If a disk * is connected, its FRU information will be refreshed by * the disk node code. */ if (diskp->frup && (target_diskp == NULL || diskp == target_diskp)) { dm_assert(pthread_mutex_lock(&diskp->fru_mutex) == 0); dmfru_free(diskp->frup); diskp->frup = NULL; dm_assert(pthread_mutex_unlock(&diskp->fru_mutex) == 0); } wdp->pfmri = cstr; nvlist_free(nvlp); return (0); } /* * Determine the physical path to the attachment point */ if (topo_prop_get_string(node, TOPO_PGROUP_IO, TOPO_IO_AP_PATH, &unadj_physid, &err) == 0) { adjust_dynamic_ap(unadj_physid, physid); topo_hdl_strfree(thp, unadj_physid); } else { /* unadj_physid cannot have been allocated */ if (cstr) dstrfree(cstr); nvlist_free(nvlp); return (-1); } /* */ /* * Process the properties. If we encounter a property that * is not an indicator name, action, or rule, add it to the * disk's props list. */ /* Process indicators */ i = 0; indicator_name = NULL; indicator_action = NULL; do { if (indicator_name != NULL && indicator_action != NULL) { if (topoprop_indicator_add(&indp, indicator_name, indicator_action) != 0) { conf_failure = B_TRUE; } topo_hdl_strfree(thp, indicator_name); topo_hdl_strfree(thp, indicator_action); } (void) snprintf(pname, PNAME_MAX, BAY_IND_NAME "-%d", i); if (topo_prop_get_string(node, DISK_MONITOR_PROPERTIES, pname, &indicator_name, &err) != 0) break; (void) snprintf(pname, PNAME_MAX, BAY_IND_ACTION "-%d", i); if (topo_prop_get_string(node, DISK_MONITOR_PROPERTIES, pname, &indicator_action, &err) != 0) break; i++; } while (!conf_failure && indicator_name != NULL && indicator_action != NULL); if (!conf_failure && indp != NULL && (conferr = check_inds(indp)) != E_NO_ERROR) { conf_error_msg(conferr, msgbuf, MAX_CONF_MSG_LEN, NULL); log_msg(MM_CONF, "%s: Not adding disk to list\n", msgbuf); conf_failure = B_TRUE; } /* Process state rules and indicator actions */ i = 0; indrule_states = NULL; indrule_actions = NULL; do { if (indrule_states != NULL && indrule_actions != NULL) { if (topoprop_indrule_add(&indrp, indrule_states, indrule_actions) != 0) { conf_failure = B_TRUE; } topo_hdl_strfree(thp, indrule_states); topo_hdl_strfree(thp, indrule_actions); } (void) snprintf(pname, PNAME_MAX, BAY_INDRULE_STATES "-%d", i); if (topo_prop_get_string(node, DISK_MONITOR_PROPERTIES, pname, &indrule_states, &err) != 0) break; (void) snprintf(pname, PNAME_MAX, BAY_INDRULE_ACTIONS "-%d", i); if (topo_prop_get_string(node, DISK_MONITOR_PROPERTIES, pname, &indrule_actions, &err) != 0) break; i++; } while (!conf_failure && indrule_states != NULL && indrule_actions != NULL); if (!conf_failure && indrp != NULL && indp != NULL && ((conferr = check_indrules(indrp, (state_transition_t **)&ptr)) != E_NO_ERROR || (conferr = check_consistent_ind_indrules(indp, indrp, (ind_action_t **)&ptr)) != E_NO_ERROR)) { conf_error_msg(conferr, msgbuf, MAX_CONF_MSG_LEN, ptr); log_msg(MM_CONF, "%s: Not adding disk to list\n", msgbuf); conf_failure = B_TRUE; } /* * Now collect miscellaneous properties. * Each property is stored as an embedded nvlist named * TOPO_PROP_VAL. The property name is stored in the value for * key=TOPO_PROP_VAL_NAME and the property's value is * stored in the value for key=TOPO_PROP_VAL_VAL. This is all * necessary so we can subtractively decode the properties that * we do not directly handle (so that these properties are added to * the per-disk properties nvlist), increasing flexibility. */ (void) nvlist_alloc(&diskprops, NV_UNIQUE_NAME, 0); while ((nvp = nvlist_next_nvpair(nvlp, nvp)) != NULL) { /* Only care about embedded nvlists named TOPO_PROP_VAL */ if (nvpair_type(nvp) != DATA_TYPE_NVLIST || strcmp(nvpair_name(nvp), TOPO_PROP_VAL) != 0 || nvpair_value_nvlist(nvp, &prop_nvlp) != 0) continue; if (nonunique_nvlist_lookup_string(prop_nvlp, TOPO_PROP_VAL_NAME, &prop_name) != 0) continue; /* Filter out indicator properties */ if (strstr(prop_name, BAY_IND_NAME) != NULL || strstr(prop_name, BAY_IND_ACTION) != NULL || strstr(prop_name, BAY_INDRULE_STATES) != NULL || strstr(prop_name, BAY_INDRULE_ACTIONS) != NULL) continue; if (nonunique_nvlist_lookup_string(prop_nvlp, TOPO_PROP_VAL_VAL, &prop_value) != 0) continue; /* Add the property to the disk's prop list: */ if (nvlist_add_string(diskprops, prop_name, prop_value) != 0) log_msg(MM_TOPO, "Could not add disk property `%s' with " "value `%s'\n", prop_name, prop_value); } nvlist_free(nvlp); if (cstr != NULL) { namevalpr_t nvpr; nvlist_t *dmap_nvl; nvpr.name = DISK_AP_PROP_APID; nvpr.value = strncmp(physid, "/devices", 8) == 0 ? (physid + 8) : physid; /* * Set the diskmon's location to the value in this port's label. * If there's a disk plugged in, the location will be updated * to be the disk label (e.g. HD_ID_00). Until a disk is * inserted, though, there won't be a disk libtopo node * created. */ /* Pass physid without the leading "/devices": */ dmap_nvl = namevalpr_to_nvlist(&nvpr); diskp = new_diskmon(dmap_nvl, indp, indrp, diskprops); if (topo_node_label(node, &label, &err) == 0) { diskp->location = dstrdup(label); topo_hdl_strfree(thp, label); } else diskp->location = dstrdup("unknown location"); if (!conf_failure && diskp != NULL) { /* Add this diskmon to the disk list */ cfgdata_add_diskmon(config_data, diskp); if (nvlist_add_uint64(g_topo2diskmon, cstr, (uint64_t)(uintptr_t)diskp) != 0) { log_msg(MM_TOPO, "Could not add pointer to nvlist " "for `%s'!\n", cstr); } } else if (diskp != NULL) { diskmon_free(diskp); } else { if (dmap_nvl) nvlist_free(dmap_nvl); if (indp) ind_free(indp); if (indrp) indrule_free(indrp); if (diskprops) nvlist_free(diskprops); } wdp->pfmri = cstr; } return (0); }
static int topo_add_disk(topo_hdl_t *thp, tnode_t *node, walk_diskmon_t *wdp) { diskmon_t *target_diskp = wdp->target; char *devpath = NULL; char *capacity = NULL; char *firmrev = NULL; char *serial = NULL; char *manuf = NULL; char *model = NULL; char *label; uint64_t ptr = 0; int err; dm_fru_t *frup; diskmon_t *diskp; if (wdp->pfmri == NULL) { log_msg(MM_TOPO, "No diskmon for parent of node %p.\n", node); return (0); } if (nvlist_lookup_uint64(g_topo2diskmon, wdp->pfmri, &ptr) != 0) { log_msg(MM_TOPO, "No diskmon for %s: parent of node %p.\n", wdp->pfmri, node); dstrfree(wdp->pfmri); /* Skip this disk: */ return (0); } dstrfree(wdp->pfmri); wdp->pfmri = NULL; diskp = (diskmon_t *)(uintptr_t)ptr; /* If we were called upon to update a particular disk, do it */ if (target_diskp != NULL && diskp != target_diskp) { return (0); } /* * Update the diskmon's location field with the disk's label */ if (diskp->location) dstrfree(diskp->location); if (topo_node_label(node, &label, &err) == 0) { diskp->location = dstrdup(label); topo_hdl_strfree(thp, label); } else diskp->location = dstrdup("unknown location"); /* * Check for a device path property (if the disk is configured, * it will be present) and add it to the diskmon's properties) */ if (topo_prop_get_string(node, TOPO_PGROUP_IO, TOPO_IO_DEV_PATH, &devpath, &err) == 0) { char devp[PATH_MAX]; /* * Consumers of the DISK_PROP_DEVPATH property expect a raw * minor device node */ (void) snprintf(devp, PATH_MAX, "%s:q,raw", devpath); (void) nvlist_add_string(diskp->props, DISK_PROP_DEVPATH, devp); topo_hdl_strfree(thp, devpath); } /* * Add the logical disk node, if it exists */ if (topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_LOGICAL_DISK_NAME, &devpath, &err) == 0) { (void) nvlist_add_string(diskp->props, DISK_PROP_LOGNAME, devpath); topo_hdl_strfree(thp, devpath); } /* * Add the FRU information (if present in the node) to the diskmon's * fru data structure: */ (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_MODEL, &model, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_MANUFACTURER, &manuf, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_SERIAL_NUM, &serial, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_FIRMWARE_REV, &firmrev, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_CAPACITY, &capacity, &err); frup = new_dmfru(manuf, model, firmrev, serial, capacity == NULL ? 0 : strtoull(capacity, 0, 0)); if (model) topo_hdl_strfree(thp, model); if (manuf) topo_hdl_strfree(thp, manuf); if (serial) topo_hdl_strfree(thp, serial); if (firmrev) topo_hdl_strfree(thp, firmrev); if (capacity) topo_hdl_strfree(thp, capacity); /* Add the fru information to the diskmon: */ dm_assert(pthread_mutex_lock(&diskp->fru_mutex) == 0); dm_assert(diskp->frup == NULL); diskp->frup = frup; dm_assert(pthread_mutex_unlock(&diskp->fru_mutex) == 0); return (0); }
static int topo_add_disk(topo_hdl_t *thp, tnode_t *node, diskmon_t *target_diskp) { nvlist_t *fmri = NULL; nvlist_t *asru_fmri; nvlist_t *fru_fmri; char *devpath = NULL; char *capacity = NULL; char *firmrev = NULL; char *serial = NULL; char *manuf = NULL; char *model = NULL; char *cstr = NULL; char *buf; char *label; char *p; uint64_t ptr = 0; int buflen; int err; int orig_cstr_len; dm_fru_t *frup; diskmon_t *diskp; /* * Match this node to a disk in the configuration by looking at * our parent's fmri (and do that by getting our FMRI and chopping * off the last part). */ if (topo_node_resource(node, &fmri, &err) != 0) { log_msg(MM_TOPO, "topo_add_disk: Could not generate FMRI for " "node %p!\n", (void *)node); return (-1); } if (topo_fmri_nvl2str(thp, fmri, &cstr, &err) != 0) { log_msg(MM_TOPO, "topo_add_disk: Could not create string for " "node %p's FMRI!\n", (void *)node); nvlist_free(fmri); return (-1); } nvlist_free(fmri); /* * Chop off all but last path (since there's no way to get * the node's parent in the libtopo API). */ orig_cstr_len = strlen(cstr) + 1; p = strrchr(cstr, '/'); dm_assert(p != NULL); *p = 0; if (nvlist_lookup_uint64(g_topo2diskmon, cstr, &ptr) != 0) { log_msg(MM_TOPO, "No diskmon for parent of node %p.\n", node); topo_hdl_free(thp, cstr, orig_cstr_len); /* Skip this disk: */ return (0); } topo_hdl_free(thp, cstr, orig_cstr_len); diskp = (diskmon_t *)(uintptr_t)ptr; /* If we were called upon to update a particular disk, do it */ if (target_diskp != NULL && diskp != target_diskp) { return (0); } /* * Update the diskmon's ASRU and FRU with our information (this * information is cached in the diskmon so we don't have to do a * time-consuming topo traversal when we get an ereport). */ if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_ASRU, &asru_fmri, &err) == 0) { diskmon_add_asru(diskp, asru_fmri); nvlist_free(asru_fmri); } if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_FRU, &fru_fmri, &err) == 0) { diskmon_add_fru(diskp, fru_fmri); nvlist_free(fru_fmri); } if (topo_node_resource(node, &fmri, &err) == 0) { diskmon_add_disk_fmri(diskp, fmri); nvlist_free(fmri); } /* * Update the diskmon's location field with the disk's label */ if (diskp->location) dstrfree(diskp->location); if (topo_node_label(node, &label, &err) == 0) { diskp->location = dstrdup(label); topo_hdl_strfree(thp, label); } else diskp->location = dstrdup("unknown location"); /* * Check for a device path property (if the disk is configured, * it will be present) and add it to the diskmon's properties) */ if (topo_prop_get_string(node, TOPO_PGROUP_IO, TOPO_IO_DEV_PATH, &devpath, &err) == 0) { char devp[PATH_MAX]; /* * Consumers of the DISK_PROP_DEVPATH property expect a raw * minor device node */ (void) snprintf(devp, PATH_MAX, "%s:q,raw", devpath); (void) nvlist_add_string(diskp->props, DISK_PROP_DEVPATH, devp); topo_hdl_strfree(thp, devpath); } /* * Add the logical disk node, if it exists */ if (topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_LOGICAL_DISK_NAME, &devpath, &err) == 0) { (void) nvlist_add_string(diskp->props, DISK_PROP_LOGNAME, devpath); topo_hdl_strfree(thp, devpath); } /* * Add the FRU information (if present in the node) to the diskmon's * fru data structure: */ (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_MODEL, &model, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_MANUFACTURER, &manuf, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_SERIAL_NUM, &serial, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_FIRMWARE_REV, &firmrev, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_CAPACITY, &capacity, &err); frup = new_dmfru(manuf, model, firmrev, serial, capacity == NULL ? 0 : strtoull(capacity, 0, 0)); /* * Update the disk's resource FMRI with the * SunService-required members: * FM_FMRI_HC_SERIAL_ID, FM_FMRI_HC_PART, and * FM_FMRI_HC_REVISION */ (void) nvlist_add_string(diskp->disk_res_fmri, FM_FMRI_HC_SERIAL_ID, serial); transform_model_string(manuf, model, &buf, &buflen); (void) nvlist_add_string(diskp->disk_res_fmri, FM_FMRI_HC_PART, buf); /* * Add the serial number to the ASRU so that when the resource * is marked faulty in the fmd resource cache, the hc scheme * plugin can detect when the disk is no longer installed (and so, * can clear the faulty state automatically across fmd restarts). * * The serial number is only updated when a disk comes online * because that's when the disk node exists in the topo tree. * It's ok to keep a stale value in the ASRU when the disk is removed * because it's only used as part of fault creation when the disk * is configured (online), at which point it will be updated with * the (current) serial number of the disk inserted. */ (void) nvlist_add_string(diskp->asru_fmri, FM_FMRI_HC_SERIAL_ID, serial); dfree(buf, buflen); (void) nvlist_add_string(diskp->disk_res_fmri, FM_FMRI_HC_REVISION, firmrev); if (model) { topo_hdl_strfree(thp, model); } if (manuf) { topo_hdl_strfree(thp, manuf); } if (serial) { topo_hdl_strfree(thp, serial); } if (firmrev) { topo_hdl_strfree(thp, firmrev); } if (capacity) { topo_hdl_strfree(thp, capacity); } /* Add the fru information to the diskmon: */ dm_assert(pthread_mutex_lock(&diskp->fru_mutex) == 0); dm_assert(diskp->frup == NULL); diskp->frup = frup; dm_assert(pthread_mutex_unlock(&diskp->fru_mutex) == 0); 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); }
/* * 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); }
/*ARGSUSED*/ static int do_slot_mapping_cb(topo_hdl_t *thp, tnode_t *node, void *arg) { int err, ret; nvlist_t *rsrc = NULL; const char *match = arg; char *s, *fmri = NULL; char *didstr = NULL, *driver = NULL, *vidstr = NULL; boolean_t printed = B_FALSE; ret = TOPO_WALK_NEXT; if (topo_node_resource(node, &rsrc, &err) < 0) goto next; if (topo_fmri_nvl2str(thp, rsrc, &fmri, &err) < 0) goto next; if ((s = strstr(fmri, match)) == NULL) goto next; if (s[strlen(match)] != '\0') goto next; /* At this point we think we've found a match */ ret = TOPO_WALK_TERMINATE; if (topo_prop_get_string(node, TOPO_PGROUP_IO, TOPO_IO_DRIVER, &driver, &err) != 0) driver = NULL; if (topo_prop_get_string(node, TOPO_PGROUP_PCI, TOPO_PCI_VENDID, &vidstr, &err) != 0) goto next; if (topo_prop_get_string(node, TOPO_PGROUP_PCI, TOPO_PCI_DEVID, &didstr, &err) != 0) goto next; if (prt_php != NULL) { long vid, did; vid = strtol(vidstr, NULL, 16); did = strtol(didstr, NULL, 16); if (vid >= 0 && vid <= UINT16_MAX && did >= 0 && did <= UINT16_MAX) { pcidb_device_t *pdev; pdev = pcidb_lookup_device(prt_php, vid, did); if (pdev != NULL) { pcidb_vendor_t *pvend; pvend = pcidb_device_vendor(pdev); (void) printf(gettext(", %s %s (%s)"), pcidb_vendor_name(pvend), pcidb_device_name(pdev), driver != NULL ? driver : "<unknown>"); printed = B_TRUE; } } } if (printed == B_FALSE) { (void) printf(gettext(", pci%s,%s (%s)"), vidstr, didstr, driver != NULL ? driver : "<unknown>"); } next: topo_hdl_strfree(thp, didstr); topo_hdl_strfree(thp, driver); topo_hdl_strfree(thp, vidstr); topo_hdl_strfree(thp, fmri); nvlist_free(rsrc); return (ret); }
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 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); }
static int xml_read(topo_hdl_t *hp, ttree_t *tp) { topo_file_t *tfp; char *pplat, *pmach; int err, e; char _topo_file[MAXNAMELEN * 2]; char _topo_path[PATH_MAX]; tfp = (topo_file_t *)tp->tt_file; (void) snprintf(_topo_file, 2 * MAXNAMELEN, TOPO_DEFAULT_FILE, tp->tt_scheme); /* * Look for a platform-specific topology file first */ e = topo_prop_get_string(tp->tt_root, TOPO_PGROUP_SYSTEM, TOPO_PROP_PLATFORM, &pplat, &err); if (e < 0) return (topo_hdl_seterrno(hp, err)); (void) snprintf(_topo_path, PATH_MAX, PLATFORM_TOPO_PATH, hp->th_rootdir, pplat, _topo_file); tfp->tf_fileinfo = topo_xml_read(tfp->tf_mod, _topo_path, tp->tt_scheme); if (tfp->tf_fileinfo != NULL) { topo_hdl_strfree(hp, pplat); return (0); } topo_dprintf(TOPO_DBG_MOD, "failed to load topology file %s: %s\n", _topo_path, topo_strerror(topo_hdl_errno(hp))); /* * No luck with the platform-specific file, how about a * machine-specific one? */ e = topo_prop_get_string(tp->tt_root, TOPO_PGROUP_SYSTEM, TOPO_PROP_MACHINE, &pmach, &err); if (e < 0) { topo_hdl_strfree(hp, pplat); return (topo_hdl_seterrno(hp, err)); } /* * Don't waste time trying to open the same file twice in the * cases where the platform name is identical to the machine * name */ if (strcmp(pplat, pmach) != 0) { (void) snprintf(_topo_path, PATH_MAX, PLATFORM_TOPO_PATH, hp->th_rootdir, pmach, _topo_file); tfp->tf_fileinfo = topo_xml_read(tfp->tf_mod, _topo_path, tp->tt_scheme); } if (tfp->tf_fileinfo != NULL) { topo_hdl_strfree(hp, pplat); topo_hdl_strfree(hp, pmach); return (0); } else { topo_dprintf(TOPO_DBG_MOD, "failed to load topology file %s: %s\n", _topo_path, topo_strerror(topo_hdl_errno(hp))); } topo_hdl_strfree(hp, pplat); topo_hdl_strfree(hp, pmach); (void) snprintf(_topo_path, PATH_MAX, COMMON_TOPO_PATH, hp->th_rootdir, _topo_file); tfp->tf_fileinfo = topo_xml_read(tfp->tf_mod, _topo_path, tp->tt_scheme); if (tfp->tf_fileinfo == NULL) { topo_dprintf(TOPO_DBG_MOD, "failed to load topology file %s: %s\n", _topo_path, topo_strerror(topo_hdl_errno(hp))); return (topo_hdl_seterrno(hp, ETOPO_FILE_NOENT)); } return (0); }