|
|
|
|
|
|
|
|
|
|
xen-devel
[Xen-devel] [PATCH 2/3] dom0 linux: Sort PCI resource based on priority
This patch add sorting PCI resource based on priority of allocation.
The priority is following.
1. I/O resource
2. Prefetchable high MMIO
3. Prefetchable low MMIO
4. high MMIO
5. low MMIO
This patch works when "pci=use_crs" boot parameter is specified.
Thanks,
--
Yuji Shimada
Signed-off-by: Yuji Shimada <shimada-yxb@xxxxxxxxxxxxxxx>
diff -r 13c0881b6f9d arch/i386/pci/acpi.c
--- a/arch/i386/pci/acpi.c Mon Dec 01 21:04:16 2008 +0900
+++ b/arch/i386/pci/acpi.c Mon Dec 01 21:05:35 2008 +0900
@@ -106,6 +106,75 @@ setup_resource(struct acpi_resource *acp
return AE_OK;
}
+static void __devinit sort_resources(struct pci_bus *bus)
+{
+ struct resource *res, *work;
+ int i, j;
+
+ for (i=0; i<(PCI_BUS_NUM_RESOURCES-1); i++) {
+ for (j=(PCI_BUS_NUM_RESOURCES-1); j>i; j--) {
+ res = bus->resource[j];
+ work = bus->resource[j-1];
+ if (!res || !work)
+ continue;
+
+ /* res is MMIO resource and work is I/O resource
+ * they should not be swapped */
+ if ((res->flags & IORESOURCE_MEM) &&
+ (work->flags & IORESOURCE_IO))
+ continue;
+
+ /* both is I/O resource */
+ if ((res->flags & IORESOURCE_IO) &&
+ (work->flags & IORESOURCE_IO))
+ /* work's size is bigger than res's or equal
+ * they should not be swapped */
+ if ((work->end - work->start) >=
+ (res->end - res->start))
+ continue;
+
+ /* both is MMIO resource */
+ if ((res->flags & IORESOURCE_MEM) &&
+ (work->flags & IORESOURCE_MEM)) {
+ /* res isn't prefetchable and
+ * work is prefetchable */
+ if (!(res->flags & IORESOURCE_PREFETCH) &&
+ (work->flags & IORESOURCE_PREFETCH))
+ continue;
+
+ /* both is prefetchable or
+ * both is not prefetchable */
+ if (((res->flags & IORESOURCE_PREFETCH) &&
+ (work->flags & IORESOURCE_PREFETCH)) ||
+ (!(res->flags & IORESOURCE_PREFETCH) &&
+ !(work->flags & IORESOURCE_PREFETCH))) {
+
+ /* res is Low area and work is High area
+ * they should not be swapped */
+ if ((res->start >> 32) == 0 &&
+ (work->start >> 32) != 0)
+ continue;
+
+ /* both is same area (High or Low) */
+ if (((res->start >> 32) != 0 &&
+ (work->start >> 32) != 0) ||
+ ((res->start >> 32) == 0 &&
+ (work->start >> 32) == 0))
+ /* work's size is bigger or
+ * equal than res's size
+ * they should not be swapped */
+ if ((work->end - work->start)
>=
+ (res->end - res->start))
+ continue;
+ }
+ }
+ /* swap res and work */
+ bus->resource[j-1] = res;
+ bus->resource[j] = work;
+ }
+ }
+}
+
/* This function is backported from 2.6.26 kernel */
static void __devinit adjust_transparent_bridge_resources(struct pci_bus *bus)
{
@@ -155,6 +224,7 @@ get_current_resources(struct acpi_device
acpi_walk_resources(device->handle, METHOD_NAME__CRS,
setup_resource, &info);
if (info.res_num) {
+ sort_resources(bus);
adjust_transparent_bridge_resources(bus);
}
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|
|
|
|
|