[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 2/3] dom0 linux: Sort PCI resource based on priority of allocation.
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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |