PSARC/2008/092 OPL Ikkaku Platform Support
6655597 Support for SPARC Enterprise Ikkaku
--- a/usr/src/cmd/fm/modules/sun4u/cpumem-diagnosis/cmd_opl.c Wed Mar 26 17:37:28 2008 -0700
+++ b/usr/src/cmd/fm/modules/sun4u/cpumem-diagnosis/cmd_opl.c Wed Mar 26 20:38:30 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.
*/
@@ -166,6 +166,9 @@
comp = frustr + sizeof (OPL_CPU_FRU_FMRI_FF2) - 1;
(void) sscanf(comp, "%d", &cmu_num);
cmu_num /= 2;
+ } else if (strncmp(frustr, OPL_CPU_FRU_FMRI_IKKAKU,
+ sizeof (OPL_CPU_FRU_FMRI_IKKAKU) - 1) == 0) {
+ cmu_num = 0;
} else {
CMD_STAT_BUMP(bad_cpu_asru);
fmd_hdl_strfree(hdl, frustr);
--- a/usr/src/cmd/fm/modules/sun4u/cpumem-diagnosis/cmd_opl.h Wed Mar 26 17:37:28 2008 -0700
+++ b/usr/src/cmd/fm/modules/sun4u/cpumem-diagnosis/cmd_opl.h Wed Mar 26 20:38:30 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.
*/
@@ -116,6 +116,8 @@
FM_FMRI_LEGACY_HC"=/MBU_A/CPUM"
#define OPL_CPU_FRU_FMRI_FF2 FM_FMRI_SCHEME_HC":///" \
FM_FMRI_LEGACY_HC"=/MBU_B/CPUM"
+#define OPL_CPU_FRU_FMRI_IKKAKU FM_FMRI_SCHEME_HC":///" \
+ FM_FMRI_LEGACY_HC"=/MBU_A"
#define STR_BUFLEN 32
#define NPAIRS 5
--- a/usr/src/cmd/fm/schemes/mem/mem_unum.c Wed Mar 26 17:37:28 2008 -0700
+++ b/usr/src/cmd/fm/schemes/mem/mem_unum.c Wed Mar 26 20:38:30 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.
*/
@@ -93,6 +93,7 @@
{ "MB/C%*d/P%*d/%nB%*d/D%*d:%n%n", " B%*d/D%*d%n" },
{ "/MBU_A/MEMB%*d/%n%nMEM%*d%*1c%n", " MEM%*d%*1c%n" },
{ "/MBU_B/MEMB%*d/%n%nMEM%*d%*1c%n", " MEM%*d%*1c%n" },
+ { "/MBU_A/%n%nMEM%*d%*1c%n", " MEM%*d%*1c%n" },
{ "/CMU%*2d/%n%nMEM%*2d%*1c%n", " MEM%*2d%*1c%n" },
{ "MB/CMP%*d/BR%*d%n:%n%n", " CH%*d/D%*d/J%*4d%n", "/" },
{ "%n%nMB/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n",
--- a/usr/src/lib/fm/topo/modules/SUNW,SPARC-Enterprise/ioboard/opl_ioboard.c Wed Mar 26 17:37:28 2008 -0700
+++ b/usr/src/lib/fm/topo/modules/SUNW,SPARC-Enterprise/ioboard/opl_ioboard.c Wed Mar 26 20:38:30 2008 -0700
@@ -42,6 +42,10 @@
#define LABEL FRUNAME "#%d"
#define IOBDFRU "hc:///component=" LABEL
+#define IKKAKU_FRUNAME "MBU_A"
+#define IKKAKU_LABEL IKKAKU_FRUNAME
+#define IKKAKU_IOBDFRU "hc:///component=" IKKAKU_LABEL
+
static int opl_iob_enum(topo_mod_t *hdl, tnode_t *parent, const char *name,
topo_instance_t imin, topo_instance_t imax, void *notused1, void *notused2);
@@ -54,6 +58,13 @@
IOB_ENUMR_VERS,
&Iobops};
+/* OPL model type */
+typedef enum {
+ MODEL_FF,
+ MODEL_DC,
+ MODEL_IKKAKU
+} opl_model_t;
+
void
_topo_init(topo_mod_t *modhdl)
{
@@ -148,9 +159,12 @@
/*
* Create the ioboard node. Add fru and label properties, and create room
* for child hostbridge nodes.
+ *
+ * Only IKKAKU model has different IO topology.
*/
static tnode_t *
-opl_iob_node_create(topo_mod_t *mp, tnode_t *parent, int inst)
+opl_iob_node_create(topo_mod_t *mp, tnode_t *parent, int inst,
+ opl_model_t opl_model)
{
int err;
tnode_t *ion;
@@ -182,13 +196,19 @@
}
nvlist_free(fmri);
/* Create and add FRU fmri for this ioboard */
- (void) snprintf(fmri_str, sizeof (fmri_str), IOBDFRU, inst);
+ if (opl_model == MODEL_IKKAKU)
+ (void) snprintf(fmri_str, sizeof (fmri_str), IKKAKU_IOBDFRU);
+ else
+ (void) snprintf(fmri_str, sizeof (fmri_str), IOBDFRU, inst);
if (topo_mod_str2nvl(mp, fmri_str, &fmri) == 0) {
(void) topo_node_fru_set(ion, fmri, 0, &err);
nvlist_free(fmri);
}
/* Add label for this ioboard */
- (void) snprintf(label, sizeof (label), LABEL, inst);
+ if (opl_model == MODEL_IKKAKU)
+ (void) snprintf(label, sizeof (label), IKKAKU_LABEL);
+ else
+ (void) snprintf(label, sizeof (label), LABEL, inst);
(void) topo_node_label_set(ion, label, &err);
/* Create range of hostbridges on this ioboard */
@@ -201,6 +221,29 @@
return (ion);
}
+/*
+ * get the OPL model name from rootnode property "model"
+ */
+static int
+opl_get_model(topo_mod_t *mp, di_node_t opl_devtree, char *model)
+{
+ char *bufp;
+ di_prom_handle_t promh = DI_PROM_HANDLE_NIL;
+
+ if (opl_devtree == DI_NODE_NIL ||
+ (promh = topo_mod_prominfo(mp)) == DI_PROM_HANDLE_NIL)
+ return (-1);
+
+ if (di_prom_prop_lookup_bytes(promh, opl_devtree, "model",
+ (unsigned char **)&bufp) != -1) {
+ (void) strlcpy(model, bufp, MAXNAMELEN);
+ return (0);
+ } else {
+ return (-1);
+ }
+
+}
+
/*ARGSUSED*/
static int
opl_iob_enum(topo_mod_t *mp, tnode_t *parent, const char *name,
@@ -213,6 +256,8 @@
int lsb_to_psb[OPL_IOB_MAX];
ioboard_contents_t ioboard_list[OPL_IOB_MAX];
int retval = 0;
+ char model[MAXNAMELEN];
+ opl_model_t opl_model = MODEL_FF;
/* Validate the name is correct */
if (strcmp(name, "ioboard") != 0) {
@@ -232,6 +277,19 @@
return (-1);
}
+ if (opl_get_model(mp, opl_devtree, model) == -1) {
+ topo_mod_dprintf(mp, "opl_get_model failed.\n");
+ } else {
+ if (strncmp(model, "FF", 2) == 0)
+ opl_model = MODEL_FF;
+ else if (strncmp(model, "DC", 2) == 0)
+ opl_model = MODEL_DC;
+ else if (strcmp(model, "IKKAKU") == 0)
+ opl_model = MODEL_IKKAKU;
+
+ topo_mod_dprintf(mp, "opl_get_model %s found.\n", model);
+ }
+
/*
* Create a mapping from logical board numbers (which are part of
* the device node bus address) to physical board numbers, so we
@@ -280,7 +338,7 @@
continue;
}
/* Create node for this ioboard */
- ion = opl_iob_node_create(mp, parent, inst);
+ ion = opl_iob_node_create(mp, parent, inst, opl_model);
if (ion == NULL) {
topo_mod_dprintf(mp,
"enumeration of ioboard failed: %s\n",
--- a/usr/src/uts/sun4u/opl/io/mc-opl.c Wed Mar 26 17:37:28 2008 -0700
+++ b/usr/src/uts/sun4u/opl/io/mc-opl.c Wed Mar 26 20:38:30 2008 -0700
@@ -23,7 +23,7 @@
* Use is subject to license terms.
*/
/*
- * All Rights Reserved, Copyright (c) FUJITSU LIMITED 2007
+ * All Rights Reserved, Copyright (c) FUJITSU LIMITED 2008
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -157,9 +157,10 @@
*/
static enum {
- MODEL_FF1 = 0,
- MODEL_FF2 = 1,
- MODEL_DC = 2
+ MODEL_FF1,
+ MODEL_FF2,
+ MODEL_DC,
+ MODEL_IKKAKU
} plat_model = MODEL_DC; /* The default behaviour is DC */
static struct plat_model_names {
@@ -168,7 +169,8 @@
} model_names[] = {
{ "MBU_A", "MEMB" },
{ "MBU_B", "MEMB" },
- { "CMU", "" }
+ { "CMU", "" },
+ { "MBU_A", "" }
};
/*
@@ -191,7 +193,7 @@
};
/*
- * The DIMM Names for FF1/FF2 platforms.
+ * The DIMM Names for FF1/FF2/IKKAKU platforms.
* The index into this table is made up of (board, bank, dslot),
* Where dslot occupies bits 0-1, bank occupies 2-4 and
* board occupies the bit 5.
@@ -384,6 +386,8 @@
plat_model = MODEL_FF2;
else if (strncmp(model, "DC", 2) == 0)
plat_model = MODEL_DC;
+ else if (strcmp(model, "IKKAKU") == 0)
+ plat_model = MODEL_IKKAKU;
}
error = mod_install(&modlinkage);
@@ -816,10 +820,15 @@
* y = 0..3 (slot info).
* Z = 'A' or 'B'
*
- * UNUM format for FF2 is "/MBU_B/MEMBx/MEMyZ"
+ * UNUM format for FF2 is "/MBU_B/MEMBx/MEMyZ", where
* x = 0..7 (MEMB number)
* y = 0..3 (slot info).
* Z = 'A' or 'B'
+ *
+ * UNUM format for IKKAKU is "/MBU_A/MEMyZ", where
+ * y = 0..3 (slot info).
+ * Z = 'A' or 'B'
+ *
*/
int
mc_set_mem_unum(char *buf, int buflen, int sb, int bank,
@@ -833,7 +842,8 @@
cs = SLOT_TO_CS(d_slot);
- if (plat_model == MODEL_DC) {
+ switch (plat_model) {
+ case MODEL_DC:
if (mf_type == FLT_TYPE_INTERMITTENT_CE ||
mf_type == FLT_TYPE_PERMANENT_CE) {
i = BD_BK_SLOT_TO_INDEX(0, bank, d_slot);
@@ -848,7 +858,9 @@
mc_dc_dimm_unum_table[j],
mc_dc_dimm_unum_table[j + 1]);
}
- } else {
+ break;
+ case MODEL_FF1:
+ case MODEL_FF2:
if (mf_type == FLT_TYPE_INTERMITTENT_CE ||
mf_type == FLT_TYPE_PERMANENT_CE) {
i = BD_BK_SLOT_TO_INDEX(sb, bank, d_slot);
@@ -868,6 +880,26 @@
&mc_ff_dimm_unum_table[j][1],
&mc_ff_dimm_unum_table[j + 1][1]);
}
+ break;
+ case MODEL_IKKAKU:
+ if (mf_type == FLT_TYPE_INTERMITTENT_CE ||
+ mf_type == FLT_TYPE_PERMANENT_CE) {
+ i = BD_BK_SLOT_TO_INDEX(sb, bank, d_slot);
+ dimmnm = mc_ff_dimm_unum_table[i];
+ snprintf(buf, buflen, "/%s/MEM%s",
+ model_names[plat_model].unit_name, &dimmnm[1]);
+ } else {
+ i = BD_BK_SLOT_TO_INDEX(sb, bank, 0);
+ j = (cs == 0) ? i : i + 2;
+ memb_num = mc_ff_dimm_unum_table[i][0],
+ snprintf(buf, buflen, "/%s/MEM%s MEM%s",
+ model_names[plat_model].unit_name,
+ &mc_ff_dimm_unum_table[j][1],
+ &mc_ff_dimm_unum_table[j + 1][1]);
+ }
+ break;
+ default:
+ return (-1);
}
return (0);
}
@@ -2133,11 +2165,11 @@
if (wrapped) {
MAC_CLEAR_MAX(mcp, i);
mcp->mc_period[ebk]++;
- if (IS_MIRROR(mcp, i))
+ if (IS_MIRROR(mcp, i)) {
MC_LOG("mirror mc period %ld on "
"/LSB%d/B%d\n", mcp->mc_period[ebk],
mcp->mc_board_num, i);
- else {
+ } else {
MC_LOG("mc period %ld on "
"/LSB%d/B%d\n", mcp->mc_period[ebk],
mcp->mc_board_num, i);
@@ -2913,6 +2945,7 @@
int sb;
int bank;
int cs;
+ int rv = 0;
mc_opl_t *mcp;
char memb_num;
@@ -2939,14 +2972,17 @@
return (ENXIO);
}
- if (plat_model == MODEL_DC) {
+ switch (plat_model) {
+ case MODEL_DC:
i = BD_BK_SLOT_TO_INDEX(0, bank, 0);
j = (cs == 0) ? i : i + 2;
snprintf(buf, buflen, "/%s%02d/MEM%s MEM%s",
model_names[plat_model].unit_name, sb,
mc_dc_dimm_unum_table[j],
mc_dc_dimm_unum_table[j + 1]);
- } else {
+ break;
+ case MODEL_FF2:
+ case MODEL_FF1:
i = BD_BK_SLOT_TO_INDEX(sb, bank, 0);
j = (cs == 0) ? i : i + 2;
memb_num = mc_ff_dimm_unum_table[i][0];
@@ -2955,12 +2991,23 @@
model_names[plat_model].mem_name, memb_num,
&mc_ff_dimm_unum_table[j][1],
&mc_ff_dimm_unum_table[j + 1][1]);
+ break;
+ case MODEL_IKKAKU:
+ i = BD_BK_SLOT_TO_INDEX(sb, bank, 0);
+ j = (cs == 0) ? i : i + 2;
+ snprintf(buf, buflen, "/%s/MEM%s MEM%s",
+ model_names[plat_model].unit_name,
+ &mc_ff_dimm_unum_table[j][1],
+ &mc_ff_dimm_unum_table[j + 1][1]);
+ break;
+ default:
+ rv = ENXIO;
}
if (lenp) {
*lenp = strlen(buf);
}
mutex_exit(&mcmutex);
- return (0);
+ return (rv);
}
int
@@ -3368,18 +3415,26 @@
y = c[1];
z = c[2];
} else if ((c = strstr(unum, "MBU_")) != NULL) {
- /* FF1/FF2 Model */
+ /* FF1/FF2/Ikkaku Model */
c += 4;
if ((c[0] != 'A') && (c[0] != 'B')) {
return (4);
}
- if ((c = strstr(c, "MEMB")) == NULL) {
- return (5);
+ if (plat_model == MODEL_IKKAKU) {
+ /* Ikkaku Model */
+ x = '0';
+ *board = 0;
+ } else {
+ /* FF1/FF2 Model */
+ if ((c = strstr(c, "MEMB")) == NULL) {
+ return (5);
+ }
+ c += 4;
+
+ x = c[0];
+ *board = ((uint8_t)stoi(&c)) / 4;
}
- c += 4;
-
- x = c[0];
- *board = ((uint8_t)stoi(&c)) / 4;
+
if ((c = strstr(c, "MEM")) == NULL) {
return (6);
}
@@ -3453,9 +3508,15 @@
if (mf_type == FLT_TYPE_INTERMITTENT_CE ||
mf_type == FLT_TYPE_PERMANENT_CE) {
if (plat_model == MODEL_DC) {
+ /*
+ * All DC models
+ */
id = BD_BK_SLOT_TO_INDEX(0, bank, d_slot);
dimmnm = mc_dc_dimm_unum_table[id];
} else {
+ /*
+ * All FF and Ikkaku models
+ */
id = BD_BK_SLOT_TO_INDEX(sb, bank, d_slot);
dimmnm = mc_ff_dimm_unum_table[id];
}
@@ -3561,10 +3622,16 @@
int tsz;
char **tbl;
- if (plat_model == MODEL_DC) { /* DC */
+ if (plat_model == MODEL_DC) {
+ /*
+ * All DC models
+ */
tbl = mc_dc_dimm_unum_table;
tsz = OPL_MAX_DIMMS;
} else {
+ /*
+ * All FF and Ikkaku models
+ */
tbl = mc_ff_dimm_unum_table;
tsz = 2 * OPL_MAX_DIMMS;
}
--- a/usr/src/uts/sun4u/opl/os/opl.c Wed Mar 26 17:37:28 2008 -0700
+++ b/usr/src/uts/sun4u/opl/os/opl.c Wed Mar 26 20:38:30 2008 -0700
@@ -86,6 +86,7 @@
{ "DC1", OPL_MAX_BOARDS_DC1, DC1, STD_DISPATCH_TABLE },
{ "DC2", OPL_MAX_BOARDS_DC2, DC2, EXT_DISPATCH_TABLE },
{ "DC3", OPL_MAX_BOARDS_DC3, DC3, EXT_DISPATCH_TABLE },
+ { "IKKAKU", OPL_MAX_BOARDS_IKKAKU, IKKAKU, STD_DISPATCH_TABLE },
};
static int opl_num_models = sizeof (opl_models)/sizeof (opl_model_info_t);
@@ -156,7 +157,7 @@
/*
* If model not matched, it's an unknown model.
- * just return.
+ * Just return. It will default to standard dispatch tables.
*/
if (i == opl_num_models)
return;
@@ -167,7 +168,8 @@
* Based on a platform model, select a dispatch table.
* Only DC2 and DC3 systems uses the alternate/extended
* TS dispatch table.
- * FF1, FF2 and DC1 systems used standard dispatch tables.
+ * IKKAKU, FF1, FF2 and DC1 systems use standard dispatch
+ * tables.
*/
ts_dispatch_extended = 1;
}
@@ -888,6 +890,10 @@
CHIP_ID(cpuid));
break;
+ case IKKAKU:
+ plen = snprintf(buf, buflen, "/%s", "MBU_A");
+ break;
+
default:
/* This should never happen */
return (ENODEV);
--- a/usr/src/uts/sun4u/sys/opl.h Wed Mar 26 17:37:28 2008 -0700
+++ b/usr/src/uts/sun4u/sys/opl.h Wed Mar 26 20:38:30 2008 -0700
@@ -70,6 +70,7 @@
/*
* Max. boards supported in a domain per model.
*/
+#define OPL_MAX_BOARDS_IKKAKU 1
#define OPL_MAX_BOARDS_FF1 1
#define OPL_MAX_BOARDS_FF2 2
#define OPL_MAX_BOARDS_DC1 4
@@ -78,7 +79,12 @@
/* OPL model type */
typedef enum {
- FF1 = 0, FF2, DC1, DC2, DC3
+ FF1,
+ FF2,
+ DC1,
+ DC2,
+ DC3,
+ IKKAKU
} opl_type_t;
/* OPL model specific cmds selection */