]> www.infradead.org Git - users/hch/misc.git/commitdiff
PCI: Use pbus_select_window() during BAR resize
authorIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Fri, 29 Aug 2025 13:11:04 +0000 (16:11 +0300)
committerBjorn Helgaas <bhelgaas@google.com>
Tue, 16 Sep 2025 16:19:38 +0000 (11:19 -0500)
Prior to a BAR resize, __resource_resize_store() loops through the normal
resources of the PCI device and releases those that match to the flags of
the BAR to be resized. This is necessary to allow resizing also the
upstream bridge window as only childless bridge windows can be resized.

While the flags check (mostly) works (if corner cases are ignored), the
more straightforward way is to check if the resources share the bridge
window. Change __resource_resize_store() to do the check using
pbus_select_window().

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://patch.msgid.link/20250829131113.36754-16-ilpo.jarvinen@linux.intel.com
drivers/pci/pci-sysfs.c

index 162a5241c7f702aeff268dbf2770fc3d8573cfaa..ce3923c4aa80b2bc7643bfc7622e57bac163b650 100644 (file)
@@ -1562,13 +1562,19 @@ static ssize_t __resource_resize_store(struct device *dev, int n,
                                       const char *buf, size_t count)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
-       unsigned long size, flags;
+       struct pci_bus *bus = pdev->bus;
+       struct resource *b_win, *res;
+       unsigned long size;
        int ret, i;
        u16 cmd;
 
        if (kstrtoul(buf, 0, &size) < 0)
                return -EINVAL;
 
+       b_win = pbus_select_window(bus, pci_resource_n(pdev, n));
+       if (!b_win)
+               return -EINVAL;
+
        device_lock(dev);
        if (dev->driver || pci_num_vf(pdev)) {
                ret = -EBUSY;
@@ -1588,19 +1594,19 @@ static ssize_t __resource_resize_store(struct device *dev, int n,
        pci_write_config_word(pdev, PCI_COMMAND,
                              cmd & ~PCI_COMMAND_MEMORY);
 
-       flags = pci_resource_flags(pdev, n);
-
        pci_remove_resource_files(pdev);
 
-       for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) {
-               if (pci_resource_len(pdev, i) &&
-                   pci_resource_flags(pdev, i) == flags)
+       pci_dev_for_each_resource(pdev, res, i) {
+               if (i >= PCI_BRIDGE_RESOURCES)
+                       break;
+
+               if (b_win == pbus_select_window(bus, res))
                        pci_release_resource(pdev, i);
        }
 
        ret = pci_resize_resource(pdev, n, size);
 
-       pci_assign_unassigned_bus_resources(pdev->bus);
+       pci_assign_unassigned_bus_resources(bus);
 
        if (pci_create_resource_files(pdev))
                pci_warn(pdev, "Failed to recreate resource files after BAR resizing\n");