PSARC/2008/092 OPL Ikkaku Platform Support
authorjl139090
Wed, 26 Mar 2008 20:38:30 -0700
changeset 6297 410df87bc54b
parent 6296 b2fd3d371933
child 6298 060278005c21
PSARC/2008/092 OPL Ikkaku Platform Support 6655597 Support for SPARC Enterprise Ikkaku
usr/src/cmd/fm/modules/sun4u/cpumem-diagnosis/cmd_opl.c
usr/src/cmd/fm/modules/sun4u/cpumem-diagnosis/cmd_opl.h
usr/src/cmd/fm/schemes/mem/mem_unum.c
usr/src/lib/fm/topo/modules/SUNW,SPARC-Enterprise/ioboard/opl_ioboard.c
usr/src/uts/sun4u/opl/io/mc-opl.c
usr/src/uts/sun4u/opl/os/opl.c
usr/src/uts/sun4u/sys/opl.h
--- 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  */