aboutsummaryrefslogtreecommitdiff
path: root/core/hmi.c
diff options
context:
space:
mode:
authorMahesh Salgaonkar <mahesh@linux.vnet.ibm.com>2018-04-16 23:04:23 +0530
committerStewart Smith <stewart@linux.ibm.com>2018-04-17 03:52:10 -0500
commit5362f85e04bd1b03d94711c62c20de3111234f25 (patch)
treec8a801cdf38ab6e0e53b7243ad6f825ea8612925 /core/hmi.c
parent377cd39bc5e148cd84d766f0b3324a5979d4558e (diff)
downloadskiboot-5362f85e04bd1b03d94711c62c20de3111234f25.zip
skiboot-5362f85e04bd1b03d94711c62c20de3111234f25.tar.gz
skiboot-5362f85e04bd1b03d94711c62c20de3111234f25.tar.bz2
opal/hmi: check thread 0 tfmr to validate latched tfmr errors.
Due to P9 errata, HDEC parity and TB residue errors are latched for non-zero threads 1-3 even if they are cleared. But these are not latched on thread 0. Hence, use xscom SCOMC/SCOMD to read thread 0 tfmr value and ignore them on non-zero threads if they are not present on thread 0. Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
Diffstat (limited to 'core/hmi.c')
-rw-r--r--core/hmi.c61
1 files changed, 42 insertions, 19 deletions
diff --git a/core/hmi.c b/core/hmi.c
index b062428..9b98fbd 100644
--- a/core/hmi.c
+++ b/core/hmi.c
@@ -22,6 +22,7 @@
#include <processor.h>
#include <chiptod.h>
#include <xscom.h>
+#include <xscom-p9-regs.h>
#include <pci.h>
#include <cpu.h>
#include <chip.h>
@@ -1047,6 +1048,45 @@ error_out:
return recover;
}
+static uint64_t read_tfmr_t0(void)
+{
+ uint64_t tfmr_t0;
+ uint32_t chip_id = this_cpu()->chip_id;
+ uint32_t core_id = pir_to_core_id(this_cpu()->pir);
+
+ lock(&hmi_lock);
+
+ xscom_write(chip_id, XSCOM_ADDR_P9_EC(core_id, P9_SCOM_SPRC),
+ SETFIELD(P9_SCOMC_SPR_SELECT, 0, P9_SCOMC_TFMR_T0));
+ xscom_read(chip_id, XSCOM_ADDR_P9_EC(core_id, P9_SCOM_SPRD),
+ &tfmr_t0);
+ unlock(&hmi_lock);
+ return tfmr_t0;
+}
+
+/* P9 errata: In theory, an HDEC error is sent to all threads. However,
+ * due to an errata on P9 where TFMR bit 26 (HDEC parity) cannot be
+ * cleared on thread 1..3, I am not confident we can do a rendez-vous
+ * in all cases.
+ *
+ * Our current approach is to ignore that error unless it is present
+ * on thread 0 TFMR. Also, ignore TB residue error due to a similar
+ * errata as above.
+ */
+static void validate_latched_errors(uint64_t *tfmr)
+{
+ if ((*tfmr & (SPR_TFMR_HDEC_PARITY_ERROR | SPR_TFMR_TB_RESIDUE_ERR))
+ && this_cpu()->is_secondary) {
+ uint64_t tfmr_t0 = read_tfmr_t0();
+
+ if (!(tfmr_t0 & SPR_TFMR_HDEC_PARITY_ERROR))
+ *tfmr &= ~SPR_TFMR_HDEC_PARITY_ERROR;
+
+ if (!(tfmr_t0 & SPR_TFMR_TB_RESIDUE_ERR))
+ *tfmr &= ~SPR_TFMR_TB_RESIDUE_ERR;
+ }
+}
+
static int handle_tfac_errors(struct OpalHMIEvent *hmi_evt, uint64_t *out_flags)
{
int recover = -1;
@@ -1063,25 +1103,8 @@ static int handle_tfac_errors(struct OpalHMIEvent *hmi_evt, uint64_t *out_flags)
this_cpu()->tb_invalid = !(tfmr & SPR_TFMR_TB_VALID);
- /* P9 errata: In theory, an HDEC error is sent to all threads. However,
- * due to an errata on P9 where TFMR bit 26 (HDEC parity) cannot be
- * cleared on thread 1..3, I am not confident we can do a rendez-vous
- * in all cases.
- *
- * Our current approach is to ignore that error unless no other TFAC
- * error is present in the TFMR. The error will be re-detected and
- * re-reported if necessary.
- */
- if (proc_gen == proc_gen_p9 && (tfmr & SPR_TFMR_HDEC_PARITY_ERROR)) {
- if (this_cpu()->tb_invalid || (tfmr & SPR_TFMR_OTHER_ERRORS))
- tfmr &= ~SPR_TFMR_HDEC_PARITY_ERROR;
- }
-
- /* The TB residue error is ignored if TB is valid due to a similar
- * errata as above
- */
- if ((tfmr & SPR_TFMR_TB_RESIDUE_ERR) && !this_cpu()->tb_invalid)
- tfmr &= ~SPR_TFMR_TB_RESIDUE_ERR;
+ if (proc_gen == proc_gen_p9)
+ validate_latched_errors(&tfmr);
/* First, handle thread local errors */
if (tfmr & SPR_TFMR_THREAD_ERRORS) {