[Skiboot] [PATCH 53/61] phb5: Workaround for PCI bug HW551382

Vasant Hegde hegdevasant at linux.vnet.ibm.com
Mon Jul 19 23:20:04 AEST 2021


From: Frederic Barrat <fbarrat at linux.ibm.com>

The workaround forces a state machine deep in the PHB to start from
scratch and to block its evolution until after the link has been
reset. It applies on all paths where the link can go down
unexpectedly, though it's probably useless on the creset path, since
we're going to deep-reset the PHB anyway. But it doesn't hurt and it
keeps the set/unset path symmetrical.

Signed-off-by: Frederic Barrat <fbarrat at linux.ibm.com>
Signed-off-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
---
 hw/phb4.c           | 35 +++++++++++++++++++++++++++++++++++
 include/phb4-regs.h |  2 +-
 2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/hw/phb4.c b/hw/phb4.c
index b2160a925..e3cf9038e 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -3072,6 +3072,18 @@ static void phb4_assert_perst(struct pci_slot *slot, bool assert)
 	phb4_pcicfg_write16(&p->phb, 0, p->ecap + PCICAP_EXP_LCTL, linkctl);
 }
 
+static void set_sys_disable_detect(struct phb4 *p, bool set)
+{
+	uint64_t val;
+
+	val = in_be64(p->regs + PHB_PCIE_DLP_TRAIN_CTL);
+	if (set)
+		val |= PHB_PCIE_DLP_SYS_DISABLEDETECT;
+	else
+		val &= ~PHB_PCIE_DLP_SYS_DISABLEDETECT;
+	out_be64(p->regs + PHB_PCIE_DLP_TRAIN_CTL, val);
+}
+
 static int64_t phb4_hreset(struct pci_slot *slot)
 {
 	struct phb4 *p = phb_to_phb4(slot->phb);
@@ -3088,6 +3100,12 @@ static int64_t phb4_hreset(struct pci_slot *slot)
 			return OPAL_SUCCESS;
 		}
 
+		/* circumvention for HW551382 */
+		if (is_phb5()) {
+			PHBINF(p, "HRESET: Workaround for HW551382\n");
+			set_sys_disable_detect(p, true);
+		}
+
 		PHBDBG(p, "HRESET: Prepare for link down\n");
 		phb4_prepare_link_change(slot, false);
 		/* fall through */
@@ -3120,6 +3138,8 @@ static int64_t phb4_hreset(struct pci_slot *slot)
 		pci_slot_set_state(slot, PHB4_SLOT_HRESET_DELAY2);
 		return pci_slot_set_sm_timeout(slot, secs_to_tb(1));
 	case PHB4_SLOT_HRESET_DELAY2:
+		if (is_phb5())
+			set_sys_disable_detect(p, false);
 		pci_slot_set_state(slot, PHB4_SLOT_LINK_START);
 		return slot->ops.poll_link(slot);
 	default:
@@ -3146,6 +3166,12 @@ static int64_t phb4_freset(struct pci_slot *slot)
 		phb4_prepare_link_change(slot, false);
 
 		if (!p->skip_perst) {
+			/* circumvention for HW551382 */
+			if (is_phb5()) {
+				PHBINF(p, "FRESET: Workaround for HW551382\n");
+				set_sys_disable_detect(p, true);
+			}
+
 			PHBDBG(p, "FRESET: Assert\n");
 			phb4_assert_perst(slot, true);
 			pci_slot_set_state(slot, PHB4_SLOT_FRESET_ASSERT_DELAY);
@@ -3169,6 +3195,9 @@ static int64_t phb4_freset(struct pci_slot *slot)
 		if (pci_tracing)
 			phb4_link_trace(p, PHB_PCIE_DLP_LTSSM_L0, 3000);
 
+		if (is_phb5())
+			set_sys_disable_detect(p, false);
+
 		pci_slot_set_state(slot, PHB4_SLOT_LINK_START);
 		return slot->ops.poll_link(slot);
 	default:
@@ -3398,6 +3427,12 @@ static int64_t phb4_creset(struct pci_slot *slot)
 
 		p->creset_start_time = mftb();
 
+		/* circumvention for HW551382 */
+		if (is_phb5()) {
+			PHBINF(p, "CRESET: Workaround for HW551382\n");
+			set_sys_disable_detect(p, true);
+		}
+
 		phb4_prepare_link_change(slot, false);
 		/* Clear error inject register, preventing recursive errors */
 		xscom_write(p->chip_id, p->pe_xscom + 0x2, 0x0);
diff --git a/include/phb4-regs.h b/include/phb4-regs.h
index 8ab78c377..85d2cf2ea 100644
--- a/include/phb4-regs.h
+++ b/include/phb4-regs.h
@@ -275,7 +275,7 @@
 #define   PHB_PCIE_DLP_DL_PGRESET	PPC_BIT(22)
 #define   PHB_PCIE_DLP_TRAINING		PPC_BIT(20)
 #define   PHB_PCIE_DLP_INBAND_PRESENCE  PPC_BIT(19)
-
+#define   PHB_PCIE_DLP_SYS_DISABLEDETECT	PPC_BIT(12)
 #define PHB_PCIE_DLP_CTL		0x1A78
 #define   PHB_PCIE_DLP_CTL_BYPASS_PH2	PPC_BIT(4)
 #define   PHB_PCIE_DLP_CTL_BYPASS_PH3	PPC_BIT(5)
-- 
2.31.1



More information about the Skiboot mailing list