]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
PCI: Adjust the position of reading the Link Control 2 register
authorJiwei Sun <sunjw10@lenovo.com>
Thu, 23 Jan 2025 05:51:55 +0000 (13:51 +0800)
committerBjorn Helgaas <bhelgaas@google.com>
Tue, 24 Jun 2025 20:54:26 +0000 (15:54 -0500)
In a89c82249c37 ("PCI: Work around PCIe link training failures"), if the
speed limit is set to 2.5 GT/s and the retraining is successful, an attempt
will be made to lift the speed limit. One condition for lifting the speed
limit is to check whether the link speed field of the Link Control 2
register is PCI_EXP_LNKCTL2_TLS_2_5GT.

However, since de9a6c8d5dbf ("PCI/bwctrl: Add pcie_set_target_speed() to
set PCIe Link Speed"), the `lnkctl2` local variable does not undergo any
changes during the speed limit setting and retraining process. As a result,
the code intended to lift the speed limit is not executed.

To address this issue, adjust the position of the Link Control 2 register
read operation in the code and place it before its use.

Fixes: de9a6c8d5dbf ("PCI/bwctrl: Add pcie_set_target_speed() to set PCIe Link Speed")
Suggested-by: Maciej W. Rozycki <macro@orcam.me.uk>
Suggested-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Jiwei Sun <sunjw10@lenovo.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://patch.msgid.link/20250123055155.22648-3-sjiwei@163.com
drivers/pci/quirks.c

index d7f4ee634263c264e65dc50b10fc734634e6f36e..db6e142b082daa30c4003a69e5a8d3860c586360 100644 (file)
@@ -105,13 +105,13 @@ int pcie_failed_link_retrain(struct pci_dev *dev)
            !pcie_cap_has_lnkctl2(dev) || !dev->link_active_reporting)
                return ret;
 
-       pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &lnkctl2);
        pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta);
        if (!(lnksta & PCI_EXP_LNKSTA_DLLLA) && pcie_lbms_seen(dev, lnksta)) {
-               u16 oldlnkctl2 = lnkctl2;
+               u16 oldlnkctl2;
 
                pci_info(dev, "broken device, retraining non-functional downstream link at 2.5GT/s\n");
 
+               pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &oldlnkctl2);
                ret = pcie_set_target_speed(dev, PCIE_SPEED_2_5GT, false);
                if (ret) {
                        pci_info(dev, "retraining failed\n");
@@ -123,6 +123,8 @@ int pcie_failed_link_retrain(struct pci_dev *dev)
                pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta);
        }
 
+       pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &lnkctl2);
+
        if ((lnksta & PCI_EXP_LNKSTA_DLLLA) &&
            (lnkctl2 & PCI_EXP_LNKCTL2_TLS) == PCI_EXP_LNKCTL2_TLS_2_5GT &&
            pci_match_id(ids, dev)) {