[kernel] Add patches to fix problems with PCI _CRS

Chuck Ebbert cebbert at fedoraproject.org
Fri Sep 24 01:41:56 UTC 2010


commit 121bfe2c6a61630a4c03891824204e28ebdd235f
Author: Chuck Ebbert <cebbert at redhat.com>
Date:   Thu Sep 23 21:40:59 2010 -0400

    Add patches to fix problems with PCI _CRS

 kernel.spec                                        |   18 ++++-
 ...ck-doesn-t-allocate-below-available-start.patch |   28 +++++++
 ...rom-the-end-of-a-region-not-the-beginning.patch |   40 ++++++++++
 ...e-space-within-a-region-from-the-top-down.patch |   71 +++++++++++++++++
 ...-allocate-bus-resources-from-the-top-down.patch |   80 ++++++++++++++++++++
 5 files changed, 235 insertions(+), 2 deletions(-)
---
diff --git a/kernel.spec b/kernel.spec
index 16258e4..692d233 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -703,8 +703,8 @@ Patch12115: wacom-04-add-support-for-the-bamboo-touch-trackpad.patch
 Patch12120: wacom-05-add-a-quirk-for-low-resolution-bamboo-devices.patch
 Patch12125: wacom-06-request-tablet-data-for-bamboo-pens.patch
 Patch12130: wacom-07-move-bamboo-touch-irq-to-its-own-function.patch
-Patch12035: wacom-08-add-support-for-bamboo-pen.patch
-Patch12040: wacom-09-disable-bamboo-touchpad-when-pen-is-being-used.patch
+Patch12135: wacom-08-add-support-for-bamboo-pen.patch
+Patch12140: wacom-09-disable-bamboo-touchpad-when-pen-is-being-used.patch
 
 # Runtime power management
 Patch12200: linux-2.6-bluetooth-autosuspend.patch
@@ -712,6 +712,12 @@ Patch12201: linux-2.6-uvc-autosuspend.patch
 Patch12202: linux-2.6-qcserial-autosuspend.patch
 Patch12203: linux-2.6-usb-pci-autosuspend.patch
 
+# PCI patches to fix problems with _CRS
+Patch12221: pci-v2-1-4-resources-ensure-alignment-callback-doesn-t-allocate-below-available-start.patch
+Patch12222: pci-v2-2-4-x86-PCI-allocate-space-from-the-end-of-a-region-not-the-beginning.patch
+Patch12223: pci-v2-3-4-resources-allocate-space-within-a-region-from-the-top-down.patch
+Patch12224: pci-v2-4-4-PCI-allocate-bus-resources-from-the-top-down.patch
+
 Patch12300: btusb-macbookpro-7-1.patch
 Patch12301: btusb-macbookpro-6-2.patch
 
@@ -1307,6 +1313,13 @@ ApplyPatch linux-2.6-uvc-autosuspend.patch
 ApplyPatch linux-2.6-qcserial-autosuspend.patch
 ApplyPatch linux-2.6-usb-pci-autosuspend.patch
 
+# PCI patches to fix problems with _CRS
+# ( from https://bugzilla.kernel.org/show_bug.cgi?id=16228#c49 )
+ApplyPatch pci-v2-1-4-resources-ensure-alignment-callback-doesn-t-allocate-below-available-start.patch
+ApplyPatch pci-v2-2-4-x86-PCI-allocate-space-from-the-end-of-a-region-not-the-beginning.patch
+ApplyPatch pci-v2-3-4-resources-allocate-space-within-a-region-from-the-top-down.patch
+ApplyPatch pci-v2-4-4-PCI-allocate-bus-resources-from-the-top-down.patch
+
 ApplyPatch btusb-macbookpro-7-1.patch
 ApplyPatch btusb-macbookpro-6-2.patch
 
@@ -1922,6 +1935,7 @@ fi
 - Drop merged patches:
   fix-icebp-breakpoints.patch
   linux-2.6.35.4-virtio_console-fix-poll.patch
+- Add patches to fix problems with PCI _CRS
 
 * Thu Sep 23 2010 Kyle McMartin <kyle at redhat.com> 2.6.36-0.25.rc5
 - Add s390 vdso AFTER_LINK to Roland's linux-2.6-makefile-after_link.patch
diff --git a/pci-v2-1-4-resources-ensure-alignment-callback-doesn-t-allocate-below-available-start.patch b/pci-v2-1-4-resources-ensure-alignment-callback-doesn-t-allocate-below-available-start.patch
new file mode 100644
index 0000000..d1f4aba
--- /dev/null
+++ b/pci-v2-1-4-resources-ensure-alignment-callback-doesn-t-allocate-below-available-start.patch
@@ -0,0 +1,28 @@
+diff --git a/kernel/resource.c b/kernel/resource.c
+index 7b36976..ace2269 100644
+--- a/kernel/resource.c
++++ b/kernel/resource.c
+@@ -371,6 +371,7 @@ static int find_resource(struct resource *root, struct resource *new,
+ {
+ 	struct resource *this = root->child;
+ 	struct resource tmp = *new;
++	resource_size_t start;
+ 
+ 	tmp.start = root->start;
+ 	/*
+@@ -391,8 +392,13 @@ static int find_resource(struct resource *root, struct resource *new,
+ 		if (tmp.end > max)
+ 			tmp.end = max;
+ 		tmp.start = ALIGN(tmp.start, align);
+-		if (alignf)
+-			tmp.start = alignf(alignf_data, &tmp, size, align);
++		if (alignf) {
++			start = alignf(alignf_data, &tmp, size, align);
++			if (tmp.start <= start && start <= tmp.end)
++				tmp.start = start;
++			else
++				tmp.start = tmp.end;
++		}
+ 		if (tmp.start < tmp.end && tmp.end - tmp.start >= size - 1) {
+ 			new->start = tmp.start;
+ 			new->end = tmp.start + size - 1;
diff --git a/pci-v2-2-4-x86-PCI-allocate-space-from-the-end-of-a-region-not-the-beginning.patch b/pci-v2-2-4-x86-PCI-allocate-space-from-the-end-of-a-region-not-the-beginning.patch
new file mode 100644
index 0000000..48ad106
--- /dev/null
+++ b/pci-v2-2-4-x86-PCI-allocate-space-from-the-end-of-a-region-not-the-beginning.patch
@@ -0,0 +1,40 @@
+diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
+index 5525309..fe866c8 100644
+--- a/arch/x86/pci/i386.c
++++ b/arch/x86/pci/i386.c
+@@ -37,6 +37,7 @@
+ #include <asm/pci_x86.h>
+ #include <asm/io_apic.h>
+ 
++#define ALIGN_DOWN(x, a)	((x) & ~(a - 1))
+ 
+ static int
+ skip_isa_ioresource_align(struct pci_dev *dev) {
+@@ -65,16 +66,21 @@ pcibios_align_resource(void *data, const struct resource *res,
+ 			resource_size_t size, resource_size_t align)
+ {
+ 	struct pci_dev *dev = data;
+-	resource_size_t start = res->start;
++	resource_size_t start = ALIGN_DOWN(res->end - size + 1, align);
+ 
+ 	if (res->flags & IORESOURCE_IO) {
+-		if (skip_isa_ioresource_align(dev))
+-			return start;
+-		if (start & 0x300)
+-			start = (start + 0x3ff) & ~0x3ff;
++
++		/*
++		 * If we're avoiding ISA aliases, the largest contiguous I/O
++		 * port space is 256 bytes.  Clearing bits 9 and 10 preserves
++		 * all 256-byte and smaller alignments, so the result will
++		 * still be correctly aligned.
++		 */
++		if (!skip_isa_ioresource_align(dev))
++			start &= ~0x300;
+ 	} else if (res->flags & IORESOURCE_MEM) {
+ 		if (start < BIOS_END)
+-			start = BIOS_END;
++			start = res->end;	/* fail; no space */
+ 	}
+ 	return start;
+ }
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 0000000..2a5d09f
--- /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;
+ }
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 0000000..c1412b5
--- /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;


More information about the scm-commits mailing list