From 73a0e614580fb650846be1e9315f6b7b6069b9cc Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 6 Apr 2010 13:24:08 -0600 Subject: x86/PCI: ignore Consumer/Producer bit in ACPI window descriptions ACPI Address Space Descriptors (used in _CRS) have a Consumer/Producer bit that is supposed to distinguish regions that are consumed directly by a device from those that are forwarded ("produced") by a bridge. But BIOSes have apparently not used this consistently, and Windows seems to ignore it, so I think Linux should ignore it as well. I can't point to any of these supposed broken BIOSes, but since we now rely on _CRS by default, I think it's safer to ignore this bit from the start. Here are details of my experiments with how Windows handles it: https://bugzilla.kernel.org/show_bug.cgi?id=15701 Signed-off-by: Bjorn Helgaas Signed-off-by: Jesse Barnes --- arch/x86/pci/acpi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index c7b1ebfb7da..334153ca4c3 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -71,8 +71,7 @@ resource_to_addr(struct acpi_resource *resource, if (ACPI_SUCCESS(status) && (addr->resource_type == ACPI_MEMORY_RANGE || addr->resource_type == ACPI_IO_RANGE) && - addr->address_length > 0 && - addr->producer_consumer == ACPI_PRODUCER) { + addr->address_length > 0) { return AE_OK; } return AE_ERROR; -- cgit v1.2.3-70-g09d2 From 66528fdd45b082bf7c74687d72ae08afa4a446f8 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 20 Apr 2010 13:52:41 -0600 Subject: x86/PCI: parse additional host bridge window resource types This adds support for Memory24, Memory32, and Memory32Fixed descriptors in PCI host bridge _CRS. I experimentally determined that Windows (2008 R2) accepts these descriptors and treats them as windows that are forwarded to the PCI bus, e.g., if it finds any PCI devices with BARs outside the windows, it moves them into the windows. I don't know whether any machines actually use these descriptors in PCI host bridge _CRS methods, but if any exist and they're new enough that we automatically turn on "pci=use_crs", they will work with Windows but not with Linux. Here are the details: https://bugzilla.kernel.org/show_bug.cgi?id=15817 Signed-off-by: Bjorn Helgaas Signed-off-by: Jesse Barnes --- arch/x86/pci/acpi.c | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 334153ca4c3..44f83ce0247 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -66,13 +66,44 @@ resource_to_addr(struct acpi_resource *resource, struct acpi_resource_address64 *addr) { acpi_status status; - - status = acpi_resource_to_address64(resource, addr); - if (ACPI_SUCCESS(status) && - (addr->resource_type == ACPI_MEMORY_RANGE || - addr->resource_type == ACPI_IO_RANGE) && - addr->address_length > 0) { + struct acpi_resource_memory24 *memory24; + struct acpi_resource_memory32 *memory32; + struct acpi_resource_fixed_memory32 *fixed_memory32; + + memset(addr, 0, sizeof(*addr)); + switch (resource->type) { + case ACPI_RESOURCE_TYPE_MEMORY24: + memory24 = &resource->data.memory24; + addr->resource_type = ACPI_MEMORY_RANGE; + addr->minimum = memory24->minimum; + addr->address_length = memory24->address_length; + addr->maximum = addr->minimum + addr->address_length - 1; + return AE_OK; + case ACPI_RESOURCE_TYPE_MEMORY32: + memory32 = &resource->data.memory32; + addr->resource_type = ACPI_MEMORY_RANGE; + addr->minimum = memory32->minimum; + addr->address_length = memory32->address_length; + addr->maximum = addr->minimum + addr->address_length - 1; return AE_OK; + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: + fixed_memory32 = &resource->data.fixed_memory32; + addr->resource_type = ACPI_MEMORY_RANGE; + addr->minimum = fixed_memory32->address; + addr->address_length = fixed_memory32->address_length; + addr->maximum = addr->minimum + addr->address_length - 1; + return AE_OK; + case ACPI_RESOURCE_TYPE_ADDRESS16: + case ACPI_RESOURCE_TYPE_ADDRESS32: + case ACPI_RESOURCE_TYPE_ADDRESS64: + status = acpi_resource_to_address64(resource, addr); + if (ACPI_SUCCESS(status) && + (addr->resource_type == ACPI_MEMORY_RANGE || + addr->resource_type == ACPI_IO_RANGE) && + addr->address_length > 0) { + return AE_OK; + } + break; } return AE_ERROR; } -- cgit v1.2.3-70-g09d2