changeset 10519:5d153c0fe8de

PSARC 2009/441 SES enumeration of subchassis 6865478 SES topo plugin should support subchassis
author Sundeep Panicker <Sundeep.Panicker@Sun.COM>
date Mon, 14 Sep 2009 10:21:57 -0700
parents 5e20d81ceb17
children 1303da84e47a
files usr/src/lib/fm/topo/libtopo/common/hc.c usr/src/lib/fm/topo/libtopo/common/topo_hc.h usr/src/lib/fm/topo/modules/common/ses/ses.c usr/src/lib/scsi/plugins/ses/SUN/common/sun_spms.c usr/src/lib/scsi/plugins/ses/libses/common/libses.h
diffstat 5 files changed, 416 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/fm/topo/libtopo/common/hc.c	Mon Sep 14 10:09:29 2009 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/hc.c	Mon Sep 14 10:21:57 2009 -0700
@@ -183,6 +183,7 @@
 	{ SHELF, TOPO_STABILITY_PRIVATE },
 	{ SES_ENCLOSURE, TOPO_STABILITY_PRIVATE },
 	{ STRAND, TOPO_STABILITY_PRIVATE },
+	{ SUBCHASSIS, TOPO_STABILITY_PRIVATE },
 	{ SYSTEMBOARD, TOPO_STABILITY_PRIVATE },
 	{ XAUI, TOPO_STABILITY_PRIVATE },
 	{ XFP, TOPO_STABILITY_PRIVATE }
--- a/usr/src/lib/fm/topo/libtopo/common/topo_hc.h	Mon Sep 14 10:09:29 2009 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_hc.h	Mon Sep 14 10:21:57 2009 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -79,6 +79,7 @@
 #define	RISER		"riser"
 #define	SHELF		"shelf"
 #define	SES_ENCLOSURE	"ses-enclosure"
+#define	SUBCHASSIS	"subchassis"
 #define	SYSTEMBOARD	"systemboard"
 #define	XAUI		"xaui"
 #define	XFP		"xfp"
--- a/usr/src/lib/fm/topo/modules/common/ses/ses.c	Mon Sep 14 10:09:29 2009 -0700
+++ b/usr/src/lib/fm/topo/modules/common/ses/ses.c	Mon Sep 14 10:21:57 2009 -0700
@@ -70,12 +70,15 @@
 
 typedef struct ses_enum_chassis {
 	topo_list_t		sec_link;
+	topo_list_t		sec_subchassis;
 	topo_list_t		sec_nodes;
 	topo_list_t		sec_targets;
 	const char		*sec_csn;
+	const char		*sec_lid;
 	ses_node_t		*sec_enclosure;
 	ses_enum_target_t	*sec_target;
 	topo_instance_t		sec_instance;
+	topo_instance_t		sec_scinstance;
 	boolean_t		sec_hasdev;
 	boolean_t		sec_internal;
 } ses_enum_chassis_t;
@@ -91,6 +94,13 @@
 	topo_instance_t		sed_instance;
 } ses_enum_data_t;
 
+typedef enum {
+	SES_NEW_CHASSIS		= 0x1,
+	SES_NEW_SUBCHASSIS	= 0x2,
+	SES_DUP_CHASSIS		= 0x4,
+	SES_DUP_SUBCHASSIS	= 0x8
+} ses_chassis_type_e;
+
 static int ses_present(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
     nvlist_t **);
 static int ses_contains(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
@@ -133,16 +143,23 @@
 }
 
 static void
-ses_data_free(ses_enum_data_t *sdp)
+ses_data_free(ses_enum_data_t *sdp, ses_enum_chassis_t *pcp)
 {
 	topo_mod_t *mod = sdp->sed_mod;
 	ses_enum_chassis_t *cp;
 	ses_enum_node_t *np;
 	ses_enum_target_t *tp;
 	ses_alt_node_t *ap;
+	topo_list_t *cpl;
 
-	while ((cp = topo_list_next(&sdp->sed_chassis)) != NULL) {
-		topo_list_delete(&sdp->sed_chassis, cp);
+
+	if (pcp != NULL)
+		cpl = &pcp->sec_subchassis;
+	else
+		cpl = &sdp->sed_chassis;
+
+	while ((cp = topo_list_next(cpl)) != NULL) {
+		topo_list_delete(cpl, cp);
 
 		while ((np = topo_list_next(&cp->sec_nodes)) != NULL) {
 			while ((ap = topo_list_next(&np->sen_alt_nodes)) !=
@@ -162,8 +179,10 @@
 		topo_mod_free(mod, cp, sizeof (ses_enum_chassis_t));
 	}
 
-	disk_list_free(mod, &sdp->sed_disks);
-	topo_mod_free(mod, sdp, sizeof (ses_enum_data_t));
+	if (pcp == NULL) {
+		disk_list_free(mod, &sdp->sed_disks);
+		topo_mod_free(mod, sdp, sizeof (ses_enum_data_t));
+	}
 }
 
 /*
@@ -802,7 +821,7 @@
 		return (0);
 
 	topo_mod_dprintf(mod, "%s: creating %llu %s nodes",
-	    cp->sec_csn, max, nodename);
+	    cp->sec_csn, max + 1, nodename);
 
 	if (dorange && topo_node_range_create(mod, pnode,
 	    nodename, 0, max) != 0) {
@@ -825,6 +844,130 @@
 }
 
 /*
+ * Instantiate a new subchassis instance in the topology.
+ */
+static int
+ses_create_subchassis(ses_enum_data_t *sdp, tnode_t *pnode,
+    ses_enum_chassis_t *scp)
+{
+	topo_mod_t *mod = sdp->sed_mod;
+	tnode_t *tn;
+	nvlist_t *props;
+	nvlist_t *auth = NULL, *fmri = NULL;
+	char *part = NULL, *revision = NULL;
+	uint64_t instance = scp->sec_instance;
+	char *desc;
+	char label[128];
+	char **paths;
+	int i, err;
+	ses_enum_target_t *stp;
+	int ret = -1;
+
+	/*
+	 * Copy authority information from parent enclosure node
+	 */
+	if ((auth = topo_mod_auth(mod, pnode)) == NULL)
+		goto error;
+
+	/*
+	 * Record the subchassis serial number in the FMRI.
+	 * For now, we assume that logical id is the subchassis serial number.
+	 * If this assumption changes in future, then the following
+	 * piece of code will need to be updated via an RFE.
+	 */
+	if ((fmri = topo_mod_hcfmri(mod, pnode, FM_HC_SCHEME_VERSION,
+	    SUBCHASSIS, (topo_instance_t)instance, NULL, auth, part, revision,
+	    scp->sec_lid)) == NULL) {
+		topo_mod_dprintf(mod, "topo_mod_hcfmri() failed: %s",
+		    topo_mod_errmsg(mod));
+		goto error;
+	}
+
+	if ((tn = topo_node_bind(mod, pnode, SUBCHASSIS,
+	    instance, fmri)) == NULL) {
+		topo_mod_dprintf(mod, "topo_node_bind() failed: %s",
+		    topo_mod_errmsg(mod));
+		goto error;
+	}
+
+	props = ses_node_props(scp->sec_enclosure);
+
+	/*
+	 * Look for the subchassis label in the following order:
+	 *	<ses-description>
+	 *	<ses-class-description> <instance>
+	 *	<default-type-label> <instance>
+	 *
+	 * For subchassis, the default label is "SUBCHASSIS"
+	 */
+	if (nvlist_lookup_string(props, SES_PROP_DESCRIPTION, &desc) != 0 ||
+	    desc[0] == '\0') {
+		if (nvlist_lookup_string(props, SES_PROP_CLASS_DESCRIPTION,
+		    &desc) == 0 && desc[0] != '\0')
+			(void) snprintf(label, sizeof (label), "%s %llu", desc,
+			    instance);
+		else
+			(void) snprintf(label, sizeof (label),
+			    "SUBCHASSIS %llu", instance);
+		desc = label;
+	}
+
+	if (topo_node_label_set(tn, desc, &err) != 0)
+		goto error;
+
+	if (ses_set_standard_props(mod, tn, NULL,
+	    ses_node_id(scp->sec_enclosure), scp->sec_target->set_devpath) != 0)
+		goto error;
+
+	/*
+	 * For enclosures, we want to include all possible targets (for upgrade
+	 * purposes).
+	 */
+	for (i = 0, stp = topo_list_next(&scp->sec_targets); stp != NULL;
+	    stp = topo_list_next(stp), i++)
+		;
+
+	verify(i != 0);
+	paths = alloca(i * sizeof (char *));
+
+	for (i = 0, stp = topo_list_next(&scp->sec_targets); stp != NULL;
+	    stp = topo_list_next(stp), i++)
+		paths[i] = stp->set_devpath;
+
+	if (topo_prop_set_string_array(tn, TOPO_PGROUP_SES,
+	    TOPO_PROP_PATHS, TOPO_PROP_IMMUTABLE, (const char **)paths,
+	    i, &err) != 0) {
+		topo_mod_dprintf(mod, "failed to create property %s: %s\n",
+		    TOPO_PROP_PATHS, topo_strerror(err));
+		goto error;
+	}
+
+	if (topo_method_register(mod, tn, ses_enclosure_methods) != 0) {
+		topo_mod_dprintf(mod, "topo_method_register() failed: %s",
+		    topo_mod_errmsg(mod));
+		goto error;
+	}
+
+	/*
+	 * Create the nodes for controllers and bays.
+	 */
+	if (ses_create_children(sdp, tn, SES_ET_ESC_ELECTRONICS,
+	    CONTROLLER, "CONTROLLER", scp, B_TRUE) != 0 ||
+	    ses_create_children(sdp, tn, SES_ET_DEVICE,
+	    BAY, "BAY", scp, B_TRUE) != 0 ||
+	    ses_create_children(sdp, tn, SES_ET_ARRAY_DEVICE,
+	    BAY, "BAY", scp, B_TRUE) != 0)
+		goto error;
+
+	ret = 0;
+
+error:
+	nvlist_free(auth);
+	nvlist_free(fmri);
+	return (ret);
+}
+
+/*
  * Instantiate a new chassis instance in the topology.
  */
 static int
@@ -843,7 +986,9 @@
 	int ret = -1;
 	ses_enum_node_t *snp;
 	ses_enum_target_t *stp;
+	ses_enum_chassis_t *scp;
 	int i, err;
+	uint64_t sc_count = 0;
 
 	/*
 	 * Ignore any internal enclosures.
@@ -985,6 +1130,30 @@
 	    BAY, "BAY", cp, B_TRUE) != 0)
 		goto error;
 
+	if (cp->sec_scinstance > 0 &&
+	    topo_node_range_create(mod, tn, SUBCHASSIS, 0,
+	    cp->sec_scinstance - 1) != 0) {
+		topo_mod_dprintf(mod, "topo_node_create_range() failed: %s",
+		    topo_mod_errmsg(mod));
+		goto error;
+	}
+
+	for (scp = topo_list_next(&cp->sec_subchassis); scp != NULL;
+	    scp = topo_list_next(scp)) {
+
+		if (ses_create_subchassis(sdp, tn, scp) != 0)
+			goto error;
+
+		topo_mod_dprintf(mod, "created Subchassis node with "
+		    "LID (%s)\n  and target (%s) under Chassis with CSN (%s)",
+		    scp->sec_lid, scp->sec_target->set_devpath, cp->sec_csn);
+
+		sc_count++;
+	}
+
+	topo_mod_dprintf(mod, "%s: created %llu %s nodes",
+	    cp->sec_csn, sc_count, SUBCHASSIS);
+
 	cp->sec_target->set_refcount++;
 	topo_node_setspecific(tn, cp->sec_target);
 
@@ -1033,6 +1202,65 @@
 
 	return (0);
 }
+
+/*
+ * Initialize chassis or subchassis.
+ */
+static int
+ses_init_chassis(topo_mod_t *mod, ses_enum_data_t *sdp, ses_enum_chassis_t *pcp,
+    ses_enum_chassis_t *cp, ses_node_t *np, nvlist_t *props,
+    char *lid, ses_chassis_type_e flags)
+{
+	boolean_t internal, ident;
+
+	assert((flags & (SES_NEW_CHASSIS | SES_NEW_SUBCHASSIS |
+	    SES_DUP_CHASSIS | SES_DUP_SUBCHASSIS)) != 0);
+
+	assert((cp != NULL) && (np != NULL) && (props != NULL) &&
+	    (lid != NULL));
+
+	if (flags & (SES_NEW_SUBCHASSIS | SES_DUP_SUBCHASSIS))
+		assert(pcp != NULL);
+
+	topo_mod_dprintf(mod, "ses_init_chassis: %s: lid(%s), flags (%d)",
+	    sdp->sed_name, lid, flags);
+
+	if (flags & (SES_NEW_CHASSIS | SES_NEW_SUBCHASSIS)) {
+
+		topo_mod_dprintf(mod, "new chassis/subchassis");
+		if (nvlist_lookup_boolean_value(props,
+		    LIBSES_EN_PROP_INTERNAL, &internal) == 0)
+			cp->sec_internal = internal;
+
+		cp->sec_lid = lid;
+		cp->sec_enclosure = np;
+		cp->sec_target = sdp->sed_target;
+
+		if (flags & SES_NEW_CHASSIS) {
+			cp->sec_instance = sdp->sed_instance++;
+			topo_list_append(&sdp->sed_chassis, cp);
+		} else {
+			cp->sec_instance = pcp->sec_scinstance++;
+			topo_list_append(&pcp->sec_subchassis, cp);
+		}
+
+	} else {
+		topo_mod_dprintf(mod, "dup chassis/subchassis");
+		if (nvlist_lookup_boolean_value(props,
+		    SES_PROP_IDENT, &ident) == 0) {
+			topo_mod_dprintf(mod,  "overriding enclosure node");
+
+			cp->sec_enclosure = np;
+			cp->sec_target = sdp->sed_target;
+		}
+	}
+
+	topo_list_append(&cp->sec_targets, sdp->sed_target);
+	sdp->sed_current = cp;
+
+	return (0);
+}
+
 /*
  * Gather nodes from the current SES target into our chassis list, merging the
  * results if necessary.
@@ -1043,13 +1271,15 @@
 	nvlist_t *props = ses_node_props(np);
 	ses_enum_data_t *sdp = data;
 	topo_mod_t *mod = sdp->sed_mod;
-	ses_enum_chassis_t *cp;
+	ses_enum_chassis_t *cp, *scp;
 	ses_enum_node_t *snp;
 	ses_alt_node_t *sap;
 	char *csn;
 	uint64_t instance, type;
 	uint64_t prevstatus, status;
-	boolean_t report, internal, ident;
+	boolean_t report;
+	boolean_t have_subchassis = B_TRUE;
+	char *lid;
 
 	if (ses_node_type(np) == SES_NODE_ENCLOSURE) {
 		/*
@@ -1063,59 +1293,165 @@
 		/*
 		 * Go through the list of chassis we have seen so far and see
 		 * if this serial number matches one of the known values.
+		 * If so, check whether this enclosure is a subchassis.
 		 */
 		if (nvlist_lookup_string(props, LIBSES_EN_PROP_CSN,
 		    &csn) != 0)
 			return (SES_WALK_ACTION_TERMINATE);
 
-		for (cp = topo_list_next(&sdp->sed_chassis); cp != NULL;
-		    cp = topo_list_next(cp)) {
-			if (strcmp(cp->sec_csn, csn) == 0) {
-				topo_mod_dprintf(mod, "%s: part of already "
-				    "known chassis %s", sdp->sed_name, csn);
-				break;
-			}
+		if (nvlist_lookup_string(props, LIBSES_EN_PROP_SUBCHASSIS_ID,
+		    &lid) != 0) {
+			have_subchassis = B_FALSE;
+			if ((lid = topo_mod_zalloc(mod, sizeof (char))) == NULL)
+				goto error;
 		}
 
+		topo_mod_dprintf(mod, "ses_enum_gather: Enclosure Node (%s) "
+		    "CSN (%s), LID (%s)", sdp->sed_name, csn, lid);
+
+		/*
+		 * We need to determine whether this enclosure node
+		 * represents a chassis or a subchassis. Since we may
+		 * receive the enclosure nodes in a non-deterministic
+		 * manner, we need to account for all possible combinations:
+		 *	1. Chassis for the current CSN has not yet been
+		 *	   allocated
+		 *		1.1 This is a new chassis:
+		 *			allocate and instantiate the chassis
+		 *		1.2 This is a new subchassis:
+		 *			allocate a placeholder chassis
+		 *			allocate and instantiate the subchassis
+		 *			link the subchassis to the chassis
+		 *	2. Chassis for the current CSN has been allocated
+		 *		2.1 This is a duplicate chassis enclosure
+		 *			check whether to override old chassis
+		 *			append to chassis' target list
+		 *		2.2 Only placeholder chassis exists
+		 *			fill in the chassis fields
+		 *		2.3 This is a new subchassis
+		 *			allocate and instantiate the subchassis
+		 *			link the subchassis to the chassis
+		 *		2.4 This is a duplicate subchassis enclosure
+		 *			 check whether to override old chassis
+		 *			 append to chassis' target list
+		 */
+
+		for (cp = topo_list_next(&sdp->sed_chassis); cp != NULL;
+		    cp = topo_list_next(cp))
+			if (strcmp(cp->sec_csn, csn) == 0)
+				break;
+
 		if (cp == NULL) {
-			topo_mod_dprintf(mod, "%s: creating chassis %s",
-			    sdp->sed_name, csn);
+			/* 1. Haven't seen a chassis with this CSN before */
 
 			if ((cp = topo_mod_zalloc(mod,
 			    sizeof (ses_enum_chassis_t))) == NULL)
 				goto error;
 
-			if (nvlist_lookup_boolean_value(props,
-			    LIBSES_EN_PROP_INTERNAL, &internal) == 0)
-				cp->sec_internal = internal;
+			cp->sec_csn = csn;
+
+			if (!have_subchassis || strcmp(csn, lid) == 0) {
+				/* 1.1 This is a new chassis */
+
+				topo_mod_dprintf(mod, "%s: Initialize new "
+				    "chassis with CSN (%s) and LID (%s)",
+				    sdp->sed_name, csn, lid);
+
+				if (ses_init_chassis(mod, sdp, NULL, cp,
+				    np, props, lid, SES_NEW_CHASSIS) < 0)
+					goto error;
+			} else {
+				/* 1.2 This is a new subchassis */
 
-			cp->sec_csn = csn;
-			cp->sec_enclosure = np;
-			cp->sec_target = sdp->sed_target;
-			cp->sec_instance = sdp->sed_instance++;
-			topo_list_append(&sdp->sed_chassis, cp);
+				topo_mod_dprintf(mod, "%s: Initialize new "
+				    "subchassis with CSN (%s) and LID (%s)",
+				    sdp->sed_name, csn, lid);
+
+				if ((scp = topo_mod_zalloc(mod,
+				    sizeof (ses_enum_chassis_t))) == NULL)
+					goto error;
+
+				scp->sec_csn = csn;
+
+				if (ses_init_chassis(mod, sdp, cp, scp,
+				    np, props, lid, SES_NEW_SUBCHASSIS) < 0)
+					goto error;
+			}
 		} else {
-			/*
-			 * For the enclosure node, it is possible to have
-			 * multiple targets, only one of which support an
-			 * enclosure element descriptor.  We assume that this
-			 * is the one that is responsible for managing the
-			 * enclosure itself, so we prefer one with the
-			 * SES_PROP_IDENT property (which is only present for a
-			 * target that has an enclosure element descriptor).
-			 */
-			if (nvlist_lookup_boolean_value(props, SES_PROP_IDENT,
-			    &ident) == 0) {
-				topo_mod_dprintf(mod,
-				    "overriding enclosure node");
-				cp->sec_enclosure = np;
-				cp->sec_target = sdp->sed_target;
+			/* 2. We have a chassis with this CSN */
+
+			if (!have_subchassis || strcmp(csn, lid) == 0) {
+				/* This is a chassis */
+
+				if (!have_subchassis ||
+				    strlen(cp->sec_lid) > 0) {
+					/* 2.1 This is a duplicate chassis */
+
+					topo_mod_dprintf(mod, "%s: Append "
+					    "duplicate chassis with CSN (%s) "
+					    "and LID (%s)",
+					    sdp->sed_name, csn, lid);
+
+					if (ses_init_chassis(mod, sdp, NULL, cp,
+					    np, props, lid,
+					    SES_DUP_CHASSIS) < 0)
+						goto error;
+				} else {
+					/* 2.2 Init the placeholder chassis */
+
+					topo_mod_dprintf(mod, "%s: Initialize"
+					    "placeholder chassis with CSN (%s) "
+					    "and LID (%s)",
+					    sdp->sed_name, csn, lid);
+
+					if (ses_init_chassis(mod, sdp, NULL, cp,
+					    np, props, lid,
+					    SES_NEW_CHASSIS) < 0)
+						goto error;
+
+				}
+			} else {
+				/* This is a subchassis */
+
+				for (scp = topo_list_next(&cp->sec_subchassis);
+				    scp != NULL; scp = topo_list_next(scp))
+					if (strcmp(scp->sec_lid, lid) == 0)
+						break;
+
+				if (scp == NULL) {
+					/* 2.3 This is a new subchassis */
+
+					topo_mod_dprintf(mod, "%s: Initialize "
+					    "new subchassis with CSN (%s) "
+					    "and LID (%s)",
+					    sdp->sed_name, csn, lid);
+
+					if ((scp = topo_mod_zalloc(mod,
+					    sizeof (ses_enum_chassis_t)))
+					    == NULL)
+						goto error;
+
+					scp->sec_csn = csn;
+
+					if (ses_init_chassis(mod, sdp, cp, scp,
+					    np, props, lid,
+					    SES_NEW_SUBCHASSIS) < 0)
+						goto error;
+				} else {
+					/* 2.4 This is a duplicate subchassis */
+
+					topo_mod_dprintf(mod, "%s: Append "
+					    "duplicate subchassis with "
+					    "CSN (%s) and LID (%s)",
+					    sdp->sed_name, csn, lid);
+
+					if (ses_init_chassis(mod, sdp, cp, scp,
+					    np, props, lid,
+					    SES_DUP_SUBCHASSIS) < 0)
+						goto error;
+				}
 			}
 		}
-
-		topo_list_append(&cp->sec_targets, sdp->sed_target);
-		sdp->sed_current = cp;
-
 	} else if (ses_node_type(np) == SES_NODE_ELEMENT) {
 		/*
 		 * If we haven't yet seen an enclosure node and identified the
@@ -1390,13 +1726,19 @@
 	 * for the 'ses-enclosure' node last.
 	 */
 	if (strcmp(name, SES_ENCLOSURE) == 0) {
-		ses_data_free(data);
+		for (cp = topo_list_next(&data->sed_chassis); cp != NULL;
+		    cp = topo_list_next(cp))
+			ses_data_free(data, cp);
+		ses_data_free(data, NULL);
 		topo_mod_setspecific(mod, NULL);
 	}
 	return (0);
 
 error:
-	ses_data_free(data);
+	for (cp = topo_list_next(&data->sed_chassis); cp != NULL;
+	    cp = topo_list_next(cp))
+		ses_data_free(data, cp);
+	ses_data_free(data, NULL);
 	topo_mod_setspecific(mod, NULL);
 	return (-1);
 }
--- a/usr/src/lib/scsi/plugins/ses/SUN/common/sun_spms.c	Mon Sep 14 10:09:29 2009 -0700
+++ b/usr/src/lib/scsi/plugins/ses/SUN/common/sun_spms.c	Mon Sep 14 10:21:57 2009 -0700
@@ -69,11 +69,12 @@
 sun_parse_node(ses_plugin_t *sp, ses_node_t *np)
 {
 	ses_sun_spms_vs_t *sfbp;
-	nvlist_t *encprops;
+	nvlist_t *encprops, *lid_nv;
 	uint8_t *vsp;
 	uint_t vsp_len;
 	uint_t cid_off, cid_len;
-	char *csn;
+	uint64_t wwn;
+	char lid[17];
 	int nverr;
 
 	if (ses_node_type(np) != SES_NODE_ENCLOSURE)
@@ -90,6 +91,20 @@
 	if (strncmp(sfbp->ssvs_spms_header, "SPMS", 4) != 0)
 		return (0);
 
+
+	/*
+	 * NOTE - The following is a temporary mechanism to identify
+	 *	subchassis until SPMS defines a formal method to do so.
+	 */
+	if (nvlist_lookup_nvlist(encprops, SES_EN_PROP_LID, &lid_nv) != 0 ||
+	    nvlist_lookup_uint64(lid_nv, SPC3_NAA_INT, &wwn) != 0)
+		return (0);
+
+	(void) snprintf(lid, sizeof (lid), "%llx", wwn);
+
+	SES_NV_ADD(fixed_string, nverr, encprops, LIBSES_EN_PROP_SUBCHASSIS_ID,
+	    lid, 16);
+
 	if (sfbp->ssvs_chassis_id_off < 96)
 		return (0);
 
@@ -109,12 +124,8 @@
 	if (cid_off + cid_len > vsp_len)
 		return (0);
 
-	csn = alloca((size_t)cid_len + 1);
-	csn[cid_len] = '\0';
-
-	bcopy((void *)(vsp + cid_off), csn, cid_len);
 	SES_NV_ADD(fixed_string, nverr, encprops, LIBSES_EN_PROP_CSN,
-	    csn, cid_len + 1);
+	    (char *)(vsp + cid_off), cid_len);
 
 	return (0);
 }
--- a/usr/src/lib/scsi/plugins/ses/libses/common/libses.h	Mon Sep 14 10:09:29 2009 -0700
+++ b/usr/src/lib/scsi/plugins/ses/libses/common/libses.h	Mon Sep 14 10:21:57 2009 -0700
@@ -20,15 +20,13 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #ifndef	_FRAMEWORK_LIBSES_H
 #define	_FRAMEWORK_LIBSES_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #ifdef	__cplusplus
 extern "C" {
 #endif
@@ -72,6 +70,12 @@
  */
 #define	LIBSES_EN_PROP_INTERNAL		"libses-internal"
 
+/*
+ * This property identifies the subchassis id for those systems that
+ * support the concept of a subchassis.
+ */
+#define	LIBSES_EN_PROP_SUBCHASSIS_ID	"libses-subchassis-id"
+
 #ifdef	__cplusplus
 }
 #endif