2004-09-03 19:39:10

by Matthew Wilcox

[permalink] [raw]
Subject: ACPI pci hotplug patch series


A series of 5 patches coming up that make acpiphp work on an rx8620.
Unfortunately, they'll cause i386 to not work, so don't apply these
for now.

01-pci-bus-address.diff
Adds a way to convert from a global system address to a local pci bus address.

02-ia64-fixups.diff
Fix some bugs. Nothing earth-shattering.

03-acpiphp-domains.diff
Make acpiphp handle domains properly

04-acpiphp-pcidev.diff
Prevent acpiphp from crashing the system in nasty untracable ways

05-acpiphp-misc.diff
Some minor cleanups

--
"Next the statesmen will invent cheap lies, putting the blame upon
the nation that is attacked, and every man will be glad of those
conscience-soothing falsities, and will diligently study them, and refuse
to examine any refutations of them; and thus he will by and by convince
himself that the war is just, and will thank God for the better sleep
he enjoys after this process of grotesque self-deception." -- Mark Twain


2004-09-03 19:43:56

by Matthew Wilcox

[permalink] [raw]
Subject: [PATCH] acpiphp domain support [3/5]


acpiphp doesn't work very well on a machine with multiple PCI domains.
This patch improves the situation by using pci_get_slot() instead of
pci_find_slot(). The new reference couting rules are documented at the
top of acpiphp_glue.c. This necessitated some cleanup of error handling
paths and change of calling conventions.

The seg/bus/sub entries are removed from struct acpiphp_bridge and
retrieved from the pci_bus when necessary. The per-bridge removal code
is moved from acpiphp_glue_exit() to the remove_bridge() method where
it should have been all along.

I've added my copyright and bumped the version number.

diff -urpNX build-tools/dontdiff linux-2.6/drivers/pci/hotplug/acpiphp.h hotplug-2.6/drivers/pci/hotplug/acpiphp.h
--- linux-2.6/drivers/pci/hotplug/acpiphp.h 2004-05-23 17:52:23.000000000 -0600
+++ hotplug-2.6/drivers/pci/hotplug/acpiphp.h 2004-09-02 13:35:46.000000000 -0600
@@ -101,10 +101,6 @@ struct acpiphp_bridge {
int type;
int nr_slots;

- u8 seg;
- u8 bus;
- u8 sub;
-
u32 flags;

/* This bus (host bridge) or Secondary bus (PCI-to-PCI bridge) */
diff -urpNX build-tools/dontdiff linux-2.6/drivers/pci/hotplug/acpiphp_core.c hotplug-2.6/drivers/pci/hotplug/acpiphp_core.c
--- linux-2.6/drivers/pci/hotplug/acpiphp_core.c 2004-05-23 17:52:23.000000000 -0600
+++ hotplug-2.6/drivers/pci/hotplug/acpiphp_core.c 2004-09-03 08:09:15.181670908 -0600
@@ -7,6 +7,8 @@
* Copyright (C) 2002 Hiroshi Aono ([email protected])
* Copyright (C) 2002,2003 Takayoshi Kochi ([email protected])
* Copyright (C) 2002,2003 NEC Corporation
+ * Copyright (C) 2003,2004 Matthew Wilcox ([email protected])
+ * Copyright (C) 2003,2004 Hewlett Packard
*
* All rights reserved.
*
@@ -52,8 +54,8 @@ static LIST_HEAD(slot_list);
/* local variables */
static int num_slots;

-#define DRIVER_VERSION "0.4"
-#define DRIVER_AUTHOR "Greg Kroah-Hartman <[email protected]>, Takayoshi Kochi <[email protected]>"
+#define DRIVER_VERSION "0.5"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <[email protected]>, Takayoshi Kochi <[email protected]>, Matthew Wilcox <[email protected]>"
#define DRIVER_DESC "ACPI Hot Plug PCI Controller Driver"

MODULE_AUTHOR(DRIVER_AUTHOR);
diff -urpNX build-tools/dontdiff linux-2.6/drivers/pci/hotplug/acpiphp_glue.c hotplug-2.6/drivers/pci/hotplug/acpiphp_glue.c
--- linux-2.6/drivers/pci/hotplug/acpiphp_glue.c 2004-07-20 16:06:36.000000000 -0600
+++ hotplug-2.6/drivers/pci/hotplug/acpiphp_glue.c 2004-09-03 09:27:41.741039272 -0600
@@ -26,6 +26,16 @@
*
*/

+/*
+ * Lifetime rules for pci_dev:
+ * - The one in acpiphp_func has its refcount elevated by pci_get_slot()
+ * when the driver is loaded or when an insertion event occurs. It loses
+ * a refcount when its ejected or the driver unloads.
+ * - The one in acpiphp_bridge has its refcount elevated by pci_get_slot()
+ * when the bridge is scanned and it loses a refcount when the bridge
+ * is removed.
+ */
+
#include <linux/init.h>
#include <linux/module.h>

@@ -178,18 +188,20 @@ register_slot(acpi_handle handle, u32 lv

bridge->nr_slots++;

- dbg("found ACPI PCI Hotplug slot at PCI %02x:%02x Slot:%d\n",
- slot->bridge->bus, slot->device, slot->sun);
+ dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n",
+ slot->sun, pci_domain_nr(bridge->pci_bus),
+ bridge->pci_bus->number, slot->device);
}

newfunc->slot = slot;
list_add_tail(&newfunc->sibling, &slot->funcs);

/* associate corresponding pci_dev */
- newfunc->pci_dev = pci_find_slot(bridge->bus,
+ newfunc->pci_dev = pci_get_slot(bridge->pci_bus,
PCI_DEVFN(device, function));
if (newfunc->pci_dev) {
if (acpiphp_init_func_resource(newfunc) < 0) {
+ pci_dev_put(newfunc->pci_dev);
kfree(newfunc);
return AE_ERROR;
}
@@ -371,7 +383,7 @@ static void init_bridge_misc(struct acpi


/* allocate and initialize host bridge data structure */
-static void add_host_bridge(acpi_handle *handle, int seg, int bus)
+static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus)
{
acpi_status status;
struct acpiphp_bridge *bridge;
@@ -384,16 +396,11 @@ static void add_host_bridge(acpi_handle

bridge->type = BRIDGE_TYPE_HOST;
bridge->handle = handle;
- bridge->seg = seg;
- bridge->bus = bus;

- bridge->pci_bus = pci_find_bus(seg, bus);
+ bridge->pci_bus = pci_bus;

bridge->res_lock = SPIN_LOCK_UNLOCKED;

- /* to be overridden when we decode _CRS */
- bridge->sub = bridge->bus;
-
/* decode resources */

status = acpi_walk_resources(handle, METHOD_NAME__CRS,
@@ -414,8 +421,18 @@ static void add_host_bridge(acpi_handle
acpiphp_dump_resource(bridge);

if (bridge->bus_head) {
- bridge->bus = bridge->bus_head->base;
- bridge->sub = bridge->bus_head->base + bridge->bus_head->length - 1;
+ int base = bridge->bus_head->base;
+ int max = base + bridge->bus_head->length - 1;
+ if (bridge->bus_head->base != bridge->pci_bus->number) {
+ warn("ACPI says we have bus %d but Linux found "
+ "bus %d\n", base,
+ bridge->pci_bus->number);
+ }
+ if (max < bridge->pci_bus->subordinate) {
+ warn("ACPI says busses available up to %d, but "
+ "we found %d\n", max,
+ bridge->pci_bus->subordinate);
+ }
}

init_bridge_misc(bridge);
@@ -423,7 +440,7 @@ static void add_host_bridge(acpi_handle


/* allocate and initialize PCI-to-PCI bridge data structure */
-static void add_p2p_bridge(acpi_handle *handle, int seg, int bus, int dev, int fn)
+static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev)
{
struct acpiphp_bridge *bridge;
u8 tmp8;
@@ -441,35 +458,24 @@ static void add_p2p_bridge(acpi_handle *

bridge->type = BRIDGE_TYPE_P2P;
bridge->handle = handle;
- bridge->seg = seg;
-
- bridge->pci_dev = pci_find_slot(bus, PCI_DEVFN(dev, fn));
- if (!bridge->pci_dev) {
- err("Can't get pci_dev\n");
- kfree(bridge);
- return;
- }

- bridge->pci_bus = bridge->pci_dev->subordinate;
+ bridge->pci_dev = pci_dev_get(pci_dev);
+ bridge->pci_bus = pci_dev->subordinate;
if (!bridge->pci_bus) {
err("This is not a PCI-to-PCI bridge!\n");
- kfree(bridge);
- return;
+ goto err;
}

bridge->res_lock = SPIN_LOCK_UNLOCKED;

- bridge->bus = bridge->pci_bus->number;
- bridge->sub = bridge->pci_bus->subordinate;
-
/*
* decode resources under this P2P bridge
*/

/* I/O resources */
- pci_read_config_byte(bridge->pci_dev, PCI_IO_BASE, &tmp8);
+ pci_read_config_byte(pci_dev, PCI_IO_BASE, &tmp8);
base = tmp8;
- pci_read_config_byte(bridge->pci_dev, PCI_IO_LIMIT, &tmp8);
+ pci_read_config_byte(pci_dev, PCI_IO_LIMIT, &tmp8);
limit = tmp8;

switch (base & PCI_IO_RANGE_TYPE_MASK) {
@@ -477,26 +483,22 @@ static void add_p2p_bridge(acpi_handle *
base = (base << 8) & 0xf000;
limit = ((limit << 8) & 0xf000) + 0xfff;
bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1);
- if (!bridge->io_head) {
- err("out of memory\n");
- kfree(bridge);
- return;
- }
+ if (!bridge->io_head)
+ goto oom;
+
dbg("16bit I/O range: %04x-%04x\n",
(u32)bridge->io_head->base,
(u32)(bridge->io_head->base + bridge->io_head->length - 1));
break;
case PCI_IO_RANGE_TYPE_32:
- pci_read_config_word(bridge->pci_dev, PCI_IO_BASE_UPPER16, &tmp16);
+ pci_read_config_word(pci_dev, PCI_IO_BASE_UPPER16, &tmp16);
base = ((u32)tmp16 << 16) | ((base << 8) & 0xf000);
- pci_read_config_word(bridge->pci_dev, PCI_IO_LIMIT_UPPER16, &tmp16);
+ pci_read_config_word(pci_dev, PCI_IO_LIMIT_UPPER16, &tmp16);
limit = (((u32)tmp16 << 16) | ((limit << 8) & 0xf000)) + 0xfff;
bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1);
- if (!bridge->io_head) {
- err("out of memory\n");
- kfree(bridge);
- return;
- }
+ if (!bridge->io_head)
+ goto oom;
+
dbg("32bit I/O range: %08x-%08x\n",
(u32)bridge->io_head->base,
(u32)(bridge->io_head->base + bridge->io_head->length - 1));
@@ -509,24 +511,22 @@ static void add_p2p_bridge(acpi_handle *
}

/* Memory resources (mandatory for P2P bridge) */
- pci_read_config_word(bridge->pci_dev, PCI_MEMORY_BASE, &tmp16);
+ pci_read_config_word(pci_dev, PCI_MEMORY_BASE, &tmp16);
base = (tmp16 & 0xfff0) << 16;
- pci_read_config_word(bridge->pci_dev, PCI_MEMORY_LIMIT, &tmp16);
+ pci_read_config_word(pci_dev, PCI_MEMORY_LIMIT, &tmp16);
limit = ((tmp16 & 0xfff0) << 16) | 0xfffff;
bridge->mem_head = acpiphp_make_resource((u64)base, limit - base + 1);
- if (!bridge->mem_head) {
- err("out of memory\n");
- kfree(bridge);
- return;
- }
+ if (!bridge->mem_head)
+ goto oom;
+
dbg("32bit Memory range: %08x-%08x\n",
(u32)bridge->mem_head->base,
(u32)(bridge->mem_head->base + bridge->mem_head->length-1));

/* Prefetchable Memory resources (optional) */
- pci_read_config_word(bridge->pci_dev, PCI_PREF_MEMORY_BASE, &tmp16);
+ pci_read_config_word(pci_dev, PCI_PREF_MEMORY_BASE, &tmp16);
base = tmp16;
- pci_read_config_word(bridge->pci_dev, PCI_PREF_MEMORY_LIMIT, &tmp16);
+ pci_read_config_word(pci_dev, PCI_PREF_MEMORY_LIMIT, &tmp16);
limit = tmp16;

switch (base & PCI_MEMORY_RANGE_TYPE_MASK) {
@@ -534,27 +534,21 @@ static void add_p2p_bridge(acpi_handle *
base = (base & 0xfff0) << 16;
limit = ((limit & 0xfff0) << 16) | 0xfffff;
bridge->p_mem_head = acpiphp_make_resource((u64)base, limit - base + 1);
- if (!bridge->p_mem_head) {
- err("out of memory\n");
- kfree(bridge);
- return;
- }
+ if (!bridge->p_mem_head)
+ goto oom;
dbg("32bit Prefetchable memory range: %08x-%08x\n",
(u32)bridge->p_mem_head->base,
(u32)(bridge->p_mem_head->base + bridge->p_mem_head->length - 1));
break;
case PCI_PREF_RANGE_TYPE_64:
- pci_read_config_dword(bridge->pci_dev, PCI_PREF_BASE_UPPER32, &base32u);
- pci_read_config_dword(bridge->pci_dev, PCI_PREF_LIMIT_UPPER32, &limit32u);
+ pci_read_config_dword(pci_dev, PCI_PREF_BASE_UPPER32, &base32u);
+ pci_read_config_dword(pci_dev, PCI_PREF_LIMIT_UPPER32, &limit32u);
base64 = ((u64)base32u << 32) | ((base & 0xfff0) << 16);
limit64 = (((u64)limit32u << 32) | ((limit & 0xfff0) << 16)) + 0xfffff;

bridge->p_mem_head = acpiphp_make_resource(base64, limit64 - base64 + 1);
- if (!bridge->p_mem_head) {
- err("out of memory\n");
- kfree(bridge);
- return;
- }
+ if (!bridge->p_mem_head)
+ goto oom;
dbg("64bit Prefetchable memory range: %08x%08x-%08x%08x\n",
(u32)(bridge->p_mem_head->base >> 32),
(u32)(bridge->p_mem_head->base & 0xffffffff),
@@ -568,6 +562,13 @@ static void add_p2p_bridge(acpi_handle *
}

init_bridge_misc(bridge);
+ return;
+ oom:
+ err("out of memory\n");
+ err:
+ pci_dev_put(pci_dev);
+ kfree(bridge);
+ return;
}


@@ -577,14 +578,10 @@ find_p2p_bridge(acpi_handle handle, u32
{
acpi_status status;
acpi_handle dummy_handle;
- unsigned long *segbus = context;
unsigned long tmp;
- int seg, bus, device, function;
+ int device, function;
struct pci_dev *dev;
-
- /* get PCI address */
- seg = (*segbus >> 8) & 0xff;
- bus = *segbus & 0xff;
+ struct pci_bus *pci_bus = context;

status = acpi_get_handle(handle, "_ADR", &dummy_handle);
if (ACPI_FAILURE(status))
@@ -599,20 +596,19 @@ find_p2p_bridge(acpi_handle handle, u32
device = (tmp >> 16) & 0xffff;
function = tmp & 0xffff;

- dev = pci_find_slot(bus, PCI_DEVFN(device, function));
+ dev = pci_get_slot(pci_bus, PCI_DEVFN(device, function));

- if (!dev)
- return AE_OK;
-
- if (!dev->subordinate)
- return AE_OK;
+ if (!dev || !dev->subordinate)
+ goto out;

/* check if this bridge has ejectable slots */
if (detect_ejectable_slots(handle) > 0) {
dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev));
- add_p2p_bridge(handle, seg, bus, device, function);
+ add_p2p_bridge(handle, dev);
}

+ out:
+ pci_dev_put(dev);
return AE_OK;
}

@@ -624,6 +620,7 @@ static int add_bridge(acpi_handle handle
unsigned long tmp;
int seg, bus;
acpi_handle dummy_handle;
+ struct pci_bus *pci_bus;

/* if the bridge doesn't have _STA, we assume it is always there */
status = acpi_get_handle(handle, "_STA", &dummy_handle);
@@ -653,18 +650,22 @@ static int add_bridge(acpi_handle handle
bus = 0;
}

+ pci_bus = pci_find_bus(seg, bus);
+ if (!pci_bus) {
+ err("Can't find bus %04x:%02x\n", seg, bus);
+ return 0;
+ }
+
/* check if this bridge has ejectable slots */
if (detect_ejectable_slots(handle) > 0) {
dbg("found PCI host-bus bridge with hot-pluggable slots\n");
- add_host_bridge(handle, seg, bus);
+ add_host_bridge(handle, pci_bus);
return 0;
}

- tmp = seg << 8 | bus;
-
/* search P2P bridges under this host bridge */
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
- find_p2p_bridge, &tmp, NULL);
+ find_p2p_bridge, pci_bus, NULL);

if (ACPI_FAILURE(status))
warn("find_p2p_bridge faied (error code = 0x%x)\n",status);
@@ -672,10 +673,68 @@ static int add_bridge(acpi_handle handle
return 0;
}

+static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
+{
+ struct list_head *head;
+ list_for_each(head, &bridge_list) {
+ struct acpiphp_bridge *bridge = list_entry(head,
+ struct acpiphp_bridge, list);
+ if (bridge->handle == handle)
+ return bridge;
+ }
+
+ return NULL;
+}

static void remove_bridge(acpi_handle handle)
{
- /* No-op for now .. */
+ struct list_head *list, *tmp;
+ struct acpiphp_bridge *bridge;
+ struct acpiphp_slot *slot;
+ acpi_status status;
+
+ bridge = acpiphp_handle_to_bridge(handle);
+ if (!bridge) {
+ err("Could not find bridge for handle %p\n", handle);
+ return;
+ }
+
+ status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+ handle_hotplug_event_bridge);
+ if (ACPI_FAILURE(status))
+ err("failed to remove notify handler\n");
+
+ slot = bridge->slots;
+ while (slot) {
+ struct acpiphp_slot *next = slot->next;
+ list_for_each_safe (list, tmp, &slot->funcs) {
+ struct acpiphp_func *func;
+ func = list_entry(list, struct acpiphp_func, sibling);
+ acpiphp_free_resource(&func->io_head);
+ acpiphp_free_resource(&func->mem_head);
+ acpiphp_free_resource(&func->p_mem_head);
+ acpiphp_free_resource(&func->bus_head);
+ status = acpi_remove_notify_handler(func->handle,
+ ACPI_SYSTEM_NOTIFY,
+ handle_hotplug_event_func);
+ if (ACPI_FAILURE(status))
+ err("failed to remove notify handler\n");
+ pci_dev_put(func->pci_dev);
+ list_del(list);
+ kfree(func);
+ }
+ kfree(slot);
+ slot = next;
+ }
+
+ acpiphp_free_resource(&bridge->io_head);
+ acpiphp_free_resource(&bridge->mem_head);
+ acpiphp_free_resource(&bridge->p_mem_head);
+ acpiphp_free_resource(&bridge->bus_head);
+
+ pci_dev_put(bridge->pci_dev);
+ list_del(&bridge->list);
+ kfree(bridge);
}


@@ -782,9 +841,9 @@ static int power_off_slot(struct acpiphp
*/
static int enable_device(struct acpiphp_slot *slot)
{
- u8 bus;
struct pci_dev *dev;
struct pci_bus *child;
+ struct pci_bus *bus = slot->bridge->pci_bus;
struct list_head *l;
struct acpiphp_func *func;
int retval = 0;
@@ -794,10 +853,11 @@ static int enable_device(struct acpiphp_
goto err_exit;

/* sanity check: dev should be NULL when hot-plugged in */
- dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0));
+ dev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0));
if (dev) {
/* This case shouldn't happen */
err("pci_dev structure already exists.\n");
+ pci_dev_put(dev);
retval = -1;
goto err_exit;
}
@@ -807,21 +867,28 @@ static int enable_device(struct acpiphp_
if (retval)
goto err_exit;

- /* returned `dev' is the *first function* only! */
- num = pci_scan_slot(slot->bridge->pci_bus, PCI_DEVFN(slot->device, 0));
- if (num)
- pci_bus_add_devices(slot->bridge->pci_bus);
- dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0));
-
- if (!dev) {
+ num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0));
+ if (num == 0) {
err("No new device found\n");
retval = -1;
goto err_exit;
}

+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ /* Skip the devices we didn't just add */
+ if (!list_empty(&dev->global_list))
+ continue;
+ pcibios_fixup_device_resources(dev, bus);
+ }
+
+ pci_bus_add_devices(bus);
+ /* returned `dev' is the *first function* only! */
+ dev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0));
+
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- pci_read_config_byte(dev, PCI_SECONDARY_BUS, &bus);
- child = (struct pci_bus*) pci_add_new_bus(dev->bus, dev, bus);
+ u8 bus_nr;
+ pci_read_config_byte(dev, PCI_SECONDARY_BUS, &bus_nr);
+ child = pci_add_new_bus(dev->bus, dev, bus_nr);
pci_do_scan_bus(child);
}

@@ -829,16 +896,17 @@ static int enable_device(struct acpiphp_
list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling);

- func->pci_dev = pci_find_slot(slot->bridge->bus,
- PCI_DEVFN(slot->device,
+ func->pci_dev = pci_get_slot(bus, PCI_DEVFN(slot->device,
func->function));
if (!func->pci_dev)
continue;

/* configure device */
retval = acpiphp_configure_function(func);
- if (retval)
+ if (retval) {
+ pci_dev_put(func->pci_dev);
goto err_exit;
+ }
}

slot->flags |= SLOT_ENABLED;
@@ -866,9 +934,12 @@ static int disable_device(struct acpiphp

list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling);
+ if (!func->pci_dev)
+ continue;

- if (func->pci_dev)
- acpiphp_unconfigure_function(func);
+ acpiphp_unconfigure_function(func);
+ pci_dev_put(func->pci_dev);
+ func->pci_dev = NULL;
}

slot->flags &= (~SLOT_ENABLED);
@@ -1116,46 +1187,6 @@ int __init acpiphp_glue_init(void)
*/
void __exit acpiphp_glue_exit(void)
{
- struct list_head *l1, *l2, *n1, *n2;
- struct acpiphp_bridge *bridge;
- struct acpiphp_slot *slot, *next;
- struct acpiphp_func *func;
- acpi_status status;
-
- list_for_each_safe (l1, n1, &bridge_list) {
- bridge = (struct acpiphp_bridge *)l1;
- slot = bridge->slots;
- while (slot) {
- next = slot->next;
- list_for_each_safe (l2, n2, &slot->funcs) {
- func = list_entry(l2, struct acpiphp_func, sibling);
- acpiphp_free_resource(&func->io_head);
- acpiphp_free_resource(&func->mem_head);
- acpiphp_free_resource(&func->p_mem_head);
- acpiphp_free_resource(&func->bus_head);
- status = acpi_remove_notify_handler(func->handle,
- ACPI_SYSTEM_NOTIFY,
- handle_hotplug_event_func);
- if (ACPI_FAILURE(status))
- err("failed to remove notify handler\n");
- kfree(func);
- }
- kfree(slot);
- slot = next;
- }
- status = acpi_remove_notify_handler(bridge->handle, ACPI_SYSTEM_NOTIFY,
- handle_hotplug_event_bridge);
- if (ACPI_FAILURE(status))
- err("failed to remove notify handler\n");
-
- acpiphp_free_resource(&bridge->io_head);
- acpiphp_free_resource(&bridge->mem_head);
- acpiphp_free_resource(&bridge->p_mem_head);
- acpiphp_free_resource(&bridge->bus_head);
-
- kfree(bridge);
- }
-
acpi_pci_unregister_driver(&acpi_pci_hp_driver);
}

@@ -1173,11 +1204,14 @@ int __init acpiphp_get_num_slots(void)

list_for_each (node, &bridge_list) {
bridge = (struct acpiphp_bridge *)node;
- dbg("Bus%d %dslot(s)\n", bridge->bus, bridge->nr_slots);
+ dbg("Bus %04x:%02x has %d slot%s\n",
+ pci_domain_nr(bridge->pci_bus),
+ bridge->pci_bus->number, bridge->nr_slots,
+ bridge->nr_slots == 1 ? "" : "s");
num_slots += bridge->nr_slots;
}

- dbg("Total %dslots\n", num_slots);
+ dbg("Total %d slots\n", num_slots);
return num_slots;
}

@@ -1349,9 +1383,10 @@ u8 acpiphp_get_adapter_status(struct acp
u32 acpiphp_get_address(struct acpiphp_slot *slot)
{
u32 address;
+ struct pci_bus *pci_bus = slot->bridge->pci_bus;

- address = ((slot->bridge->seg) << 16) |
- ((slot->bridge->bus) << 8) |
+ address = (pci_domain_nr(pci_bus) << 16) |
+ (pci_bus->number << 8) |
slot->device;

return address;

--
"Next the statesmen will invent cheap lies, putting the blame upon
the nation that is attacked, and every man will be glad of those
conscience-soothing falsities, and will diligently study them, and refuse
to examine any refutations of them; and thus he will by and by convince
himself that the war is just, and will thank God for the better sleep
he enjoys after this process of grotesque self-deception." -- Mark Twain

2004-09-03 19:45:47

by Matthew Wilcox

[permalink] [raw]
Subject: [PATCH] acpiphp resource usage [4/5]


Reading the config size from a PCI BAR can only be done when the device
is quiesced. With the current code, loading the acpiphp driver at
runtime can cause all kinds of interesting errors.

This patch makes acpiphp use the resources embedded in the pci_dev instead
where possible. It uses the new pci_bus_address() function introduced
in patch 01 of this series. By using the pci_dev resources instead of
reading the BARs directly, this also cures some of the problems found
with plugin cards that contain PCI-to-PCI bridges.

diff -urpNX build-tools/dontdiff linux-2.6/drivers/pci/hotplug/acpiphp_pci.c hotplug-2.6/drivers/pci/hotplug/acpiphp_pci.c
--- linux-2.6/drivers/pci/hotplug/acpiphp_pci.c 2004-04-28 13:12:37.000000000 -0600
+++ hotplug-2.6/drivers/pci/hotplug/acpiphp_pci.c 2004-09-02 13:34:23.000000000 -0600
@@ -45,44 +45,29 @@
/* allocate mem/pmem/io resource to a new function */
static int init_config_space (struct acpiphp_func *func)
{
- u32 bar, len;
- u32 address[] = {
- PCI_BASE_ADDRESS_0,
- PCI_BASE_ADDRESS_1,
- PCI_BASE_ADDRESS_2,
- PCI_BASE_ADDRESS_3,
- PCI_BASE_ADDRESS_4,
- PCI_BASE_ADDRESS_5,
- 0
- };
int count;
- struct acpiphp_bridge *bridge;
- struct pci_resource *res;
- struct pci_bus *pbus;
- int bus, device, function;
- unsigned int devfn;
u16 tmp;

- bridge = func->slot->bridge;
- pbus = bridge->pci_bus;
- bus = bridge->bus;
- device = func->slot->device;
- function = func->function;
- devfn = PCI_DEVFN(device, function);
-
- for (count = 0; address[count]; count++) { /* for 6 BARs */
- pci_bus_write_config_dword(pbus, devfn,
- address[count], 0xFFFFFFFF);
- pci_bus_read_config_dword(pbus, devfn, address[count], &bar);
+ struct acpiphp_bridge *bridge = func->slot->bridge;
+ struct pci_bus *pbus = bridge->pci_bus;
+ int bus = pbus->number;
+ int device = func->slot->device;
+ int function = func->function;
+ int devfn = PCI_DEVFN(device, function);
+
+ for (count = 0; count < 6; count++) {
+ struct pci_resource *res;
+ u32 bar, len;
+ unsigned int address = PCI_BASE_ADDRESS_0 + (count << 2);
+ pci_bus_write_config_dword(pbus, devfn, address, 0xFFFFFFFF);
+ pci_bus_read_config_dword(pbus, devfn, address, &bar);

- if (!bar) /* This BAR is not implemented */
+ if (!bar || bar == 0xffffffff)
continue;

dbg("Device %02x.%02x BAR %d wants %x\n", device, function, count, bar);

- if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
- /* This is IO */
-
+ if ((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
len = len & ~(len - 1);

@@ -97,82 +82,52 @@ static int init_config_space (struct acp
bus, device, function, len);
return -1;
}
- pci_bus_write_config_dword(pbus, devfn,
- address[count],
+ pci_bus_write_config_dword(pbus, devfn, address,
(u32)res->base);
res->next = func->io_head;
func->io_head = res;
-
} else {
- /* This is Memory */
- if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH) {
- /* pfmem */
-
- len = bar & 0xFFFFFFF0;
- len = ~len + 1;
-
- dbg("len in PFMEM %x, BAR %d\n", len, count);
-
- spin_lock(&bridge->res_lock);
- res = acpiphp_get_resource(&bridge->p_mem_head, len);
- spin_unlock(&bridge->res_lock);
-
- if (!res) {
- err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
- bus, device, function, len);
- return -1;
- }
-
- pci_bus_write_config_dword(pbus, devfn,
- address[count],
- (u32)res->base);
-
- if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
- dbg("inside the pfmem 64 case, count %d\n", count);
- count += 1;
- pci_bus_write_config_dword(pbus, devfn,
- address[count],
- (u32)(res->base >> 32));
- }
+ struct pci_resource **bridge_mem_head;
+ struct pci_resource **func_mem_head;

- res->next = func->p_mem_head;
- func->p_mem_head = res;
+ len = bar & PCI_BASE_ADDRESS_MEM_MASK;
+ len = ~len + 1;
+ dbg("len in MEM %x, BAR %d\n", len, count);

+ if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+ bridge_mem_head = &bridge->p_mem_head;
+ func_mem_head = &func->p_mem_head;
} else {
- /* regular memory */
+ bridge_mem_head = &bridge->mem_head;
+ func_mem_head = &func->mem_head;
+ }

- len = bar & 0xFFFFFFF0;
- len = ~len + 1;
+ spin_lock(&bridge->res_lock);
+ res = acpiphp_get_resource(bridge_mem_head, len);
+ spin_unlock(&bridge->res_lock);

- dbg("len in MEM %x, BAR %d\n", len, count);
+ if (!res) {
+ err("cannot allocate requested mem for "
+ "%02x:%02x.%d len %x\n",
+ bus, device, function, len);
+ return -1;
+ }
+ dbg("received address 0x%lx\n", res->base);

- spin_lock(&bridge->res_lock);
- res = acpiphp_get_resource(&bridge->mem_head, len);
- spin_unlock(&bridge->res_lock);
-
- if (!res) {
- err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
- bus, device, function, len);
- return -1;
- }
+ pci_bus_write_config_dword(pbus, devfn, address,
+ (u32)res->base);

+ if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+ /* takes up another dword */
+ dbg("inside the mem 64 case, count %d\n", count);
+ count++;
pci_bus_write_config_dword(pbus, devfn,
- address[count],
- (u32)res->base);
-
- if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {
- /* takes up another dword */
- dbg("inside mem 64 case, reg. mem, count %d\n", count);
- count += 1;
- pci_bus_write_config_dword(pbus, devfn,
- address[count],
- (u32)(res->base >> 32));
- }
-
- res->next = func->mem_head;
- func->mem_head = res;
-
+ address + 4,
+ (u32)(res->base >> 32));
}
+
+ res->next = *func_mem_head;
+ *func_mem_head = res;
}
}

@@ -214,6 +169,7 @@ static int detect_used_resource (struct

dbg("BAR[%d] 0x%lx - 0x%lx (0x%lx)\n", count, base,
base + len - 1, flags);
+ base = pci_bus_address(dev, base, flags);

if (flags & IORESOURCE_IO) {
head = &bridge->io_head;
@@ -255,100 +211,43 @@ int acpiphp_detect_pci_resource (struct


/**
- * acpiphp_init_slot_resource - gather resource usage information of a slot
+ * acpiphp_init_func_resource - gather resource usage information of a slot
* @slot: ACPI slot object to be checked, should have valid pci_dev member
- *
- * TBD: PCI-to-PCI bridge case
- * use pci_dev->resource[]
*/
int acpiphp_init_func_resource (struct acpiphp_func *func)
{
- u64 base;
- u32 bar, len;
- u32 address[] = {
- PCI_BASE_ADDRESS_0,
- PCI_BASE_ADDRESS_1,
- PCI_BASE_ADDRESS_2,
- PCI_BASE_ADDRESS_3,
- PCI_BASE_ADDRESS_4,
- PCI_BASE_ADDRESS_5,
- 0
- };
int count;
- struct pci_resource *res;
- struct pci_dev *dev;
-
- dev = func->pci_dev;
+ struct pci_dev *dev = func->pci_dev;
dbg("Hot-pluggable device %s\n", pci_name(dev));

- for (count = 0; address[count]; count++) { /* for 6 BARs */
- pci_read_config_dword(dev, address[count], &bar);
-
- if (!bar) /* This BAR is not implemented */
- continue;
+ for (count = 0; count < DEVICE_COUNT_RESOURCE; count++) {
+ struct pci_resource *res;

- pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
- pci_read_config_dword(dev, address[count], &len);
+ unsigned long base = dev->resource[count].start;
+ unsigned long len = dev->resource[count].end - base + 1;
+ unsigned long flags = dev->resource[count].flags;

- if (len & PCI_BASE_ADDRESS_SPACE_IO) {
- /* This is IO */
- base = bar & 0xFFFFFFFC;
- len = len & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
- len = len & ~(len - 1);
+ if (!flags)
+ continue;

- dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
+ dbg("BAR[%d] 0x%lx - 0x%lx (0x%lx)\n", count, base,
+ base + len - 1, flags);
+ base = pci_bus_address(dev, base, flags);

- res = acpiphp_make_resource(base, len);
- if (!res)
- goto no_memory;
+ res = acpiphp_make_resource(base, len);
+ if (!res)
+ goto no_memory;

+ if (flags & IORESOURCE_IO) {
res->next = func->io_head;
func->io_head = res;
-
+ } else if (flags & IORESOURCE_PREFETCH) {
+ res->next = func->p_mem_head;
+ func->p_mem_head = res;
} else {
- /* This is Memory */
- base = bar & 0xFFFFFFF0;
- if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) {
- /* pfmem */
-
- len &= 0xFFFFFFF0;
- len = ~len + 1;
-
- if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
- dbg("prefetch mem 64\n");
- count += 1;
- }
- dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1);
- res = acpiphp_make_resource(base, len);
- if (!res)
- goto no_memory;
-
- res->next = func->p_mem_head;
- func->p_mem_head = res;
-
- } else {
- /* regular memory */
-
- len &= 0xFFFFFFF0;
- len = ~len + 1;
-
- if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
- /* takes up another dword */
- dbg("mem 64\n");
- count += 1;
- }
- dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1);
- res = acpiphp_make_resource(base, len);
- if (!res)
- goto no_memory;
-
- res->next = func->mem_head;
- func->mem_head = res;
-
- }
+ res->next = func->mem_head;
+ func->mem_head = res;
}
-
- pci_write_config_dword(dev, address[count], bar);
}
#if 1
acpiphp_dump_func_resource(func);

--
"Next the statesmen will invent cheap lies, putting the blame upon
the nation that is attacked, and every man will be glad of those
conscience-soothing falsities, and will diligently study them, and refuse
to examine any refutations of them; and thus he will by and by convince
himself that the war is just, and will thank God for the better sleep
he enjoys after this process of grotesque self-deception." -- Mark Twain

2004-09-03 19:47:52

by Matthew Wilcox

[permalink] [raw]
Subject: [PATCH] acpiphp misc fixes [5/5]


Two minor fixes:

- Correct the docbook (parameter renamed to value)
- If a resource is 64-bit, the debug code was previously truncating its value.

diff -urpNX build-tools/dontdiff linux-2.6/drivers/pci/hotplug/acpiphp_core.c hotplug-2.6/drivers/pci/hotplug/acpiphp_core.c
--- linux-2.6/drivers/pci/hotplug/acpiphp_core.c 2004-05-23 17:52:23.000000000 -0600
+++ hotplug-2.6/drivers/pci/hotplug/acpiphp_core.c 2004-09-03 08:09:15.181670908 -0600
@@ -210,8 +212,7 @@ static int get_adapter_status(struct hot
/**
* get_address - get pci address of a slot
* @hotplug_slot: slot to get status
- * @busdev: pointer to struct pci_busdev (seg, bus, dev)
- *
+ * @value: pointer to struct pci_busdev (seg, bus, dev)
*/
static int get_address(struct hotplug_slot *hotplug_slot, u32 *value)
{
diff -urpNX build-tools/dontdiff linux-2.6/drivers/pci/hotplug/acpiphp_res.c hotplug-2.6/drivers/pci/hotplug/acpiphp_res.c
--- linux-2.6/drivers/pci/hotplug/acpiphp_res.c 2004-05-23 17:52:23.000000000 -0600
+++ hotplug-2.6/drivers/pci/hotplug/acpiphp_res.c 2004-09-02 10:51:54.000000000 -0600
@@ -669,8 +669,8 @@ static void dump_resource(struct pci_res
cnt = 0;

while (p) {
- dbg("[%02d] %08x - %08x\n",
- cnt++, (u32)p->base, (u32)p->base + p->length - 1);
+ dbg("[%02d] 0x%llx - 0x%llx\n", cnt++, (long long)p->base,
+ (long long)(p->base + p->length - 1));
p = p->next;
}
}

--
"Next the statesmen will invent cheap lies, putting the blame upon
the nation that is attacked, and every man will be glad of those
conscience-soothing falsities, and will diligently study them, and refuse
to examine any refutations of them; and thus he will by and by convince
himself that the war is just, and will thank God for the better sleep
he enjoys after this process of grotesque self-deception." -- Mark Twain

2004-09-03 20:04:27

by Matthew Wilcox

[permalink] [raw]
Subject: [PATCH] pci_bus_address [1/5]


pci_bus_address() allows one to convert a global system address to a
local PCI bus address. In Documentation/IO-mapping.txt terms, this is
a phys_to_bus() call, except that we pass the PCI bus or PCI device so
we know which bus is being referred to.

diff -urpNX build-tools/dontdiff linux-2.6/arch/ia64/pci/pci.c hotplug-2.6/arch/ia64/pci/pci.c
--- linux-2.6/arch/ia64/pci/pci.c 2004-07-20 16:05:26.000000000 -0600
+++ hotplug-2.6/arch/ia64/pci/pci.c 2004-09-02 13:10:03.000000000 -0600
@@ -370,6 +371,27 @@ pcibios_fixup_bus (struct pci_bus *b)
return;
}

+unsigned long pcibios_bus_address(struct pci_controller *controller,
+ unsigned long addr, int flags)
+{
+ int i;
+ for (i = 0; i < controller->windows; i++) {
+ struct pci_window *window = &controller->window[i];
+ unsigned long offset = window->offset;
+ unsigned long bus_addr = addr - offset;
+ if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) !=
+ window->resource.flags)
+ continue;
+ if (bus_addr < window->resource.start)
+ continue;
+ if (window->resource.end < bus_addr)
+ continue;
+ return bus_addr;
+ }
+
+ return addr;
+}
+
void __devinit
pcibios_update_irq (struct pci_dev *dev, int irq)
{
diff -urpNX build-tools/dontdiff linux-2.6/include/asm-ia64/pci.h hotplug-2.6/include/asm-ia64/pci.h
--- linux-2.6/include/asm-ia64/pci.h 2004-03-16 08:40:37.000000000 -0700
+++ hotplug-2.6/include/asm-ia64/pci.h 2004-09-02 13:56:21.000000000 -0600
@@ -119,6 +119,12 @@ static inline void pcibios_add_platform_
{
}

+extern unsigned long pcibios_bus_address(struct pci_controller *,
+ unsigned long, int);
+
+#define pci_bus_address(busdev, addr, flags) \
+ pcibios_bus_address(PCI_CONTROLLER(busdev), (addr), (flags))
+
/* generic pci stuff */
#include <asm-generic/pci.h>

diff -urpNX build-tools/dontdiff linux-2.6/include/linux/pci.h hotplug-2.6/include/linux/pci.h
--- linux-2.6/include/linux/pci.h 2004-08-13 08:30:23.000000000 -0600
+++ hotplug-2.6/include/linux/pci.h 2004-09-02 13:55:57.000000000 -0600
@@ -951,6 +951,14 @@ static inline int pci_name_bus(char *nam

#endif /* !CONFIG_PCI */

+/*
+ * Convert from a global physical address to a bus-local address. You can
+ * override this in asm/pci.h
+ */
+#ifndef pci_bus_address
+#define pci_bus_address(busdev, addr, flags) (addr)
+#endif
+
/* these helpers provide future and backwards compatibility
* for accessing popular PCI BAR info */
#define pci_resource_start(dev,bar) ((dev)->resource[(bar)].start)

--
"Next the statesmen will invent cheap lies, putting the blame upon
the nation that is attacked, and every man will be glad of those
conscience-soothing falsities, and will diligently study them, and refuse
to examine any refutations of them; and thus he will by and by convince
himself that the war is just, and will thank God for the better sleep
he enjoys after this process of grotesque self-deception." -- Mark Twain

2004-09-03 19:33:55

by Matthew Wilcox

[permalink] [raw]
Subject: [PATCH] ia64 misc fixes [2/5]


Some miscellaneous fixes:

- flags can be a simple assignment since the resource is newly created
- Zero the allocated memory for the PCI windows
- pcibios_fixup_device_resources is called from pcibios_fixup_bus which
is __devinit, so it cannot be __init.
- pci_claim_resource is called from pcibios_fixup_device_resources so must
also be __devinit.

diff -urpNX build-tools/dontdiff linux-2.6/arch/ia64/pci/pci.c hotplug-2.6/arch/ia64/pci/pci.c
--- linux-2.6/arch/ia64/pci/pci.c 2004-07-20 16:05:26.000000000 -0600
+++ hotplug-2.6/arch/ia64/pci/pci.c 2004-09-02 13:10:03.000000000 -0600
@@ -272,7 +272,7 @@ add_window (struct acpi_resource *res, v
return AE_OK;

window = &info->controller->window[info->controller->windows++];
- window->resource.flags |= flags;
+ window->resource.flags = flags;
window->resource.start = addr.min_address_range;
window->resource.end = addr.max_address_range;
window->offset = offset;
@@ -305,6 +305,7 @@ pci_acpi_scan_root (struct acpi_device *
controller->window = kmalloc(sizeof(*controller->window) * windows, GFP_KERNEL);
if (!controller->window)
goto out2;
+ memset(controller->window, 0, sizeof(*controller->window) * windows);

name = kmalloc(16, GFP_KERNEL);
if (!name)
@@ -325,7 +326,7 @@ out1:
return NULL;
}

-void __init
+void __devinit
pcibios_fixup_device_resources (struct pci_dev *dev, struct pci_bus *bus)
{
struct pci_controller *controller = PCI_CONTROLLER(dev);
diff -urpNX build-tools/dontdiff linux-2.6/drivers/pci/setup-res.c hotplug-2.6/drivers/pci/setup-res.c
--- linux-2.6/drivers/pci/setup-res.c 2004-03-20 13:29:41.000000000 -0700
+++ hotplug-2.6/drivers/pci/setup-res.c 2004-09-02 08:07:37.000000000 -0600
@@ -90,7 +90,7 @@ pci_update_resource(struct pci_dev *dev,
new & ~PCI_REGION_FLAG_MASK));
}

-int __init
+int __devinit
pci_claim_resource(struct pci_dev *dev, int resource)
{
struct resource *res = &dev->resource[resource];

--
"Next the statesmen will invent cheap lies, putting the blame upon
the nation that is attacked, and every man will be glad of those
conscience-soothing falsities, and will diligently study them, and refuse
to examine any refutations of them; and thus he will by and by convince
himself that the war is just, and will thank God for the better sleep
he enjoys after this process of grotesque self-deception." -- Mark Twain

2004-09-15 18:22:43

by Matthew Wilcox

[permalink] [raw]
Subject: [PATCH] build acpiphp modular and on i386/x86_64 [6/5]


After the first five patches I sent, in order to build acpiphp on
i386/x86_64 or as a module on ia64, we need these exports and defines
currently. I have a much better scheme in mind but it's not ready yet.
I promise I'll replace this with something much more portable.

diff -urpNX build-tools/dontdiff hotplug-2.6/arch/ia64/pci/pci.c modular-2.6/arch/ia64/pci/pci.c
--- hotplug-2.6/arch/ia64/pci/pci.c 2004-09-13 09:30:28.000000000 -0600
+++ modular-2.6/arch/ia64/pci/pci.c 2004-09-15 11:54:17.886305856 -0600
@@ -354,6 +354,7 @@ pcibios_fixup_device_resources (struct p
pci_claim_resource(dev, i);
}
}
+EXPORT_SYMBOL(pcibios_fixup_device_resources);

/*
* Called after each bus is probed, but before its children are examined.
diff -urpNX build-tools/dontdiff hotplug-2.6/include/asm-i386/pci.h modular-2.6/include/asm-i386/pci.h
--- hotplug-2.6/include/asm-i386/pci.h 2004-03-16 08:40:36.000000000 -0700
+++ modular-2.6/include/asm-i386/pci.h 2004-09-15 10:50:02.126390608 -0600
@@ -99,6 +99,9 @@ static inline void pcibios_add_platform_
{
}

+/* XXX: temporary hack for acpiphp */
+#define pcibios_fixup_device_resources() do { } while (0)
+
#endif /* __KERNEL__ */

/* implement the pci_ DMA API in terms of the generic device dma_ one */
diff -urpNX build-tools/dontdiff hotplug-2.6/include/asm-ia64/pci.h modular-2.6/include/asm-ia64/pci.h
--- hotplug-2.6/include/asm-ia64/pci.h 2004-09-02 13:56:21.000000000 -0600
+++ modular-2.6/include/asm-ia64/pci.h 2004-09-15 10:52:39.422526206 -0600
@@ -125,6 +125,9 @@ extern unsigned long pcibios_bus_address
#define pci_bus_address(busdev, addr, flags) \
pcibios_bus_address(PCI_CONTROLLER(busdev), (addr), (flags))

+/* XXX: temporary hack for acpiphp */
+extern void pcibios_fixup_device_resources(struct pci_dev *, struct pci_bus *);
+
/* generic pci stuff */
#include <asm-generic/pci.h>

diff -urpNX build-tools/dontdiff hotplug-2.6/include/asm-x86_64/pci.h modular-2.6/include/asm-x86_64/pci.h
--- hotplug-2.6/include/asm-x86_64/pci.h 2004-09-13 09:31:17.000000000 -0600
+++ modular-2.6/include/asm-x86_64/pci.h 2004-09-15 10:50:16.191929342 -0600
@@ -132,6 +132,9 @@ static inline void pcibios_add_platform_
{
}

+/* XXX: temporary hack for acpiphp */
+#define pcibios_fixup_device_resources() do { } while (0)
+
#endif /* __KERNEL__ */

/* generic pci stuff */

--
"Next the statesmen will invent cheap lies, putting the blame upon
the nation that is attacked, and every man will be glad of those
conscience-soothing falsities, and will diligently study them, and refuse
to examine any refutations of them; and thus he will by and by convince
himself that the war is just, and will thank God for the better sleep
he enjoys after this process of grotesque self-deception." -- Mark Twain