I have observed LBMS becoming set when DPC is triggered on some Intel Root ports. Since the primary feature of DPC is to contain errors by disabling the link it is desirable to avoid carrying previous LBMS state into the next time the link comes up after DPC status is cleared. Specifically when DPC driver waits for secondary bus it should not take previous assertions of LBMS into account which could have occurred as a result of DPC or for some other reason a very long time ago. This prevents the kernel from being heavy handed with the pcie_failed_link_retrain which may thereby force a link to 2.5GT/s when it could have achieved its max speed. If the EP defers bringing up the link until the quirk pcie_failed_link_retrain() has written 2.5GT/s speed to TLS register the link would be forced to 2.5GT/s until user intervention or a later hot-plug/dpc event. Signed-off-by: Matthew W Carlis <mattc@xxxxxxxxxxxxxxx> --- drivers/pci/pcie/dpc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c index fc18349614d7..0bcc99231dfc 100644 --- a/drivers/pci/pcie/dpc.c +++ b/drivers/pci/pcie/dpc.c @@ -164,6 +164,13 @@ pci_ers_result_t dpc_reset_link(struct pci_dev *pdev) */ if (!pcie_wait_for_link(pdev, false)) pci_info(pdev, "Data Link Layer Link Active not cleared in 1000 msec\n"); + /* + * Some RP's observed setting LBMS when DPC triggers & we should also not + * consider an LBMS assertion from an indeterminable amount of time in the past. + * Provide a "fresh start" when waiting for secondary bus & thereby prevent + * pcie_failed_link_retrain from degrading a healthy link. + */ + pcie_reset_lbms(pdev); if (pdev->dpc_rp_extensions && dpc_wait_rp_inactive(pdev)) { clear_bit(PCI_DPC_RECOVERED, &pdev->priv_flags); @@ -330,6 +337,9 @@ static void dpc_handle_surprise_removal(struct pci_dev *pdev) pci_info(pdev, "Data Link Layer Link Active not cleared in 1000 msec\n"); goto out; } + /* + * pciehp will pcie_reset_lbms() in remove_board(). + */ if (pdev->dpc_rp_extensions && dpc_wait_rp_inactive(pdev)) goto out; -- 2.46.0