diff options
author | Christophe Lombard <clombard@linux.vnet.ibm.com> | 2017-09-20 13:39:06 +0200 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-09-20 23:25:01 -0500 |
commit | 5779c11fdc57c4dc474beb00f044f34ec1c58368 (patch) | |
tree | ca7b432bc6b58f59a7fdb0382ca89ccefbb1f5de | |
parent | 577b75727d9ee9d57e1468e52275a7d838bbabf0 (diff) | |
download | skiboot-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>
-rw-r--r-- | hw/phb4.c | 59 |
1 files changed, 54 insertions, 5 deletions
@@ -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 &= ~(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 |= 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) |