@@ -920,7 +920,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));
@@ -940,11 +940,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);
@@ -953,8 +957,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 ... */
@@ -988,8 +994,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 */
@@ -1008,7 +1013,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 */
@@ -1070,7 +1075,7 @@ static int handle_tfac_errors(uint64_t hmer, struct OpalHMIEvent *hmi_evt,
prlog(PR_ERR, "HMI: TB invalid without core error reported !\n");
}
- 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;
@@ -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
@@ -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);