aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorMahesh Salgaonkar <mahesh@linux.vnet.ibm.com>2015-03-11 16:00:02 +0530
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-03-26 11:12:18 +1100
commit28160facbc16b87d155804ecfd3e4bb3ba78fd27 (patch)
tree8fbb970e96989136e56114a91b47abdb6abe6feb /hw
parent26103de5e42d9d9c699b08568267c5c0701beffe (diff)
downloadskiboot-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>
Diffstat (limited to 'hw')
-rw-r--r--hw/chiptod.c37
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;
}