aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorFrederic Barrat <fbarrat@linux.ibm.com>2021-08-04 12:51:30 +0530
committerVasant Hegde <hegdevasant@linux.vnet.ibm.com>2021-08-06 12:29:59 +0530
commit6af8ac2e00cddcdbdf673b3ea3ead9453c5445ba (patch)
treee1011336fa5366677757020eef267524f0029d5b /hw
parentc226e8bade288835fd78dad3f3751ae322819139 (diff)
downloadskiboot-6af8ac2e00cddcdbdf673b3ea3ead9453c5445ba.zip
skiboot-6af8ac2e00cddcdbdf673b3ea3ead9453c5445ba.tar.gz
skiboot-6af8ac2e00cddcdbdf673b3ea3ead9453c5445ba.tar.bz2
phb5: Workaround for PCI bug HW551382
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@linux.ibm.com> Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/phb4.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/hw/phb4.c b/hw/phb4.c
index 9bc8d47..e30339f 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);