summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/lib/fm/topo/modules/common/disk/disk_common.c4
-rw-r--r--usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c147
-rw-r--r--usr/src/lib/fm/topo/modules/common/ipmi/ipmi_enum.c6
-rw-r--r--usr/src/lib/fm/topo/modules/common/ses/ses.c21
-rw-r--r--usr/src/lib/fm/topo/modules/common/ses/ses.h2
-rw-r--r--usr/src/lib/fm/topo/modules/common/ses/ses_facility.c2
6 files changed, 164 insertions, 18 deletions
diff --git a/usr/src/lib/fm/topo/modules/common/disk/disk_common.c b/usr/src/lib/fm/topo/modules/common/disk/disk_common.c
index f4749e2da0..174d2dc64e 100644
--- a/usr/src/lib/fm/topo/modules/common/disk/disk_common.c
+++ b/usr/src/lib/fm/topo/modules/common/disk/disk_common.c
@@ -787,13 +787,13 @@ disk_list_gather(topo_mod_t *mod, topo_list_t *listp)
if ((devtree = topo_mod_devinfo(mod)) == DI_NODE_NIL) {
topo_mod_dprintf(mod, "disk_list_gather: "
- "di_init failed");
+ "topo_mod_devinfo() failed");
return (-1);
}
if ((devhdl = di_devlink_init(NULL, 0)) == DI_NODE_NIL) {
topo_mod_dprintf(mod, "disk_list_gather: "
- "di_devlink_init failed");
+ "di_devlink_init() failed");
return (-1);
}
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 e78b481790..715c7311da 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
@@ -48,6 +48,7 @@
*/
#define MAX_ID_LEN 33
+#define TOPO_METH_IPMI_PLATFORM_MESSAGE_VERSION 0
#define TOPO_METH_IPMI_READING_VERSION 0
#define TOPO_METH_IPMI_STATE_VERSION 0
#define TOPO_METH_IPMI_MODE_VERSION 0
@@ -72,6 +73,8 @@ static int dimm_ipmi_entity(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
nvlist_t **);
static int cs_ipmi_entity(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
nvlist_t **);
+static int ipmi_platform_message(topo_mod_t *, tnode_t *, topo_version_t,
+ nvlist_t *, nvlist_t **);
static int ipmi_sensor_reading(topo_mod_t *, tnode_t *, topo_version_t,
nvlist_t *, nvlist_t **);
static int ipmi_sensor_state(topo_mod_t *, tnode_t *, topo_version_t,
@@ -109,6 +112,9 @@ static const topo_method_t ipmi_node_methods[] = {
};
static const topo_method_t ipmi_fac_methods[] = {
+ { "ipmi_platform_message", TOPO_PROP_METH_DESC,
+ TOPO_METH_IPMI_PLATFORM_MESSAGE_VERSION,
+ TOPO_STABILITY_INTERNAL, ipmi_platform_message },
{ "ipmi_sensor_reading", TOPO_PROP_METH_DESC,
TOPO_METH_IPMI_READING_VERSION,
TOPO_STABILITY_INTERNAL, ipmi_sensor_reading },
@@ -181,6 +187,147 @@ strarr_free(topo_mod_t *mod, char **arr, uint_t nelems)
topo_mod_free(mod, arr, (nelems * sizeof (char *)));
}
+/*
+ * Some platforms (most notably G1/2N) use the 'platform event message' command
+ * to manipulate disk fault LEDs over IPMI, but uses the standard sensor
+ * reading to read the value. This method implements this alternative
+ * interface for these platforms.
+ */
+/*ARGSUSED*/
+static int
+ipmi_platform_message(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
+ nvlist_t *in, nvlist_t **out)
+{
+ char *entity_ref;
+ ipmi_sdr_compact_sensor_t *csp;
+ ipmi_handle_t *hdl;
+ int err, ret;
+ uint32_t mode;
+ nvlist_t *pargs, *nvl;
+ ipmi_platform_event_message_t pem;
+ ipmi_sensor_reading_t *reading;
+
+ if (vers > TOPO_METH_IPMI_PLATFORM_MESSAGE_VERSION)
+ return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
+
+ /*
+ * Get an IPMI handle and then lookup the generic device locator sensor
+ * data record referenced by the entity_ref prop val
+ */
+ if ((hdl = topo_mod_ipmi_hold(mod)) == NULL) {
+ topo_mod_dprintf(mod, "Failed to get IPMI handle\n");
+ return (-1);
+ }
+
+ if (topo_prop_get_string(node, TOPO_PGROUP_FACILITY, "entity_ref",
+ &entity_ref, &err) != 0) {
+ topo_mod_dprintf(mod, "Failed to lookup entity_ref property "
+ "(%s)", topo_strerror(err));
+ topo_mod_ipmi_rele(mod);
+ return (-1);
+ }
+
+ if ((csp = ipmi_sdr_lookup_compact_sensor(hdl, entity_ref)) == NULL) {
+ topo_mod_dprintf(mod, "Failed to lookup SDR for %s (%s)\n",
+ entity_ref, ipmi_errmsg(hdl));
+ topo_mod_strfree(mod, entity_ref);
+ topo_mod_ipmi_rele(mod);
+ return (-1);
+ }
+
+ /*
+ * Now look for a private argument list to figure out whether we're
+ * doing a get or a set operation, and then do it.
+ */
+ if ((nvlist_lookup_nvlist(in, TOPO_PROP_PARGS, &pargs) == 0) &&
+ nvlist_exists(pargs, TOPO_PROP_VAL_VAL)) {
+ /*
+ * Set the LED mode
+ */
+ if ((ret = nvlist_lookup_uint32(pargs, TOPO_PROP_VAL_VAL,
+ &mode)) != 0) {
+ topo_mod_dprintf(mod, "Failed to lookup %s nvpair "
+ "(%s)\n", TOPO_PROP_VAL_VAL, strerror(ret));
+ topo_mod_strfree(mod, entity_ref);
+ (void) topo_mod_seterrno(mod, EMOD_NVL_INVAL);
+ topo_mod_ipmi_rele(mod);
+ return (-1);
+ }
+
+ if (mode != TOPO_LED_STATE_OFF &&
+ mode != TOPO_LED_STATE_ON) {
+ topo_mod_dprintf(mod, "Invalid property value: %d\n",
+ mode);
+ topo_mod_strfree(mod, entity_ref);
+ (void) topo_mod_seterrno(mod, EMOD_NVL_INVAL);
+ topo_mod_ipmi_rele(mod);
+ return (-1);
+ }
+
+ pem.ipem_sensor_type = csp->is_cs_type;
+ pem.ipem_sensor_num = csp->is_cs_number;
+ pem.ipem_event_type = csp->is_cs_reading_type;
+
+ /*
+ * The spec states that any values between 0x20 and 0x29 are
+ * legitimate for "system software". However, some versions of
+ * Sun's ILOM rejects messages over /dev/bmc with a generator
+ * of 0x20, so we use 0x21 instead.
+ */
+ pem.ipem_generator = 0x21;
+ pem.ipem_event_dir = 0;
+ pem.ipem_rev = 0x04;
+ if (mode == TOPO_LED_STATE_ON)
+ pem.ipem_event_data[0] = 1;
+ else
+ pem.ipem_event_data[0] = 0;
+ pem.ipem_event_data[1] = 0xff;
+ pem.ipem_event_data[2] = 0xff;
+
+ if (ipmi_event_platform_message(hdl, &pem) < 0) {
+ topo_mod_dprintf(mod, "Failed to set LED mode for %s "
+ "(%s)\n", entity_ref, ipmi_errmsg(hdl));
+ topo_mod_strfree(mod, entity_ref);
+ topo_mod_ipmi_rele(mod);
+ return (-1);
+ }
+ } else {
+ /*
+ * Get the LED mode
+ */
+ if ((reading = ipmi_get_sensor_reading(hdl, csp->is_cs_number))
+ == NULL) {
+ topo_mod_dprintf(mod, "Failed to get sensor reading "
+ "for sensor %s: %s\n", entity_ref,
+ ipmi_errmsg(hdl));
+ topo_mod_strfree(mod, entity_ref);
+ topo_mod_ipmi_rele(mod);
+ return (-1);
+ }
+
+ if (reading->isr_state &
+ TOPO_SENSOR_STATE_GENERIC_STATE_ASSERTED)
+ mode = TOPO_LED_STATE_ON;
+ else
+ mode = TOPO_LED_STATE_OFF;
+ }
+ topo_mod_strfree(mod, entity_ref);
+
+ topo_mod_ipmi_rele(mod);
+
+ 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, mode) != 0) {
+ topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n");
+ nvlist_free(nvl);
+ return (topo_mod_seterrno(mod, EMOD_NOMEM));
+ }
+ *out = nvl;
+
+ return (0);
+}
+
/*ARGSUSED*/
static int
ipmi_sensor_state(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
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 3ded4075c3..0afe3c5ade 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
@@ -114,6 +114,9 @@ ipmi_present(topo_mod_t *mod, tnode_t *tn, topo_version_t version,
return (-1);
}
+ topo_mod_dprintf(mod,
+ "ipmi_entity_present_sdr(%s) = %d\n", name,
+ present);
topo_mod_strfree(mod, name);
} else {
if (topo_prop_get_string(tn, TOPO_PGROUP_IPMI,
@@ -151,6 +154,9 @@ ipmi_present(topo_mod_t *mod, tnode_t *tn, topo_version_t version,
topo_mod_ipmi_rele(mod);
return (-1);
}
+
+ topo_mod_dprintf(mod,
+ "ipmi_entity_present() = %d\n", present);
}
topo_mod_ipmi_rele(mod);
diff --git a/usr/src/lib/fm/topo/modules/common/ses/ses.c b/usr/src/lib/fm/topo/modules/common/ses/ses.c
index c1ef0efe18..8c78474d34 100644
--- a/usr/src/lib/fm/topo/modules/common/ses/ses.c
+++ b/usr/src/lib/fm/topo/modules/common/ses/ses.c
@@ -41,7 +41,7 @@
#define SES_VERSION 1
-#define SES_SNAP_FREQ 1000 /* in milliseconds */
+static int ses_snap_freq = 250; /* in milliseconds */
#define SES_STATUS_UNAVAIL(s) \
((s) == SES_ESC_UNSUPPORTED || (s) >= SES_ESC_NOT_INSTALLED)
@@ -298,9 +298,8 @@ ses_contains(topo_mod_t *mod, tnode_t *tn, topo_version_t version,
ses_node_t *
ses_node_lock(topo_mod_t *mod, tnode_t *tn)
{
- struct timeval tv;
ses_enum_target_t *tp = topo_node_getspecific(tn);
- uint64_t prev, now;
+ hrtime_t now;
ses_snap_t *snap;
int err;
uint64_t nodeid;
@@ -316,16 +315,9 @@ ses_node_lock(topo_mod_t *mod, tnode_t *tn)
/*
* Determine if we need to take a new snapshot.
*/
- if (gettimeofday(&tv, NULL) != 0) {
- tv.tv_sec = time(NULL);
- tv.tv_usec = 0;
- }
-
- now = tv.tv_sec * 1000 + tv.tv_usec / 1000;
- prev = tp->set_snaptime.tv_sec * 1000 +
- tp->set_snaptime.tv_usec / 1000;
+ now = gethrtime();
- if (now - prev > SES_SNAP_FREQ &&
+ if (now - tp->set_snaptime > (ses_snap_freq * 1000 * 1000) &&
(snap = ses_snap_new(tp->set_target)) != NULL) {
if (ses_snap_generation(snap) !=
ses_snap_generation(tp->set_snap)) {
@@ -347,7 +339,7 @@ ses_node_lock(topo_mod_t *mod, tnode_t *tn)
ses_snap_rele(tp->set_snap);
tp->set_snap = snap;
}
- tp->set_snaptime = tv;
+ tp->set_snaptime = gethrtime();
}
snap = tp->set_snap;
@@ -1629,8 +1621,7 @@ ses_process_dir(const char *dirpath, ses_enum_data_t *sdp)
stp->set_refcount = 1;
sdp->sed_target = stp;
stp->set_snap = ses_snap_hold(stp->set_target);
- if (gettimeofday(&stp->set_snaptime, NULL) != 0)
- stp->set_snaptime.tv_sec = time(NULL);
+ stp->set_snaptime = gethrtime();
/*
* Enumerate over all SES elements and merge them into the
diff --git a/usr/src/lib/fm/topo/modules/common/ses/ses.h b/usr/src/lib/fm/topo/modules/common/ses/ses.h
index 909663d60a..94ae7266ef 100644
--- a/usr/src/lib/fm/topo/modules/common/ses/ses.h
+++ b/usr/src/lib/fm/topo/modules/common/ses/ses.h
@@ -51,7 +51,7 @@ typedef struct ses_enum_target {
topo_list_t set_link;
ses_target_t *set_target;
ses_snap_t *set_snap;
- struct timeval set_snaptime;
+ hrtime_t set_snaptime;
char *set_devpath;
int set_refcount;
pthread_mutex_t set_lock;
diff --git a/usr/src/lib/fm/topo/modules/common/ses/ses_facility.c b/usr/src/lib/fm/topo/modules/common/ses/ses_facility.c
index 55c54d9113..08d3efb709 100644
--- a/usr/src/lib/fm/topo/modules/common/ses/ses_facility.c
+++ b/usr/src/lib/fm/topo/modules/common/ses/ses_facility.c
@@ -137,6 +137,7 @@ ses_indicator_mode(topo_mod_t *mod, tnode_t *tn, topo_version_t vers,
uint32_t mode;
boolean_t current, altcurrent;
nvlist_t *nvl;
+ ses_enum_target_t *tp = topo_node_getspecific(tn);
if (vers > TOPO_METH_SES_MODE_VERSION)
return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
@@ -193,6 +194,7 @@ ses_indicator_mode(topo_mod_t *mod, tnode_t *tn, topo_version_t vers,
goto error;
}
+ tp->set_snaptime = 0;
nvlist_free(nvl);
} else {
/* get operation */