ChangeSet 1.1982.179.1, 2005/03/08 11:57:10-08:00, [EMAIL PROTECTED]
[IA64] pci.c: PCI root busses need resources
Using the generic setup-bus.c code currently fails on HP's Integrity
servers because the root busses have their resources set to the whole
of ioport space and the whole of iomem space, instead of just the ranges
that are routed to that particular bus.
This patch uses the resources in the pci_windows to provide the ranges
to each PCI root bus. In order to do that, I had to change them from
being bus addresses to system addresses.
Signed-off-by: Matthew Wilcox <[EMAIL PROTECTED]>
Signed-off-by: Tony Luck <[EMAIL PROTECTED]>
pci.c | 130 +++++++++++++++++++++++++++++++++++-------------------------------
1 files changed, 69 insertions(+), 61 deletions(-)
diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
--- a/arch/ia64/pci/pci.c 2005-03-31 18:05:56 -08:00
+++ b/arch/ia64/pci/pci.c 2005-03-31 18:05:56 -08:00
@@ -197,30 +197,6 @@
return controller;
}
-static int __devinit
-alloc_resource (char *name, struct resource *root, unsigned long start,
unsigned long end,
- unsigned long flags)
-{
- struct resource *res;
-
- res = kmalloc(sizeof(*res), GFP_KERNEL);
- if (!res)
- return -ENOMEM;
-
- memset(res, 0, sizeof(*res));
- res->name = name;
- res->start = start;
- res->end = end;
- res->flags = flags;
-
- if (insert_resource(root, res)) {
- kfree(res);
- return -EBUSY;
- }
-
- return 0;
-}
-
static u64 __devinit
add_io_space (struct acpi_resource_address64 *addr)
{
@@ -273,10 +249,9 @@
char *name;
};
-static acpi_status __devinit
-add_window (struct acpi_resource *res, void *data)
+static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
{
- struct pci_root_info *info = (struct pci_root_info *) data;
+ struct pci_root_info *info = data;
struct pci_window *window;
struct acpi_resource_address64 addr;
acpi_status status;
@@ -284,45 +259,71 @@
struct resource *root;
status = acpi_resource_to_address64(res, &addr);
- if (ACPI_SUCCESS(status)) {
- if (!addr.address_length)
- return AE_OK;
+ if (!ACPI_SUCCESS(status))
+ return AE_OK;
- if (addr.resource_type == ACPI_MEMORY_RANGE) {
- flags = IORESOURCE_MEM;
- root = &iomem_resource;
- offset = addr.address_translation_offset;
- } else if (addr.resource_type == ACPI_IO_RANGE) {
- flags = IORESOURCE_IO;
- root = &ioport_resource;
- offset = add_io_space(&addr);
- if (offset == ~0)
- return AE_OK;
- } else
+ if (!addr.address_length)
+ return AE_OK;
+
+ if (addr.resource_type == ACPI_MEMORY_RANGE) {
+ flags = IORESOURCE_MEM;
+ root = &iomem_resource;
+ offset = addr.address_translation_offset;
+ } else if (addr.resource_type == ACPI_IO_RANGE) {
+ flags = IORESOURCE_IO;
+ root = &ioport_resource;
+ offset = add_io_space(&addr);
+ if (offset == ~0)
return AE_OK;
+ } else
+ return AE_OK;
- window = &info->controller->window[info->controller->windows++];
- window->resource.flags = flags;
- window->resource.start = addr.min_address_range;
- window->resource.end = addr.max_address_range;
- window->offset = offset;
-
- if (alloc_resource(info->name, root, addr.min_address_range +
offset,
- addr.max_address_range + offset, flags))
- printk(KERN_ERR "alloc 0x%lx-0x%lx from %s for %s
failed\n",
- addr.min_address_range + offset,
addr.max_address_range + offset,
- root->name, info->name);
+ window = &info->controller->window[info->controller->windows++];
+ window->resource.name = info->name;
+ window->resource.flags = flags;
+ window->resource.start = addr.min_address_range + offset;
+ window->resource.end = addr.max_address_range + offset;
+ window->resource.child = NULL;
+ window->offset = offset;
+
+ if (insert_resource(root, &window->resource)) {
+ printk(KERN_ERR "alloc 0x%lx-0x%lx from %s for %s failed\n",
+ window->resource.start, window->resource.end,
+ root->name, info->name);
}
return AE_OK;
}
+static void __devinit
+pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl)
+{
+ int i, j;
+
+ j = 0;
+ for (i = 0; i < ctrl->windows; i++) {
+ struct resource *res = &ctrl->window[i].resource;
+ /* HP's firmware has a hack to work around a Windows bug.
+ * Ignore these tiny memory ranges */
+ if ((res->flags & IORESOURCE_MEM) &&
+ (res->end - res->start < 16))
+ continue;
+ if (j >= PCI_BUS_NUM_RESOURCES) {
+ printk("Ignoring range [%lx-%lx] (%lx)\n", res->start,
+ res->end, res->flags);
+ continue;
+ }
+ bus->resource[j++] = res;
+ }
+}
+
struct pci_bus * __devinit
-pci_acpi_scan_root (struct acpi_device *device, int domain, int bus)
+pci_acpi_scan_root(struct acpi_device *device, int domain, int bus)
{
struct pci_root_info info;
struct pci_controller *controller;
unsigned int windows = 0;
+ struct pci_bus *pbus;
char *name;
controller = alloc_pci_controller(domain);
@@ -331,8 +332,10 @@
controller->acpi_handle = device->handle;
- acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window,
&windows);
- controller->window = kmalloc(sizeof(*controller->window) * windows,
GFP_KERNEL);
+ acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window,
+ &windows);
+ controller->window = kmalloc(sizeof(*controller->window) * windows,
+ GFP_KERNEL);
if (!controller->window)
goto out2;
@@ -343,9 +346,14 @@
sprintf(name, "PCI Bus %04x:%02x", domain, bus);
info.controller = controller;
info.name = name;
- acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window,
&info);
+ acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window,
+ &info);
+
+ pbus = pci_scan_bus(bus, &pci_root_ops, controller);
+ if (pbus)
+ pcibios_setup_root_windows(pbus, controller);
- return pci_scan_bus(bus, &pci_root_ops, controller);
+ return pbus;
out3:
kfree(controller->window);
@@ -366,9 +374,9 @@
struct pci_window *window = &controller->window[i];
if (!(window->resource.flags & res->flags))
continue;
- if (window->resource.start > res->start - window->offset)
+ if (window->resource.start > res->start)
continue;
- if (window->resource.end < res->end - window->offset)
+ if (window->resource.end < res->end)
continue;
offset = window->offset;
break;
@@ -390,9 +398,9 @@
struct pci_window *window = &controller->window[i];
if (!(window->resource.flags & res->flags))
continue;
- if (window->resource.start > region->start)
+ if (window->resource.start - window->offset > region->start)
continue;
- if (window->resource.end < region->end)
+ if (window->resource.end - window->offset < region->end)
continue;
offset = window->offset;
break;
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html