[Skiboot] [PATCH 01/14] phb4: Only clear some PHB config space registers on errors

Michael Neuling mikey at neuling.org
Wed Jul 26 20:50:00 AEST 2017


Currently on error we clear the entire PHB config space.  This is a
problem as the PCIe Maximum Payload Size (MPS) negotiation may have
already occurred. Clearing MPS in the PHB back to a default of 128
bytes will result an error for a device which already has a larger MPS
configured.

This will manifest itself as error due to a malformed TLP packet. ie.
  phbPblErrorStatus bit 41  = "Malformed TLP error"
This has been seen after kexec on with some adapters.

This fixes the problem by only clearing a subset of registers on a phb
error.

Reported-by: Rob Lippert <rlippert at google.com>
Signed-off-by: Michael Neuling <mikey at neuling.org>
---
 hw/phb4.c | 51 ++++++++++++++++++++++++++++++++-------------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/hw/phb4.c b/hw/phb4.c
index cdc02cad16..8a4d055874 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -120,7 +120,6 @@
 #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, \
@@ -1792,6 +1791,34 @@ static int64_t phb4_get_msi_64(struct phb *phb,
 	return OPAL_SUCCESS;
 }
 
+static void phb4_rc_err_clear(struct phb4 *p)
+{
+	/* Init_47 - Clear errors */
+	phb4_pcicfg_write16(&p->phb, 0, PCI_CFG_SECONDARY_STATUS, 0xffff);
+
+	if (p->ecap <= 0)
+		return;
+
+	phb4_pcicfg_write16(&p->phb, 0, p->ecap + PCICAP_EXP_DEVSTAT,
+			     PCICAP_EXP_DEVSTAT_CE	|
+			     PCICAP_EXP_DEVSTAT_NFE	|
+			     PCICAP_EXP_DEVSTAT_FE	|
+			     PCICAP_EXP_DEVSTAT_UE);
+
+	if (p->aercap <= 0)
+		return;
+
+	/* Clear all UE status */
+	phb4_pcicfg_write32(&p->phb, 0, p->aercap + PCIECAP_AER_UE_STATUS,
+			     0xffffffff);
+	/* Clear all CE status */
+	phb4_pcicfg_write32(&p->phb, 0, p->aercap + PCIECAP_AER_CE_STATUS,
+			     0xffffffff);
+	/* Clear root error status */
+	phb4_pcicfg_write32(&p->phb, 0, p->aercap + PCIECAP_AER_RERR_STA,
+			     0xffffffff);
+}
+
 /*
  * The function can be called during error recovery for all classes of
  * errors.  This is new to PHB4; previous revisions had separate
@@ -1808,8 +1835,7 @@ static void phb4_err_clear(struct phb4 *p)
 	/* 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);
+	phb4_rc_err_clear(p);
 
 	/* Rec 16/17: Clear PBL errors */
 	val64 = phb4_read_reg(p, PHB_PBL_ERR_STATUS);
@@ -3667,7 +3693,7 @@ static bool phb4_init_rc_cfg(struct phb4 *p)
 	phb4_pcicfg_write32(&p->phb, 0, PCI_CFG_PRIMARY_BUS, 0x00ff0100);
 
 	/* Init_47 - Clear errors */
-	phb4_pcicfg_write16(&p->phb, 0, PCI_CFG_SECONDARY_STATUS, 0xffff);
+	/* see phb4_rc_err_clear() called below */
 
 	/* Init_48
 	 *
@@ -3693,12 +3719,6 @@ static bool phb4_init_rc_cfg(struct phb4 *p)
 		ecap = p->ecap;
 	}
 
-	phb4_pcicfg_write16(&p->phb, 0, ecap + PCICAP_EXP_DEVSTAT,
-			     PCICAP_EXP_DEVSTAT_CE	|
-			     PCICAP_EXP_DEVSTAT_NFE	|
-			     PCICAP_EXP_DEVSTAT_FE	|
-			     PCICAP_EXP_DEVSTAT_UE);
-
 	phb4_pcicfg_write16(&p->phb, 0, ecap + PCICAP_EXP_DEVCTL,
 			     PCICAP_EXP_DEVCTL_CE_REPORT	|
 			     PCICAP_EXP_DEVCTL_NFE_REPORT	|
@@ -3726,25 +3746,18 @@ static bool phb4_init_rc_cfg(struct phb4 *p)
 		aercap = p->aercap;
 	}
 
-	/* Clear all UE status */
-	phb4_pcicfg_write32(&p->phb, 0, aercap + PCIECAP_AER_UE_STATUS,
-			     0xffffffff);
 	/* Disable some error reporting as per the PHB4 spec */
 	phb4_pcicfg_write32(&p->phb, 0, aercap + PCIECAP_AER_UE_MASK,
 			     PCIECAP_AER_UE_POISON_TLP		|
 			     PCIECAP_AER_UE_COMPL_TIMEOUT	|
 			     PCIECAP_AER_UE_COMPL_ABORT);
 
-	/* Clear all CE status */
-	phb4_pcicfg_write32(&p->phb, 0, aercap + PCIECAP_AER_CE_STATUS,
-			     0xffffffff);
 	/* Enable ECRC generation & checking */
 	phb4_pcicfg_write32(&p->phb, 0, aercap + PCIECAP_AER_CAPCTL,
 			     PCIECAP_AER_CAPCTL_ECRCG_EN	|
 			     PCIECAP_AER_CAPCTL_ECRCC_EN);
-	/* Clear root error status */
-	phb4_pcicfg_write32(&p->phb, 0, aercap + PCIECAP_AER_RERR_STA,
-			     0xffffffff);
+
+	phb4_rc_err_clear(p);
 
 	return true;
 }
-- 
2.11.0



More information about the Skiboot mailing list