Make the released resources of a bridge valid for later re-assignment:
clear the STARTALIGN flag.

Resources marked with PCI_FIXED must preserve their offset and size.

Signed-off-by: Sergey Miroshnichenko <s.miroshniche...@yadro.com>
---
 drivers/pci/setup-bus.c | 47 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 46 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index ec44a0f3a7ac..3644feb13179 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1483,6 +1483,51 @@ static void __pci_bridge_assign_resources(const struct 
pci_dev *bridge,
        (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH |\
         IORESOURCE_MEM_64)
 
+/*
+ * Similar to release_child_resources(), but aware of PCI_FIXED and STARTALIGN 
flags
+ */
+static void pci_release_child_resources(struct resource *r)
+{
+       struct resource *tmp, *p;
+
+       if (!r)
+               return;
+
+       if (r->flags & IORESOURCE_PCI_FIXED)
+               return;
+
+       p = r->child;
+       r->child = NULL;
+       while (p) {
+               resource_size_t size = resource_size(p);
+
+               tmp = p;
+               p = p->sibling;
+
+               tmp->parent = NULL;
+               tmp->sibling = NULL;
+               pci_release_child_resources(tmp);
+
+               if (!tmp->flags)
+                       continue;
+
+               if (tmp->flags & IORESOURCE_PCI_FIXED) {
+                       pr_debug("PCI: release fixed %pR (%s), keep its flags, 
base and size\n",
+                                tmp, tmp->name);
+                       continue;
+               }
+
+               pr_debug("PCI: release %pR (%s)\n", tmp, tmp->name);
+
+               /* need to restore size, and keep all the flags but STARTALIGN 
*/
+               tmp->start = 0;
+               tmp->end = size - 1;
+
+               tmp->flags &= ~IORESOURCE_STARTALIGN;
+               tmp->flags |= IORESOURCE_SIZEALIGN;
+       }
+}
+
 static void pci_bridge_release_resources(struct pci_bus *bus,
                                          unsigned long type)
 {
@@ -1528,7 +1573,7 @@ static void pci_bridge_release_resources(struct pci_bus 
*bus,
         * if there are children under that, we should release them
         *  all
         */
-       release_child_resources(r);
+       pci_release_child_resources(r);
        if (!release_resource(r)) {
                type = old_flags = r->flags & PCI_RES_TYPE_MASK;
                pci_printk(KERN_DEBUG, dev, "resource %d %pR released\n",
-- 
2.20.1

Reply via email to