diff options
-rw-r--r-- | core/hmi.c | 21 | ||||
-rw-r--r-- | hw/chiptod.c | 6 | ||||
-rw-r--r-- | include/chiptod.h | 2 |
3 files changed, 19 insertions, 10 deletions
@@ -955,7 +955,7 @@ static int handle_thread_tfac_error(uint64_t tfmr, uint64_t *out_flags) static int handle_all_core_tfac_error(uint64_t tfmr, uint64_t *out_flags) { struct cpu_thread *t, *t0; - int recover = 1; + int recover = -1; t = this_cpu(); t0 = find_cpu_by_pir(cpu_get_thread0(t)); @@ -975,11 +975,15 @@ static int handle_all_core_tfac_error(uint64_t tfmr, uint64_t *out_flags) if (tfmr & SPR_TFMR_TFMR_CORRUPT) { /* Check if it's still in error state */ if (mfspr(SPR_TFMR) & SPR_TFMR_TFMR_CORRUPT) - if (!recover_corrupt_tfmr()) + if (!recover_corrupt_tfmr()) { + unlock(&hmi_lock); recover = 0; + } - if (!recover) + if (!recover) { + unlock(&hmi_lock); goto error_out; + } tfmr = mfspr(SPR_TFMR); @@ -988,8 +992,10 @@ static int handle_all_core_tfac_error(uint64_t tfmr, uint64_t *out_flags) recover = handle_thread_tfac_error(tfmr, out_flags); tfmr &= ~SPR_TFMR_THREAD_ERRORS; } - if (!recover) + if (!recover) { + unlock(&hmi_lock); goto error_out; + } } /* Tell the OS ... */ @@ -1023,8 +1029,7 @@ static int handle_all_core_tfac_error(uint64_t tfmr, uint64_t *out_flags) /* Now perform the actual TB recovery on thread 0 */ if (t == t0) - recover = chiptod_recover_tb_errors(tfmr, - &this_cpu()->tb_resynced); + recover = chiptod_recover_tb_errors(&this_cpu()->tb_resynced); error_out: /* Last rendez-vous */ @@ -1043,7 +1048,7 @@ error_out: static int handle_tfac_errors(uint64_t hmer, struct OpalHMIEvent *hmi_evt, uint64_t *out_flags) { - int recover = 1; + int recover = -1; uint64_t tfmr = mfspr(SPR_TFMR); /* A TFMR parity error makes us ignore all the local stuff */ @@ -1106,7 +1111,7 @@ static int handle_tfac_errors(uint64_t hmer, struct OpalHMIEvent *hmi_evt, mfspr(SPR_TFMR)); } - if (hmi_evt) { + if (recover != -1 && hmi_evt) { hmi_evt->severity = OpalHMI_SEV_ERROR_SYNC; hmi_evt->type = OpalHMI_ERROR_TFAC; hmi_evt->tfmr = tfmr; diff --git a/hw/chiptod.c b/hw/chiptod.c index a160e5a..f6ef9a4 100644 --- a/hw/chiptod.c +++ b/hw/chiptod.c @@ -1505,8 +1505,9 @@ bool tfmr_clear_core_errors(uint64_t tfmr) * 1 <= Successfully recovered from errors * -1 <= No errors found. Errors are already been fixed. */ -int chiptod_recover_tb_errors(uint64_t tfmr, bool *out_resynced) +int chiptod_recover_tb_errors(bool *out_resynced) { + uint64_t tfmr; int rc = -1; *out_resynced = false; @@ -1516,6 +1517,9 @@ int chiptod_recover_tb_errors(uint64_t tfmr, bool *out_resynced) lock(&chiptod_lock); + /* Get fresh copy of TFMR */ + tfmr = mfspr(SPR_TFMR); + /* * Check for TB errors. * On Sync check error, bit 44 of TFMR is set. Check for it and diff --git a/include/chiptod.h b/include/chiptod.h index 7708d48..667e6fd 100644 --- a/include/chiptod.h +++ b/include/chiptod.h @@ -29,7 +29,7 @@ enum chiptod_topology { extern void chiptod_init(void); extern bool chiptod_wakeup_resync(void); -extern int chiptod_recover_tb_errors(uint64_t tfmr, bool *out_resynced); +extern int chiptod_recover_tb_errors(bool *out_resynced); extern bool tfmr_recover_local_errors(uint64_t tfmr); extern bool recover_corrupt_tfmr(void); extern void tfmr_cleanup_core_errors(uint64_t tfmr); |