6593380 topology for Sun x64 platforms should include serial numbers for dimms
6671247 missing DIMM FRU labels on 4600/4600M2 platforms with family 15 modules
6672188 chip FRU labels computed incorrectly on 2-socket AF4+ blades
6675806 libipmi: ipmi_fru_read() can leak memory on failure
--- a/usr/src/cmd/fm/eversholt/files/i386/i86pc/amd64.esc Wed Mar 26 11:58:25 2008 -0700
+++ b/usr/src/cmd/fm/eversholt/files/i386/i86pc/amd64.esc Wed Mar 26 13:39:54 2008 -0700
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -224,14 +224,14 @@
engine stat.ckpgflt@chip/memory-controller/dimm/rank;
event fault.memory.page_sb@chip/memory-controller/dimm/rank,
- FITrate=PAGE_FIT, ASRU=dimm/rank, message=0,
+ FITrate=PAGE_FIT, FRU=dimm, ASRU=dimm/rank, message=0,
count=stat.sbpgflt@chip/memory-controller/dimm/rank,
action=confcall("rewrite-ASRU"); /* rewrite ASRU to identify page in rank */
#define SB_PGFLTS (count(stat.sbpgflt@chip/memory-controller/dimm/rank))
event fault.memory.page_ck@chip/memory-controller/dimm/rank,
- FITrate=PAGE_FIT, ASRU=dimm/rank, message=0,
+ FITrate=PAGE_FIT, FRU=dimm, ASRU=dimm/rank, message=0,
count=stat.ckpgflt@chip/memory-controller/dimm/rank,
action=confcall("rewrite-ASRU"); /* rewrite ASRU to identify page in rank */
@@ -434,7 +434,7 @@
action=confcall("rewrite-ASRU"); /* rewrite non-leaf ASRU in mem scheme */
event fault.memory.page_ue@chip/memory-controller/dimm/rank,
- FITrate=PAGE_FIT, ASRU=dimm/rank, message=0,
+ FITrate=PAGE_FIT, FRU=dimm, ASRU=dimm/rank, message=0,
action=confcall("rewrite-ASRU"); /* rewrite ASRU to identify page in rank */
event ereport.memory.dimm_ue_trip@chip/memory-controller/dimm/rank{within(5s)};
--- a/usr/src/cmd/fm/eversholt/files/i386/i86pc/intel.esc Wed Mar 26 11:58:25 2008 -0700
+++ b/usr/src/cmd/fm/eversholt/files/i386/i86pc/intel.esc Wed Mar 26 13:39:54 2008 -0700
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -315,6 +315,7 @@
event fault.memory.intel.page_ue@
motherboard/memory-controller/dram-channel/dimm/rank,
FITrate=PAGE_FIT,
+ FRU=motherboard/memory-controller/dram-channel/dimm,
ASRU=motherboard/memory-controller/dram-channel/dimm/rank, message=0,
action=confcall("rewrite-ASRU"); /* rewrite ASRU to identify page in rank */
event ereport.memory.page_ue_trip@motherboard/memory-controller{within(12s)};
@@ -442,6 +443,7 @@
event fault.memory.intel.page_ce@
motherboard/memory-controller/dram-channel/dimm/rank,
FITrate=PAGE_FIT,
+ FRU=motherboard/memory-controller/dram-channel/dimm,
ASRU=motherboard/memory-controller/dram-channel/dimm/rank, message=0,
count=stat.ce_pgflt@motherboard/memory-controller/dram-channel/dimm,
action=confcall("rewrite-ASRU"); /* rewrite ASRU to identify page in rank */
--- a/usr/src/cmd/fm/fmd/common/fmd_api.c Wed Mar 26 11:58:25 2008 -0700
+++ b/usr/src/cmd/fm/fmd/common/fmd_api.c Wed Mar 26 13:39:54 2008 -0700
@@ -1684,7 +1684,7 @@
fmd_module_t *mp;
topo_hdl_t *thp;
nvlist_t *nvl;
- char *loc = NULL;
+ char *loc = NULL, *serial = NULL;
int err;
mp = fmd_api_module_lock(hdl);
@@ -1698,6 +1698,21 @@
*/
(void) topo_fmri_label(thp, fru, &loc, &err);
+ /*
+ * In some cases, serial information for the resource will not be
+ * available at enumeration but may instead be available by invoking
+ * a dynamic property method on the FRU. In order to ensure the serial
+ * number is persisted properly in the ASRU cache, we'll fetch the
+ * property, if it exists, and add it to the resource and fru fmris.
+ */
+ if (fru != NULL) {
+ (void) topo_fmri_serial(thp, fru, &serial, &err);
+ if (serial != NULL) {
+ (void) nvlist_add_string(rsrc, "serial", serial);
+ (void) nvlist_add_string(fru, "serial", serial);
+ topo_hdl_strfree(thp, serial);
+ }
+ }
nvl = fmd_protocol_fault(class, certainty, asru, fru, rsrc, loc);
if (loc != NULL)
--- a/usr/src/cmd/fm/schemes/mem/mem.c Wed Mar 26 11:58:25 2008 -0700
+++ b/usr/src/cmd/fm/schemes/mem/mem.c Wed Mar 26 13:39:54 2008 -0700
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -36,6 +36,8 @@
#ifdef sparc
#include <sys/fm/ldom.h>
ldom_hdl_t *mem_scheme_lhp;
+#else
+#include <fm/libtopo.h>
#endif /* sparc */
mem_t mem;
@@ -169,6 +171,7 @@
return (0);
}
+#ifdef sparc
static int
serids_eq(char **serids1, uint_t nserids1, char **serids2, uint_t nserids2)
{
@@ -184,19 +187,28 @@
return (1);
}
+#endif /* sparc */
int
fmd_fmri_present(nvlist_t *nvl)
{
- char *unum, **nvlserids, **serids;
+ char *unum = NULL;
+ int rc;
+#ifdef sparc
+ char **nvlserids, **serids;
uint_t nnvlserids;
size_t nserids;
uint64_t memconfig;
- int rc;
+#else
+ struct topo_hdl *thp;
+ nvlist_t *unum_nvl;
+ int err;
+#endif /* sparc */
if (mem_fmri_get_unum(nvl, &unum) < 0)
return (-1); /* errno is set for us */
+#ifdef sparc
if (nvlist_lookup_string_array(nvl, FM_FMRI_MEM_SERIAL_ID, &nvlserids,
&nnvlserids) != 0) {
/*
@@ -246,7 +258,27 @@
rc = serids_eq(serids, nserids, nvlserids, nnvlserids);
mem_strarray_free(serids, nserids);
+#else
+ /*
+ * On X86 we will invoke the topo is_present method passing in the
+ * unum, which is in hc scheme. The libtopo hc-scheme is_present method
+ * will invoke the node-specific is_present method, which is implemented
+ * by the chip enumerator for rank nodes. The rank node's is_present
+ * method will compare the serial number in the unum with the current
+ * serial to determine if the same DIMM is present.
+ */
+ if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) {
+ fmd_fmri_warn("failed to get handle to topology");
+ return (-1);
+ }
+ if (topo_fmri_str2nvl(thp, unum, &unum_nvl, &err) == 0) {
+ rc = topo_fmri_present(thp, unum_nvl, &err);
+ nvlist_free(unum_nvl);
+ } else
+ rc = fmd_fmri_set_errno(EINVAL);
+ fmd_fmri_topo_rele(thp);
+#endif /* sparc */
return (rc);
}
--- a/usr/src/lib/fm/topo/libtopo/common/libtopo.h Wed Mar 26 11:58:25 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/libtopo.h Wed Mar 26 13:39:54 2008 -0700
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -89,6 +89,7 @@
extern int topo_fmri_fru(topo_hdl_t *, nvlist_t *, nvlist_t **,
int *);
extern int topo_fmri_label(topo_hdl_t *, nvlist_t *, char **, int *);
+extern int topo_fmri_serial(topo_hdl_t *, nvlist_t *, char **, int *);
extern int topo_fmri_compare(topo_hdl_t *, nvlist_t *, nvlist_t *, int *);
/*
--- a/usr/src/lib/fm/topo/libtopo/common/mapfile-vers Wed Mar 26 11:58:25 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/mapfile-vers Wed Mar 26 13:39:54 2008 -0700
@@ -40,6 +40,7 @@
topo_fmri_label;
topo_fmri_nvl2str;
topo_fmri_present;
+ topo_fmri_serial;
topo_fmri_setprop;
topo_fmri_str2nvl;
topo_fmri_unusable;
--- a/usr/src/lib/fm/topo/libtopo/common/topo_fmri.c Wed Mar 26 11:58:25 2008 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_fmri.c Wed Mar 26 13:39:54 2008 -0700
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -399,6 +399,29 @@
return (0);
}
+int
+topo_fmri_serial(topo_hdl_t *thp, nvlist_t *nvl, char **serial, int *err)
+{
+ nvlist_t *prop = NULL;
+ char *sp;
+
+ if (fmri_prop(thp, nvl, TOPO_PGROUP_PROTOCOL, FM_FMRI_HC_SERIAL_ID,
+ NULL, &prop, err) < 0)
+ return (set_error(thp, *err, err, "topo_fmri_serial", NULL));
+
+ if (nvlist_lookup_string(prop, TOPO_PROP_VAL_VAL, &sp) != 0)
+ return (set_error(thp, ETOPO_PROP_NVL, err, "topo_fmri_serial",
+ prop));
+
+ if ((*serial = topo_hdl_strdup(thp, sp)) == NULL)
+ return (set_error(thp, ETOPO_PROP_NOMEM, err,
+ "topo_fmri_serial", prop));
+
+ nvlist_free(prop);
+
+ return (0);
+}
+
int topo_fmri_getprop(topo_hdl_t *thp, nvlist_t *nvl, const char *pg,
const char *pname, nvlist_t *args, nvlist_t **prop,
int *err)
--- a/usr/src/lib/fm/topo/maps/i86pc/chip-hc-topology.xml Wed Mar 26 11:58:25 2008 -0700
+++ b/usr/src/lib/fm/topo/maps/i86pc/chip-hc-topology.xml Wed Mar 26 13:39:54 2008 -0700
@@ -48,7 +48,7 @@
</set>
<set type='product'
- setlist='Sun-Fire(TM)-X2100|Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4200E|Sun-Fire-X4500|X2100-M2|Sun-Blade-X8440-Server-Module|Sun-Fire-X4140|Sun-Fire-X4240|Sun-Fire-X4440'>
+ setlist='Sun-Fire(TM)-X2100|Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4200E|Sun-Fire-X4500|X2100-M2|Sun-Fire-X4140|Sun-Fire-X4240|Sun-Fire-X4440'>
<propgroup name='protocol' version='1'
name-stability='Private' data-stability='Private' >
@@ -97,6 +97,22 @@
</propgroup>
</set>
+ <set type='product'
+ setlist='Sun-Blade-X8420-Server-Module|Sun-Blade-X8440-Server-Module|SUN-BLADE-X8440-SERVER-MODULE'>
+
+ <propgroup name='protocol' version='1'
+ name-stability='Private' data-stability='Private' >
+
+ <propmethod name='a4fplus_chip_label' version='0'
+ propname='label' proptype='string' >
+
+ <argval name='format' type='string' value='CPU %d' />
+
+ </propmethod>
+
+ </propgroup>
+
+ </set>
<dependents grouping='children'>
@@ -167,7 +183,36 @@
</propgroup>
</set>
- <set type='product' setlist='Sun-Fire-V20z|Sun-Fire-V40z|Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4200E'>
+ <set type='product' setlist='Sun-Fire-V20z|Sun-Fire-V40z'>
+
+ <propgroup name='protocol' version='1'
+ name-stability='Private'
+ data-stability='Private' >
+
+ <propmethod name='simple_dimm_label_mp' version='0'
+ propname='label' proptype='string' >
+
+ <argval name='format' type='string'
+ value='CPU %d DIMM %d' />
+ <argval name='offset' type='uint32' value='0' />
+ <argval name='order' type='string'
+ value='forward' />
+ <argval name='dimms_per_chip' type='uint32'
+ value='4' />
+
+ </propmethod>
+ <propmethod name='get_dimm_serial' version='0'
+ propname='serial' proptype='string' >
+
+ <argval name='format' type='string'
+ value='cpu%d.mem%d.vpd' />
+ <argval name='offset' type='uint32' value='0' />
+
+ </propmethod>
+
+ </propgroup>
+ </set>
+ <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4200E|Sun-Fire-X4500'>
<propgroup name='protocol' version='1'
name-stability='Private'
@@ -185,6 +230,58 @@
value='4' />
</propmethod>
+ <propmethod name='get_dimm_serial' version='0'
+ propname='serial' proptype='string' >
+
+ <argval name='format' type='string'
+ value='p%d.d%d.fru' />
+ <argval name='offset' type='uint32' value='0' />
+
+ </propmethod>
+
+ </propgroup>
+
+ </set>
+ <set type='product' setlist='Sun-Fire-X4100-M2|Sun-Fire-X4200-M2'>
+
+ <propgroup name='protocol' version='1'
+ name-stability='Private'
+ data-stability='Private' >
+
+ <propmethod name='get_dimm_serial' version='0'
+ propname='serial' proptype='string' >
+
+ <argval name='format' type='string'
+ value='p%d.d%d.fru' />
+ <argval name='offset' type='uint32' value='0' />
+
+ </propmethod>
+
+ </propgroup>
+
+ </set>
+ <set type='product' setlist='Sun-Fire-X4600|Sun-Fire-X4600-M2'>
+
+ <propgroup name='protocol' version='1'
+ name-stability='Private'
+ data-stability='Private' >
+
+ <propmethod name='g4_dimm_label' version='0'
+ propname='label' proptype='string' >
+
+ <argval name='format' type='string'
+ value='%s DIMM %d' />
+ <argval name='offset' type='uint32' value='0' />
+
+ </propmethod>
+ <propmethod name='get_dimm_serial' version='0'
+ propname='serial' proptype='string' >
+
+ <argval name='format' type='string'
+ value='p%d.d%d.fru' />
+ <argval name='offset' type='uint32' value='0' />
+
+ </propmethod>
</propgroup>
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/Makefile Wed Mar 26 11:58:25 2008 -0700
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/Makefile Wed Mar 26 13:39:54 2008 -0700
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -27,8 +27,9 @@
MODULE = chip
ARCH = i86pc
CLASS = arch
-MODULESRCS = chip.c chip_label.c chip_subr.c chip_amd.c chip_intel.c
+MODULESRCS = chip.c chip_label.c chip_subr.c chip_amd.c chip_intel.c\
+chip_serial.c
include ../../Makefile.plugin
-LDLIBS += -lkstat
+LDLIBS += -lkstat -lipmi
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c Wed Mar 26 11:58:25 2008 -0700
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c Wed Mar 26 13:39:54 2008 -0700
@@ -77,6 +77,8 @@
TOPO_STABILITY_INTERNAL, simple_chip_label},
{ G4_CHIP_LBL, "Property method", 0,
TOPO_STABILITY_INTERNAL, g4_chip_label},
+ { A4FPLUS_CHIP_LBL, "Property method", 0,
+ TOPO_STABILITY_INTERNAL, a4fplus_chip_label},
{ NULL }
};
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h Wed Mar 26 11:58:25 2008 -0700
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h Wed Mar 26 13:39:54 2008 -0700
@@ -71,10 +71,17 @@
#define SIMPLE_DIMM_LBL "simple_dimm_label"
#define SIMPLE_DIMM_LBL_MP "simple_dimm_label_mp"
#define SEQ_DIMM_LBL "seq_dimm_label"
+#define G4_DIMM_LBL "g4_dimm_label"
#define SIMPLE_CHIP_LBL "simple_chip_label"
#define G4_CHIP_LBL "g4_chip_label"
+#define A4FPLUS_CHIP_LBL "a4fplus_chip_label"
#define SIMPLE_CS_LBL_MP "simple_cs_label_mp"
+/*
+ * DIMM serial number property methods
+ */
+#define GET_DIMM_SERIAL "get_dimm_serial"
+
typedef struct chip {
kstat_ctl_t *chip_kc;
kstat_t **chip_cpustats;
@@ -90,15 +97,24 @@
extern int seq_dimm_label(topo_mod_t *, tnode_t *, topo_version_t,
nvlist_t *, nvlist_t **);
+extern int g4_dimm_label(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
+ nvlist_t **);
+
extern int simple_chip_label(topo_mod_t *, tnode_t *, topo_version_t,
nvlist_t *, nvlist_t **);
extern int g4_chip_label(topo_mod_t *, tnode_t *, topo_version_t,
nvlist_t *, nvlist_t **);
+extern int a4fplus_chip_label(topo_mod_t *, tnode_t *, topo_version_t,
+ nvlist_t *, nvlist_t **);
+
extern int simple_cs_label_mp(topo_mod_t *, tnode_t *, topo_version_t,
nvlist_t *, nvlist_t **);
+extern int get_dimm_serial(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
+ nvlist_t **);
+
/*
* Support functions of chip_subr.c
*/
@@ -116,6 +132,8 @@
extern nvlist_t *mem_fmri_create(topo_mod_t *, const char *);
extern int mem_asru_compute(topo_mod_t *, tnode_t *, topo_version_t,
nvlist_t *, nvlist_t **);
+extern int rank_fmri_present(topo_mod_t *, tnode_t *, topo_version_t,
+ nvlist_t *, nvlist_t **);
extern int mem_asru_create(topo_mod_t *, nvlist_t *, nvlist_t **);
/*
@@ -130,6 +148,10 @@
extern int mc_offchip_open(void);
extern int mc_offchip_create(topo_mod_t *, tnode_t *, const char *, nvlist_t *);
+extern char *get_fmtstr(topo_mod_t *, nvlist_t *);
+extern int store_prop_val(topo_mod_t *, char *, char *, nvlist_t **out);
+
+
#ifdef __cplusplus
}
#endif
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_amd.c Wed Mar 26 11:58:25 2008 -0700
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_amd.c Wed Mar 26 13:39:54 2008 -0700
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -65,6 +65,10 @@
TOPO_STABILITY_INTERNAL, simple_dimm_label_mp},
{ SEQ_DIMM_LBL, "Property method", 0,
TOPO_STABILITY_INTERNAL, seq_dimm_label},
+ { G4_DIMM_LBL, "Property method", 0,
+ TOPO_STABILITY_INTERNAL, g4_dimm_label},
+ { GET_DIMM_SERIAL, "Property method", 0,
+ TOPO_STABILITY_INTERNAL, get_dimm_serial},
{ NULL }
};
@@ -72,6 +76,9 @@
{ TOPO_METH_ASRU_COMPUTE, TOPO_METH_ASRU_COMPUTE_DESC,
TOPO_METH_ASRU_COMPUTE_VERSION, TOPO_STABILITY_INTERNAL,
mem_asru_compute },
+ { TOPO_METH_PRESENT, TOPO_METH_PRESENT_DESC,
+ TOPO_METH_PRESENT_VERSION, TOPO_STABILITY_INTERNAL,
+ rank_fmri_present },
{ NULL }
};
@@ -391,7 +398,7 @@
}
if (topo_method_register(mod, dimmnode, dimm_methods) < 0)
- whinge(mod, &nerr, "dimm_create: "
+ whinge(mod, &nerr, "amd_dimm_create: "
"topo_method_register failed");
/*
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_label.c Wed Mar 26 11:58:25 2008 -0700
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_label.c Wed Mar 26 13:39:54 2008 -0700
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -32,12 +32,14 @@
#include <string.h>
#include <strings.h>
#include <libnvpair.h>
+#include <kstat.h>
+#include <unistd.h>
#include <sys/types.h>
#include <fm/topo_mod.h>
#define BUFSZ 128
-static char *
+char *
get_fmtstr(topo_mod_t *mod, nvlist_t *in)
{
char *fmtstr;
@@ -61,7 +63,7 @@
return (fmtstr);
}
-static int
+int
store_prop_val(topo_mod_t *mod, char *buf, char *propname, nvlist_t **out)
{
if (topo_mod_nvalloc(mod, out, NV_UNIQUE_NAME) != 0) {
@@ -471,6 +473,110 @@
}
/*
+ * Utility function used by a4fplus_chip_label to determine the number of chips
+ * (as opposed to processors) that are installed in the system by dividing the
+ * number of installed processors (cores) by the number of cores per chip
+ * (from kstat). This assumes that an an A4F+ blade won't have some weird
+ * configuration of mixed chip models with differing numbers of cores per chip,
+ * which I think is a relatively safe assumption here.
+ */
+static int
+get_num_chips(topo_mod_t *mod)
+{
+ kstat_t *ksp;
+ kstat_ctl_t *kctl;
+ kstat_named_t *k;
+
+ if ((kctl = kstat_open()) == NULL) {
+ topo_mod_dprintf(mod, NULL, "kstat_open failed (%s)\n",
+ strerror(errno));
+ return (-1);
+ }
+ if ((ksp = kstat_lookup(kctl, "cpu_info", -1, NULL)) == NULL) {
+ topo_mod_dprintf(mod, NULL, "kstat_lookup failed (%s)\n",
+ strerror(errno));
+ (void) kstat_close(kctl);
+ return (-1);
+ }
+ if (kstat_read(kctl, ksp, NULL) < 0) {
+ topo_mod_dprintf(mod, NULL, "kstat_read failed (%s)\n",
+ strerror(errno));
+ (void) kstat_close(kctl);
+ return (-1);
+ }
+ if ((k = kstat_data_lookup(ksp, "ncore_per_chip")) == NULL) {
+ topo_mod_dprintf(mod, NULL, "kstat_data_lookup failed (%s)\n",
+ strerror(errno));
+ (void) kstat_close(kctl);
+ return (-1);
+ }
+ (void) kstat_close(kctl);
+ return (sysconf(_SC_NPROCESSORS_CONF) / k->value.l);
+}
+
+/*
+ * This is a custom property method for generating the CPU slot label for the
+ * Andromeda Fplus platforms.
+ *
+ * format: a string containing a printf-like format with a single %d token
+ * which this method computes
+ *
+ * i.e.: CPU %d
+ */
+/* ARGSUSED */
+int
+a4fplus_chip_label(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
+ nvlist_t *in, nvlist_t **out)
+{
+ char *fmtstr, buf[BUFSZ];
+ int num_nodes;
+
+ topo_mod_dprintf(mod, "a4fplus_chip_label() called\n");
+ if ((fmtstr = get_fmtstr(mod, in)) == NULL) {
+ topo_mod_dprintf(mod, "Failed to retrieve 'format' arg\n");
+ /* topo errno already set */
+ return (-1);
+ }
+
+ /*
+ * Normally we'd figure out the total number of chip nodes by looking
+ * at the CoherentNodes property. However, due to the lack of a memory
+ * controller driver for family 0x10, this property wont exist on the
+ * chip nodes on A4Fplus.
+ */
+ if ((num_nodes = get_num_chips(mod)) < 0) {
+ topo_mod_dprintf(mod, "Failed to determine number of chip "
+ "nodes\n");
+ return (topo_mod_seterrno(mod, EMOD_UNKNOWN));
+ }
+ switch (num_nodes) {
+ case (2):
+ /* LINTED: E_SEC_PRINTF_VAR_FMT */
+ (void) snprintf(buf, BUFSZ, fmtstr,
+ topo_node_instance(node) + 2);
+ break;
+ case (4):
+ /* LINTED: E_SEC_PRINTF_VAR_FMT */
+ (void) snprintf(buf, BUFSZ, fmtstr,
+ topo_node_instance(node));
+ break;
+ default:
+ topo_mod_dprintf(mod, "Invalid number of chip nodes:"
+ " %d\n", num_nodes);
+ return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+ }
+
+
+ if (store_prop_val(mod, buf, "label", out) != 0) {
+ topo_mod_dprintf(mod, "Failed to set label\n");
+ /* topo errno already set */
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
* This is a somewhat generic property method for labelling the chip-select
* nodes on multi-socket AMD family 0x10 platforms. This is necessary because
* these platforms are not supported by the current AMD memory controller driver
@@ -542,3 +648,61 @@
return (0);
}
+
+/* ARGSUSED */
+int
+g4_dimm_label(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
+ nvlist_t *in, nvlist_t **out)
+{
+ char *fmtstr, *chip_lbl, buf[BUFSZ];
+ tnode_t *chip;
+ int ret, err = 0;
+ uint32_t offset;
+ nvlist_t *args;
+
+ topo_mod_dprintf(mod, "g4_dimm_label() called\n");
+
+ if ((ret = nvlist_lookup_nvlist(in, TOPO_PROP_ARGS, &args)) != 0) {
+ topo_mod_dprintf(mod, "Failed to lookup 'args' list (%s)\n",
+ strerror(ret));
+ return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+ }
+ if ((ret = nvlist_lookup_uint32(args, "offset", &offset)) != 0) {
+ topo_mod_dprintf(mod, "Failed to lookup 'offset' arg (%s)\n",
+ strerror(ret));
+ return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+ }
+ if ((fmtstr = get_fmtstr(mod, in)) == NULL) {
+ topo_mod_dprintf(mod, "Failed to retrieve 'format' arg\n");
+ /* topo errno already set */
+ return (-1);
+ }
+
+ /*
+ * The 4600/4600M2 have a weird way of labeling the chip nodes, so
+ * instead of trying to recompute it, we'll simply look it up and
+ * prepend it to our dimm label.
+ */
+ chip = topo_node_parent(topo_node_parent(node));
+ if (topo_prop_get_string(chip, TOPO_PGROUP_PROTOCOL, "label", &chip_lbl,
+ &err) != 0) {
+ topo_mod_dprintf(mod, "Failed to lookup label prop on %s=%d\n",
+ topo_node_name(chip), topo_node_instance(chip),
+ topo_strerror(err));
+ return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+ }
+
+ /* LINTED: E_SEC_PRINTF_VAR_FMT */
+ (void) snprintf(buf, BUFSZ, fmtstr, chip_lbl,
+ (topo_node_instance(node) + offset));
+
+ topo_mod_strfree(mod, chip_lbl);
+
+ if (store_prop_val(mod, buf, "label", out) != 0) {
+ topo_mod_dprintf(mod, "Failed to set label\n");
+ /* topo errno already set */
+ return (-1);
+ }
+
+ return (0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_serial.c Wed Mar 26 13:39:54 2008 -0700
@@ -0,0 +1,246 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <strings.h>
+#include <libnvpair.h>
+#include <sys/types.h>
+#include <libipmi.h>
+#include <fm/topo_mod.h>
+#include <ctype.h>
+#include "chip.h"
+
+#define BUFSZ 128
+#define JEDEC_TBL_SZ 4
+
+/*
+ * The following table maps DIMM manufacturer names to a JEDEC ID as sourced
+ * from JEDEC publication JEP106W. This is (obviously) a sparse table which
+ * only contains entries for manufacturers whose DIMM's have been qualified
+ * for use on Sun platforms.
+ */
+static const char *jedec_tbl[JEDEC_TBL_SZ][2] =
+{
+ { "INFINEON", "00C1" },
+ { "MICRON TECHNOLOGY", "002C" },
+ { "QIMONDA", "7F51" },
+ { "SAMSUNG", "00CE" },
+};
+
+static int
+ipmi_serial_lookup(topo_mod_t *mod, char *ipmi_tag, char *buf)
+{
+ char *fru_data;
+ int i, found_id = 0, serial_len;
+ ipmi_handle_t *hdl;
+ ipmi_sdr_fru_locator_t *fru_loc;
+ ipmi_fru_prod_info_t prod_info;
+
+ topo_mod_dprintf(mod, "ipmi_serial_lookup() called\n");
+ if ((hdl = topo_mod_ipmi(mod)) == NULL) {
+ topo_mod_dprintf(mod, "Failed to get IPMI handle\n");
+ return (topo_mod_seterrno(mod, EMOD_UNKNOWN));
+ }
+
+ topo_mod_dprintf(mod, "Looking up FRU data for %s ...\n", ipmi_tag);
+ if ((fru_loc = ipmi_sdr_lookup_fru(hdl, (const char *)ipmi_tag))
+ == NULL) {
+ topo_mod_dprintf(mod, "Failed to lookup %s (%s)\n", ipmi_tag,
+ ipmi_errmsg(hdl));
+ return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+ }
+
+
+ topo_mod_dprintf(mod, "Reading FRU data ...\n");
+ if (ipmi_fru_read(hdl, fru_loc, &fru_data) < 0) {
+ topo_mod_dprintf(mod, "Failed to read FRU data (%s)\n",
+ ipmi_errmsg(hdl));
+ return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+ }
+
+ topo_mod_dprintf(mod, "Parsing product info area ...\n");
+ if (ipmi_fru_parse_product(hdl, fru_data, &prod_info) < 0) {
+ topo_mod_dprintf(mod, "Failed to read FRU product info (%s)\n",
+ ipmi_errmsg(hdl));
+ free(fru_data);
+ return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+ }
+ free(fru_data);
+
+ topo_mod_dprintf(mod, "FRU Product Serial: %s\n",
+ prod_info.ifpi_product_serial);
+ topo_mod_dprintf(mod, "Manufacturer Name: \"%s\"\n",
+ prod_info.ifpi_manuf_name);
+
+ serial_len = strnlen(prod_info.ifpi_product_serial, FRU_INFO_MAXLEN);
+
+ /*
+ * Newer ILOM software that has the fix for CR 6607996 will have
+ * an 18-character serial number that has been synthesized using
+ * the recipe from the Sun SPD JEDEC DIMM specification. If we
+ * find an 18-character then we'll simply use it, as-is, and
+ * return.
+ */
+ if (serial_len == 18) {
+ (void) memcpy(buf, prod_info.ifpi_product_serial, 18);
+ *(buf+18) = '\0';
+ return (0);
+ }
+ /*
+ * Older ILOM software that DOESN'T have the fix for CR 6607996 will
+ * only provide the 8 character manufacturer serial number.
+ *
+ * However, if for some reason the product info area doesn't have the
+ * serial information or if the serial isn't 8 characters (we may
+ * encounter SP's that don't populate the serial field or are buggy and
+ * populate it with garbage), then we'll stop right now and just set the
+ * buf to an empty string.
+ */
+ if (serial_len != 8) {
+ *buf = '\0';
+ return (0);
+ }
+
+ /*
+ * What follows is a very crude adaptation of the recipe from the
+ * Sun SPD JEDEC DIMM specification for synthesizing globally unique
+ * serial numbers from the 8 character manufacturer serial number.
+ *
+ * The Sun serial number takes the following form:
+ *
+ * jjjjllyywwssssssss
+ *
+ * The components are:
+ *
+ * yyyy: JEDEC ID in hex (2 byte manufacture ID, 2 byte continuation
+ * code).
+ *
+ * ll: The memory module's manufacturing location.
+ *
+ * yyww: The module's manufacturing date (2-digit year/2-digit week)
+ *
+ * ssssssss: The 8 character maufacturer serial number
+ */
+ /*
+ * First we need to normalize the manufacturer name we pulled out of
+ * the FRU product info area. Our normalization algorithm is fairly
+ * simple:
+ * - convert all alpha chars to uppercase
+ * - convert non-alphanumeric characters to a single space
+ *
+ * We use the normalized name to lookup the JEDEC ID from a static
+ * table. If the FRU area didn't have a manufacturer name or if the ID
+ * lookup fails we'll set jjjj to 0000.
+ */
+ for (i = 0; prod_info.ifpi_manuf_name[i]; i++) {
+ prod_info.ifpi_manuf_name[i] =
+ toupper(prod_info.ifpi_manuf_name[i]);
+ if (!isalpha(prod_info.ifpi_manuf_name[i]) &&
+ !isdigit(prod_info.ifpi_manuf_name[i]))
+ prod_info.ifpi_manuf_name[i] = (char)0x20;
+ }
+ topo_mod_dprintf(mod, "Normalized Manufacturer Name \"%s\"\n",
+ prod_info.ifpi_manuf_name);
+
+ for (i = 0; i < JEDEC_TBL_SZ; i++)
+ if (strcmp(prod_info.ifpi_manuf_name, jedec_tbl[i][0]) == 0) {
+ found_id = 1;
+ break;
+ }
+
+ if (found_id)
+ (void) memcpy(buf, jedec_tbl[i][1], 4);
+ else
+ (void) memcpy(buf, (char *)("0000"), 4);
+
+ /*
+ * The manufacturing location and date is not available via IPMI on
+ * Sun platforms, so we simply set these six digits to zeros.
+ */
+ (void) memcpy((buf+4), (char *)("000000"), 6);
+
+ /*
+ * Finally, we just copy the 8 character product serial straight over
+ * and then NULL terminate the string.
+ */
+ (void) memcpy((buf+10), prod_info.ifpi_product_serial, 8);
+ *(buf+18) = '\0';
+
+ return (0);
+}
+
+/* ARGSUSED */
+int
+get_dimm_serial(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
+ nvlist_t *in, nvlist_t **out)
+{
+ char *fmtstr, ipmi_tag[BUFSZ], fru_serial[FRU_INFO_MAXLEN];
+ tnode_t *chip;
+ int ret;
+ uint32_t offset;
+ nvlist_t *args;
+
+ topo_mod_dprintf(mod, "get_dimm_serial() called\n");
+ if ((ret = nvlist_lookup_nvlist(in, "args", &args)) != 0) {
+ topo_mod_dprintf(mod, "Failed to lookup 'args' list (%s)\n",
+ strerror(ret));
+ return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+ }
+ if ((ret = nvlist_lookup_uint32(args, "offset", &offset)) != 0) {
+ topo_mod_dprintf(mod, "Failed to lookup 'offset' arg (%s)\n",
+ strerror(ret));
+ return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+ }
+ if ((fmtstr = get_fmtstr(mod, in)) == NULL) {
+ /* topo errno set */
+ topo_mod_dprintf(mod, "Failed to retrieve format arg\n");
+ return (-1);
+ }
+
+ chip = topo_node_parent(topo_node_parent(node));
+
+ /* LINTED: E_SEC_PRINTF_VAR_FMT */
+ (void) snprintf(ipmi_tag, BUFSZ, fmtstr, topo_node_instance(chip),
+ (topo_node_instance(node) + offset));
+
+ if (ipmi_serial_lookup(mod, ipmi_tag, fru_serial) != 0) {
+ topo_mod_dprintf(mod, "Failed to lookup serial for %s\n",
+ ipmi_tag);
+ (void) strcpy(fru_serial, "");
+ }
+
+ if (store_prop_val(mod, fru_serial, "serial", out) != 0) {
+ topo_mod_dprintf(mod, "Failed to set serial\n");
+ /* topo errno already set */
+ return (-1);
+ }
+ return (0);
+}
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_subr.c Wed Mar 26 11:58:25 2008 -0700
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_subr.c Wed Mar 26 13:39:54 2008 -0700
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -390,3 +390,67 @@
return (0);
}
+
+/*
+ * If we're getting called then the question of whether this dimm is plugged
+ * in has already been answered. What we don't know for sure is whether it's
+ * the same dimm or a different one plugged in the same slot. To check, we
+ * try and compare the serial numbers on the dimm in the current topology with
+ * the serial num from the unum fmri that got passed into this function as the
+ * argument.
+ *
+ * In the event we encounter problems comparing serials or if a comparison isn't
+ * possible, we err on the side of caution and set is_present to TRUE.
+ */
+/* ARGSUSED */
+int
+rank_fmri_present(topo_mod_t *mod, tnode_t *node, topo_version_t version,
+ nvlist_t *in, nvlist_t **out)
+{
+ tnode_t *dimmnode;
+ int err, is_present = 1;
+ nvlist_t *unum;
+ char *curr_serial, *old_serial = NULL;
+
+ /*
+ * If a serial number for the dimm was available at the time of the
+ * fault, it will have been added as a string to the unum nvlist
+ */
+ unum = in;
+ if (nvlist_lookup_string(unum, FM_FMRI_HC_SERIAL_ID, &old_serial) != 0)
+ goto done;
+
+ /*
+ * If the current serial number is available for the DIMM that this rank
+ * belongs to, it will be accessible as a property on the parent (dimm)
+ * node.
+ */
+ dimmnode = topo_node_parent(node);
+ if (topo_prop_get_string(dimmnode, TOPO_PGROUP_PROTOCOL,
+ FM_FMRI_HC_SERIAL_ID, &curr_serial, &err) != 0) {
+ if (err != ETOPO_PROP_NOENT) {
+ whinge(mod, &err, "rank_fmri_present: Unexpected error "
+ "retrieving serial from node");
+ return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+ } else
+ goto done;
+ }
+
+ if (strcmp(old_serial, curr_serial) != 0)
+ is_present = 0;
+
+ topo_mod_strfree(mod, curr_serial);
+done:
+ if (topo_mod_nvalloc(mod, out, NV_UNIQUE_NAME) < 0) {
+ whinge(mod, &err,
+ "rank_fmri_present: failed to allocate nvlist!");
+ return (topo_mod_seterrno(mod, EMOD_NOMEM));
+ }
+
+ if (nvlist_add_uint32(*out, TOPO_METH_PRESENT_RET, is_present) != 0) {
+ nvlist_free(*out);
+ return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+ }
+
+ return (0);
+}
--- a/usr/src/lib/libipmi/common/ipmi_fru.c Wed Mar 26 11:58:25 2008 -0700
+++ b/usr/src/lib/libipmi/common/ipmi_fru.c Wed Mar 26 13:39:54 2008 -0700
@@ -55,6 +55,7 @@
uint8_t count, devid;
uint16_t sz, offset = 0;
ipmi_fru_read_t cmd_data_in;
+ char *tmp;
devid = fru_loc->_devid_or_slaveaddr._logical._is_fl_devid;
/*
@@ -76,7 +77,7 @@
}
(void) memcpy(&sz, resp->ic_data, sizeof (uint16_t));
- if ((*buf = malloc(sz)) == NULL) {
+ if ((tmp = malloc(sz)) == NULL) {
(void) ipmi_set_error(ihp, EIPMI_NOMEM, NULL);
return (-1);
}
@@ -96,18 +97,22 @@
cmd.ic_dlen = sizeof (ipmi_fru_read_t);
cmd.ic_lun = 0;
- if ((resp = ipmi_send(ihp, &cmd)) == NULL)
+ if ((resp = ipmi_send(ihp, &cmd)) == NULL) {
+ free(tmp);
return (-1);
+ }
(void) memcpy(&count, resp->ic_data, sizeof (uint8_t));
if (count != cmd_data_in.ifr_count) {
(void) ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH,
NULL);
+ free(tmp);
return (-1);
}
- (void) memcpy((*buf)+offset, (char *)(resp->ic_data)+1, count);
+ (void) memcpy(tmp+offset, (char *)(resp->ic_data)+1, count);
offset += count;
}
+ *buf = tmp;
return (sz);
}
@@ -136,35 +141,35 @@
tmp = fru_area + (fru_hdr.ifh_product_info_off * 8) + 3;
(void) memcpy(&typelen, tmp, sizeof (uint8_t));
- len = BITX(typelen, 4, 0);
+ len = BITX(typelen, 5, 0);
ipmi_decode_string((typelen >> 6), len, tmp+1, buf->ifpi_manuf_name);
tmp += len + 1;
(void) memcpy(&typelen, tmp, sizeof (uint8_t));
- len = BITX(typelen, 4, 0);
+ len = BITX(typelen, 5, 0);
ipmi_decode_string((typelen >> 6), len, tmp+1,
buf->ifpi_product_name);
tmp += len + 1;
(void) memcpy(&typelen, tmp, sizeof (uint8_t));
- len = BITX(typelen, 4, 0);
+ len = BITX(typelen, 5, 0);
ipmi_decode_string((typelen >> 6), len, tmp+1, buf->ifpi_part_number);
tmp += len + 1;
(void) memcpy(&typelen, tmp, sizeof (uint8_t));
- len = BITX(typelen, 4, 0);
+ len = BITX(typelen, 5, 0);
ipmi_decode_string((typelen >> 6), len, tmp+1,
buf->ifpi_product_version);
tmp += len + 1;
(void) memcpy(&typelen, tmp, sizeof (uint8_t));
- len = BITX(typelen, 4, 0);
+ len = BITX(typelen, 5, 0);
ipmi_decode_string((typelen >> 6), len, tmp+1,
buf->ifpi_product_serial);
tmp += len + 1;
(void) memcpy(&typelen, tmp, sizeof (uint8_t));
- len = BITX(typelen, 4, 0);
+ len = BITX(typelen, 5, 0);
ipmi_decode_string((typelen >> 6), len, tmp+1, buf->ifpi_asset_tag);
return (0);
@@ -202,23 +207,23 @@
tmp += 3;
(void) memcpy(&typelen, tmp, sizeof (uint8_t));
- len = BITX(typelen, 4, 0);
+ len = BITX(typelen, 5, 0);
ipmi_decode_string((typelen >> 6), len, tmp+1, buf->ifbi_manuf_name);
tmp += len + 1;
(void) memcpy(&typelen, tmp, sizeof (uint8_t));
- len = BITX(typelen, 4, 0);
+ len = BITX(typelen, 5, 0);
ipmi_decode_string((typelen >> 6), len, tmp+1, buf->ifbi_board_name);
tmp += len + 1;
(void) memcpy(&typelen, tmp, sizeof (uint8_t));
- len = BITX(typelen, 4, 0);
+ len = BITX(typelen, 5, 0);
ipmi_decode_string((typelen >> 6), len, tmp+1,
buf->ifbi_product_serial);
tmp += len + 1;
(void) memcpy(&typelen, tmp, sizeof (uint8_t));
- len = BITX(typelen, 4, 0);
+ len = BITX(typelen, 5, 0);
ipmi_decode_string((typelen >> 6), len, tmp+1, buf->ifbi_part_number);
return (0);