|
@@ -697,6 +697,38 @@ static resource_size_t calculate_memsize(resource_size_t size,
|
|
|
return size;
|
|
|
}
|
|
|
|
|
|
+resource_size_t __weak pcibios_window_alignment(struct pci_bus *bus,
|
|
|
+ unsigned long type)
|
|
|
+{
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+#define PCI_P2P_DEFAULT_MEM_ALIGN 0x100000 /* 1MiB */
|
|
|
+#define PCI_P2P_DEFAULT_IO_ALIGN 0x1000 /* 4KiB */
|
|
|
+#define PCI_P2P_DEFAULT_IO_ALIGN_1K 0x400 /* 1KiB */
|
|
|
+
|
|
|
+static resource_size_t window_alignment(struct pci_bus *bus,
|
|
|
+ unsigned long type)
|
|
|
+{
|
|
|
+ resource_size_t align = 1, arch_align;
|
|
|
+
|
|
|
+ if (type & IORESOURCE_MEM)
|
|
|
+ align = PCI_P2P_DEFAULT_MEM_ALIGN;
|
|
|
+ else if (type & IORESOURCE_IO) {
|
|
|
+ /*
|
|
|
+ * Per spec, I/O windows are 4K-aligned, but some
|
|
|
+ * bridges have an extension to support 1K alignment.
|
|
|
+ */
|
|
|
+ if (bus->self->io_window_1k)
|
|
|
+ align = PCI_P2P_DEFAULT_IO_ALIGN_1K;
|
|
|
+ else
|
|
|
+ align = PCI_P2P_DEFAULT_IO_ALIGN;
|
|
|
+ }
|
|
|
+
|
|
|
+ arch_align = pcibios_window_alignment(bus, type);
|
|
|
+ return max(align, arch_align);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* pbus_size_io() - size the io window of a given bus
|
|
|
*
|
|
@@ -717,17 +749,12 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
|
|
|
struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
|
|
|
unsigned long size = 0, size0 = 0, size1 = 0;
|
|
|
resource_size_t children_add_size = 0;
|
|
|
- resource_size_t min_align = 4096, align;
|
|
|
+ resource_size_t min_align, io_align, align;
|
|
|
|
|
|
if (!b_res)
|
|
|
return;
|
|
|
|
|
|
- /*
|
|
|
- * Per spec, I/O windows are 4K-aligned, but some bridges have an
|
|
|
- * extension to support 1K alignment.
|
|
|
- */
|
|
|
- if (bus->self->io_window_1k)
|
|
|
- min_align = 1024;
|
|
|
+ io_align = min_align = window_alignment(bus, IORESOURCE_IO);
|
|
|
list_for_each_entry(dev, &bus->devices, bus_list) {
|
|
|
int i;
|
|
|
|
|
@@ -754,8 +781,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (min_align > 4096)
|
|
|
- min_align = 4096;
|
|
|
+ if (min_align > io_align)
|
|
|
+ min_align = io_align;
|
|
|
|
|
|
size0 = calculate_iosize(size, min_size, size1,
|
|
|
resource_size(b_res), min_align);
|
|
@@ -785,6 +812,28 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static inline resource_size_t calculate_mem_align(resource_size_t *aligns,
|
|
|
+ int max_order)
|
|
|
+{
|
|
|
+ resource_size_t align = 0;
|
|
|
+ resource_size_t min_align = 0;
|
|
|
+ int order;
|
|
|
+
|
|
|
+ for (order = 0; order <= max_order; order++) {
|
|
|
+ resource_size_t align1 = 1;
|
|
|
+
|
|
|
+ align1 <<= (order + 20);
|
|
|
+
|
|
|
+ if (!align)
|
|
|
+ min_align = align1;
|
|
|
+ else if (ALIGN(align + min_align, min_align) < align1)
|
|
|
+ min_align = align1 >> 1;
|
|
|
+ align += aligns[order];
|
|
|
+ }
|
|
|
+
|
|
|
+ return min_align;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* pbus_size_mem() - size the memory window of a given bus
|
|
|
*
|
|
@@ -864,19 +913,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
|
|
children_add_size += get_res_add_size(realloc_head, r);
|
|
|
}
|
|
|
}
|
|
|
- align = 0;
|
|
|
- min_align = 0;
|
|
|
- for (order = 0; order <= max_order; order++) {
|
|
|
- resource_size_t align1 = 1;
|
|
|
|
|
|
- align1 <<= (order + 20);
|
|
|
-
|
|
|
- if (!align)
|
|
|
- min_align = align1;
|
|
|
- else if (ALIGN(align + min_align, min_align) < align1)
|
|
|
- min_align = align1 >> 1;
|
|
|
- align += aligns[order];
|
|
|
- }
|
|
|
+ min_align = calculate_mem_align(aligns, max_order);
|
|
|
+ min_align = max(min_align, window_alignment(bus, b_res->flags & mask));
|
|
|
size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
|
|
|
if (children_add_size > add_size)
|
|
|
add_size = children_add_size;
|