diff mbox

[v2,6/9] opal: Recover from TFMR HDEC parity error.

Message ID 20150311103143.10209.48066.stgit@mars.in.ibm.com
State Accepted
Headers show

Commit Message

Mahesh J Salgaonkar March 11, 2015, 10:31 a.m. UTC
From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>

Recovery process for HDEC parity error:
- Reset HDEC Register.
- Reset TFMR HDEC parity error bit.

To inject HDEC parity error issue:
        $ putscom pu.ex 10013281 0002080000000000 -all

Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
---
 hw/chiptod.c        |   41 +++++++++++++++++++++++++++++++++++++++++
 include/processor.h |    1 +
 2 files changed, 42 insertions(+)
diff mbox

Patch

diff --git a/hw/chiptod.c b/hw/chiptod.c
index b00c3cf..6f6800f 100644
--- a/hw/chiptod.c
+++ b/hw/chiptod.c
@@ -685,6 +685,35 @@  static bool tfmr_recover_tb_errors(uint64_t tfmr)
 	return true;
 }
 
+static bool tfmr_recover_non_tb_errors(uint64_t tfmr)
+{
+	uint64_t tfmr_reset_errors = 0;
+
+	if (tfmr & SPR_TFMR_HDEC_PARITY_ERROR) {
+		/* Reset HDEC register */
+		mtspr(SPR_HDEC, 0);
+
+		/* Set bit 26 to clear TFMR HDEC parity error. */
+		tfmr_reset_errors |= SPR_TFMR_HDEC_PARITY_ERROR;
+	}
+
+	/* Write TFMR twice to clear the error */
+	mtspr(SPR_TFMR, base_tfmr | tfmr_reset_errors);
+	mtspr(SPR_TFMR, base_tfmr | tfmr_reset_errors);
+
+	/* Get fresh copy of TFMR */
+	tfmr = mfspr(SPR_TFMR);
+
+	/* Check if TFMR non-TB errors still present. */
+	if (tfmr & tfmr_reset_errors) {
+		prerror(
+		"CHIPTOD: TFMR non-TB error recovery failed! TFMR=0x%016lx\n",
+							mfspr(SPR_TFMR));
+		return false;
+	}
+	return true;
+}
+
 /*
  * TFMR parity error recovery as per pc_workbook:
  *	MT(TFMR) bits 11 and 60 are b’1’
@@ -815,6 +844,18 @@  int chiptod_recover_tb_errors(void)
 		/* We have successfully able to get TB running. */
 		rc = 1;
 	}
+
+	/*
+	 * Now that TB is running, check for TFMR non-TB errors.
+	 */
+	if (tfmr & SPR_TFMR_HDEC_PARITY_ERROR) {
+		if (!tfmr_recover_non_tb_errors(tfmr)) {
+			rc = 0;
+			goto error_out;
+		}
+		rc = 1;
+	}
+
 error_out:
 	unlock(&chiptod_lock);
 	return rc;
diff --git a/include/processor.h b/include/processor.h
index 31ed72d..9140564 100644
--- a/include/processor.h
+++ b/include/processor.h
@@ -63,6 +63,7 @@ 
 #define SPR_PVR		0x11f	/* RO: Processor version register */
 #define SPR_HSPRG0	0x130	/* RW: Hypervisor scratch 0 */
 #define SPR_HSPRG1	0x131	/* RW: Hypervisor scratch 1 */
+#define SPR_HDEC	0x136	/* RW: Hypervisor Decrementer */
 #define SPR_HSRR0	0x13a	/* RW: HV Exception save/restore reg 0 */
 #define SPR_HSRR1	0x13b	/* RW: HV Exception save/restore reg 1 */
 #define SPR_TFMR	0x13d