The PCI_FIXED and other immovable BARs must be assigned after the bridge windows of parent bridge and before "usual" BARs, but currently they are assigned the last by the pdev_assign_fixed_resources(). Let the immovable BARs be handled by pci_assign_resource() in the same way as it does for movable ones, assigning them in correct order, unifying the code. Allow matching IORESOURCE_PCI_FIXED prefetchable BARs to non-prefetchable windows, so they follow the same rules as immovable BARs. Signed-off-by: Sergei Miroshnichenko <s.miroshnichenko@xxxxxxxxx> --- drivers/pci/pci.h | 2 ++ drivers/pci/setup-bus.c | 25 ++++++++++++++++++------- drivers/pci/setup-res.c | 5 ++++- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index ddd6fd33f9c3..3ffbee2c3243 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -293,6 +293,8 @@ void pci_bus_put(struct pci_bus *bus); bool pci_dev_bar_movable(struct pci_dev *dev, struct resource *res); void pci_bus_update_realloc_range(struct pci_bus *bus); +int assign_fixed_resource_on_bus(struct pci_bus *b, struct resource *r); + /* PCIe link information */ #define PCIE_SPEED2STR(speed) \ ((speed) == PCIE_SPEED_16_0GT ? "16 GT/s" : \ diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 71babb968830..cdbf4afe1334 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1356,21 +1356,31 @@ void pci_bus_size_bridges(struct pci_bus *bus) } EXPORT_SYMBOL(pci_bus_size_bridges); -static void assign_fixed_resource_on_bus(struct pci_bus *b, struct resource *r) +int assign_fixed_resource_on_bus(struct pci_bus *b, struct resource *r) { int i; struct resource *parent_r; - unsigned long mask = IORESOURCE_IO | IORESOURCE_MEM | - IORESOURCE_PREFETCH; + unsigned long mask = IORESOURCE_TYPE_BITS; pci_bus_for_each_resource(b, parent_r, i) { if (!parent_r) continue; - if ((r->flags & mask) == (parent_r->flags & mask) && - resource_contains(parent_r, r)) - request_resource(parent_r, r); + if ((r->flags & mask) != (parent_r->flags & mask)) + continue; + + if (parent_r->flags & IORESOURCE_PREFETCH && + !(r->flags & IORESOURCE_PREFETCH)) + continue; + + if (resource_contains(parent_r, r)) { + if (!request_resource(parent_r, r)) + return 0; + } } + + dev_err(&b->dev, "failed to assign immovable %pR\n", r); + return -EBUSY; } /* @@ -1410,7 +1420,8 @@ void __pci_bus_assign_resources(const struct pci_bus *bus, if (!pci_dev_bars_enabled(dev)) continue; - pdev_assign_fixed_resources(dev); + if (!pci_can_move_bars) + pdev_assign_fixed_resources(dev); b = dev->subordinate; if (!b) diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 3582ae68840b..a7d81816d1ea 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -339,7 +339,10 @@ int pci_assign_resource(struct pci_dev *dev, int resno) resource_size_t align, size; int ret; - if (res->flags & IORESOURCE_PCI_FIXED) + if (pci_can_move_bars && !pci_dev_bar_movable(dev, res) && + resno < PCI_ROM_RESOURCE && res->start) + return assign_fixed_resource_on_bus(dev->bus, res); + else if (!pci_can_move_bars && res->flags & IORESOURCE_PCI_FIXED) return 0; res->flags |= IORESOURCE_UNSET; -- 2.24.1