@@ -1510,6 +1510,56 @@ static void __pci_bridge_assign_resources(const struct pci_dev *bridge,
(IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH |\
IORESOURCE_MEM_64)
+/*
+ * Similar to generic release_child_resources(), but aware of fixed BARs and the
+ * STARTALIGN flag.
+ */
+static void pci_release_child_resources(struct pci_bus *bus, struct resource *r)
+{
+ struct pci_dev *dev;
+
+ if (!pci_can_move_bars)
+ return release_child_resources(r);
+
+ if (!bus || !r)
+ return;
+
+ r->child = NULL;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ int i;
+
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ struct resource *tmp = &dev->resource[i];
+ resource_size_t size = resource_size(tmp);
+
+ if (!tmp->flags || !tmp->parent)
+ continue;
+
+ tmp->parent = NULL;
+ tmp->sibling = NULL;
+
+ pci_release_child_resources(dev->subordinate, tmp);
+
+ tmp->flags &= ~IORESOURCE_STARTALIGN;
+ tmp->flags |= IORESOURCE_SIZEALIGN;
+
+ if (pci_dev_bar_fixed(dev, tmp)) {
+ pci_dbg(dev, "release fixed BAR %d %pR (%s), keep its flags, base and size\n",
+ i, tmp, tmp->name);
+ continue;
+ }
+
+ pci_dbg(dev, "release BAR %d %pR (%s)\n", i, tmp, tmp->name);
+
+ if (i >= PCI_BRIDGE_RESOURCES)
+ tmp->flags = 0;
+ tmp->start = 0;
+ tmp->end = size - 1;
+ }
+ }
+}
+
static void pci_bridge_release_resources(struct pci_bus *bus,
unsigned long type)
{
@@ -1550,7 +1600,8 @@ static void pci_bridge_release_resources(struct pci_bus *bus,
return;
/* If there are children, release them all */
- release_child_resources(r);
+ pci_release_child_resources(bus, r);
+
if (!release_resource(r)) {
type = old_flags = r->flags & PCI_RES_TYPE_MASK;
pci_info(dev, "resource %d %pR released\n",
When release_child_resources() is applied to a bridge window, it drops the .start field of children BARs to zero, but the STARTALIGN flag remains set, leaving the resource in a state not valid for later re-assignment. Fixed BARs must preserve their offset and size: those marked with the PCI_FIXED or which are bound by drivers without support of the movable BARs feature. Add the pci_release_child_resources() to replace release_child_resources() in handling the described PCI-specific cases. Signed-off-by: Sergei Miroshnichenko <s.miroshnichenko@yadro.com> --- drivers/pci/setup-bus.c | 53 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-)