@@ -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" : \
@@ -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)
@@ -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;
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@yadro.com> --- drivers/pci/pci.h | 2 ++ drivers/pci/setup-bus.c | 25 ++++++++++++++++++------- drivers/pci/setup-res.c | 5 ++++- 3 files changed, 24 insertions(+), 8 deletions(-)