diff options
author | Chuck Ebbert <cebbert@redhat.com> | 2010-09-23 21:40:59 -0400 |
---|---|---|
committer | Chuck Ebbert <cebbert@redhat.com> | 2010-09-23 21:40:59 -0400 |
commit | 121bfe2c6a61630a4c03891824204e28ebdd235f (patch) | |
tree | 76bd390d2bd9e4614b2a0cd6e5bec1e258b25dda /pci-v2-4-4-PCI-allocate-bus-resources-from-the-top-down.patch | |
parent | 9e5584957c9cc106f9775d9fdc52a8d1300d749e (diff) | |
download | kernel-121bfe2c6a61630a4c03891824204e28ebdd235f.tar.gz kernel-121bfe2c6a61630a4c03891824204e28ebdd235f.tar.xz kernel-121bfe2c6a61630a4c03891824204e28ebdd235f.zip |
Add patches to fix problems with PCI _CRS
Diffstat (limited to 'pci-v2-4-4-PCI-allocate-bus-resources-from-the-top-down.patch')
-rw-r--r-- | pci-v2-4-4-PCI-allocate-bus-resources-from-the-top-down.patch | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/pci-v2-4-4-PCI-allocate-bus-resources-from-the-top-down.patch b/pci-v2-4-4-PCI-allocate-bus-resources-from-the-top-down.patch new file mode 100644 index 000000000..c1412b5bd --- /dev/null +++ b/pci-v2-4-4-PCI-allocate-bus-resources-from-the-top-down.patch @@ -0,0 +1,80 @@ +diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c +index 7f0af0e..172bf26 100644 +--- a/drivers/pci/bus.c ++++ b/drivers/pci/bus.c +@@ -64,6 +64,49 @@ void pci_bus_remove_resources(struct pci_bus *bus) + } + } + ++/* ++ * Find the highest-address bus resource below the cursor "res". If the ++ * cursor is NULL, return the highest resource. ++ */ ++static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus, ++ unsigned int type, ++ struct resource *res) ++{ ++ struct resource *r, *prev = NULL; ++ int i; ++ ++ pci_bus_for_each_resource(bus, r, i) { ++ if (!r) ++ continue; ++ ++ if ((r->flags & IORESOURCE_TYPE_BITS) != type) ++ continue; ++ ++ /* If this resource is at or past the cursor, skip it */ ++ if (res) { ++ if (r == res) ++ continue; ++ if (r->end > res->end) ++ continue; ++ if (r->end == res->end && r->start > res->start) ++ continue; ++ } ++ ++ if (!prev) ++ prev = r; ++ ++ /* ++ * A small resource is higher than a large one that ends at ++ * the same address. ++ */ ++ if (r->end > prev->end || ++ (r->end == prev->end && r->start > prev->start)) ++ prev = r; ++ } ++ ++ return prev; ++} ++ + /** + * pci_bus_alloc_resource - allocate a resource from a parent bus + * @bus: PCI bus +@@ -89,9 +132,10 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, + resource_size_t), + void *alignf_data) + { +- int i, ret = -ENOMEM; ++ int ret = -ENOMEM; + struct resource *r; + resource_size_t max = -1; ++ unsigned int type = res->flags & IORESOURCE_TYPE_BITS; + + type_mask |= IORESOURCE_IO | IORESOURCE_MEM; + +@@ -99,10 +143,9 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, + if (!(res->flags & IORESOURCE_MEM_64)) + max = PCIBIOS_MAX_MEM_32; + +- pci_bus_for_each_resource(bus, r, i) { +- if (!r) +- continue; +- ++ /* Look for space at highest addresses first */ ++ r = pci_bus_find_resource_prev(bus, type, NULL); ++ for ( ; r; r = pci_bus_find_resource_prev(bus, type, r)) { + /* type_mask must match */ + if ((res->flags ^ r->flags) & type_mask) + continue; |