changeset 10527:239e78cbcf46

6881719 debug message typo in disk_list_gather() 6881732 add facility method for platform event message service LED 6881744 ses enumerator snapshot caching is broken
author Eric Schrock <Eric.Schrock@Sun.COM>
date Mon, 14 Sep 2009 16:49:06 -0700
parents a1c57e83a4db
children 9c88f2e713fc
files usr/src/lib/fm/topo/modules/common/disk/disk_common.c usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c usr/src/lib/fm/topo/modules/common/ipmi/ipmi_enum.c usr/src/lib/fm/topo/modules/common/ses/ses.c usr/src/lib/fm/topo/modules/common/ses/ses.h usr/src/lib/fm/topo/modules/common/ses/ses_facility.c
diffstat 6 files changed, 164 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/fm/topo/modules/common/disk/disk_common.c	Mon Sep 14 15:13:58 2009 -0600
+++ b/usr/src/lib/fm/topo/modules/common/disk/disk_common.c	Mon Sep 14 16:49:06 2009 -0700
@@ -787,13 +787,13 @@
 
 	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);
 	}
 
--- a/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c	Mon Sep 14 15:13:58 2009 -0600
+++ b/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c	Mon Sep 14 16:49:06 2009 -0700
@@ -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 @@
     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_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 @@
 	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,
--- a/usr/src/lib/fm/topo/modules/common/ipmi/ipmi_enum.c	Mon Sep 14 15:13:58 2009 -0600
+++ b/usr/src/lib/fm/topo/modules/common/ipmi/ipmi_enum.c	Mon Sep 14 16:49:06 2009 -0700
@@ -114,6 +114,9 @@
 				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 @@
 			topo_mod_ipmi_rele(mod);
 			return (-1);
 		}
+
+		topo_mod_dprintf(mod,
+		    "ipmi_entity_present() = %d\n", present);
 	}
 
 	topo_mod_ipmi_rele(mod);
--- a/usr/src/lib/fm/topo/modules/common/ses/ses.c	Mon Sep 14 15:13:58 2009 -0600
+++ b/usr/src/lib/fm/topo/modules/common/ses/ses.c	Mon Sep 14 16:49:06 2009 -0700
@@ -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_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 @@
 	/*
 	 * Determine if we need to take a new snapshot.
 	 */
-	if (gettimeofday(&tv, NULL) != 0) {
-		tv.tv_sec = time(NULL);
-		tv.tv_usec = 0;
-	}
+	now = gethrtime();
 
-	now = tv.tv_sec * 1000 + tv.tv_usec / 1000;
-	prev = tp->set_snaptime.tv_sec * 1000 +
-	    tp->set_snaptime.tv_usec / 1000;
-
-	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_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 @@
 		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
--- a/usr/src/lib/fm/topo/modules/common/ses/ses.h	Mon Sep 14 15:13:58 2009 -0600
+++ b/usr/src/lib/fm/topo/modules/common/ses/ses.h	Mon Sep 14 16:49:06 2009 -0700
@@ -51,7 +51,7 @@
 	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;
--- a/usr/src/lib/fm/topo/modules/common/ses/ses_facility.c	Mon Sep 14 15:13:58 2009 -0600
+++ b/usr/src/lib/fm/topo/modules/common/ses/ses_facility.c	Mon Sep 14 16:49:06 2009 -0700
@@ -137,6 +137,7 @@
 	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 @@
 			goto error;
 		}
 
+		tp->set_snaptime = 0;
 		nvlist_free(nvl);
 	} else {
 		/* get operation */