[Skiboot] [PATCH v2 12/12] opal: Recover from TOD register parity errors.

Mahesh J Salgaonkar mahesh at linux.vnet.ibm.com
Sat Jun 6 04:10:52 AEST 2015


From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>

This patch implements recovery from parity errors on below listed TOD
control registers:

- Master Path control register (0x00040000)
- Primary Port-0 control register (0x00040001)
- Primary Port-1 control register (0x00040002)
- Secondary Port-0 control register (0x00040003)
- Secondary Port-1 control register (0x00040004)
- Slave Path control register (0x00040005)
- Internal Path control register (0x00040006)
- Primary/secondary master/slave control register (0x00040007)
- Chip control register (0x00040010)

To inject TOD register parity error issue:
	putscom pu 40031 8000000000000000 -pall  # (00040000)
	putscom pu 40031 1000000000000000 -pall  # (00040001)
	putscom pu 40031 0800000000000000 -pall  # (00040002)
	putscom pu 40031 0400000000000000 -pall  # (00040003)
	putscom pu 40031 0200000000000000 -pall  # (00040004)
	putscom pu 40031 0100000000000000 -pall  # (00040005)
	putscom pu 40031 0080000000000000 -pall  # (00040006)
	putscom pu 40031 0040000000000000 -pall  # (00040007)
	putscom pu 40031 0000000080000000 -pall  # (00040010)

Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
---
 hw/chiptod.c |   39 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)

diff --git a/hw/chiptod.c b/hw/chiptod.c
index 148ed91..c81b507 100644
--- a/hw/chiptod.c
+++ b/hw/chiptod.c
@@ -957,6 +957,9 @@ bool chiptod_wakeup_resync(void)
 static int chiptod_recover_tod_errors(void)
 {
 	uint64_t terr;
+	uint64_t treset = 0;
+	int i;
+	int32_t chip_id = this_cpu()->chip_id;
 
 	/* Read TOD error register */
 	if (xscom_readme(TOD_ERROR, &terr) != 0) {
@@ -971,9 +974,41 @@ static int chiptod_recover_tod_errors(void)
 		(terr & TOD_ERR_DELAY_COMPL_PARITY) ||
 		(terr & TOD_ERR_TOD_REGISTER_PARITY)) {
 		chiptod_reset_tod_errors();
-		return 1;
 	}
-	return 0;
+
+	/*
+	 * Check for TOD control register parity errors and restore those
+	 * registers with last saved valid values.
+	 */
+	for (i = 0; i < ARRAY_SIZE(chiptod_tod_regs); i++) {
+		if (!(terr & chiptod_tod_regs[i].error_bit))
+			continue;
+
+		/* Check if we have valid last saved register value. */
+		if (!chiptod_tod_regs[i].val[chip_id].valid) {
+			prerror("CHIPTOD: Failed to restore TOD register: "
+			"%08llx", chiptod_tod_regs[i].xscom_addr);
+			return 0;
+		}
+
+		prlog(PR_DEBUG, "CHIPTOD: parity error, "
+				"Restoring TOD register: %08llx\n",
+				chiptod_tod_regs[i].xscom_addr);
+		if (xscom_writeme(chiptod_tod_regs[i].xscom_addr,
+			chiptod_tod_regs[i].val[chip_id].data) != 0) {
+			prerror("CHIPTOD: XSCOM error writing 0x%08llx reg.\n",
+					chiptod_tod_regs[i].xscom_addr);
+			return 0;
+		}
+		treset |= chiptod_tod_regs[i].error_bit;
+	}
+
+	if (treset && (xscom_writeme(TOD_ERROR, treset) != 0)) {
+		prerror("CHIPTOD: XSCOM error writing TOD_ERROR !\n");
+		return 0;
+	}
+	/* We have handled all the TOD errors routed to hypervisor */
+	return 1;
 }
 
 static int32_t chiptod_get_active_master(void)



More information about the Skiboot mailing list