aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorChristophe Lombard <clombard@linux.vnet.ibm.com>2017-09-20 13:39:06 +0200
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-09-20 23:25:01 -0500
commit5779c11fdc57c4dc474beb00f044f34ec1c58368 (patch)
treeca7b432bc6b58f59a7fdb0382ca89ccefbb1f5de /hw
parent577b75727d9ee9d57e1468e52275a7d838bbabf0 (diff)
downloadskiboot-5779c11fdc57c4dc474beb00f044f34ec1c58368.zip
skiboot-5779c11fdc57c4dc474beb00f044f34ec1c58368.tar.gz
skiboot-5779c11fdc57c4dc474beb00f044f34ec1c58368.tar.bz2
capi: CAPP recovery
CAPP recovery is initiated when a CAPP Machine Check is detected. The capp recovery procedure is initiated via a Hypervisor Maintenance interrupt (HMI). CAPP Machine Check may arise from either an error that results in a PHB freeze or from an internal CAPP error with CAPP checkstop FIR action. An error that causes a PHB freeze will result in the link down signal being asserted. The system continues running and the CAPP and PSL will be re-initialized. Tests performed on some of the old/new hardware. Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com> Reviewed-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/phb4.c59
1 files changed, 54 insertions, 5 deletions
diff --git a/hw/phb4.c b/hw/phb4.c
index 69ae5dd..32310d8 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -2792,6 +2792,27 @@ static int64_t load_capp_ucode(struct phb4 *p)
return rc;
}
+static void do_capp_recovery_scoms(struct phb4 *p)
+{
+ uint64_t reg;
+ uint32_t offset;
+
+ PHBDBG(p, "Doing CAPP recovery scoms\n");
+
+ offset = PHB4_CAPP_REG_OFFSET(p);
+ /* disable snoops */
+ xscom_write(p->chip_id, SNOOP_CAPI_CONFIG + offset, 0);
+ load_capp_ucode(p);
+ /* clear err rpt reg*/
+ xscom_write(p->chip_id, CAPP_ERR_RPT_CLR + offset, 0);
+ /* clear capp fir */
+ xscom_write(p->chip_id, CAPP_FIR + offset, 0);
+
+ xscom_read(p->chip_id, CAPP_ERR_STATUS_CTRL + offset, &reg);
+ reg &= ~(PPC_BIT(0) | PPC_BIT(1));
+ xscom_write(p->chip_id, CAPP_ERR_STATUS_CTRL + offset, reg);
+}
+
static int64_t phb4_creset(struct pci_slot *slot)
{
struct phb4 *p = phb_to_phb4(slot->phb);
@@ -2806,11 +2827,9 @@ static int64_t phb4_creset(struct pci_slot *slot)
case PHB4_SLOT_CRESET_START:
PHBDBG(p, "CRESET: Starts\n");
- /* do steps 3-5 of capp recovery procedure */
-#if 0
+ /* capp recovery */
if (p->flags & PHB4_CAPP_RECOVERY)
do_capp_recovery_scoms(p);
-#endif
phb4_prepare_link_change(slot, false);
/* Clear error inject register, preventing recursive errors */
@@ -3523,6 +3542,10 @@ static void phb4_init_capp_regs(struct phb4 *p)
xscom_read(p->chip_id, SNOOP_CONTROL + offset, &reg);
reg |= PPC_BIT(0);
reg |= PPC_BIT(35);
+ reg |= PPC_BIT(45);
+ reg |= PPC_BIT(46);
+ reg |= PPC_BIT(47);
+ reg |= PPC_BIT(50);
xscom_write(p->chip_id, SNOOP_CONTROL + offset, reg);
/* Transport Control Register */
@@ -3553,12 +3576,12 @@ static void phb4_init_capp_regs(struct phb4 *p)
/* Flush SUE State Map Register */
xscom_write(p->chip_id, FLUSH_SUE_STATE_MAP + offset,
- 0x1DCF5F6600000000);
+ 0x08020A0000000000);
if (p->rev == PHB4_REV_NIMBUS_DD20) {
/* Flush SUE uOP1 Register */
xscom_write(p->chip_id, FLUSH_SUE_UOP1 + offset,
- 0xE310280428000000);
+ 0xDCE0280428000000);
}
/* capp owns PHB read buffers */
@@ -3576,6 +3599,15 @@ static void phb4_init_capp_regs(struct phb4 *p)
0xFFFFF00E00000000);
}
+ /* CAPP FIR Action 0 */
+ xscom_write(p->chip_id, CAPP_FIR_ACTION0 + offset, 0x0b1c000104060000);
+
+ /* CAPP FIR Action 1 */
+ xscom_write(p->chip_id, CAPP_FIR_ACTION1 + offset, 0x2b9c0001240E0000);
+
+ /* CAPP FIR MASK */
+ xscom_write(p->chip_id, CAPP_FIR_MASK + offset, 0x80031f98d8717000);
+
/* Deassert TLBI_FENCED and tlbi_psl_is_dead */
xscom_write(p->chip_id, CAPP_ERR_STATUS_CTRL + offset, 0);
}
@@ -3927,6 +3959,22 @@ static void phb4_set_p2p(struct phb *phb, uint64_t mode, uint64_t flags,
}
}
+static int64_t phb4_set_capp_recovery(struct phb *phb)
+{
+ struct phb4 *p = phb_to_phb4(phb);
+
+ if (p->flags & PHB4_CAPP_RECOVERY)
+ return 0;
+
+ /* set opal event flag to indicate eeh condition */
+ opal_update_pending_evt(OPAL_EVENT_PCI_ERROR,
+ OPAL_EVENT_PCI_ERROR);
+
+ p->flags |= PHB4_CAPP_RECOVERY;
+
+ return 0;
+}
+
static const struct phb_ops phb4_ops = {
.cfg_read8 = phb4_pcicfg_read8,
.cfg_read16 = phb4_pcicfg_read16,
@@ -3961,6 +4009,7 @@ static const struct phb_ops phb4_ops = {
.tce_kill = phb4_tce_kill,
.set_capi_mode = phb4_set_capi_mode,
.set_p2p = phb4_set_p2p,
+ .set_capp_recovery = phb4_set_capp_recovery,
};
static void phb4_init_ioda3(struct phb4 *p)