summaryrefslogtreecommitdiffstats
path: root/pci-v2-3-4-resources-allocate-space-within-a-region-from-the-top-down.patch
diff options
context:
space:
mode:
authorChuck Ebbert <cebbert@redhat.com>2010-09-23 21:40:59 -0400
committerChuck Ebbert <cebbert@redhat.com>2010-09-23 21:40:59 -0400
commit121bfe2c6a61630a4c03891824204e28ebdd235f (patch)
tree76bd390d2bd9e4614b2a0cd6e5bec1e258b25dda /pci-v2-3-4-resources-allocate-space-within-a-region-from-the-top-down.patch
parent9e5584957c9cc106f9775d9fdc52a8d1300d749e (diff)
downloadkernel-121bfe2c6a61630a4c03891824204e28ebdd235f.tar.gz
kernel-121bfe2c6a61630a4c03891824204e28ebdd235f.tar.xz
kernel-121bfe2c6a61630a4c03891824204e28ebdd235f.zip
Add patches to fix problems with PCI _CRS
Diffstat (limited to 'pci-v2-3-4-resources-allocate-space-within-a-region-from-the-top-down.patch')
-rw-r--r--pci-v2-3-4-resources-allocate-space-within-a-region-from-the-top-down.patch71
1 files changed, 71 insertions, 0 deletions
diff --git a/pci-v2-3-4-resources-allocate-space-within-a-region-from-the-top-down.patch b/pci-v2-3-4-resources-allocate-space-within-a-region-from-the-top-down.patch
new file mode 100644
index 000000000..2a5d09f09
--- /dev/null
+++ b/pci-v2-3-4-resources-allocate-space-within-a-region-from-the-top-down.patch
@@ -0,0 +1,71 @@
+diff --git a/kernel/resource.c b/kernel/resource.c
+index ace2269..1a2a40e 100644
+--- a/kernel/resource.c
++++ b/kernel/resource.c
+@@ -358,6 +358,20 @@ int __weak page_is_ram(unsigned long pfn)
+ }
+
+ /*
++ * Find the resource before "child" in the sibling list of "root" children.
++ */
++static struct resource *find_sibling_prev(struct resource *root, struct resource *child)
++{
++ struct resource *this;
++
++ for (this = root->child; this; this = this->sibling)
++ if (this->sibling == child)
++ return this;
++
++ return NULL;
++}
++
++/*
+ * Find empty slot in the resource tree given range and alignment.
+ */
+ static int find_resource(struct resource *root, struct resource *new,
+@@ -369,24 +383,18 @@ static int find_resource(struct resource *root, struct resource *new,
+ resource_size_t),
+ void *alignf_data)
+ {
+- struct resource *this = root->child;
++ struct resource *this;
+ struct resource tmp = *new;
+ resource_size_t start;
+
+- tmp.start = root->start;
+- /*
+- * Skip past an allocated resource that starts at 0, since the assignment
+- * of this->start - 1 to tmp->end below would cause an underflow.
+- */
+- if (this && this->start == 0) {
+- tmp.start = this->end + 1;
+- this = this->sibling;
+- }
+- for(;;) {
++ tmp.end = root->end;
++
++ this = find_sibling_prev(root, NULL);
++ for (;;) {
+ if (this)
+- tmp.end = this->start - 1;
++ tmp.start = this->end + 1;
+ else
+- tmp.end = root->end;
++ tmp.start = root->start;
+ if (tmp.start < min)
+ tmp.start = min;
+ if (tmp.end > max)
+@@ -404,10 +412,10 @@ static int find_resource(struct resource *root, struct resource *new,
+ new->end = tmp.start + size - 1;
+ return 0;
+ }
+- if (!this)
++ if (!this || this->start == root->start)
+ break;
+- tmp.start = this->end + 1;
+- this = this->sibling;
++ tmp.end = this->start - 1;
++ this = find_sibling_prev(root, this);
+ }
+ return -EBUSY;
+ }