aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/phb4.c56
-rw-r--r--include/phb4-regs.h1
2 files changed, 57 insertions, 0 deletions
diff --git a/hw/phb4.c b/hw/phb4.c
index ecb73f6..cdc02ca 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -139,6 +139,7 @@ static bool phb4_init_rc_cfg(struct phb4 *p);
#endif
static bool verbose_eeh;
+static bool pci_tracing;
enum capi_dma_tvt {
CAPI_DMA_TVT0,
@@ -2258,6 +2259,58 @@ static int64_t phb4_retry_state(struct pci_slot *slot)
return pci_slot_set_sm_timeout(slot, msecs_to_tb(1));
}
+static void phb4_train_info(struct phb4 *p, uint64_t reg, unsigned long time)
+{
+ char s[80];
+
+ snprintf(s, sizeof(s), "TRACE: 0x%016llx % 2lims",
+ reg, tb_to_msecs(time));
+
+ if (reg & PHB_PCIE_DLP_TL_LINKACT)
+ snprintf(s, sizeof(s), "%s trained", s);
+ else if (reg & PHB_PCIE_DLP_TRAINING)
+ snprintf(s, sizeof(s), "%s training", s);
+ else if (reg & PHB_PCIE_DLP_INBAND_PRESENCE)
+ snprintf(s, sizeof(s), "%s presence", s);
+
+ PHBERR(p, "%s\n", s);
+}
+
+/*
+ * This is a trace function to watch what's happening duing pcie link
+ * training. If any errors are detected it simply returns so the
+ * normal code can deal with it.
+ */
+static void phb4_training_trace(struct phb4 *p)
+{
+ uint64_t reg, reglast = -1;
+ unsigned long now, start = mftb();
+
+ if (!pci_tracing)
+ return;
+
+ while(1) {
+ now = mftb();
+ reg = in_be64(p->regs + PHB_PCIE_DLP_TRAIN_CTL);
+ if (reg != reglast)
+ phb4_train_info(p, reg, now - start);
+ reglast = reg;
+
+ if (!phb4_check_reg(p, reg)) {
+ PHBERR(p, "TRACE: PHB fence waiting link.\n");
+ break;
+ }
+ if (reg & PHB_PCIE_DLP_TL_LINKACT) {
+ PHBERR(p, "TRACE: Link trained.\n");
+ break;
+ }
+ if ((now - start) > secs_to_tb(3)) {
+ PHBERR(p, "TRACE: Timeout waiting for link up.\n");
+ break;
+ }
+ }
+}
+
static int64_t phb4_poll_link(struct pci_slot *slot)
{
struct phb4 *p = phb_to_phb4(slot->phb);
@@ -2464,6 +2517,8 @@ static int64_t phb4_freset(struct pci_slot *slot)
pci_slot_set_state(slot,
PHB4_SLOT_FRESET_DEASSERT_DELAY);
+ phb4_training_trace(p);
+
/* Move on to link poll right away */
return pci_slot_set_sm_timeout(slot, msecs_to_tb(1));
case PHB4_SLOT_FRESET_DEASSERT_DELAY:
@@ -4683,6 +4738,7 @@ void probe_phb4(void)
if (verbose_eeh)
prlog(PR_INFO, "PHB4: Verbose EEH enabled\n");
+ pci_tracing = nvram_query_eq("pci-tracing", "true");
/* Look for PBCQ XSCOM nodes */
dt_for_each_compatible(dt_root, np, "ibm,power9-pbcq")
phb4_probe_pbcq(np);
diff --git a/include/phb4-regs.h b/include/phb4-regs.h
index 14e9351..932da5b 100644
--- a/include/phb4-regs.h
+++ b/include/phb4-regs.h
@@ -284,6 +284,7 @@
#define PHB_PCIE_DLP_TRAIN_CTL 0x1A40
#define PHB_PCIE_DLP_TL_LINKACT PPC_BIT(23)
#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_ERRLOG1 0x1AA0