From: Brian Norris Date: Mon, 20 Oct 2025 20:41:36 +0000 (-0700) Subject: PCI/sysfs: Ensure devices are powered for config reads (part 2) X-Git-Tag: v5.15.196~79 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ae9ad3b6732528cfd60f7b86b77d8d8bc4662b9e;p=thirdparty%2Fkernel%2Fstable.git PCI/sysfs: Ensure devices are powered for config reads (part 2) Commit 48991e493507 ("PCI/sysfs: Ensure devices are powered for config reads") was applied to various linux-stable trees. However, prior to 6.12.y, we do not have commit d2bd39c0456b ("PCI: Store all PCIe Supported Link Speeds"). Therefore, we also need to apply the change to max_link_speed_show(). This was pointed out here: Re: Patch "PCI/sysfs: Ensure devices are powered for config reads" has been added to the 6.6-stable tree https://lore.kernel.org/all/aPEMIreBYZ7yk3cm@google.com/ Original change description follows: The "max_link_width", "current_link_speed", "current_link_width", "secondary_bus_number", and "subordinate_bus_number" sysfs files all access config registers, but they don't check the runtime PM state. If the device is in D3cold or a parent bridge is suspended, we may see -EINVAL, bogus values, or worse, depending on implementation details. Wrap these access in pci_config_pm_runtime_{get,put}() like most of the rest of the similar sysfs attributes. Notably, "max_link_speed" does not access config registers; it returns a cached value since d2bd39c0456b ("PCI: Store all PCIe Supported Link Speeds"). Fixes: 56c1af4606f0 ("PCI: Add sysfs max_link_speed/width, current_link_speed/width, etc") Link: https://lore.kernel.org/all/aPEMIreBYZ7yk3cm@google.com/ Signed-off-by: Brian Norris Signed-off-by: Brian Norris Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 5f86f49ad3c8..2943c4ca5c08 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -164,9 +164,15 @@ 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; + + /* We read PCI_EXP_LNKCAP, so we need the device to be accessible. */ + pci_config_pm_runtime_get(pdev); + ret = sysfs_emit(buf, "%s\n", + pci_speed_string(pcie_get_speed_cap(pdev))); + pci_config_pm_runtime_put(pdev); - return sysfs_emit(buf, "%s\n", - pci_speed_string(pcie_get_speed_cap(pdev))); + return ret; } static DEVICE_ATTR_RO(max_link_speed);