diff options
Diffstat (limited to 'arch/x86/pci')
-rw-r--r-- | arch/x86/pci/acpi.c | 84 | ||||
-rw-r--r-- | arch/x86/pci/i386.c | 3 | ||||
-rw-r--r-- | arch/x86/pci/mrst.c | 4 |
3 files changed, 46 insertions, 45 deletions
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index c7b1ebfb7da..31930fd30ea 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -66,14 +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 && - addr->producer_consumer == ACPI_PRODUCER) { + 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; } @@ -91,30 +121,6 @@ count_resource(struct acpi_resource *acpi_res, void *data) return AE_OK; } -static void -align_resource(struct acpi_device *bridge, struct resource *res) -{ - int align = (res->flags & IORESOURCE_MEM) ? 16 : 4; - - /* - * Host bridge windows are not BARs, but the decoders on the PCI side - * that claim this address space have starting alignment and length - * constraints, so fix any obvious BIOS goofs. - */ - if (!IS_ALIGNED(res->start, align)) { - dev_printk(KERN_DEBUG, &bridge->dev, - "host bridge window %pR invalid; " - "aligning start to %d-byte boundary\n", res, align); - res->start &= ~(align - 1); - } - if (!IS_ALIGNED(res->end + 1, align)) { - dev_printk(KERN_DEBUG, &bridge->dev, - "host bridge window %pR invalid; " - "aligning end to %d-byte boundary\n", res, align); - res->end = ALIGN(res->end, align) - 1; - } -} - static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data) { @@ -124,7 +130,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data) acpi_status status; unsigned long flags; struct resource *root, *conflict; - u64 start, end, max_len; + u64 start, end; status = resource_to_addr(acpi_res, &addr); if (!ACPI_SUCCESS(status)) @@ -141,19 +147,8 @@ setup_resource(struct acpi_resource *acpi_res, void *data) } else return AE_OK; - max_len = addr.maximum - addr.minimum + 1; - if (addr.address_length > max_len) { - dev_printk(KERN_DEBUG, &info->bridge->dev, - "host bridge window length %#llx doesn't fit in " - "%#llx-%#llx, trimming\n", - (unsigned long long) addr.address_length, - (unsigned long long) addr.minimum, - (unsigned long long) addr.maximum); - addr.address_length = max_len; - } - start = addr.minimum + addr.translation_offset; - end = start + addr.address_length - 1; + end = addr.maximum + addr.translation_offset; res = &info->res[info->res_num]; res->name = info->name; @@ -161,7 +156,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data) res->start = start; res->end = end; res->child = NULL; - align_resource(info->bridge, res); if (!pci_use_crs) { dev_printk(KERN_DEBUG, &info->bridge->dev, diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 46fd43f7910..97da2ba9344 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -72,6 +72,9 @@ pcibios_align_resource(void *data, const struct resource *res, return start; if (start & 0x300) start = (start + 0x3ff) & ~0x3ff; + } else if (res->flags & IORESOURCE_MEM) { + if (start < BIOS_END) + start = BIOS_END; } return start; } diff --git a/arch/x86/pci/mrst.c b/arch/x86/pci/mrst.c index 8bf2fcb88d0..1cdc02cf8fa 100644 --- a/arch/x86/pci/mrst.c +++ b/arch/x86/pci/mrst.c @@ -247,6 +247,10 @@ static void __devinit pci_fixed_bar_fixup(struct pci_dev *dev) u32 size; int i; + /* Must have extended configuration space */ + if (dev->cfg_size < PCIE_CAP_OFFSET + 4) + return; + /* Fixup the BAR sizes for fixed BAR devices and make them unmoveable */ offset = fixed_bar_cap(dev->bus, dev->devfn); if (!offset || PCI_DEVFN(2, 0) == dev->devfn || |