diff options
author | Matthias Scheler <matthias.scheler@wdc.com> | 2019-11-04 15:41:15 +0000 |
---|---|---|
committer | Dan McDonald <danmcd@joyent.com> | 2019-11-09 18:56:18 -0500 |
commit | 985366be3b9cf10a0fd786cf0d9c1a6558c2b596 (patch) | |
tree | 92b8747cc32beeee3eeb3b96798808a09e638162 /usr/src/lib/fm | |
parent | 42cd19316c818c8b8283fc48263a1b4ce99cf049 (diff) | |
download | illumos-gate-985366be3b9cf10a0fd786cf0d9c1a6558c2b596.tar.gz |
11818 IPMI topo plugin shouldn't return data from unavailable sensors
Reviewed by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
Reviewed by: Paul Winder <paul@winders.demon.co.uk>
Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src/lib/fm')
-rw-r--r-- | usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c | 8 | ||||
-rw-r--r-- | usr/src/lib/fm/topo/modules/common/ipmi/ipmi_enum.c | 249 |
2 files changed, 193 insertions, 64 deletions
diff --git a/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c b/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c index 64309245b0..b85395990a 100644 --- a/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c +++ b/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c @@ -24,6 +24,7 @@ */ /* * Copyright (c) 2019, Joyent, Inc. + * Copyright 2019 by Western Digital Corporation */ #include <unistd.h> #include <stdio.h> @@ -427,6 +428,13 @@ ipmi_sensor_state(topo_mod_t *mod, tnode_t *node, topo_version_t vers, topo_mod_ipmi_rele(mod); return (-1); } + if (reading->isr_state_unavailable) { + topo_mod_dprintf(mod, "Unavailable sensor %s, sensor_num=%d\n", + entity_refs[i], sensor_num); + strarr_free(mod, entity_refs, nelems); + topo_mod_ipmi_rele(mod); + return (-1); + } strarr_free(mod, entity_refs, nelems); topo_mod_ipmi_rele(mod); diff --git a/usr/src/lib/fm/topo/modules/common/ipmi/ipmi_enum.c b/usr/src/lib/fm/topo/modules/common/ipmi/ipmi_enum.c index ef7a2d23ac..32b555a3bd 100644 --- a/usr/src/lib/fm/topo/modules/common/ipmi/ipmi_enum.c +++ b/usr/src/lib/fm/topo/modules/common/ipmi/ipmi_enum.c @@ -22,6 +22,7 @@ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, Joyent, Inc. + * Copyright 2019 by Western Digital Corporation */ #include <assert.h> @@ -30,7 +31,7 @@ #include <sys/fm/protocol.h> #include <string.h> -#define TOPO_PGROUP_IPMI "ipmi" +#define TOPO_PGROUP_IPMI "ipmi" #define TOPO_PROP_IPMI_ENTITY_REF "entity_ref" #define TOPO_PROP_IPMI_ENTITY_PRESENT "entity_present" #define FAC_PROV_IPMI "fac_prov_ipmi" @@ -47,6 +48,8 @@ typedef struct ipmi_enum_data { static int ipmi_present(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, nvlist_t **); +static int ipmi_unusable(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, + nvlist_t **); static int ipmi_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t, topo_instance_t, void *, void *); static int ipmi_post_process(topo_mod_t *, tnode_t *); @@ -60,6 +63,9 @@ extern int ipmi_fru_fmri(topo_mod_t *mod, tnode_t *node, static const topo_method_t ipmi_methods[] = { { TOPO_METH_PRESENT, TOPO_METH_PRESENT_DESC, TOPO_METH_PRESENT_VERSION0, TOPO_STABILITY_INTERNAL, ipmi_present }, + { TOPO_METH_UNUSABLE, TOPO_METH_UNUSABLE_DESC, + TOPO_METH_UNUSABLE_VERSION, TOPO_STABILITY_INTERNAL, + ipmi_unusable }, { "ipmi_fru_label", "Property method", 0, TOPO_STABILITY_INTERNAL, ipmi_fru_label}, { "ipmi_fru_fmri", "Property method", 0, @@ -75,91 +81,111 @@ const topo_modops_t ipmi_ops = { ipmi_enum, NULL }; const topo_modinfo_t ipmi_info = { "ipmi", FM_FMRI_SCHEME_HC, TOPO_VERSION, &ipmi_ops }; -/* - * Determine if the entity is present. - */ -/*ARGSUSED*/ +/* Common code used by topo methods below to find an IPMI entity */ static int -ipmi_present(topo_mod_t *mod, tnode_t *tn, topo_version_t version, - nvlist_t *in, nvlist_t **out) +ipmi_find_entity(topo_mod_t *mod, tnode_t *tn, ipmi_handle_t **ihpp, + ipmi_entity_t **epp, char **namep, ipmi_sdr_t **sdrpp) { ipmi_handle_t *ihp; ipmi_entity_t *ep; - boolean_t present; - nvlist_t *nvl; - int err, i; - char *name, **names; - ipmi_sdr_t *sdrp; - uint_t nelems; + int err; + char *name = NULL, **names; + ipmi_sdr_t *sdrp = NULL; + uint_t nelems, i; + + *ihpp = NULL; + *epp = NULL; + *namep = NULL; + *sdrpp = NULL; if ((ihp = topo_mod_ipmi_hold(mod)) == NULL) return (topo_mod_seterrno(mod, ETOPO_METHOD_UNKNOWN)); ep = topo_node_getspecific(tn); - if (ep == NULL) { - if (topo_prop_get_string(tn, TOPO_PGROUP_IPMI, - TOPO_PROP_IPMI_ENTITY_PRESENT, &name, &err) == 0) { + if (ep != NULL) { + *ihpp = ihp; + *epp = ep; + return (0); + } + + if (topo_prop_get_string(tn, TOPO_PGROUP_IPMI, + TOPO_PROP_IPMI_ENTITY_PRESENT, &name, &err) == 0) { + /* + * Some broken IPMI implementations don't export correct + * entities, so referring to an entity isn't sufficient. + * For these platforms, we allow the XML to specify a + * single SDR record that represents the current present + * state. + */ + sdrp = ipmi_sdr_lookup(ihp, name); + } else { + if (topo_prop_get_string_array(tn, TOPO_PGROUP_IPMI, + TOPO_PROP_IPMI_ENTITY_REF, &names, &nelems, &err) != 0) { /* - * Some broken IPMI implementations don't export correct - * entities, so referring to an entity isn't sufficient. - * For these platforms, we allow the XML to specify a - * single SDR record that represents the current present - * state. + * Not all nodes have an entity_ref attribute. + * For these cases, return ENOTSUP so that we + * fall back to the default hc presence + * detection. */ - if ((sdrp = ipmi_sdr_lookup(ihp, name)) == NULL || - ipmi_entity_present_sdr(ihp, sdrp, &present) != 0) { - topo_mod_dprintf(mod, - "Failed to get present state of %s (%s)\n", - name, ipmi_errmsg(ihp)); - topo_mod_strfree(mod, name); - topo_mod_ipmi_rele(mod); - return (-1); - } + topo_mod_ipmi_rele(mod); + return (topo_mod_seterrno(mod, ETOPO_METHOD_NOTSUP)); + } - topo_mod_dprintf(mod, - "ipmi_entity_present_sdr(%s) = %d\n", name, - present); - topo_mod_strfree(mod, name); - } else { - if (topo_prop_get_string_array(tn, TOPO_PGROUP_IPMI, - TOPO_PROP_IPMI_ENTITY_REF, &names, &nelems, &err) - != 0) { - /* - * Not all nodes have an entity_ref attribute. - * For these cases, return ENOTSUP so that we - * fall back to the default hc presence - * detection. - */ - topo_mod_ipmi_rele(mod); - return (topo_mod_seterrno(mod, - ETOPO_METHOD_NOTSUP)); + for (i = 0; i < nelems; i++) { + if ((ep = ipmi_entity_lookup_sdr(ihp, names[i])) + != NULL) { + name = names[i]; + names[i] = NULL; + break; } + } - for (i = 0; i < nelems; i++) - if ((ep = ipmi_entity_lookup_sdr(ihp, names[i])) - != NULL) - break; - - for (i = 0; i < nelems; i++) - topo_mod_strfree(mod, names[i]); - topo_mod_free(mod, names, (nelems * sizeof (char *))); - - if (ep == NULL) { - topo_mod_dprintf(mod, - "Failed to get present state of %s=%d\n", - topo_node_name(tn), topo_node_instance(tn)); - topo_mod_ipmi_rele(mod); - return (-1); - } - topo_node_setspecific(tn, ep); + for (i = 0; i < nelems; i++) + topo_mod_strfree(mod, names[i]); + topo_mod_free(mod, names, (nelems * sizeof (char *))); + + if (ep == NULL) { + topo_mod_dprintf(mod, + "Failed to get present state of %s=%d\n", + topo_node_name(tn), topo_node_instance(tn)); + topo_mod_ipmi_rele(mod); + return (-1); } + topo_node_setspecific(tn, ep); } + *ihpp = ihp; + *namep = name; + *sdrpp = sdrp; + return (0); +} + +/* + * Determine if the entity is present. + */ +/*ARGSUSED*/ +static int +ipmi_present(topo_mod_t *mod, tnode_t *tn, topo_version_t version, + nvlist_t *in, nvlist_t **out) +{ + ipmi_handle_t *ihp; + ipmi_entity_t *ep; + char *name; + ipmi_sdr_t *sdrp; + int err; + boolean_t present = B_FALSE; + nvlist_t *nvl; + + err = ipmi_find_entity(mod, tn, &ihp, &ep, &name, &sdrp); + if (err != 0) + return (err); + if (ep != NULL) { if (ipmi_entity_present(ihp, ep, &present) != 0) { topo_mod_dprintf(mod, "ipmi_entity_present() failed: %s", ipmi_errmsg(ihp)); + topo_mod_strfree(mod, name); topo_mod_ipmi_rele(mod); return (-1); } @@ -167,8 +193,21 @@ ipmi_present(topo_mod_t *mod, tnode_t *tn, topo_version_t version, topo_mod_dprintf(mod, "ipmi_entity_present(%d, %d) = %d\n", ep->ie_type, ep->ie_instance, present); + } else if (sdrp != NULL) { + if (ipmi_entity_present_sdr(ihp, sdrp, &present) != 0) { + topo_mod_dprintf(mod, + "Failed to get present state of %s (%s)\n", + name, ipmi_errmsg(ihp)); + topo_mod_strfree(mod, name); + topo_mod_ipmi_rele(mod); + return (-1); + } + + topo_mod_dprintf(mod, "ipmi_entity_present_sdr(%s) = %d\n", + name, present); } + topo_mod_strfree(mod, name); topo_mod_ipmi_rele(mod); if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0) @@ -185,6 +224,88 @@ ipmi_present(topo_mod_t *mod, tnode_t *tn, topo_version_t version, } /* + * Check whether an IPMI entity is a sensor that is unavailable + */ +static int +ipmi_check_sensor(ipmi_handle_t *ihp, ipmi_entity_t *ep, const char *name, + ipmi_sdr_t *sdrp, void *data) +{ + ipmi_sdr_full_sensor_t *fsp; + ipmi_sdr_compact_sensor_t *csp; + uint8_t sensor_number; + ipmi_sensor_reading_t *reading; + + switch (sdrp->is_type) { + case IPMI_SDR_TYPE_FULL_SENSOR: + fsp = (ipmi_sdr_full_sensor_t *)sdrp->is_record; + sensor_number = fsp->is_fs_number; + break; + + case IPMI_SDR_TYPE_COMPACT_SENSOR: + csp = (ipmi_sdr_compact_sensor_t *)sdrp->is_record; + sensor_number = csp->is_cs_number; + break; + + default: + return (0); + } + + reading = ipmi_get_sensor_reading(ihp, sensor_number); + if (reading != NULL && reading->isr_state_unavailable) + return (1); + + return (0); +} + +/* + * Determine if the entity is unusable + */ +/*ARGSUSED*/ +static int +ipmi_unusable(topo_mod_t *mod, tnode_t *tn, topo_version_t version, + nvlist_t *in, nvlist_t **out) +{ + ipmi_handle_t *ihp; + ipmi_entity_t *ep; + char *name; + ipmi_sdr_t *sdrp; + int err; + boolean_t unusable = B_FALSE; + nvlist_t *nvl; + + err = ipmi_find_entity(mod, tn, &ihp, &ep, &name, &sdrp); + if (err != 0) + return (err); + + /* + * Check whether the IPMI presented us with an entity for a + * sensor that is unavailable. + */ + if (ep != NULL) { + unusable = (ipmi_entity_iter_sdr(ihp, ep, ipmi_check_sensor, + NULL) != 0); + } else if (sdrp != NULL) { + unusable = (ipmi_check_sensor(ihp, NULL, NULL, sdrp, + NULL) != 0); + } + + topo_mod_strfree(mod, name); + topo_mod_ipmi_rele(mod); + + if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0) + return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); + + if (nvlist_add_uint32(nvl, TOPO_METH_UNUSABLE_RET, unusable) != 0) { + nvlist_free(nvl); + return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); + } + + *out = nvl; + + return (0); +} + +/* * This determines if the entity has a FRU locator record set, in which case we * treat this as a FRU, even if it's part of an association. */ |