diff options
author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2005-09-23 13:39:07 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2005-09-23 13:50:09 -0400 |
commit | 463eb297401eeb174db3fdf37a87911b576b3993 (patch) | |
tree | 1a0b2ffefc08cb4d3a2c591a5ff9bf9e5fb659ea /arch/ia64/pci/pci.c | |
parent | 12f44f46bc9c6dc79255e661b085797af395d8da (diff) |
[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/pci.c')
-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 9b5de589b82f..564319e29bd5 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) | |||
191 | return IO_SPACE_BASE(i); | 191 | return IO_SPACE_BASE(i); |
192 | } | 192 | } |
193 | 193 | ||
194 | static acpi_status __devinit resource_to_window(struct acpi_resource *resource, | ||
195 | struct acpi_resource_address64 *addr) | ||
196 | { | ||
197 | acpi_status status; | ||
198 | |||
199 | /* | ||
200 | * We're only interested in _CRS descriptors that are | ||
201 | * - address space descriptors for memory or I/O space | ||
202 | * - non-zero size | ||
203 | * - producers, i.e., the address space is routed downstream, | ||
204 | * not consumed by the bridge itself | ||
205 | */ | ||
206 | status = acpi_resource_to_address64(resource, addr); | ||
207 | if (ACPI_SUCCESS(status) && | ||
208 | (addr->resource_type == ACPI_MEMORY_RANGE || | ||
209 | addr->resource_type == ACPI_IO_RANGE) && | ||
210 | addr->address_length && | ||
211 | addr->producer_consumer == ACPI_PRODUCER) | ||
212 | return AE_OK; | ||
213 | |||
214 | return AE_ERROR; | ||
215 | } | ||
216 | |||
194 | static acpi_status __devinit | 217 | static acpi_status __devinit |
195 | count_window (struct acpi_resource *resource, void *data) | 218 | count_window (struct acpi_resource *resource, void *data) |
196 | { | 219 | { |
@@ -198,11 +221,9 @@ count_window (struct acpi_resource *resource, void *data) | |||
198 | struct acpi_resource_address64 addr; | 221 | struct acpi_resource_address64 addr; |
199 | acpi_status status; | 222 | acpi_status status; |
200 | 223 | ||
201 | status = acpi_resource_to_address64(resource, &addr); | 224 | status = resource_to_window(resource, &addr); |
202 | if (ACPI_SUCCESS(status)) | 225 | if (ACPI_SUCCESS(status)) |
203 | if (addr.resource_type == ACPI_MEMORY_RANGE || | 226 | (*windows)++; |
204 | addr.resource_type == ACPI_IO_RANGE) | ||
205 | (*windows)++; | ||
206 | 227 | ||
207 | return AE_OK; | 228 | return AE_OK; |
208 | } | 229 | } |
@@ -221,13 +242,11 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) | |||
221 | unsigned long flags, offset = 0; | 242 | unsigned long flags, offset = 0; |
222 | struct resource *root; | 243 | struct resource *root; |
223 | 244 | ||
224 | status = acpi_resource_to_address64(res, &addr); | 245 | /* Return AE_OK for non-window resources to keep scanning for more */ |
246 | status = resource_to_window(res, &addr); | ||
225 | if (!ACPI_SUCCESS(status)) | 247 | if (!ACPI_SUCCESS(status)) |
226 | return AE_OK; | 248 | return AE_OK; |
227 | 249 | ||
228 | if (!addr.address_length) | ||
229 | return AE_OK; | ||
230 | |||
231 | if (addr.resource_type == ACPI_MEMORY_RANGE) { | 250 | if (addr.resource_type == ACPI_MEMORY_RANGE) { |
232 | flags = IORESOURCE_MEM; | 251 | flags = IORESOURCE_MEM; |
233 | root = &iomem_resource; | 252 | root = &iomem_resource; |