Add patches to fix problems with PCI _CRS
This commit is contained in:
parent
9e5584957c
commit
121bfe2c6a
18
kernel.spec
18
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@redhat.com> 2.6.36-0.25.rc5
|
||||
- Add s390 vdso AFTER_LINK to Roland's linux-2.6-makefile-after_link.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;
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
Loading…
Reference in New Issue
Block a user