On Fri, Aug 22, 2025 at 10:10 PM Brian Norris briannorris@chromium.org wrote:
From: Brian Norris briannorris@google.com
max_link_speed, max_link_width, current_link_speed, current_link_width, secondary_bus_number, and subordinate_bus_number all access config registers, but they don't check the runtime PM state. If the device is in D3cold, we may see -EINVAL or even bogus values.
I've hit this bug as well, except in my case the device was behind a suspended PCI bridge, which seems to block config space accesses.
Wrap these access in pci_config_pm_runtime_{get,put}() like most of the
accesses
rest of the similar sysfs attributes.
Fixes: 56c1af4606f0 ("PCI: Add sysfs max_link_speed/width, current_link_speed/width, etc") Cc: stable@vger.kernel.org Signed-off-by: Brian Norris briannorris@google.com Signed-off-by: Brian Norris briannorris@chromium.org
drivers/pci/pci-sysfs.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 5eea14c1f7f5..160df897dc5e 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -191,9 +191,16 @@ static ssize_t max_link_speed_show(struct device *dev, struct device_attribute *attr, char *buf) { struct pci_dev *pdev = to_pci_dev(dev);
ssize_t ret;
pci_config_pm_runtime_get(pdev);
return sysfs_emit(buf, "%s\n",
pci_speed_string(pcie_get_speed_cap(pdev)));
ret = sysfs_emit(buf, "%s\n",
pci_speed_string(pcie_get_speed_cap(pdev)));
pci_speed_string() & pcie_get_speed_cap() don't access config space, so no need to change this one.
pci_config_pm_runtime_put(pdev);
return ret;