aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2010-04-27 16:45:43 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-04-28 12:17:45 -0400
commit48728e077480910df45baabc5f87b04276348c90 (patch)
tree8a8114da4840e84ba60050b953123168aefc2dcf /arch/x86
parent55051feb57eba600b366006757304a0af3ada2bd (diff)
x86/PCI: compute Address Space length rather than using _LEN
ACPI _CRS Address Space Descriptors have _MIN, _MAX, and _LEN. Linux has been computing Address Spaces as [_MIN to _MIN + _LEN - 1]. Based on the tests in the bug reports below, Windows apparently uses [_MIN to _MAX]. Per spec (ACPI 4.0, Table 6-40), for _CRS fixed-size, fixed location descriptors, "_LEN must be (_MAX - _MIN + 1)", and when that's true, it doesn't matter which way we compute the end. But of course, there are BIOSes that don't follow this rule, and we're better off if Linux handles those exceptions the same way as Windows. This patch makes Linux use [_MIN to _MAX], as Windows seems to do. This effectively reverts d558b483d5 and 03db42adfe and replaces them with simpler code. https://bugzilla.kernel.org/show_bug.cgi?id=14337 (round) https://bugzilla.kernel.org/show_bug.cgi?id=15480 (truncate) Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/pci/acpi.c40
1 files changed, 2 insertions, 38 deletions
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 44f83ce02470..31930fd30ea9 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -121,30 +121,6 @@ count_resource(struct acpi_resource *acpi_res, void *data)
121 return AE_OK; 121 return AE_OK;
122} 122}
123 123
124static void
125align_resource(struct acpi_device *bridge, struct resource *res)
126{
127 int align = (res->flags & IORESOURCE_MEM) ? 16 : 4;
128
129 /*
130 * Host bridge windows are not BARs, but the decoders on the PCI side
131 * that claim this address space have starting alignment and length
132 * constraints, so fix any obvious BIOS goofs.
133 */
134 if (!IS_ALIGNED(res->start, align)) {
135 dev_printk(KERN_DEBUG, &bridge->dev,
136 "host bridge window %pR invalid; "
137 "aligning start to %d-byte boundary\n", res, align);
138 res->start &= ~(align - 1);
139 }
140 if (!IS_ALIGNED(res->end + 1, align)) {
141 dev_printk(KERN_DEBUG, &bridge->dev,
142 "host bridge window %pR invalid; "
143 "aligning end to %d-byte boundary\n", res, align);
144 res->end = ALIGN(res->end, align) - 1;
145 }
146}
147
148static acpi_status 124static acpi_status
149setup_resource(struct acpi_resource *acpi_res, void *data) 125setup_resource(struct acpi_resource *acpi_res, void *data)
150{ 126{
@@ -154,7 +130,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
154 acpi_status status; 130 acpi_status status;
155 unsigned long flags; 131 unsigned long flags;
156 struct resource *root, *conflict; 132 struct resource *root, *conflict;
157 u64 start, end, max_len; 133 u64 start, end;
158 134
159 status = resource_to_addr(acpi_res, &addr); 135 status = resource_to_addr(acpi_res, &addr);
160 if (!ACPI_SUCCESS(status)) 136 if (!ACPI_SUCCESS(status))
@@ -171,19 +147,8 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
171 } else 147 } else
172 return AE_OK; 148 return AE_OK;
173 149
174 max_len = addr.maximum - addr.minimum + 1;
175 if (addr.address_length > max_len) {
176 dev_printk(KERN_DEBUG, &info->bridge->dev,
177 "host bridge window length %#llx doesn't fit in "
178 "%#llx-%#llx, trimming\n",
179 (unsigned long long) addr.address_length,
180 (unsigned long long) addr.minimum,
181 (unsigned long long) addr.maximum);
182 addr.address_length = max_len;
183 }
184
185 start = addr.minimum + addr.translation_offset; 150 start = addr.minimum + addr.translation_offset;
186 end = start + addr.address_length - 1; 151 end = addr.maximum + addr.translation_offset;
187 152
188 res = &info->res[info->res_num]; 153 res = &info->res[info->res_num];
189 res->name = info->name; 154 res->name = info->name;
@@ -191,7 +156,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
191 res->start = start; 156 res->start = start;
192 res->end = end; 157 res->end = end;
193 res->child = NULL; 158 res->child = NULL;
194 align_resource(info->bridge, res);
195 159
196 if (!pci_use_crs) { 160 if (!pci_use_crs) {
197 dev_printk(KERN_DEBUG, &info->bridge->dev, 161 dev_printk(KERN_DEBUG, &info->bridge->dev,