The only difference between the fixed/immovable and movable BARs is a size and offset preservation after they are released (the corresponding struct resource* detached from a bridge window for a while during a bus rescan). Include fixed/immovable BARs into result of pbus_size_mem(). Signed-off-by: Sergei Miroshnichenko <s.miroshnichenko@xxxxxxxxx> --- drivers/pci/setup-bus.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index e87fefa12f62..5874c352b41e 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -891,6 +891,11 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, resource_size_t children_add_size = 0; resource_size_t min_align, align; + resource_size_t fixed_start = bus->immovable_range[0].start; + resource_size_t fixed_end = bus->immovable_range[0].end; + resource_size_t fixed_size = (fixed_start < fixed_end) ? + (fixed_end - fixed_start + 1) : 0; + if (!b_res) return; @@ -898,6 +903,9 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, if (b_res->parent) return; + if (min_size < fixed_size) + min_size = fixed_size; + min_align = window_alignment(bus, IORESOURCE_IO); list_for_each_entry(dev, &bus->devices, bus_list) { int i; @@ -1006,6 +1014,15 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, resource_size_t children_add_size = 0; resource_size_t children_add_align = 0; resource_size_t add_align = 0; + int idx = pci_get_bridge_resource_idx(b_res); + + resource_size_t fixed_start = bus->immovable_range[idx].start; + resource_size_t fixed_end = bus->immovable_range[idx].end; + resource_size_t fixed_size = (fixed_start < fixed_end) ? + (fixed_end - fixed_start + 1) : 0; + + if (min_size < fixed_size) + min_size = fixed_size; if (!b_res) return -ENOSPC; @@ -1028,12 +1045,22 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, struct resource *r = &dev->resource[i]; resource_size_t r_size; - if (r->parent || (r->flags & IORESOURCE_PCI_FIXED) || + if (r->parent || ((r->flags & mask) != type && (r->flags & mask) != type2 && (r->flags & mask) != type3)) continue; r_size = resource_size(r); + + if (pci_can_move_bars && !pci_dev_bar_movable(dev, r)) { + size += r_size; + + continue; + } else if (!pci_can_move_bars && + (r->flags & IORESOURCE_PCI_FIXED)) { + continue; + } + #ifdef CONFIG_PCI_IOV /* Put SRIOV requested res to the optional list */ if (realloc_head && i >= PCI_IOV_RESOURCES && -- 2.24.1