@@ -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",
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.miroshnichenko@yadro.com> --- drivers/pci/setup-bus.c | 47 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-)