[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