diff options
author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2005-09-23 11:39:07 -0600 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2005-09-23 10:50:09 -0700 |
commit | 463eb297401eeb174db3fdf37a87911b576b3993 (patch) | |
tree | 1a0b2ffefc08cb4d3a2c591a5ff9bf9e5fb659ea /arch/ia64/pci | |
parent | 12f44f46bc9c6dc79255e661b085797af395d8da (diff) | |
download | op-kernel-dev-463eb297401eeb174db3fdf37a87911b576b3993.zip op-kernel-dev-463eb297401eeb174db3fdf37a87911b576b3993.tar.gz |
[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 <bjorn.helgaas@hp.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/pci')
-rw-r--r-- | arch/ia64/pci/pci.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 9b5de58..564319e 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; |