changeset 2867:acd9a4fc9952

6473791 errors on odd banks are not reported by mc-opl in mirror mode
author hyw
date Thu, 05 Oct 2006 14:56:57 -0700
parents c4183dac96f1
children c6c11cf3e587
files usr/src/uts/sun4u/opl/io/mc-opl.c
diffstat 1 files changed, 48 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/sun4u/opl/io/mc-opl.c	Thu Oct 05 11:31:43 2006 -0700
+++ b/usr/src/uts/sun4u/opl/io/mc-opl.c	Thu Oct 05 14:56:57 2006 -0700
@@ -235,6 +235,15 @@
 
 #define	MC_CNTL_SPEED_SHIFT 26
 
+/*
+ * In mirror mode, we normalized the bank idx to "even" since
+ * the HW treats them as one unit w.r.t programming.
+ * This bank index will be the "effective" bank index.
+ * All mirrored bank state info on mc_period, mc_speedup_period
+ * will be stored in the even bank structure to avoid code duplication.
+ */
+#define	MIRROR_IDX(bankidx)	(bankidx & ~1)
+
 static mc_scan_speed_t	mc_scan_speeds[MC_MAX_SPEEDS] = {
 	{0x6 << MC_CNTL_SPEED_SHIFT, 0},
 	{0x5 << MC_CNTL_SPEED_SHIFT, 32},
@@ -1434,7 +1443,9 @@
 void
 mc_write_cntl(mc_opl_t *mcp, int bank, uint32_t value)
 {
-	if (mcp->mc_speedup_period[bank] > 0)
+	int ebank = (IS_MIRROR(mcp, bank)) ? MIRROR_IDX(bank) : bank;
+
+	if (mcp->mc_speedup_period[ebank] > 0)
 		value |= mc_max_speed;
 	else
 		value |= mcp->mc_speed;
@@ -1890,6 +1901,7 @@
 	uint32_t stat, cntl;
 	int running;
 	int wrapped;
+	int ebk;
 
 	/*
 	 * scan errors.
@@ -1904,6 +1916,9 @@
 			running = cntl & MAC_CNTL_PTRL_START;
 			wrapped = cntl & MAC_CNTL_PTRL_ADD_MAX;
 
+			/* Compute the effective bank idx */
+			ebk = (IS_MIRROR(mcp, i)) ? MIRROR_IDX(i) : i;
+
 			if (mc_debug_show_all || stat) {
 				MC_LOG("/LSB%d/B%d stat %x cntl %x\n",
 					mcp->mc_board_num, i,
@@ -1915,11 +1930,17 @@
 			 * wrapped around in its scan.
 			 */
 			if (wrapped) {
-				mcp->mc_period[i]++;
-				MC_LOG("mc period %ld on "
-				    "/LSB%d/B%d\n", mcp->mc_period[i],
-				    mcp->mc_board_num, i);
 				MAC_CLEAR_MAX(mcp, i);
+				mcp->mc_period[ebk]++;
+				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 {
+				    MC_LOG("mc period %ld on "
+					"/LSB%d/B%d\n", mcp->mc_period[ebk],
+					mcp->mc_board_num, i);
+				}
 			}
 
 			if (running) {
@@ -1950,9 +1971,9 @@
 				 * to stop. We only do it if HW patrol scan
 				 * wrapped (counted as completing a 'period').
 				 */
-				if (mcp->mc_speedup_period[i] > 0) {
+				if (mcp->mc_speedup_period[ebk] > 0) {
 				    if (wrapped &&
-					(--mcp->mc_speedup_period[i] == 0)) {
+					(--mcp->mc_speedup_period[ebk] == 0)) {
 					/*
 					 * We did try to speed up.
 					 * The speed up period has expired
@@ -1960,11 +1981,19 @@
 					 * The errors must be intermittent.
 					 * We have no choice but to ignore
 					 * them, reset the scan speed to normal
-					 * and clear the MI error bits.
+					 * and clear the MI error bits. For
+					 * mirror mode, we need to clear errors
+					 * on both banks.
 					 */
 					MC_LOG("Clearing MI errors\n");
 					MAC_CLEAR_ERRS(mcp, i,
 					    MAC_CNTL_MI_ERRS);
+
+					if (IS_MIRROR(mcp, i)) {
+					    MC_LOG("Clearing Mirror MI errs\n");
+					    MAC_CLEAR_ERRS(mcp, i^1,
+						MAC_CNTL_MI_ERRS);
+					}
 				    }
 				} else if (stat & MAC_STAT_MI_ERRS) {
 					/*
@@ -1977,7 +2006,7 @@
 					 * location that cause the HW patrol
 					 * to stop.
 					 */
-					mcp->mc_speedup_period[i] = 2;
+					mcp->mc_speedup_period[ebk] = 2;
 					MAC_CMD(mcp, i, 0);
 				}
 			} else if (stat & (MAC_STAT_PTRL_ERRS |
@@ -1986,11 +2015,10 @@
 				 * HW Patrol has stopped and we found errors.
 				 * Proceed to collect and report error info.
 				 */
-				mcp->mc_speedup_period[i] = 0;
+				mcp->mc_speedup_period[ebk] = 0;
 				rsaddr_info.mi_valid = 0;
 				rsaddr_info.mi_injectrestart = 0;
 				if (IS_MIRROR(mcp, i)) {
-				    mcp->mc_speedup_period[i^1] = 0;
 				    mc_error_handler_mir(mcp, i, &rsaddr_info);
 				} else {
 				    mc_error_handler(mcp, i, &rsaddr_info);
@@ -2003,8 +2031,13 @@
 				 * HW patrol scan has apparently stopped
 				 * but no errors detected/flagged.
 				 * Restart the HW patrol just to be sure.
+				 * In mirror mode, the odd bank might have
+				 * reported errors that caused the patrol to
+				 * stop. We'll defer the restart to the odd
+				 * bank in this case.
 				 */
-				restart_patrol(mcp, i, NULL);
+				if (!IS_MIRROR(mcp, i) || (i & 0x1))
+					restart_patrol(mcp, i, NULL);
 			}
 		}
 	}
@@ -2986,6 +3019,7 @@
 
 	if (flags & MC_INJECT_FLAG_POLL) {
 		int running;
+		int ebank = (IS_MIRROR(mcp, bank)) ? MIRROR_IDX(bank) : bank;
 
 		MC_LOG("Poll patrol error\n");
 		stat = LD_MAC_REG(MAC_PTRL_STAT(mcp, bank));
@@ -2998,11 +3032,10 @@
 			 * HW patrol stopped and we have errors to
 			 * report. Do it.
 			 */
-			mcp->mc_speedup_period[bank] = 0;
+			mcp->mc_speedup_period[ebank] = 0;
 			rsaddr.mi_valid = 0;
 			rsaddr.mi_injectrestart = 0;
 			if (IS_MIRROR(mcp, bank)) {
-				mcp->mc_speedup_period[bank^1] = 0;
 				mc_error_handler_mir(mcp, bank, &rsaddr);
 			} else {
 				mc_error_handler(mcp, bank, &rsaddr);
@@ -3015,7 +3048,7 @@
 			 * errors but the HW patrol is still running.
 			 * Speed up the scanning
 			 */
-			mcp->mc_speedup_period[bank] = 2;
+			mcp->mc_speedup_period[ebank] = 2;
 			MAC_CMD(mcp, bank, 0);
 			restart_patrol(mcp, bank, NULL);
 		}