aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci-sysfs.c
diff options
context:
space:
mode:
authorIlpo Järvinen <ilpo.jarvinen@linux.intel.com>2025-08-29 16:11:04 +0300
committerBjorn Helgaas <bhelgaas@google.com>2025-09-16 11:19:38 -0500
commit7dc58aa7f1b32a215fb0b7c6ca30ddf4663dedf4 (patch)
tree1a3c7fbdde2649c638ed8c09cb8bc39495a28980 /drivers/pci/pci-sysfs.c
parentPCI: Warn if bridge window cannot be released when resizing BAR (diff)
downloadlinux-7dc58aa7f1b32a215fb0b7c6ca30ddf4663dedf4.tar.gz
linux-7dc58aa7f1b32a215fb0b7c6ca30ddf4663dedf4.zip
PCI: Use pbus_select_window() during BAR resize
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
Diffstat (limited to 'drivers/pci/pci-sysfs.c')
-rw-r--r--drivers/pci/pci-sysfs.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 162a5241c7f7..ce3923c4aa80 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -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");