aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorRussell Currey <ruscur@russell.cc>2017-06-09 16:06:05 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-06-15 13:37:37 +1000
commitb2da4f4e6c0a3ea312376c44afb16bb9321145aa (patch)
tree442616e02651e87a26aebaded8f192dc35fdc7ae /hw
parent9953b4d15c4d47b11f9029b1b90f77537af1a715 (diff)
downloadskiboot-b2da4f4e6c0a3ea312376c44afb16bb9321145aa.zip
skiboot-b2da4f4e6c0a3ea312376c44afb16bb9321145aa.tar.gz
skiboot-b2da4f4e6c0a3ea312376c44afb16bb9321145aa.tar.bz2
phb4: Error clear implementation
In PHB3 there were separate recovery procedures depending on the class of error. PHB4 performs almost exactly the same steps in recovering from any class of error, so change phbX_err_ER_clear() to phbX_err_clear() for this implementation. Since the same sequence gets used, call this function in phb4_creset() - which is used to handle fatal (fence) errors - where it was not called in previous hardware revisions. Signed-off-by: Russell Currey <ruscur@russell.cc> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/phb4.c125
1 files changed, 57 insertions, 68 deletions
diff --git a/hw/phb4.c b/hw/phb4.c
index c0bc634..3a54e03 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -60,6 +60,7 @@
#define DISABLE_ERR_INTS
static void phb4_init_hw(struct phb4 *p, bool first_init);
+static bool phb4_init_rc_cfg(struct phb4 *p);
#define PHBDBG(p, fmt, a...) prlog(PR_DEBUG, "PHB#%04x[%d:%d]: " fmt, \
(p)->phb.opal_id, (p)->chip_id, \
@@ -1466,86 +1467,71 @@ static int64_t phb4_get_msi_64(struct phb *phb,
}
/*
- * The function can be called during error recovery for INF
- * and ER class. For INF case, it's expected to be called
- * when grabbing the error log. We will call it explicitly
- * when clearing frozen PE state for ER case.
+ * The function can be called during error recovery for all classes of
+ * errors. This is new to PHB4; previous revisions had separate
+ * sequences for INF/ER/Fatal errors.
+ *
+ * "Rec #" in this function refer to "Recov_#" steps in the
+ * PHB4 INF recovery sequence.
*/
-static void phb4_err_ER_clear(struct phb4 *p)
+static void phb4_err_clear(struct phb4 *p)
{
-#if 0
- uint32_t val32;
uint64_t val64;
uint64_t fir = in_be64(p->regs + PHB_LEM_FIR_ACCUM);
- /* Rec 1: Grab the PCI config lock */
- /* Removed... unnecessary. We have our own lock here */
-
- /* Rec 2/3/4: Take all inbound transactions */
- out_be64(p->regs + PHB_CONFIG_ADDRESS, 0x8000001c00000000ul);
- out_be32(p->regs + PHB_CONFIG_DATA, 0x10000000);
-
- /* Rec 5/6/7: Clear pending non-fatal errors */
- out_be64(p->regs + PHB_CONFIG_ADDRESS, 0x8000005000000000ul);
- val32 = in_be32(p->regs + PHB_CONFIG_DATA);
- out_be32(p->regs + PHB_CONFIG_DATA, (val32 & 0xe0700000) | 0x0f000f00);
-
- /* Rec 8/9/10: Clear pending fatal errors for AER */
- out_be64(p->regs + PHB_CONFIG_ADDRESS, 0x8000010400000000ul);
- out_be32(p->regs + PHB_CONFIG_DATA, 0xffffffff);
-
- /* Rec 11/12/13: Clear pending non-fatal errors for AER */
- out_be64(p->regs + PHB_CONFIG_ADDRESS, 0x8000011000000000ul);
- out_be32(p->regs + PHB_CONFIG_DATA, 0xffffffff);
-
- /* Rec 22/23/24: Clear root port errors */
- out_be64(p->regs + PHB_CONFIG_ADDRESS, 0x8000013000000000ul);
- out_be32(p->regs + PHB_CONFIG_DATA, 0xffffffff);
+ /* Rec 1: Acquire the PCI config lock (we don't need to do this) */
+
+ /* Rec 2...15: Clear error status in RC config space */
+ /* Reset steps are the same as the init sequence */
+ phb4_init_rc_cfg(p);
+
+ /* Rec 16/17: Clear PBL errors */
+ val64 = in_be64(p->regs + PHB_PBL_ERR_STATUS);
+ out_be64(p->regs + PHB_PBL_ERR_STATUS, val64);
+
+ /* Rec 18/19: Clear REGB errors */
+ val64 = in_be64(p->regs + PHB_REGB_ERR_STATUS);
+ out_be64(p->regs + PHB_REGB_ERR_STATUS, val64);
+
+ /* Rec 20...59: Clear PHB error trap */
+ val64 = in_be64(p->regs + PHB_TXE_ERR_STATUS);
+ out_be64(p->regs + PHB_TXE_ERR_STATUS, val64);
+ out_be64(p->regs + PHB_TXE_ERR1_STATUS, 0x0ul);
+ out_be64(p->regs + PHB_TXE_ERR_LOG_0, 0x0ul);
+ out_be64(p->regs + PHB_TXE_ERR_LOG_1, 0x0ul);
+
+ val64 = in_be64(p->regs + PHB_RXE_ARB_ERR_STATUS);
+ out_be64(p->regs + PHB_RXE_ARB_ERR_STATUS, val64);
+ out_be64(p->regs + PHB_RXE_ARB_ERR1_STATUS, 0x0ul);
+ out_be64(p->regs + PHB_RXE_ARB_ERR_LOG_0, 0x0ul);
+ out_be64(p->regs + PHB_RXE_ARB_ERR_LOG_1, 0x0ul);
+
+ val64 = in_be64(p->regs + PHB_RXE_MRG_ERR_STATUS);
+ out_be64(p->regs + PHB_RXE_MRG_ERR_STATUS, val64);
+ out_be64(p->regs + PHB_RXE_MRG_ERR1_STATUS, 0x0ul);
+ out_be64(p->regs + PHB_RXE_MRG_ERR_LOG_0, 0x0ul);
+ out_be64(p->regs + PHB_RXE_MRG_ERR_LOG_1, 0x0ul);
+
+ val64 = in_be64(p->regs + PHB_RXE_TCE_ERR_STATUS);
+ out_be64(p->regs + PHB_RXE_TCE_ERR_STATUS, val64);
+ out_be64(p->regs + PHB_RXE_TCE_ERR1_STATUS, 0x0ul);
+ out_be64(p->regs + PHB_RXE_TCE_ERR_LOG_0, 0x0ul);
+ out_be64(p->regs + PHB_RXE_TCE_ERR_LOG_1, 0x0ul);
- /* Rec 25/26/27: Enable IO and MMIO bar */
- out_be64(p->regs + PHB_CONFIG_ADDRESS, 0x8000004000000000ul);
- out_be32(p->regs + PHB_CONFIG_DATA, 0x470100f8);
-
- /* Rec 28: Release the PCI config lock */
- /* Removed... unnecessary. We have our own lock here */
-
- /* Rec 29...34: Clear UTL errors */
- val64 = in_be64(p->regs + UTL_SYS_BUS_AGENT_STATUS);
- out_be64(p->regs + UTL_SYS_BUS_AGENT_STATUS, val64);
- val64 = in_be64(p->regs + UTL_PCIE_PORT_STATUS);
- out_be64(p->regs + UTL_PCIE_PORT_STATUS, val64);
- val64 = in_be64(p->regs + UTL_RC_STATUS);
- out_be64(p->regs + UTL_RC_STATUS, val64);
-
- /* Rec 39...66: Clear PHB error trap */
val64 = in_be64(p->regs + PHB_ERR_STATUS);
out_be64(p->regs + PHB_ERR_STATUS, val64);
out_be64(p->regs + PHB_ERR1_STATUS, 0x0ul);
out_be64(p->regs + PHB_ERR_LOG_0, 0x0ul);
out_be64(p->regs + PHB_ERR_LOG_1, 0x0ul);
- val64 = in_be64(p->regs + PHB_OUT_ERR_STATUS);
- out_be64(p->regs + PHB_OUT_ERR_STATUS, val64);
- out_be64(p->regs + PHB_OUT_ERR1_STATUS, 0x0ul);
- out_be64(p->regs + PHB_OUT_ERR_LOG_0, 0x0ul);
- out_be64(p->regs + PHB_OUT_ERR_LOG_1, 0x0ul);
-
- val64 = in_be64(p->regs + PHB_INA_ERR_STATUS);
- out_be64(p->regs + PHB_INA_ERR_STATUS, val64);
- out_be64(p->regs + PHB_INA_ERR1_STATUS, 0x0ul);
- out_be64(p->regs + PHB_INA_ERR_LOG_0, 0x0ul);
- out_be64(p->regs + PHB_INA_ERR_LOG_1, 0x0ul);
-
- val64 = in_be64(p->regs + PHB_INB_ERR_STATUS);
- out_be64(p->regs + PHB_INB_ERR_STATUS, val64);
- out_be64(p->regs + PHB_INB_ERR1_STATUS, 0x0ul);
- out_be64(p->regs + PHB_INB_ERR_LOG_0, 0x0ul);
- out_be64(p->regs + PHB_INB_ERR_LOG_1, 0x0ul);
-
- /* Rec 67/68: Clear FIR/WOF */
+ /* Rec 61/62: Clear FIR/WOF */
out_be64(p->regs + PHB_LEM_FIR_AND_MASK, ~fir);
out_be64(p->regs + PHB_LEM_WOF, 0x0ul);
-#endif
+
+ /* Rec 63: Update LEM mask to its initial value */
+ out_be64(p->regs + PHB_LEM_ERROR_MASK, 0x0ul);
+
+ /* Rec 64: Clear the PCI config lock (we don't need to do this) */
}
static void phb4_read_phb_status(struct phb4 *p,
@@ -2148,6 +2134,9 @@ static int64_t phb4_creset(struct pci_slot *slot)
xscom_write(p->chip_id, p->pe_stk_xscom + 0x2,
0x000000f000000000);
+ /* Clear errors, following the proper sequence */
+ phb4_err_clear(p);
+
/* Clear errors in NFIR and raise ETU reset */
xscom_read(p->chip_id, p->pe_stk_xscom + 0x0, &p->nfir_cache);
xscom_read(p->chip_id, p->pci_stk_xscom + 0x0, &p->pfir_cache);
@@ -2330,7 +2319,7 @@ static int64_t phb4_eeh_freeze_clear(struct phb *phb, uint64_t pe_number,
}
}
if (err != 0)
- phb4_err_ER_clear(p);
+ phb4_err_clear(p);
/*
* We have PEEV in system memory. It would give more performance
@@ -2556,7 +2545,7 @@ static int64_t phb4_get_diag_data(struct phb *phb,
if (phb4_err_pending(p) &&
p->err.err_class == PHB4_ERR_CLASS_INF &&
p->err.err_src == PHB4_ERR_SRC_PHB) {
- phb4_err_ER_clear(p);
+ phb4_err_clear(p);
phb4_set_err_pending(p, false);
}