aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2009-11-04 12:39:18 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-11-04 16:06:46 -0500
commit03db42adfeeabe856dbb6894dd3aaff55838330a (patch)
treef78101e96ce2171a503bd1119d08d89e31118a69 /arch
parentf1db6fde09e201218f488d7205a7cd7bc448d496 (diff)
x86/PCI: fix bogus host bridge window start/end alignment from _CRS
PCI device BARs are guaranteed to start and end on at least a four-byte (I/O) or a sixteen-byte (MMIO) boundary because they're aligned on their size and the low BAR bits are reserved. PCI-to-PCI bridge apertures have even larger alignment restrictions. However, some BIOSes (e.g., HP DL360 BIOS P31) report host bridge windows like "[io 0x0000-0x2cfe]". This is wrong because it excludes the last port at 0x2cff: it's impossible for a downstream device to claim 0x2cfe without also claiming 0x2cff. In fact, this BIOS configures a device behind the bridge to "[io 0x2c00-0x2cff]", so we know the window actually does include 0x2cff. This patch rounds the start and end of apertures to the appropriate boundary. I experimentally determined that Windows contains a similar workaround; details here: http://bugzilla.kernel.org/show_bug.cgi?id=14337 Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/pci/acpi.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 54db5a04b5e1..8ddf4f4c7253 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -59,6 +59,30 @@ bus_has_transparent_bridge(struct pci_bus *bus)
59 return false; 59 return false;
60} 60}
61 61
62static void
63align_resource(struct acpi_device *bridge, struct resource *res)
64{
65 int align = (res->flags & IORESOURCE_MEM) ? 16 : 4;
66
67 /*
68 * Host bridge windows are not BARs, but the decoders on the PCI side
69 * that claim this address space have starting alignment and length
70 * constraints, so fix any obvious BIOS goofs.
71 */
72 if (res->start & (align - 1)) {
73 dev_printk(KERN_DEBUG, &bridge->dev,
74 "host bridge window %pR invalid; "
75 "aligning start to %d-byte boundary\n", res, align);
76 res->start &= ~(align - 1);
77 }
78 if ((res->end + 1) & (align - 1)) {
79 dev_printk(KERN_DEBUG, &bridge->dev,
80 "host bridge window %pR invalid; "
81 "aligning end to %d-byte boundary\n", res, align);
82 res->end = roundup(res->end, align) - 1;
83 }
84}
85
62static acpi_status 86static acpi_status
63setup_resource(struct acpi_resource *acpi_res, void *data) 87setup_resource(struct acpi_resource *acpi_res, void *data)
64{ 88{
@@ -107,6 +131,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
107 res->start = start; 131 res->start = start;
108 res->end = end; 132 res->end = end;
109 res->child = NULL; 133 res->child = NULL;
134 align_resource(info->bridge, res);
110 135
111 if (!(pci_probe & PCI_USE__CRS)) { 136 if (!(pci_probe & PCI_USE__CRS)) {
112 dev_printk(KERN_DEBUG, &info->bridge->dev, 137 dev_printk(KERN_DEBUG, &info->bridge->dev,