PCI: Clear the LBMS bit after a link retrain

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

 



From: Maciej W. Rozycki <macro@xxxxxxxxxxx>

commit 8037ac08c2bbb3186f83a5a924f52d1048dbaec5 upstream.

The LBMS bit, where implemented, is set by hardware either in response
to the completion of retraining caused by writing 1 to the Retrain Link
bit or whenever hardware has changed the link speed or width in attempt
to correct unreliable link operation.  It is never cleared by hardware
other than by software writing 1 to the bit position in the Link Status
register and we never do such a write.

We currently have two places, namely apply_bad_link_workaround() and
pcie_failed_link_retrain() in drivers/pci/controller/dwc/pcie-tegra194.c
and drivers/pci/quirks.c respectively where we check the state of the LBMS
bit and neither is interested in the state of the bit resulting from the
completion of retraining, both check for a link fault.

And in particular pcie_failed_link_retrain() causes issues consequently, by
trying to retrain a link where there's no downstream device anymore and the
state of 1 in the LBMS bit has been retained from when there was a device
downstream that has since been removed.

Clear the LBMS bit then at the conclusion of pcie_retrain_link(), so that
we have a single place that controls it and that our code can track link
speed or width changes resulting from unreliable link operation.

Fixes: a89c82249c37 ("PCI: Work around PCIe link training failures")
Link: https://lore.kernel.org/r/alpine.DEB.2.21.2408091133140.61955@xxxxxxxxxxxxxxxxx
Reported-by: Matthew W Carlis <mattc@xxxxxxxxxxxxxxx>
Link: https://lore.kernel.org/r/20240806000659.30859-1-mattc@xxxxxxxxxxxxxxx/
Link: https://lore.kernel.org/r/20240722193407.23255-1-mattc@xxxxxxxxxxxxxxx/
Signed-off-by: Maciej W. Rozycki <macro@xxxxxxxxxxx>
Signed-off-by: Bjorn Helgaas <bhelgaas@xxxxxxxxxx>
Signed-off-by: Krzysztof Wilczyński <kwilczynski@xxxxxxxxxx>
Cc: <stable@xxxxxxxxxxxxxxx> # v6.5+
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
 drivers/pci/pci.c |   10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4718,7 +4718,15 @@ int pcie_retrain_link(struct pci_dev *pd
 		pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_RL);
 	}
 
-	return pcie_wait_for_link_status(pdev, use_lt, !use_lt);
+	rc = pcie_wait_for_link_status(pdev, use_lt, !use_lt);
+
+	/*
+	 * Clear LBMS after a manual retrain so that the bit can be used
+	 * to track link speed or width changes made by hardware itself
+	 * in attempt to correct unreliable link operation.
+	 */
+	pcie_capability_write_word(pdev, PCI_EXP_LNKSTA, PCI_EXP_LNKSTA_LBMS);
+	return rc;
 }
 
 /**


Patches currently in stable-queue which might be from macro@xxxxxxxxxxx are

queue-6.11/pci-revert-to-the-original-speed-after-pcie-failed-link-retraining.patch
queue-6.11/pci-correct-error-reporting-with-pcie-failed-link-retraining.patch
queue-6.11/pci-use-an-error-code-with-pcie-failed-link-retraining.patch
queue-6.11/pci-clear-the-lbms-bit-after-a-link-retrain.patch




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux