Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI: Adjust the position of reading the Link Control 2 register

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

authored by

Jiwei Sun and committed by
Bjorn Helgaas
b85af48d 9989e0ca

+4 -2
+4 -2
drivers/pci/quirks.c
··· 105 105 !pcie_cap_has_lnkctl2(dev) || !dev->link_active_reporting) 106 106 return ret; 107 107 108 - pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &lnkctl2); 109 108 pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta); 110 109 if (!(lnksta & PCI_EXP_LNKSTA_DLLLA) && pcie_lbms_seen(dev, lnksta)) { 111 - u16 oldlnkctl2 = lnkctl2; 110 + u16 oldlnkctl2; 112 111 113 112 pci_info(dev, "broken device, retraining non-functional downstream link at 2.5GT/s\n"); 114 113 114 + pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &oldlnkctl2); 115 115 ret = pcie_set_target_speed(dev, PCIE_SPEED_2_5GT, false); 116 116 if (ret) { 117 117 pci_info(dev, "retraining failed\n"); ··· 122 122 123 123 pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta); 124 124 } 125 + 126 + pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &lnkctl2); 125 127 126 128 if ((lnksta & PCI_EXP_LNKSTA_DLLLA) && 127 129 (lnkctl2 & PCI_EXP_LNKCTL2_TLS) == PCI_EXP_LNKCTL2_TLS_2_5GT &&