---
drivers/pci/setup-bus.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
===================================================================
@@ -1118,6 +1118,52 @@ handle_done:
;
}
+static void pbus_check_mem64(struct pci_bus *bus, unsigned long mask,
+ unsigned long type, struct list_head *realloc_head)
+{
+ struct pci_dev *dev;
+ resource_size_t align;
+ resource_size_t aligns[18]; /* Alignments from 1Mb to 128Gb */
+ int order;
+ unsigned int mem64_mask = 0;
+ struct resource *b_res = find_free_bus_resource(bus, mask, type);
+
+ if (!b_res || !(b_res->flags & IORESOURCE_MEM_64))
+ return;
+
+ memset(aligns, 0, sizeof(aligns));
+
+ mem64_mask = IORESOURCE_MEM_64;
+ b_res->flags &= ~IORESOURCE_MEM_64;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ int i;
+
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ struct resource *r = &dev->resource[i];
+
+ if (r->parent || (r->flags & mask) != type)
+ continue;
+#ifdef CONFIG_PCI_IOV
+ if (realloc_head && i >= PCI_IOV_RESOURCES &&
+ i <= PCI_IOV_RESOURCE_END)
+ continue;
+#endif
+ align = pci_resource_alignment(dev, r);
+ order = __ffs(align) - 20;
+ if (order < 0)
+ order = 0;
+ if (order >= ARRAY_SIZE(aligns))
+ continue;
+
+ if (i != PCI_ROM_RESOURCE)
+ mem64_mask &= r->flags & IORESOURCE_MEM_64;
+ }
+ }
+
+ b_res->flags |= mem64_mask;
+}
+
void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
{
struct pci_dev *dev;
@@ -1171,6 +1217,10 @@ void __pci_bus_size_bridges(struct pci_b
b_res = &bus->self->resource[PCI_BRIDGE_RESOURCES];
mask = IORESOURCE_MEM;
prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH;
+
+ if (b_res[2].flags & IORESOURCE_MEM_64)
+ pbus_check_mem64(bus, prefmask, prefmask, realloc_head);
+
if (b_res[2].flags & IORESOURCE_MEM_64) {
prefmask |= IORESOURCE_MEM_64;
ret = pbus_size_mem(bus, prefmask, prefmask,