Skip to content

Commit d558b48

Browse files
Bjorn Helgaasjbarnes993
authored andcommitted
x86/PCI: truncate _CRS windows with _LEN > _MAX - _MIN + 1
Yanko's GA-MA78GM-S2H (BIOS F11) reports the following resource in a PCI host bridge _CRS: [07] 32-Bit DWORD Address Space Resource Min Relocatability : MinFixed Max Relocatability : MaxFixed Address Minimum : CFF00000 (_MIN) Address Maximum : FEBFFFFF (_MAX) Address Length : 3EE10000 (_LEN) This is invalid per spec (ACPI 4.0, 6.4.3.5) because it's a fixed size, fixed location descriptor, but _LEN != _MAX - _MIN + 1. Based on https://bugzilla.kernel.org/show_bug.cgi?id=15480#c15, I think Windows handles this by truncating the window so it fits between _MIN and _MAX. I also verified this by modifying the SeaBIOS DSDT and booting Windows 2008 R2 with qemu. This patch makes Linux truncate the window, too, which fixes: http://bugzilla.kernel.org/show_bug.cgi?id=15480 Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Tested-by: Yanko Kaneti <yaneti@declera.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
1 parent eb9fc8e commit d558b48

File tree

1 file changed

+12
-1
lines changed

1 file changed

+12
-1
lines changed

arch/x86/pci/acpi.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
123123
acpi_status status;
124124
unsigned long flags;
125125
struct resource *root, *conflict;
126-
u64 start, end;
126+
u64 start, end, max_len;
127127

128128
status = resource_to_addr(acpi_res, &addr);
129129
if (!ACPI_SUCCESS(status))
@@ -140,6 +140,17 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
140140
} else
141141
return AE_OK;
142142

143+
max_len = addr.maximum - addr.minimum + 1;
144+
if (addr.address_length > max_len) {
145+
dev_printk(KERN_DEBUG, &info->bridge->dev,
146+
"host bridge window length %#llx doesn't fit in "
147+
"%#llx-%#llx, trimming\n",
148+
(unsigned long long) addr.address_length,
149+
(unsigned long long) addr.minimum,
150+
(unsigned long long) addr.maximum);
151+
addr.address_length = max_len;
152+
}
153+
143154
start = addr.minimum + addr.translation_offset;
144155
end = start + addr.address_length - 1;
145156

0 commit comments

Comments
 (0)