[PATCH 1/1] PCI: Reset LBMS state before clearing DPC status.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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





[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux