]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
PCI: Only treat non-pref mmio64 as pref if all bridges have MEM_64
authorYinghai Lu <yinghai@kernel.org>
Thu, 8 Oct 2015 21:38:31 +0000 (14:38 -0700)
committerSantosh Shilimkar <santosh.shilimkar@oracle.com>
Mon, 19 Oct 2015 20:41:12 +0000 (13:41 -0700)
If any bridge up to root only have 32bit pref mmio, We don't need to
treat device non-pref mmio64 as as pref mmio64.

We need to move pci_bridge_check_ranges calling early.
for parent bridges pref mmio BAR may not allocated by BIOS, res flags
is still 0, we need to have it correct set before we check them for
child device resources.

-v2: check all bus resources instead of just res[15].

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Orabug: 21826746

Signed-off-by: Khalid Aziz <khalid.aziz@oracle.com>
(cherry picked from commit 3aa4594c75c6d3a9e72d54320705859f87ff8f7f)

drivers/pci/setup-bus.c

index 6c43c43d5d610eda21a409b10a0df063a5f3ea06..b1e4595ba9348b338ba892bdfd854a50d85683e1 100644 (file)
@@ -739,6 +739,29 @@ int pci_claim_bridge_resource(struct pci_dev *bridge, int i)
        return -EINVAL;
 }
 
+static bool pci_up_path_over_pref_mem64(struct pci_bus *bus)
+{
+       if (pci_is_root_bus(bus))
+               return true;
+
+       if (bus->self) {
+               int i;
+               bool found = false;
+               struct resource *res;
+
+               pci_bus_for_each_resource(bus, res, i)
+                       if (res->flags & IORESOURCE_MEM_64) {
+                               found = true;
+                               break;
+                       }
+
+               if (!found)
+                       return false;
+       }
+
+       return pci_up_path_over_pref_mem64(bus->parent);
+}
+
 int pci_resource_pref_compatible(const struct pci_dev *dev,
                                 struct resource *res)
 {
@@ -747,7 +770,8 @@ int pci_resource_pref_compatible(const struct pci_dev *dev,
 
        if ((res->flags & IORESOURCE_MEM) &&
            (res->flags & IORESOURCE_MEM_64) &&
-           dev->on_all_pcie_path)
+           dev->on_all_pcie_path &&
+           pci_up_path_over_pref_mem64(dev->bus))
                return res->flags | IORESOURCE_PREFETCH;
 
        return res->flags;
@@ -1239,6 +1263,10 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
        struct resource *b_res;
        int ret;
 
+       if (!pci_is_root_bus(bus) &&
+           (bus->self->class >> 8) == PCI_CLASS_BRIDGE_PCI)
+               pci_bridge_check_ranges(bus);
+
        list_for_each_entry(dev, &bus->devices, bus_list) {
                struct pci_bus *b = dev->subordinate;
                if (!b)
@@ -1266,7 +1294,6 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
                break;
 
        case PCI_CLASS_BRIDGE_PCI:
-               pci_bridge_check_ranges(bus);
                if (bus->self->is_hotplug_bridge) {
                        additional_io_size  = pci_hotplug_io_size;
                        additional_mem_size = pci_hotplug_mem_size;