PCI: Handle IORESOURCE_PCI_FIXED when assigning resources
authorDavid Daney <david.daney@cavium.com>
Thu, 29 Oct 2015 22:35:39 +0000 (17:35 -0500)
committerBjorn Helgaas <bhelgaas@google.com>
Thu, 29 Oct 2015 22:35:39 +0000 (17:35 -0500)
The new Enhanced Allocation (EA) capability support (patches to follow)
creates resources with the IORESOURCE_PCI_FIXED set.  During resource
assignment in pci_bus_assign_resources(), IORESOURCE_PCI_FIXED resources
are not given a parent.  This, in turn, causes pci_enable_resources() to
fail with a "not claimed" error.

So, in __pci_bus_assign_resources(), for IORESOURCE_PCI_FIXED resources,
try to request the resource from a parent bus.

Signed-off-by: David Daney <david.daney@cavium.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Sean O. Stalley <sean.stalley@intel.com>
drivers/pci/setup-bus.c

index 7bea2317df14de9c68afd4977010ccca14655cd1..1723ac1b30e10f2ff4213f8a65ceeb0a3ff7a786 100644 (file)
@@ -1341,6 +1341,47 @@ 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 i;
+       struct resource *parent_r;
+       unsigned long mask = IORESOURCE_IO | IORESOURCE_MEM |
+                            IORESOURCE_PREFETCH;
+
+       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);
+       }
+}
+
+/*
+ * Try to assign any resources marked as IORESOURCE_PCI_FIXED, as they
+ * are skipped by pbus_assign_resources_sorted().
+ */
+static void pdev_assign_fixed_resources(struct pci_dev *dev)
+{
+       int i;
+
+       for (i = 0; i <  PCI_NUM_RESOURCES; i++) {
+               struct pci_bus *b;
+               struct resource *r = &dev->resource[i];
+
+               if (r->parent || !(r->flags & IORESOURCE_PCI_FIXED) ||
+                   !(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+                       continue;
+
+               b = dev->bus;
+               while (b && !r->parent) {
+                       assign_fixed_resource_on_bus(b, r);
+                       b = b->parent;
+               }
+       }
+}
+
 void __pci_bus_assign_resources(const struct pci_bus *bus,
                                struct list_head *realloc_head,
                                struct list_head *fail_head)
@@ -1351,6 +1392,8 @@ void __pci_bus_assign_resources(const struct pci_bus *bus,
        pbus_assign_resources_sorted(bus, realloc_head, fail_head);
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
+               pdev_assign_fixed_resources(dev);
+
                b = dev->subordinate;
                if (!b)
                        continue;