diff options
author | Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> | 2015-03-11 16:00:02 +0530 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-03-26 11:12:18 +1100 |
commit | 28160facbc16b87d155804ecfd3e4bb3ba78fd27 (patch) | |
tree | 8fbb970e96989136e56114a91b47abdb6abe6feb | |
parent | 26103de5e42d9d9c699b08568267c5c0701beffe (diff) | |
download | skiboot-28160facbc16b87d155804ecfd3e4bb3ba78fd27.zip skiboot-28160facbc16b87d155804ecfd3e4bb3ba78fd27.tar.gz skiboot-28160facbc16b87d155804ecfd3e4bb3ba78fd27.tar.bz2 |
opal: Refactor tb errors reset code
The current implementation invokes chiptod_reset_tb_errors() function that
force write 1 to all the TB errors irrespective of whether those error
occurred or not. Refactor this code to detect individual TB error and reset
them. This change does not affect the recovery of tb errors that we handle as
of today and has been verified by running regression tests. Instead this
change introduces a better way to handle individual TB errors that we handle
currently and in subsequent patches.
The subsequent patches will recover from more TB and non-TB errors.
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r-- | hw/chiptod.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/hw/chiptod.c b/hw/chiptod.c index edf805d..e64f239 100644 --- a/hw/chiptod.c +++ b/hw/chiptod.c @@ -633,6 +633,41 @@ static int chiptod_start_tod(void) return 1; } +static bool tfmr_recover_tb_errors(uint64_t tfmr) +{ + uint64_t tfmr_reset_error; + unsigned long timeout = 0; + + /* Ask for automatic clear of errors */ + tfmr_reset_error = base_tfmr | SPR_TFMR_CLEAR_TB_ERRORS; + + /* Additionally pHyp sets these (write-1-to-clear ?) */ + if (tfmr & SPR_TFMR_TB_MISSING_SYNC) + tfmr_reset_error |= SPR_TFMR_TB_MISSING_SYNC; + + if (tfmr & SPR_TFMR_TB_MISSING_STEP) + tfmr_reset_error |= SPR_TFMR_TB_MISSING_STEP; + + mtspr(SPR_TFMR, tfmr_reset_error); + + /* We have to write "Clear TB Errors" again */ + tfmr_reset_error = base_tfmr | SPR_TFMR_CLEAR_TB_ERRORS; + mtspr(SPR_TFMR, tfmr_reset_error); + + do { + if (++timeout >= TIMEOUT_LOOPS) { + prerror("CHIPTOD: TB error reset timeout !\n"); + return false; + } + tfmr = mfspr(SPR_TFMR); + if (tfmr & SPR_TFMR_TFMR_CORRUPT) { + prerror("CHIPTOD: TB error reset: corrupt TFMR !\n"); + return false; + } + } while (tfmr & SPR_TFMR_CLEAR_TB_ERRORS); + return true; +} + /* * Recover from TB and TOD errors. * Timebase register is per core and first thread that gets chance to @@ -666,7 +701,7 @@ int chiptod_recover_tb_errors(void) */ if ((tfmr & SPR_TFMR_TB_MISSING_STEP) || (tfmr & SPR_TFMR_TB_MISSING_SYNC)) { - if (!chiptod_reset_tb_errors()) { + if (!tfmr_recover_tb_errors(tfmr)) { rc = 0; goto error_out; } |