From 463eb297401eeb174db3fdf37a87911b576b3993 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 23 Sep 2005 11:39:07 -0600 Subject: [IA64] respect ACPI producer/consumer flag for PCI root bridges Address space resources for ACPI devices have a producer/consumer flag. All devices "consume" the indicated address space. If the resource is marked as a "producer", the range is also passed on to child devices. We currently ignore this flag when setting up MMIO and I/O port windows for PCI root bridges, so we could mistakenly interpret a "consumed-only" range, like CSR space for the device itself, as a window that is routed to children. Signed-off-by: Bjorn Helgaas Signed-off-by: Tony Luck --- arch/ia64/pci/pci.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'arch/ia64/pci') diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 9b5de589b82..564319e29bd 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -191,6 +191,29 @@ add_io_space (struct acpi_resource_address64 *addr) return IO_SPACE_BASE(i); } +static acpi_status __devinit resource_to_window(struct acpi_resource *resource, + struct acpi_resource_address64 *addr) +{ + acpi_status status; + + /* + * We're only interested in _CRS descriptors that are + * - address space descriptors for memory or I/O space + * - non-zero size + * - producers, i.e., the address space is routed downstream, + * not consumed by the bridge itself + */ + 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 && + addr->producer_consumer == ACPI_PRODUCER) + return AE_OK; + + return AE_ERROR; +} + static acpi_status __devinit count_window (struct acpi_resource *resource, void *data) { @@ -198,11 +221,9 @@ count_window (struct acpi_resource *resource, void *data) struct acpi_resource_address64 addr; acpi_status status; - status = acpi_resource_to_address64(resource, &addr); + status = resource_to_window(resource, &addr); if (ACPI_SUCCESS(status)) - if (addr.resource_type == ACPI_MEMORY_RANGE || - addr.resource_type == ACPI_IO_RANGE) - (*windows)++; + (*windows)++; return AE_OK; } @@ -221,13 +242,11 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) unsigned long flags, offset = 0; struct resource *root; - status = acpi_resource_to_address64(res, &addr); + /* Return AE_OK for non-window resources to keep scanning for more */ + status = resource_to_window(res, &addr); if (!ACPI_SUCCESS(status)) return AE_OK; - if (!addr.address_length) - return AE_OK; - if (addr.resource_type == ACPI_MEMORY_RANGE) { flags = IORESOURCE_MEM; root = &iomem_resource; -- cgit v1.2.3