]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
PCI/sysfs: Ensure devices are powered for config reads (part 2)
authorBrian Norris <briannorris@google.com>
Mon, 20 Oct 2025 20:41:36 +0000 (13:41 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 29 Oct 2025 13:03:09 +0000 (14:03 +0100)
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 <briannorris@google.com>
Signed-off-by: Brian Norris <briannorris@chromium.org>
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/pci/pci-sysfs.c

index 5f86f49ad3c8b4294ce10792fbbd8924505ab05f..2943c4ca5c080f9ff4ef0efabddc340659fe0db0 100644 (file)
@@ -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);