aboutsummaryrefslogtreecommitdiffstats
path: root/pci
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2005-11-02 11:24:40 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2005-11-02 11:24:40 -0800
commit8630bdf37b417012ac07d163beaebe5bf505e4dd (patch)
treedd804f96d0e153a34c7cef9d76bde8761d18f269 /pci
parent64b3970c3dce724cffdb06e990344dd75dc50f9c (diff)
downloadpatches-8630bdf37b417012ac07d163beaebe5bf505e4dd.tar.gz
pci express hotplug patches
Diffstat (limited to 'pci')
-rw-r--r--pci/pci-pciehp-01.patch3652
-rw-r--r--pci/pci-pciehp-02.patch1309
-rw-r--r--pci/pci-pciehp-03.patch1144
-rw-r--r--pci/pci-pciehp-04.patch487
-rw-r--r--pci/pci-pciehp-05.patch533
-rw-r--r--pci/pci-pciehp-06.patch108
-rw-r--r--pci/pci-pciehp-07.patch221
-rw-r--r--pci/pci-pciehp-08.patch48
8 files changed, 7502 insertions, 0 deletions
diff --git a/pci/pci-pciehp-01.patch b/pci/pci-pciehp-01.patch
new file mode 100644
index 0000000000000..cf339f7ff97b4
--- /dev/null
+++ b/pci/pci-pciehp-01.patch
@@ -0,0 +1,3652 @@
+From pcihpd-discuss-admin@lists.sourceforge.net Mon Oct 31 17:04:37 2005
+Message-Id: <20051101002122.581862040@csdlinux-2.jf.intel.com>
+From: rajesh.shah@intel.com
+To: kristen.c.accardi@intel.com, gregkh@suse.de
+Cc: akpm@osdl.org, rajesh.shah@intel.com
+Content-Disposition: inline; filename=pciehp-use-pci-core-for-res-mgmt
+Subject: patch 1/8] pciehp: use the PCI core for hotplug resource management
+Date: Mon, 31 Oct 2005 16:20:06 -0800
+
+This patch converts the pci express hotplug controller driver
+to use the PCI core for resource management. This eliminates a
+lot of duplicated code and integrates pciehp with the system's
+normal PCI handling code.
+
+Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+ drivers/pci/hotplug/pciehp.h | 50 -
+ drivers/pci/hotplug/pciehp_core.c | 35
+ drivers/pci/hotplug/pciehp_ctrl.c | 1563 ---------------------------------
+ drivers/pci/hotplug/pciehp_pci.c | 487 +---------
+ drivers/pci/hotplug/pciehprm_acpi.c | 840 -----------------
+ drivers/pci/hotplug/pciehprm_nonacpi.c | 347 -------
+ 6 files changed, 85 insertions(+), 3237 deletions(-)
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp.h 2005-10-27 22:11:49.000000000 -0700
++++ gregkh-2.6/drivers/pci/hotplug/pciehp.h 2005-11-02 10:54:23.000000000 -0800
+@@ -59,14 +59,8 @@
+ u8 configured;
+ u8 switch_save;
+ u8 presence_save;
+- u32 base_length[0x06];
+- u8 base_type[0x06];
+ u16 reserved2;
+ u32 config_space[0x20];
+- struct pci_resource *mem_head;
+- struct pci_resource *p_mem_head;
+- struct pci_resource *io_head;
+- struct pci_resource *bus_head;
+ struct pci_dev* pci_dev;
+ };
+
+@@ -90,12 +84,6 @@
+ struct list_head slot_list;
+ };
+
+-struct pci_resource {
+- struct pci_resource * next;
+- u32 base;
+- u32 length;
+-};
+-
+ struct event_info {
+ u32 event_type;
+ u8 hp_slot;
+@@ -107,10 +95,6 @@
+ void *hpc_ctlr_handle; /* HPC controller handle */
+ int num_slots; /* Number of slots on ctlr */
+ int slot_num_inc; /* 1 or -1 */
+- struct pci_resource *mem_head;
+- struct pci_resource *p_mem_head;
+- struct pci_resource *io_head;
+- struct pci_resource *bus_head;
+ struct pci_dev *pci_dev;
+ struct pci_bus *pci_bus;
+ struct event_info event_queue[10];
+@@ -133,20 +117,6 @@
+ u8 cap_base;
+ };
+
+-struct irq_mapping {
+- u8 barber_pole;
+- u8 valid_INT;
+- u8 interrupt[4];
+-};
+-
+-struct resource_lists {
+- struct pci_resource *mem_head;
+- struct pci_resource *p_mem_head;
+- struct pci_resource *io_head;
+- struct pci_resource *bus_head;
+- struct irq_mapping *irqs;
+-};
+-
+ #define INT_BUTTON_IGNORE 0
+ #define INT_PRESENCE_ON 1
+ #define INT_PRESENCE_OFF 2
+@@ -203,14 +173,12 @@
+ #define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n"
+ #define msg_HPC_non_pcie "The PCI hot plug controller is not supported by this driver.\n"
+ #define msg_HPC_not_supported "This system is not supported by this version of pciephd module. Upgrade to a newer version of pciehpd\n"
+-#define msg_unable_to_save "Unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n"
+ #define msg_button_on "PCI slot #%d - powering on due to button press.\n"
+ #define msg_button_off "PCI slot #%d - powering off due to button press.\n"
+ #define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n"
+ #define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n"
+
+ /* controller functions */
+-extern int pciehprm_find_available_resources (struct controller *ctrl);
+ extern int pciehp_event_start_thread (void);
+ extern void pciehp_event_stop_thread (void);
+ extern struct pci_func *pciehp_slot_create (unsigned char busnumber);
+@@ -224,19 +192,12 @@
+ extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id);
+ /* extern void long_delay (int delay); */
+
+-/* resource functions */
+-extern int pciehp_resource_sort_and_combine (struct pci_resource **head);
+-
+ /* pci functions */
+ extern int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
+ /*extern int pciehp_get_bus_dev (struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/
+ extern int pciehp_save_config (struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
+-extern int pciehp_save_used_resources (struct controller *ctrl, struct pci_func * func, int flag);
+ extern int pciehp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot);
+-extern void pciehp_destroy_board_resources (struct pci_func * func);
+-extern int pciehp_return_board_resources (struct pci_func * func, struct resource_lists * resources);
+-extern void pciehp_destroy_resource_list (struct resource_lists * resources);
+-extern int pciehp_configure_device (struct controller* ctrl, struct pci_func* func);
++extern int pciehp_configure_device (struct slot *ctrl);
+ extern int pciehp_unconfigure_device (struct pci_func* func);
+
+
+@@ -289,15 +250,6 @@
+ return retval;
+ }
+
+-/* Puts node back in the resource list pointed to by head */
+-static inline void return_resource(struct pci_resource **head, struct pci_resource *node)
+-{
+- if (!node || !head)
+- return;
+- node->next = *head;
+- *head = node;
+-}
+-
+ #define SLOT_NAME_SIZE 10
+
+ static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_core.c 2005-08-28 16:41:01.000000000 -0700
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_core.c 2005-11-02 10:54:23.000000000 -0800
+@@ -433,16 +433,8 @@
+ goto err_out_free_ctrl_bus;
+ }
+
+- /* Get IO, memory, and IRQ resources for new devices */
+- rc = pciehprm_find_available_resources(ctrl);
+- ctrl->add_support = !rc;
++ ctrl->add_support = 1;
+
+- if (rc) {
+- dbg("pciehprm_find_available_resources = %#x\n", rc);
+- err("unable to locate PCI configuration resources for hot plug add.\n");
+- goto err_out_free_ctrl_bus;
+- }
+-
+ /* Setup the slot information structures */
+ rc = init_slots(ctrl);
+ if (rc) {
+@@ -521,18 +513,6 @@
+ return retval;
+ }
+
+-static inline void __exit
+-free_pciehp_res(struct pci_resource *res)
+-{
+- struct pci_resource *tres;
+-
+- while (res) {
+- tres = res;
+- res = res->next;
+- kfree(tres);
+- }
+-}
+-
+ static void __exit unload_pciehpd(void)
+ {
+ struct pci_func *next;
+@@ -546,11 +526,6 @@
+ while (ctrl) {
+ cleanup_slots(ctrl);
+
+- free_pciehp_res(ctrl->io_head);
+- free_pciehp_res(ctrl->mem_head);
+- free_pciehp_res(ctrl->p_mem_head);
+- free_pciehp_res(ctrl->bus_head);
+-
+ kfree (ctrl->pci_bus);
+
+ ctrl->hpc_ops->release_ctlr(ctrl);
+@@ -564,11 +539,6 @@
+ for (loop = 0; loop < 256; loop++) {
+ next = pciehp_slot_list[loop];
+ while (next != NULL) {
+- free_pciehp_res(next->io_head);
+- free_pciehp_res(next->mem_head);
+- free_pciehp_res(next->p_mem_head);
+- free_pciehp_res(next->bus_head);
+-
+ TempSlot = next;
+ next = next->next;
+ kfree(TempSlot);
+@@ -652,8 +622,7 @@
+ if (retval) {
+ pciehprm_cleanup();
+ pciehp_event_stop_thread();
+- } else
+- pciehprm_print_pirt();
++ };
+
+ return retval;
+ }
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_ctrl.c 2005-10-27 22:11:49.000000000 -0700
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_ctrl.c 2005-11-02 10:54:23.000000000 -0800
+@@ -42,10 +42,6 @@
+ #include "pciehp.h"
+ #include "pciehprm.h"
+
+-static u32 configure_new_device(struct controller *ctrl, struct pci_func *func,
+- u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev);
+-static int configure_new_function( struct controller *ctrl, struct pci_func *func,
+- u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev);
+ static void interrupt_event_handler(struct controller *ctrl);
+
+ static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */
+@@ -252,627 +248,6 @@
+ return rc;
+ }
+
+-
+-/**
+- * sort_by_size: sort nodes by their length, smallest first.
+- *
+- * @head: list to sort
+- */
+-static int sort_by_size(struct pci_resource **head)
+-{
+- struct pci_resource *current_res;
+- struct pci_resource *next_res;
+- int out_of_order = 1;
+-
+- if (!(*head))
+- return 1;
+-
+- if (!((*head)->next))
+- return 0;
+-
+- while (out_of_order) {
+- out_of_order = 0;
+-
+- /* Special case for swapping list head */
+- if (((*head)->next) &&
+- ((*head)->length > (*head)->next->length)) {
+- out_of_order++;
+- current_res = *head;
+- *head = (*head)->next;
+- current_res->next = (*head)->next;
+- (*head)->next = current_res;
+- }
+-
+- current_res = *head;
+-
+- while (current_res->next && current_res->next->next) {
+- if (current_res->next->length > current_res->next->next->length) {
+- out_of_order++;
+- next_res = current_res->next;
+- current_res->next = current_res->next->next;
+- current_res = current_res->next;
+- next_res->next = current_res->next;
+- current_res->next = next_res;
+- } else
+- current_res = current_res->next;
+- }
+- } /* End of out_of_order loop */
+-
+- return 0;
+-}
+-
+-
+-/*
+- * sort_by_max_size
+- *
+- * Sorts nodes on the list by their length.
+- * Largest first.
+- *
+- */
+-static int sort_by_max_size(struct pci_resource **head)
+-{
+- struct pci_resource *current_res;
+- struct pci_resource *next_res;
+- int out_of_order = 1;
+-
+- if (!(*head))
+- return 1;
+-
+- if (!((*head)->next))
+- return 0;
+-
+- while (out_of_order) {
+- out_of_order = 0;
+-
+- /* Special case for swapping list head */
+- if (((*head)->next) &&
+- ((*head)->length < (*head)->next->length)) {
+- out_of_order++;
+- current_res = *head;
+- *head = (*head)->next;
+- current_res->next = (*head)->next;
+- (*head)->next = current_res;
+- }
+-
+- current_res = *head;
+-
+- while (current_res->next && current_res->next->next) {
+- if (current_res->next->length < current_res->next->next->length) {
+- out_of_order++;
+- next_res = current_res->next;
+- current_res->next = current_res->next->next;
+- current_res = current_res->next;
+- next_res->next = current_res->next;
+- current_res->next = next_res;
+- } else
+- current_res = current_res->next;
+- }
+- } /* End of out_of_order loop */
+-
+- return 0;
+-}
+-
+-
+-/**
+- * do_pre_bridge_resource_split: return one unused resource node
+- * @head: list to scan
+- *
+- */
+-static struct pci_resource *
+-do_pre_bridge_resource_split(struct pci_resource **head,
+- struct pci_resource **orig_head, u32 alignment)
+-{
+- struct pci_resource *prevnode = NULL;
+- struct pci_resource *node;
+- struct pci_resource *split_node;
+- u32 rc;
+- u32 temp_dword;
+- dbg("do_pre_bridge_resource_split\n");
+-
+- if (!(*head) || !(*orig_head))
+- return NULL;
+-
+- rc = pciehp_resource_sort_and_combine(head);
+-
+- if (rc)
+- return NULL;
+-
+- if ((*head)->base != (*orig_head)->base)
+- return NULL;
+-
+- if ((*head)->length == (*orig_head)->length)
+- return NULL;
+-
+-
+- /* If we got here, there the bridge requires some of the resource, but
+- * we may be able to split some off of the front
+- */
+- node = *head;
+-
+- if (node->length & (alignment -1)) {
+- /* this one isn't an aligned length, so we'll make a new entry
+- * and split it up.
+- */
+- split_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+-
+- if (!split_node)
+- return NULL;
+-
+- temp_dword = (node->length | (alignment-1)) + 1 - alignment;
+-
+- split_node->base = node->base;
+- split_node->length = temp_dword;
+-
+- node->length -= temp_dword;
+- node->base += split_node->length;
+-
+- /* Put it in the list */
+- *head = split_node;
+- split_node->next = node;
+- }
+-
+- if (node->length < alignment)
+- return NULL;
+-
+- /* Now unlink it */
+- if (*head == node) {
+- *head = node->next;
+- } else {
+- prevnode = *head;
+- while (prevnode->next != node)
+- prevnode = prevnode->next;
+-
+- prevnode->next = node->next;
+- }
+- node->next = NULL;
+-
+- return node;
+-}
+-
+-
+-/**
+- * do_bridge_resource_split: return one unused resource node
+- * @head: list to scan
+- *
+- */
+-static struct pci_resource *
+-do_bridge_resource_split(struct pci_resource **head, u32 alignment)
+-{
+- struct pci_resource *prevnode = NULL;
+- struct pci_resource *node;
+- u32 rc;
+- u32 temp_dword;
+-
+- if (!(*head))
+- return NULL;
+-
+- rc = pciehp_resource_sort_and_combine(head);
+-
+- if (rc)
+- return NULL;
+-
+- node = *head;
+-
+- while (node->next) {
+- prevnode = node;
+- node = node->next;
+- kfree(prevnode);
+- }
+-
+- if (node->length < alignment) {
+- kfree(node);
+- return NULL;
+- }
+-
+- if (node->base & (alignment - 1)) {
+- /* Short circuit if adjusted size is too small */
+- temp_dword = (node->base | (alignment-1)) + 1;
+- if ((node->length - (temp_dword - node->base)) < alignment) {
+- kfree(node);
+- return NULL;
+- }
+-
+- node->length -= (temp_dword - node->base);
+- node->base = temp_dword;
+- }
+-
+- if (node->length & (alignment - 1)) {
+- /* There's stuff in use after this node */
+- kfree(node);
+- return NULL;
+- }
+-
+- return node;
+-}
+-
+-
+-/*
+- * get_io_resource
+- *
+- * this function sorts the resource list by size and then
+- * returns the first node of "size" length that is not in the
+- * ISA aliasing window. If it finds a node larger than "size"
+- * it will split it up.
+- *
+- * size must be a power of two.
+- */
+-static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size)
+-{
+- struct pci_resource *prevnode;
+- struct pci_resource *node;
+- struct pci_resource *split_node = NULL;
+- u32 temp_dword;
+-
+- if (!(*head))
+- return NULL;
+-
+- if ( pciehp_resource_sort_and_combine(head) )
+- return NULL;
+-
+- if ( sort_by_size(head) )
+- return NULL;
+-
+- for (node = *head; node; node = node->next) {
+- if (node->length < size)
+- continue;
+-
+- if (node->base & (size - 1)) {
+- /* this one isn't base aligned properly
+- so we'll make a new entry and split it up */
+- temp_dword = (node->base | (size-1)) + 1;
+-
+- /*/ Short circuit if adjusted size is too small */
+- if ((node->length - (temp_dword - node->base)) < size)
+- continue;
+-
+- split_node = kmalloc(sizeof(struct pci_resource),
+- GFP_KERNEL);
+-
+- if (!split_node)
+- return NULL;
+-
+- split_node->base = node->base;
+- split_node->length = temp_dword - node->base;
+- node->base = temp_dword;
+- node->length -= split_node->length;
+-
+- /* Put it in the list */
+- split_node->next = node->next;
+- node->next = split_node;
+- } /* End of non-aligned base */
+-
+- /* Don't need to check if too small since we already did */
+- if (node->length > size) {
+- /* this one is longer than we need
+- so we'll make a new entry and split it up */
+- split_node = kmalloc(sizeof(struct pci_resource),
+- GFP_KERNEL);
+-
+- if (!split_node)
+- return NULL;
+-
+- split_node->base = node->base + size;
+- split_node->length = node->length - size;
+- node->length = size;
+-
+- /* Put it in the list */
+- split_node->next = node->next;
+- node->next = split_node;
+- } /* End of too big on top end */
+-
+- /* For IO make sure it's not in the ISA aliasing space */
+- if (node->base & 0x300L)
+- continue;
+-
+- /* If we got here, then it is the right size
+- Now take it out of the list */
+- if (*head == node) {
+- *head = node->next;
+- } else {
+- prevnode = *head;
+- while (prevnode->next != node)
+- prevnode = prevnode->next;
+-
+- prevnode->next = node->next;
+- }
+- node->next = NULL;
+- /* Stop looping */
+- break;
+- }
+-
+- return node;
+-}
+-
+-
+-/*
+- * get_max_resource
+- *
+- * Gets the largest node that is at least "size" big from the
+- * list pointed to by head. It aligns the node on top and bottom
+- * to "size" alignment before returning it.
+- * J.I. modified to put max size limits of; 64M->32M->16M->8M->4M->1M
+- * This is needed to avoid allocating entire ACPI _CRS res to one child bridge/slot.
+- */
+-static struct pci_resource *get_max_resource(struct pci_resource **head, u32 size)
+-{
+- struct pci_resource *max;
+- struct pci_resource *temp;
+- struct pci_resource *split_node;
+- u32 temp_dword;
+- u32 max_size[] = { 0x4000000, 0x2000000, 0x1000000, 0x0800000, 0x0400000, 0x0200000, 0x0100000, 0x00 };
+- int i;
+-
+- if (!(*head))
+- return NULL;
+-
+- if (pciehp_resource_sort_and_combine(head))
+- return NULL;
+-
+- if (sort_by_max_size(head))
+- return NULL;
+-
+- for (max = *head;max; max = max->next) {
+-
+- /* If not big enough we could probably just bail,
+- instead we'll continue to the next. */
+- if (max->length < size)
+- continue;
+-
+- if (max->base & (size - 1)) {
+- /* this one isn't base aligned properly
+- so we'll make a new entry and split it up */
+- temp_dword = (max->base | (size-1)) + 1;
+-
+- /* Short circuit if adjusted size is too small */
+- if ((max->length - (temp_dword - max->base)) < size)
+- continue;
+-
+- split_node = kmalloc(sizeof(struct pci_resource),
+- GFP_KERNEL);
+-
+- if (!split_node)
+- return NULL;
+-
+- split_node->base = max->base;
+- split_node->length = temp_dword - max->base;
+- max->base = temp_dword;
+- max->length -= split_node->length;
+-
+- /* Put it next in the list */
+- split_node->next = max->next;
+- max->next = split_node;
+- }
+-
+- if ((max->base + max->length) & (size - 1)) {
+- /* this one isn't end aligned properly at the top
+- so we'll make a new entry and split it up */
+- split_node = kmalloc(sizeof(struct pci_resource),
+- GFP_KERNEL);
+-
+- if (!split_node)
+- return NULL;
+- temp_dword = ((max->base + max->length) & ~(size - 1));
+- split_node->base = temp_dword;
+- split_node->length = max->length + max->base
+- - split_node->base;
+- max->length -= split_node->length;
+-
+- /* Put it in the list */
+- split_node->next = max->next;
+- max->next = split_node;
+- }
+-
+- /* Make sure it didn't shrink too much when we aligned it */
+- if (max->length < size)
+- continue;
+-
+- for ( i = 0; max_size[i] > size; i++) {
+- if (max->length > max_size[i]) {
+- split_node = kmalloc(sizeof(struct pci_resource),
+- GFP_KERNEL);
+- if (!split_node)
+- break; /* return NULL; */
+- split_node->base = max->base + max_size[i];
+- split_node->length = max->length - max_size[i];
+- max->length = max_size[i];
+- /* Put it next in the list */
+- split_node->next = max->next;
+- max->next = split_node;
+- break;
+- }
+- }
+-
+- /* Now take it out of the list */
+- temp = (struct pci_resource*) *head;
+- if (temp == max) {
+- *head = max->next;
+- } else {
+- while (temp && temp->next != max) {
+- temp = temp->next;
+- }
+-
+- temp->next = max->next;
+- }
+-
+- max->next = NULL;
+- return max;
+- }
+-
+- /* If we get here, we couldn't find one */
+- return NULL;
+-}
+-
+-
+-/*
+- * get_resource
+- *
+- * this function sorts the resource list by size and then
+- * returns the first node of "size" length. If it finds a node
+- * larger than "size" it will split it up.
+- *
+- * size must be a power of two.
+- */
+-static struct pci_resource *get_resource(struct pci_resource **head, u32 size)
+-{
+- struct pci_resource *prevnode;
+- struct pci_resource *node;
+- struct pci_resource *split_node;
+- u32 temp_dword;
+-
+- if (!(*head))
+- return NULL;
+-
+- if ( pciehp_resource_sort_and_combine(head) )
+- return NULL;
+-
+- if ( sort_by_size(head) )
+- return NULL;
+-
+- for (node = *head; node; node = node->next) {
+- dbg("%s: req_size =0x%x node=%p, base=0x%x, length=0x%x\n",
+- __FUNCTION__, size, node, node->base, node->length);
+- if (node->length < size)
+- continue;
+-
+- if (node->base & (size - 1)) {
+- dbg("%s: not aligned\n", __FUNCTION__);
+- /* this one isn't base aligned properly
+- so we'll make a new entry and split it up */
+- temp_dword = (node->base | (size-1)) + 1;
+-
+- /* Short circuit if adjusted size is too small */
+- if ((node->length - (temp_dword - node->base)) < size)
+- continue;
+-
+- split_node = kmalloc(sizeof(struct pci_resource),
+- GFP_KERNEL);
+-
+- if (!split_node)
+- return NULL;
+-
+- split_node->base = node->base;
+- split_node->length = temp_dword - node->base;
+- node->base = temp_dword;
+- node->length -= split_node->length;
+-
+- /* Put it in the list */
+- split_node->next = node->next;
+- node->next = split_node;
+- } /* End of non-aligned base */
+-
+- /* Don't need to check if too small since we already did */
+- if (node->length > size) {
+- dbg("%s: too big\n", __FUNCTION__);
+- /* this one is longer than we need
+- so we'll make a new entry and split it up */
+- split_node = kmalloc(sizeof(struct pci_resource),
+- GFP_KERNEL);
+-
+- if (!split_node)
+- return NULL;
+-
+- split_node->base = node->base + size;
+- split_node->length = node->length - size;
+- node->length = size;
+-
+- /* Put it in the list */
+- split_node->next = node->next;
+- node->next = split_node;
+- } /* End of too big on top end */
+-
+- dbg("%s: got one!!!\n", __FUNCTION__);
+- /* If we got here, then it is the right size
+- Now take it out of the list */
+- if (*head == node) {
+- *head = node->next;
+- } else {
+- prevnode = *head;
+- while (prevnode->next != node)
+- prevnode = prevnode->next;
+-
+- prevnode->next = node->next;
+- }
+- node->next = NULL;
+- /* Stop looping */
+- break;
+- }
+- return node;
+-}
+-
+-
+-/*
+- * pciehp_resource_sort_and_combine
+- *
+- * Sorts all of the nodes in the list in ascending order by
+- * their base addresses. Also does garbage collection by
+- * combining adjacent nodes.
+- *
+- * returns 0 if success
+- */
+-int pciehp_resource_sort_and_combine(struct pci_resource **head)
+-{
+- struct pci_resource *node1;
+- struct pci_resource *node2;
+- int out_of_order = 1;
+-
+- dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head);
+-
+- if (!(*head))
+- return 1;
+-
+- dbg("*head->next = %p\n",(*head)->next);
+-
+- if (!(*head)->next)
+- return 0; /* only one item on the list, already sorted! */
+-
+- dbg("*head->base = 0x%x\n",(*head)->base);
+- dbg("*head->next->base = 0x%x\n",(*head)->next->base);
+- while (out_of_order) {
+- out_of_order = 0;
+-
+- /* Special case for swapping list head */
+- if (((*head)->next) &&
+- ((*head)->base > (*head)->next->base)) {
+- node1 = *head;
+- (*head) = (*head)->next;
+- node1->next = (*head)->next;
+- (*head)->next = node1;
+- out_of_order++;
+- }
+-
+- node1 = (*head);
+-
+- while (node1->next && node1->next->next) {
+- if (node1->next->base > node1->next->next->base) {
+- out_of_order++;
+- node2 = node1->next;
+- node1->next = node1->next->next;
+- node1 = node1->next;
+- node2->next = node1->next;
+- node1->next = node2;
+- } else
+- node1 = node1->next;
+- }
+- } /* End of out_of_order loop */
+-
+- node1 = *head;
+-
+- while (node1 && node1->next) {
+- if ((node1->base + node1->length) == node1->next->base) {
+- /* Combine */
+- dbg("8..\n");
+- node1->length += node1->next->length;
+- node2 = node1->next;
+- node1->next = node1->next->next;
+- kfree(node2);
+- } else
+- node1 = node1->next;
+- }
+-
+- return 0;
+-}
+-
+-
+ /**
+ * pciehp_slot_create - Creates a node and adds it to the proper bus.
+ * @busnumber - bus where new node is to be located
+@@ -926,7 +301,6 @@
+
+ if (next == old_slot) {
+ pciehp_slot_list[old_slot->bus] = old_slot->next;
+- pciehp_destroy_board_resources(old_slot);
+ kfree(old_slot);
+ return 0;
+ }
+@@ -937,7 +311,6 @@
+
+ if (next->next == old_slot) {
+ next->next = old_slot->next;
+- pciehp_destroy_board_resources(old_slot);
+ kfree(old_slot);
+ return 0;
+ } else
+@@ -1103,12 +476,9 @@
+ static u32 board_added(struct pci_func * func, struct controller * ctrl)
+ {
+ u8 hp_slot;
+- int index;
+ u32 temp_register = 0xFFFFFFFF;
+ u32 rc = 0;
+- struct pci_func *new_func = NULL;
+ struct slot *p_slot;
+- struct resource_lists res_lists;
+
+ p_slot = pciehp_find_slot(ctrl, func->device);
+ hp_slot = func->device - ctrl->slot_device_offset;
+@@ -1162,89 +532,43 @@
+ dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register);
+ rc = POWER_FAILURE;
+ func->status = 0;
+- } else {
+- /* Get vendor/device ID u32 */
+- rc = pci_bus_read_config_dword (ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function),
+- PCI_VENDOR_ID, &temp_register);
+- dbg("%s: pci_bus_read_config_dword returns %d\n", __FUNCTION__, rc);
+- dbg("%s: temp_register is %x\n", __FUNCTION__, temp_register);
+-
+- if (rc != 0) {
+- /* Something's wrong here */
+- temp_register = 0xFFFFFFFF;
+- dbg("%s: temp register set to %x by error\n", __FUNCTION__, temp_register);
+- }
+- /* Preset return code. It will be changed later if things go okay. */
+- rc = NO_ADAPTER_PRESENT;
++ goto err_exit;
+ }
+
+- /* All F's is an empty slot or an invalid board */
+- if (temp_register != 0xFFFFFFFF) { /* Check for a board in the slot */
+- res_lists.io_head = ctrl->io_head;
+- res_lists.mem_head = ctrl->mem_head;
+- res_lists.p_mem_head = ctrl->p_mem_head;
+- res_lists.bus_head = ctrl->bus_head;
+- res_lists.irqs = NULL;
+-
+- rc = configure_new_device(ctrl, func, 0, &res_lists, 0, 0);
+- dbg("%s: back from configure_new_device\n", __FUNCTION__);
+-
+- ctrl->io_head = res_lists.io_head;
+- ctrl->mem_head = res_lists.mem_head;
+- ctrl->p_mem_head = res_lists.p_mem_head;
+- ctrl->bus_head = res_lists.bus_head;
+-
+- pciehp_resource_sort_and_combine(&(ctrl->mem_head));
+- pciehp_resource_sort_and_combine(&(ctrl->p_mem_head));
+- pciehp_resource_sort_and_combine(&(ctrl->io_head));
+- pciehp_resource_sort_and_combine(&(ctrl->bus_head));
+-
+- if (rc) {
+- set_slot_off(ctrl, p_slot);
+- return rc;
+- }
+- pciehp_save_slot_config(ctrl, func);
++ rc = pciehp_configure_device(p_slot);
++ if (rc) {
++ err("Cannot add device 0x%x:%x\n", p_slot->bus,
++ p_slot->device);
++ goto err_exit;
++ }
+
+- func->status = 0;
+- func->switch_save = 0x10;
+- func->is_a_board = 0x01;
++ pciehp_save_slot_config(ctrl, func);
++ func->status = 0;
++ func->switch_save = 0x10;
++ func->is_a_board = 0x01;
+
+- /* next, we will instantiate the linux pci_dev structures
+- * (with appropriate driver notification, if already present)
+- */
+- index = 0;
+- do {
+- new_func = pciehp_slot_find(ctrl->slot_bus, func->device, index++);
+- if (new_func && !new_func->pci_dev) {
+- dbg("%s:call pci_hp_configure_dev, func %x\n",
+- __FUNCTION__, index);
+- pciehp_configure_device(ctrl, new_func);
+- }
+- } while (new_func);
++ /*
++ * Some PCI Express root ports require fixup after hot-plug operation.
++ */
++ if (pcie_mch_quirk)
++ pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
++ if (PWR_LED(ctrl->ctrlcap)) {
++ /* Wait for exclusive access to hardware */
++ down(&ctrl->crit_sect);
+
+- /*
+- * Some PCI Express root ports require fixup after hot-plug operation.
+- */
+- if (pcie_mch_quirk)
+- pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
+-
+- if (PWR_LED(ctrl->ctrlcap)) {
+- /* Wait for exclusive access to hardware */
+- down(&ctrl->crit_sect);
+-
+- p_slot->hpc_ops->green_led_on(p_slot);
++ p_slot->hpc_ops->green_led_on(p_slot);
+
+- /* Wait for the command to complete */
+- wait_for_ctrl_irq (ctrl);
++ /* Wait for the command to complete */
++ wait_for_ctrl_irq (ctrl);
+
+- /* Done with exclusive hardware access */
+- up(&ctrl->crit_sect);
+- }
+- } else {
+- set_slot_off(ctrl, p_slot);
+- return -1;
+- }
++ /* Done with exclusive hardware access */
++ up(&ctrl->crit_sect);
++ }
+ return 0;
++
++err_exit:
++ set_slot_off(ctrl, p_slot);
++ return -1;
+ }
+
+
+@@ -1254,13 +578,9 @@
+ */
+ static u32 remove_board(struct pci_func *func, struct controller *ctrl)
+ {
+- int index;
+- u8 skip = 0;
+ u8 device;
+ u8 hp_slot;
+ u32 rc;
+- struct resource_lists res_lists;
+- struct pci_func *temp_func;
+ struct slot *p_slot;
+
+ if (func == NULL)
+@@ -1276,27 +596,6 @@
+
+ dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
+
+- if ((ctrl->add_support) &&
+- !(func->bus_head || func->mem_head || func->p_mem_head || func->io_head)) {
+- /* Here we check to see if we've saved any of the board's
+- * resources already. If so, we'll skip the attempt to
+- * determine what's being used.
+- */
+- index = 0;
+-
+- temp_func = func;
+-
+- while ((temp_func = pciehp_slot_find(temp_func->bus, temp_func->device, index++))) {
+- if (temp_func->bus_head || temp_func->mem_head
+- || temp_func->p_mem_head || temp_func->io_head) {
+- skip = 1;
+- break;
+- }
+- }
+-
+- if (!skip)
+- rc = pciehp_save_used_resources(ctrl, func, DISABLE_CARD);
+- }
+ /* Change status to shutdown */
+ if (func->is_a_board)
+ func->status = 0x01;
+@@ -1330,26 +629,6 @@
+
+ if (ctrl->add_support) {
+ while (func) {
+- res_lists.io_head = ctrl->io_head;
+- res_lists.mem_head = ctrl->mem_head;
+- res_lists.p_mem_head = ctrl->p_mem_head;
+- res_lists.bus_head = ctrl->bus_head;
+-
+- dbg("Returning resources to ctlr lists for (B/D/F) = (%#x/%#x/%#x)\n",
+- func->bus, func->device, func->function);
+-
+- pciehp_return_board_resources(func, &res_lists);
+-
+- ctrl->io_head = res_lists.io_head;
+- ctrl->mem_head = res_lists.mem_head;
+- ctrl->p_mem_head = res_lists.p_mem_head;
+- ctrl->bus_head = res_lists.bus_head;
+-
+- pciehp_resource_sort_and_combine(&(ctrl->mem_head));
+- pciehp_resource_sort_and_combine(&(ctrl->p_mem_head));
+- pciehp_resource_sort_and_combine(&(ctrl->io_head));
+- pciehp_resource_sort_and_combine(&(ctrl->bus_head));
+-
+ if (is_bridge(func)) {
+ dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n",
+ ctrl->seg, func->bus, func->device, func->function);
+@@ -1918,787 +1197,3 @@
+ return rc;
+ }
+
+-
+-/**
+- * configure_new_device - Configures the PCI header information of one board.
+- *
+- * @ctrl: pointer to controller structure
+- * @func: pointer to function structure
+- * @behind_bridge: 1 if this is a recursive call, 0 if not
+- * @resources: pointer to set of resource lists
+- *
+- * Returns 0 if success
+- *
+- */
+-static u32 configure_new_device(struct controller * ctrl, struct pci_func * func,
+- u8 behind_bridge, struct resource_lists * resources, u8 bridge_bus, u8 bridge_dev)
+-{
+- u8 temp_byte, function, max_functions, stop_it;
+- int rc;
+- u32 ID;
+- struct pci_func *new_slot;
+- struct pci_bus lpci_bus, *pci_bus;
+- int index;
+-
+- new_slot = func;
+-
+- dbg("%s\n", __FUNCTION__);
+- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
+- pci_bus = &lpci_bus;
+- pci_bus->number = func->bus;
+-
+- /* Check for Multi-function device */
+- rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte);
+- if (rc) {
+- dbg("%s: rc = %d\n", __FUNCTION__, rc);
+- return rc;
+- }
+-
+- if (temp_byte & 0x80) /* Multi-function device */
+- max_functions = 8;
+- else
+- max_functions = 1;
+-
+- function = 0;
+-
+- do {
+- rc = configure_new_function(ctrl, new_slot, behind_bridge,
+- resources, bridge_bus, bridge_dev);
+-
+- if (rc) {
+- dbg("configure_new_function failed: %d\n", rc);
+- index = 0;
+-
+- while (new_slot) {
+- new_slot = pciehp_slot_find(new_slot->bus,
+- new_slot->device, index++);
+-
+- if (new_slot)
+- pciehp_return_board_resources(new_slot,
+- resources);
+- }
+-
+- return rc;
+- }
+-
+- function++;
+-
+- stop_it = 0;
+-
+- /* The following loop skips to the next present function
+- * and creates a board structure
+- */
+-
+- while ((function < max_functions) && (!stop_it)) {
+- pci_bus_read_config_dword(pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID);
+-
+- if (ID == 0xFFFFFFFF) { /* There's nothing there. */
+- function++;
+- } else { /* There's something there */
+- /* Setup slot structure. */
+- new_slot = pciehp_slot_create(func->bus);
+-
+- if (new_slot == NULL) {
+- /* Out of memory */
+- return 1;
+- }
+-
+- new_slot->bus = func->bus;
+- new_slot->device = func->device;
+- new_slot->function = function;
+- new_slot->is_a_board = 1;
+- new_slot->status = 0;
+-
+- stop_it++;
+- }
+- }
+-
+- } while (function < max_functions);
+- dbg("returning from %s\n", __FUNCTION__);
+-
+- return 0;
+-}
+-
+-/*
+- * Configuration logic that involves the hotplug data structures and
+- * their bookkeeping
+- */
+-
+-/**
+- * configure_bridge: fill bridge's registers, either configure or disable it.
+- */
+-static int
+-configure_bridge(struct pci_bus *pci_bus, unsigned int devfn,
+- struct pci_resource *mem_node,
+- struct pci_resource **hold_mem_node,
+- int base_addr, int limit_addr)
+-{
+- u16 temp_word;
+- u32 rc;
+-
+- if (mem_node) {
+- memcpy(*hold_mem_node, mem_node, sizeof(struct pci_resource));
+- mem_node->next = NULL;
+-
+- /* set Mem base and Limit registers */
+- RES_CHECK(mem_node->base, 16);
+- temp_word = (u16)(mem_node->base >> 16);
+- rc = pci_bus_write_config_word(pci_bus, devfn, base_addr, temp_word);
+-
+- RES_CHECK(mem_node->base + mem_node->length - 1, 16);
+- temp_word = (u16)((mem_node->base + mem_node->length - 1) >> 16);
+- rc = pci_bus_write_config_word(pci_bus, devfn, limit_addr, temp_word);
+- } else {
+- temp_word = 0xFFFF;
+- rc = pci_bus_write_config_word(pci_bus, devfn, base_addr, temp_word);
+-
+- temp_word = 0x0000;
+- rc = pci_bus_write_config_word(pci_bus, devfn, limit_addr, temp_word);
+-
+- kfree(*hold_mem_node);
+- *hold_mem_node = NULL;
+- }
+- return rc;
+-}
+-
+-static int
+-configure_new_bridge(struct controller *ctrl, struct pci_func *func,
+- u8 behind_bridge, struct resource_lists *resources,
+- struct pci_bus *pci_bus)
+-{
+- int cloop;
+- u8 temp_byte;
+- u8 device;
+- u16 temp_word;
+- u32 rc;
+- u32 ID;
+- unsigned int devfn;
+- struct pci_resource *mem_node;
+- struct pci_resource *p_mem_node;
+- struct pci_resource *io_node;
+- struct pci_resource *bus_node;
+- struct pci_resource *hold_mem_node;
+- struct pci_resource *hold_p_mem_node;
+- struct pci_resource *hold_IO_node;
+- struct pci_resource *hold_bus_node;
+- struct irq_mapping irqs;
+- struct pci_func *new_slot;
+- struct resource_lists temp_resources;
+-
+- devfn = PCI_DEVFN(func->device, func->function);
+-
+- /* set Primary bus */
+- dbg("set Primary bus = 0x%x\n", func->bus);
+- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus);
+- if (rc)
+- return rc;
+-
+- /* find range of busses to use */
+- bus_node = get_max_resource(&resources->bus_head, 1L);
+-
+- /* If we don't have any busses to allocate, we can't continue */
+- if (!bus_node) {
+- err("Got NO bus resource to use\n");
+- return -ENOMEM;
+- }
+- dbg("Got ranges of buses to use: base:len=0x%x:%x\n", bus_node->base, bus_node->length);
+-
+- /* set Secondary bus */
+- temp_byte = (u8)bus_node->base;
+- dbg("set Secondary bus = 0x%x\n", temp_byte);
+- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte);
+- if (rc)
+- return rc;
+-
+- /* set subordinate bus */
+- temp_byte = (u8)(bus_node->base + bus_node->length - 1);
+- dbg("set subordinate bus = 0x%x\n", temp_byte);
+- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
+- if (rc)
+- return rc;
+-
+- /* Set HP parameters (Cache Line Size, Latency Timer) */
+- rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_BRIDGE);
+- if (rc)
+- return rc;
+-
+- /* Setup the IO, memory, and prefetchable windows */
+-
+- io_node = get_max_resource(&(resources->io_head), 0x1000L);
+- if (io_node) {
+- dbg("io_node(base, len, next) (%x, %x, %p)\n", io_node->base,
+- io_node->length, io_node->next);
+- }
+-
+- mem_node = get_max_resource(&(resources->mem_head), 0x100000L);
+- if (mem_node) {
+- dbg("mem_node(base, len, next) (%x, %x, %p)\n", mem_node->base,
+- mem_node->length, mem_node->next);
+- }
+-
+- if (resources->p_mem_head)
+- p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000L);
+- else {
+- /*
+- * In some platform implementation, MEM and PMEM are not
+- * distinguished, and hence ACPI _CRS has only MEM entries
+- * for both MEM and PMEM.
+- */
+- dbg("using MEM for PMEM\n");
+- p_mem_node = get_max_resource(&(resources->mem_head), 0x100000L);
+- }
+- if (p_mem_node) {
+- dbg("p_mem_node(base, len, next) (%x, %x, %p)\n", p_mem_node->base,
+- p_mem_node->length, p_mem_node->next);
+- }
+-
+- /* set up the IRQ info */
+- if (!resources->irqs) {
+- irqs.barber_pole = 0;
+- irqs.interrupt[0] = 0;
+- irqs.interrupt[1] = 0;
+- irqs.interrupt[2] = 0;
+- irqs.interrupt[3] = 0;
+- irqs.valid_INT = 0;
+- } else {
+- irqs.barber_pole = resources->irqs->barber_pole;
+- irqs.interrupt[0] = resources->irqs->interrupt[0];
+- irqs.interrupt[1] = resources->irqs->interrupt[1];
+- irqs.interrupt[2] = resources->irqs->interrupt[2];
+- irqs.interrupt[3] = resources->irqs->interrupt[3];
+- irqs.valid_INT = resources->irqs->valid_INT;
+- }
+-
+- /* set up resource lists that are now aligned on top and bottom
+- * for anything behind the bridge.
+- */
+- temp_resources.bus_head = bus_node;
+- temp_resources.io_head = io_node;
+- temp_resources.mem_head = mem_node;
+- temp_resources.p_mem_head = p_mem_node;
+- temp_resources.irqs = &irqs;
+-
+- /* Make copies of the nodes we are going to pass down so that
+- * if there is a problem,we can just use these to free resources
+- */
+- hold_bus_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+- hold_IO_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+- hold_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+- hold_p_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+-
+- if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) {
+- kfree(hold_bus_node);
+- kfree(hold_IO_node);
+- kfree(hold_mem_node);
+- kfree(hold_p_mem_node);
+-
+- return 1;
+- }
+-
+- memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource));
+-
+- bus_node->base += 1;
+- bus_node->length -= 1;
+- bus_node->next = NULL;
+-
+- /* If we have IO resources copy them and fill in the bridge's
+- * IO range registers
+- */
+- if (io_node) {
+- memcpy(hold_IO_node, io_node, sizeof(struct pci_resource));
+- io_node->next = NULL;
+-
+- /* set IO base and Limit registers */
+- RES_CHECK(io_node->base, 8);
+- temp_byte = (u8)(io_node->base >> 8);
+- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte);
+-
+- RES_CHECK(io_node->base + io_node->length - 1, 8);
+- temp_byte = (u8)((io_node->base + io_node->length - 1) >> 8);
+- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
+- } else {
+- kfree(hold_IO_node);
+- hold_IO_node = NULL;
+- }
+-
+- /* If we have memory resources copy them and fill in the bridge's
+- * memory range registers. Otherwise, fill in the range
+- * registers with values that disable them.
+- */
+- rc = configure_bridge(pci_bus, devfn, mem_node, &hold_mem_node,
+- PCI_MEMORY_BASE, PCI_MEMORY_LIMIT);
+-
+- /* If we have prefetchable memory resources copy them and
+- * fill in the bridge's memory range registers. Otherwise,
+- * fill in the range registers with values that disable them.
+- */
+- rc = configure_bridge(pci_bus, devfn, p_mem_node, &hold_p_mem_node,
+- PCI_PREF_MEMORY_BASE, PCI_PREF_MEMORY_LIMIT);
+-
+- /* Adjust this to compensate for extra adjustment in first loop */
+- irqs.barber_pole--;
+-
+- rc = 0;
+-
+- /* Here we actually find the devices and configure them */
+- for (device = 0; (device <= 0x1F) && !rc; device++) {
+- irqs.barber_pole = (irqs.barber_pole + 1) & 0x03;
+-
+- ID = 0xFFFFFFFF;
+- pci_bus->number = hold_bus_node->base;
+- pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);
+- pci_bus->number = func->bus;
+-
+- if (ID != 0xFFFFFFFF) { /* device Present */
+- /* Setup slot structure. */
+- new_slot = pciehp_slot_create(hold_bus_node->base);
+-
+- if (new_slot == NULL) {
+- /* Out of memory */
+- rc = -ENOMEM;
+- continue;
+- }
+-
+- new_slot->bus = hold_bus_node->base;
+- new_slot->device = device;
+- new_slot->function = 0;
+- new_slot->is_a_board = 1;
+- new_slot->status = 0;
+-
+- rc = configure_new_device(ctrl, new_slot, 1,
+- &temp_resources, func->bus,
+- func->device);
+- dbg("configure_new_device rc=0x%x\n",rc);
+- } /* End of IF (device in slot?) */
+- } /* End of FOR loop */
+-
+- if (rc) {
+- pciehp_destroy_resource_list(&temp_resources);
+-
+- return_resource(&(resources->bus_head), hold_bus_node);
+- return_resource(&(resources->io_head), hold_IO_node);
+- return_resource(&(resources->mem_head), hold_mem_node);
+- return_resource(&(resources->p_mem_head), hold_p_mem_node);
+- return(rc);
+- }
+-
+- /* save the interrupt routing information */
+- if (resources->irqs) {
+- resources->irqs->interrupt[0] = irqs.interrupt[0];
+- resources->irqs->interrupt[1] = irqs.interrupt[1];
+- resources->irqs->interrupt[2] = irqs.interrupt[2];
+- resources->irqs->interrupt[3] = irqs.interrupt[3];
+- resources->irqs->valid_INT = irqs.valid_INT;
+- } else if (!behind_bridge) {
+- /* We need to hook up the interrupts here */
+- for (cloop = 0; cloop < 4; cloop++) {
+- if (irqs.valid_INT & (0x01 << cloop)) {
+- rc = pciehp_set_irq(func->bus, func->device,
+- 0x0A + cloop, irqs.interrupt[cloop]);
+- if (rc) {
+- pciehp_destroy_resource_list (&temp_resources);
+- return_resource(&(resources->bus_head), hold_bus_node);
+- return_resource(&(resources->io_head), hold_IO_node);
+- return_resource(&(resources->mem_head), hold_mem_node);
+- return_resource(&(resources->p_mem_head), hold_p_mem_node);
+- return rc;
+- }
+- }
+- } /* end of for loop */
+- }
+-
+- /* Return unused bus resources
+- * First use the temporary node to store information for the board
+- */
+- if (hold_bus_node && bus_node && temp_resources.bus_head) {
+- hold_bus_node->length = bus_node->base - hold_bus_node->base;
+-
+- hold_bus_node->next = func->bus_head;
+- func->bus_head = hold_bus_node;
+-
+- temp_byte = (u8)(temp_resources.bus_head->base - 1);
+-
+- /* set subordinate bus */
+- dbg("re-set subordinate bus = 0x%x\n", temp_byte);
+- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
+-
+- if (temp_resources.bus_head->length == 0) {
+- kfree(temp_resources.bus_head);
+- temp_resources.bus_head = NULL;
+- } else {
+- dbg("return bus res of b:d(0x%x:%x) base:len(0x%x:%x)\n",
+- func->bus, func->device, temp_resources.bus_head->base, temp_resources.bus_head->length);
+- return_resource(&(resources->bus_head), temp_resources.bus_head);
+- }
+- }
+-
+- /* If we have IO space available and there is some left,
+- * return the unused portion
+- */
+- if (hold_IO_node && temp_resources.io_head) {
+- io_node = do_pre_bridge_resource_split(&(temp_resources.io_head),
+- &hold_IO_node, 0x1000);
+-
+- /* Check if we were able to split something off */
+- if (io_node) {
+- hold_IO_node->base = io_node->base + io_node->length;
+-
+- RES_CHECK(hold_IO_node->base, 8);
+- temp_byte = (u8)((hold_IO_node->base) >> 8);
+- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte);
+-
+- return_resource(&(resources->io_head), io_node);
+- }
+-
+- io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000);
+-
+- /* Check if we were able to split something off */
+- if (io_node) {
+- /* First use the temporary node to store information for the board */
+- hold_IO_node->length = io_node->base - hold_IO_node->base;
+-
+- /* If we used any, add it to the board's list */
+- if (hold_IO_node->length) {
+- hold_IO_node->next = func->io_head;
+- func->io_head = hold_IO_node;
+-
+- RES_CHECK(io_node->base - 1, 8);
+- temp_byte = (u8)((io_node->base - 1) >> 8);
+- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
+-
+- return_resource(&(resources->io_head), io_node);
+- } else {
+- /* it doesn't need any IO */
+- temp_byte = 0x00;
+- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
+-
+- return_resource(&(resources->io_head), io_node);
+- kfree(hold_IO_node);
+- }
+- } else {
+- /* it used most of the range */
+- hold_IO_node->next = func->io_head;
+- func->io_head = hold_IO_node;
+- }
+- } else if (hold_IO_node) {
+- /* it used the whole range */
+- hold_IO_node->next = func->io_head;
+- func->io_head = hold_IO_node;
+- }
+-
+- /* If we have memory space available and there is some left,
+- * return the unused portion
+- */
+- if (hold_mem_node && temp_resources.mem_head) {
+- mem_node = do_pre_bridge_resource_split(&(temp_resources.mem_head), &hold_mem_node, 0x100000L);
+-
+- /* Check if we were able to split something off */
+- if (mem_node) {
+- hold_mem_node->base = mem_node->base + mem_node->length;
+-
+- RES_CHECK(hold_mem_node->base, 16);
+- temp_word = (u16)((hold_mem_node->base) >> 16);
+- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+-
+- return_resource(&(resources->mem_head), mem_node);
+- }
+-
+- mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000L);
+-
+- /* Check if we were able to split something off */
+- if (mem_node) {
+- /* First use the temporary node to store information for the board */
+- hold_mem_node->length = mem_node->base - hold_mem_node->base;
+-
+- if (hold_mem_node->length) {
+- hold_mem_node->next = func->mem_head;
+- func->mem_head = hold_mem_node;
+-
+- /* configure end address */
+- RES_CHECK(mem_node->base - 1, 16);
+- temp_word = (u16)((mem_node->base - 1) >> 16);
+- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+-
+- /* Return unused resources to the pool */
+- return_resource(&(resources->mem_head), mem_node);
+- } else {
+- /* it doesn't need any Mem */
+- temp_word = 0x0000;
+- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+-
+- return_resource(&(resources->mem_head), mem_node);
+- kfree(hold_mem_node);
+- }
+- } else {
+- /* it used most of the range */
+- hold_mem_node->next = func->mem_head;
+- func->mem_head = hold_mem_node;
+- }
+- } else if (hold_mem_node) {
+- /* it used the whole range */
+- hold_mem_node->next = func->mem_head;
+- func->mem_head = hold_mem_node;
+- }
+-
+- /* If we have prefetchable memory space available and there is some
+- * left at the end, return the unused portion
+- */
+- if (hold_p_mem_node && temp_resources.p_mem_head) {
+- p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head),
+- &hold_p_mem_node, 0x100000L);
+-
+- /* Check if we were able to split something off */
+- if (p_mem_node) {
+- hold_p_mem_node->base = p_mem_node->base + p_mem_node->length;
+-
+- RES_CHECK(hold_p_mem_node->base, 16);
+- temp_word = (u16)((hold_p_mem_node->base) >> 16);
+- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
+-
+- return_resource(&(resources->p_mem_head), p_mem_node);
+- }
+-
+- p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000L);
+-
+- /* Check if we were able to split something off */
+- if (p_mem_node) {
+- /* First use the temporary node to store information for the board */
+- hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base;
+-
+- /* If we used any, add it to the board's list */
+- if (hold_p_mem_node->length) {
+- hold_p_mem_node->next = func->p_mem_head;
+- func->p_mem_head = hold_p_mem_node;
+-
+- RES_CHECK(p_mem_node->base - 1, 16);
+- temp_word = (u16)((p_mem_node->base - 1) >> 16);
+- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+-
+- return_resource(&(resources->p_mem_head), p_mem_node);
+- } else {
+- /* it doesn't need any PMem */
+- temp_word = 0x0000;
+- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+-
+- return_resource(&(resources->p_mem_head), p_mem_node);
+- kfree(hold_p_mem_node);
+- }
+- } else {
+- /* it used the most of the range */
+- hold_p_mem_node->next = func->p_mem_head;
+- func->p_mem_head = hold_p_mem_node;
+- }
+- } else if (hold_p_mem_node) {
+- /* it used the whole range */
+- hold_p_mem_node->next = func->p_mem_head;
+- func->p_mem_head = hold_p_mem_node;
+- }
+-
+- /* We should be configuring an IRQ and the bridge's base address
+- * registers if it needs them. Although we have never seen such
+- * a device
+- */
+-
+- pciehprm_enable_card(ctrl, func, PCI_HEADER_TYPE_BRIDGE);
+-
+- dbg("PCI Bridge Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function);
+-
+- return rc;
+-}
+-
+-/**
+- * configure_new_function - Configures the PCI header information of one device
+- *
+- * @ctrl: pointer to controller structure
+- * @func: pointer to function structure
+- * @behind_bridge: 1 if this is a recursive call, 0 if not
+- * @resources: pointer to set of resource lists
+- *
+- * Calls itself recursively for bridged devices.
+- * Returns 0 if success
+- *
+- */
+-static int
+-configure_new_function(struct controller *ctrl, struct pci_func *func,
+- u8 behind_bridge, struct resource_lists *resources,
+- u8 bridge_bus, u8 bridge_dev)
+-{
+- int cloop;
+- u8 temp_byte;
+- u8 class_code;
+- u32 rc;
+- u32 temp_register;
+- u32 base;
+- unsigned int devfn;
+- struct pci_resource *mem_node;
+- struct pci_resource *io_node;
+- struct pci_bus lpci_bus, *pci_bus;
+-
+- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
+- pci_bus = &lpci_bus;
+- pci_bus->number = func->bus;
+- devfn = PCI_DEVFN(func->device, func->function);
+-
+- /* Check for Bridge */
+- rc = pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte);
+- if (rc)
+- return rc;
+- dbg("%s: bus %x dev %x func %x temp_byte = %x\n", __FUNCTION__,
+- func->bus, func->device, func->function, temp_byte);
+-
+- if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
+- rc = configure_new_bridge(ctrl, func, behind_bridge, resources,
+- pci_bus);
+-
+- if (rc)
+- return rc;
+- } else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
+- /* Standard device */
+- u64 base64;
+- rc = pci_bus_read_config_byte(pci_bus, devfn, 0x0B, &class_code);
+-
+- if (class_code == PCI_BASE_CLASS_DISPLAY)
+- return DEVICE_TYPE_NOT_SUPPORTED;
+-
+- /* Figure out IO and memory needs */
+- for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
+- temp_register = 0xFFFFFFFF;
+-
+- rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
+- rc = pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);
+- dbg("Bar[%x]=0x%x on bus:dev:func(0x%x:%x:%x)\n", cloop, temp_register,
+- func->bus, func->device, func->function);
+-
+- if (!temp_register)
+- continue;
+-
+- base64 = 0L;
+- if (temp_register & PCI_BASE_ADDRESS_SPACE_IO) {
+- /* Map IO */
+-
+- /* set base = amount of IO space */
+- base = temp_register & 0xFFFFFFFC;
+- base = ~base + 1;
+-
+- dbg("NEED IO length(0x%x)\n", base);
+- io_node = get_io_resource(&(resources->io_head),(ulong)base);
+-
+- /* allocate the resource to the board */
+- if (io_node) {
+- dbg("Got IO base=0x%x(length=0x%x)\n", io_node->base, io_node->length);
+- base = (u32)io_node->base;
+- io_node->next = func->io_head;
+- func->io_head = io_node;
+- } else {
+- err("Got NO IO resource(length=0x%x)\n", base);
+- return -ENOMEM;
+- }
+- } else { /* map MEM */
+- int prefetchable = 1;
+- struct pci_resource **res_node = &func->p_mem_head;
+- char *res_type_str = "PMEM";
+- u32 temp_register2;
+-
+- if (!(temp_register & PCI_BASE_ADDRESS_MEM_PREFETCH)) {
+- prefetchable = 0;
+- res_node = &func->mem_head;
+- res_type_str++;
+- }
+-
+- base = temp_register & 0xFFFFFFF0;
+- base = ~base + 1;
+-
+- switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
+- case PCI_BASE_ADDRESS_MEM_TYPE_32:
+- dbg("NEED 32 %s bar=0x%x(length=0x%x)\n", res_type_str, temp_register, base);
+-
+- if (prefetchable && resources->p_mem_head)
+- mem_node=get_resource(&(resources->p_mem_head), (ulong)base);
+- else {
+- if (prefetchable)
+- dbg("using MEM for PMEM\n");
+- mem_node = get_resource(&(resources->mem_head), (ulong)base);
+- }
+-
+- /* allocate the resource to the board */
+- if (mem_node) {
+- base = (u32)mem_node->base;
+- mem_node->next = *res_node;
+- *res_node = mem_node;
+- dbg("Got 32 %s base=0x%x(length=0x%x)\n", res_type_str, mem_node->base,
+- mem_node->length);
+- } else {
+- err("Got NO 32 %s resource(length=0x%x)\n", res_type_str, base);
+- return -ENOMEM;
+- }
+- break;
+- case PCI_BASE_ADDRESS_MEM_TYPE_64:
+- rc = pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
+- dbg("NEED 64 %s bar=0x%x:%x(length=0x%x)\n", res_type_str, temp_register2,
+- temp_register, base);
+-
+- if (prefetchable && resources->p_mem_head)
+- mem_node = get_resource(&(resources->p_mem_head), (ulong)base);
+- else {
+- if (prefetchable)
+- dbg("using MEM for PMEM\n");
+- mem_node = get_resource(&(resources->mem_head), (ulong)base);
+- }
+-
+- /* allocate the resource to the board */
+- if (mem_node) {
+- base64 = mem_node->base;
+- mem_node->next = *res_node;
+- *res_node = mem_node;
+- dbg("Got 64 %s base=0x%x:%x(length=%x)\n", res_type_str, (u32)(base64 >> 32),
+- (u32)base64, mem_node->length);
+- } else {
+- err("Got NO 64 %s resource(length=0x%x)\n", res_type_str, base);
+- return -ENOMEM;
+- }
+- break;
+- default:
+- dbg("reserved BAR type=0x%x\n", temp_register);
+- break;
+- }
+-
+- }
+-
+- if (base64) {
+- rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64);
+- cloop += 4;
+- base64 >>= 32;
+-
+- if (base64) {
+- dbg("%s: high dword of base64(0x%x) set to 0\n", __FUNCTION__, (u32)base64);
+- base64 = 0x0L;
+- }
+-
+- rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64);
+- } else {
+- rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, base);
+- }
+- } /* End of base register loop */
+-
+- /* disable ROM base Address */
+- rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00);
+-
+- /* Set HP parameters (Cache Line Size, Latency Timer) */
+- rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL);
+- if (rc)
+- return rc;
+-
+- pciehprm_enable_card(ctrl, func, PCI_HEADER_TYPE_NORMAL);
+-
+- dbg("PCI function Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device,
+- func->function);
+- } /* End of Not-A-Bridge else */
+- else {
+- /* It's some strange type of PCI adapter (Cardbus?) */
+- return DEVICE_TYPE_NOT_SUPPORTED;
+- }
+-
+- func->configured = 1;
+-
+- return 0;
+-}
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_pci.c 2005-11-02 09:25:02.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_pci.c 2005-11-02 10:55:54.000000000 -0800
+@@ -37,47 +37,70 @@
+ #include <linux/pci.h>
+ #include "../pci.h"
+ #include "pciehp.h"
+-#ifndef CONFIG_IA64
+-#include "../../../arch/i386/pci/pci.h" /* horrible hack showing how processor dependant we are... */
+-#endif
+
+
+-int pciehp_configure_device (struct controller* ctrl, struct pci_func* func)
++int pciehp_configure_device(struct slot *p_slot)
+ {
+- unsigned char bus;
+- struct pci_bus *child;
+- int num;
+-
+- if (func->pci_dev == NULL)
+- func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
+-
+- /* Still NULL ? Well then scan for it ! */
+- if (func->pci_dev == NULL) {
+- dbg("%s: pci_dev still null. do pci_scan_slot\n", __FUNCTION__);
+-
+- num = pci_scan_slot(ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function));
+-
+- if (num)
+- pci_bus_add_devices(ctrl->pci_dev->subordinate);
+-
+- func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
+- if (func->pci_dev == NULL) {
+- dbg("ERROR: pci_dev still null\n");
+- return 0;
+- }
++ struct pci_dev *dev;
++ struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
++ int num, fn;
++
++ dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0));
++ if (dev) {
++ err("Device %s already exists at %x:%x, cannot hot-add\n",
++ pci_name(dev), p_slot->bus, p_slot->device);
++ return -EINVAL;
+ }
+
+- if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+- pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus);
+- child = pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus);
+- pci_do_scan_bus(child);
++ num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0));
++ if (num == 0) {
++ err("No new device found\n");
++ return -ENODEV;
++ }
+
++ for (fn = 0; fn < 8; fn++) {
++ if (!(dev = pci_find_slot(p_slot->bus,
++ PCI_DEVFN(p_slot->device, fn))))
++ continue;
++ if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
++ err("Cannot hot-add display device %s\n",
++ pci_name(dev));
++ continue;
++ }
++ if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
++ (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
++ /* Find an unused bus number for the new bridge */
++ struct pci_bus *child;
++ unsigned char busnr, start = parent->secondary;
++ unsigned char end = parent->subordinate;
++ for (busnr = start; busnr <= end; busnr++) {
++ if (!pci_find_bus(pci_domain_nr(parent),
++ busnr))
++ break;
++ }
++ if (busnr >= end) {
++ err("No free bus for hot-added bridge\n");
++ continue;
++ }
++ child = pci_add_new_bus(parent, dev, busnr);
++ if (!child) {
++ err("Cannot add new bus for %s\n",
++ pci_name(dev));
++ continue;
++ }
++ child->subordinate = pci_do_scan_bus(child);
++ pci_bus_size_bridges(child);
++ }
++ /* TBD: program firmware provided _HPP values */
++ /* program_fw_provided_values(dev); */
+ }
+
++ pci_bus_assign_resources(parent);
++ pci_bus_add_devices(parent);
++ pci_enable_bridges(parent);
+ return 0;
+ }
+
+-
+ int pciehp_unconfigure_device(struct pci_func* func)
+ {
+ int rc = 0;
+@@ -105,47 +128,6 @@
+ }
+
+ /*
+- * pciehp_set_irq
+- *
+- * @bus_num: bus number of PCI device
+- * @dev_num: device number of PCI device
+- * @slot: pointer to u8 where slot number will be returned
+- */
+-int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
+-{
+-#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_IO_APIC)
+- int rc;
+- u16 temp_word;
+- struct pci_dev fakedev;
+- struct pci_bus fakebus;
+-
+- fakedev.devfn = dev_num << 3;
+- fakedev.bus = &fakebus;
+- fakebus.number = bus_num;
+- dbg("%s: dev %d, bus %d, pin %d, num %d\n",
+- __FUNCTION__, dev_num, bus_num, int_pin, irq_num);
+- rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num);
+- dbg("%s: rc %d\n", __FUNCTION__, rc);
+- if (!rc)
+- return !rc;
+-
+- /* set the Edge Level Control Register (ELCR) */
+- temp_word = inb(0x4d0);
+- temp_word |= inb(0x4d1) << 8;
+-
+- temp_word |= 0x01 << irq_num;
+-
+- /* This should only be for x86 as it sets the Edge Level Control Register */
+- outb((u8) (temp_word & 0xFF), 0x4d0);
+- outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1);
+-#endif
+- return 0;
+-}
+-
+-/* More PCI configuration routines; this time centered around hotplug controller */
+-
+-
+-/*
+ * pciehp_save_config
+ *
+ * Reads configuration for all slots in a PCI bus and saves info.
+@@ -462,366 +444,3 @@
+ return 0;
+ }
+
+-
+-/*
+- * pciehp_save_used_resources
+- *
+- * Stores used resource information for existing boards. this is
+- * for boards that were in the system when this driver was loaded.
+- * this function is for hot plug ADD
+- *
+- * returns 0 if success
+- * if disable == 1(DISABLE_CARD),
+- * it loops for all functions of the slot and disables them.
+- * else, it just get resources of the function and return.
+- */
+-int pciehp_save_used_resources(struct controller *ctrl, struct pci_func *func, int disable)
+-{
+- u8 cloop;
+- u8 header_type;
+- u8 secondary_bus;
+- u8 temp_byte;
+- u16 command;
+- u16 save_command;
+- u16 w_base, w_length;
+- u32 temp_register;
+- u32 save_base;
+- u32 base, length;
+- u64 base64 = 0;
+- int index = 0;
+- unsigned int devfn;
+- struct pci_resource *mem_node = NULL;
+- struct pci_resource *p_mem_node = NULL;
+- struct pci_resource *t_mem_node;
+- struct pci_resource *io_node;
+- struct pci_resource *bus_node;
+- struct pci_bus lpci_bus, *pci_bus;
+- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
+- pci_bus = &lpci_bus;
+-
+- if (disable)
+- func = pciehp_slot_find(func->bus, func->device, index++);
+-
+- while ((func != NULL) && func->is_a_board) {
+- pci_bus->number = func->bus;
+- devfn = PCI_DEVFN(func->device, func->function);
+-
+- /* Save the command register */
+- pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command);
+-
+- if (disable) {
+- /* disable card */
+- command = 0x00;
+- pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
+- }
+-
+- /* Check for Bridge */
+- pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
+-
+- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
+- dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n",
+- func->bus, func->device, save_command);
+- if (disable) {
+- /* Clear Bridge Control Register */
+- command = 0x00;
+- pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
+- }
+-
+- pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
+- pci_bus_read_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte);
+-
+- bus_node = kmalloc(sizeof(struct pci_resource),
+- GFP_KERNEL);
+- if (!bus_node)
+- return -ENOMEM;
+-
+- bus_node->base = (ulong)secondary_bus;
+- bus_node->length = (ulong)(temp_byte - secondary_bus + 1);
+-
+- bus_node->next = func->bus_head;
+- func->bus_head = bus_node;
+-
+- /* Save IO base and Limit registers */
+- pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &temp_byte);
+- base = temp_byte;
+- pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &temp_byte);
+- length = temp_byte;
+-
+- if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) {
+- io_node = kmalloc(sizeof(struct pci_resource),
+- GFP_KERNEL);
+- if (!io_node)
+- return -ENOMEM;
+-
+- io_node->base = (ulong)(base & PCI_IO_RANGE_MASK) << 8;
+- io_node->length = (ulong)(length - base + 0x10) << 8;
+-
+- io_node->next = func->io_head;
+- func->io_head = io_node;
+- }
+-
+- /* Save memory base and Limit registers */
+- pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
+- pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);
+-
+- if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
+- mem_node = kmalloc(sizeof(struct pci_resource),
+- GFP_KERNEL);
+- if (!mem_node)
+- return -ENOMEM;
+-
+- mem_node->base = (ulong)w_base << 16;
+- mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
+-
+- mem_node->next = func->mem_head;
+- func->mem_head = mem_node;
+- }
+- /* Save prefetchable memory base and Limit registers */
+- pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
+- pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);
+-
+- if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
+- p_mem_node = kmalloc(sizeof(struct pci_resource),
+- GFP_KERNEL);
+- if (!p_mem_node)
+- return -ENOMEM;
+-
+- p_mem_node->base = (ulong)w_base << 16;
+- p_mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
+-
+- p_mem_node->next = func->p_mem_head;
+- func->p_mem_head = p_mem_node;
+- }
+- } else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
+- dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n",
+- func->bus, func->device, save_command);
+-
+- /* Figure out IO and memory base lengths */
+- for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
+- pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base);
+-
+- temp_register = 0xFFFFFFFF;
+- pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
+- pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);
+-
+- if (!disable)
+- pci_bus_write_config_dword(pci_bus, devfn, cloop, save_base);
+-
+- if (!temp_register)
+- continue;
+-
+- base = temp_register;
+-
+- if ((base & PCI_BASE_ADDRESS_SPACE_IO) &&
+- (!disable || (save_command & PCI_COMMAND_IO))) {
+- /* IO base */
+- /* set temp_register = amount of IO space requested */
+- base = base & 0xFFFFFFFCL;
+- base = (~base) + 1;
+-
+- io_node = kmalloc(sizeof (struct pci_resource),
+- GFP_KERNEL);
+- if (!io_node)
+- return -ENOMEM;
+-
+- io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK;
+- io_node->length = (ulong)base;
+- dbg("sur adapter: IO bar=0x%x(length=0x%x)\n",
+- io_node->base, io_node->length);
+-
+- io_node->next = func->io_head;
+- func->io_head = io_node;
+- } else { /* map Memory */
+- int prefetchable = 1;
+- /* struct pci_resources **res_node; */
+- char *res_type_str = "PMEM";
+- u32 temp_register2;
+-
+- t_mem_node = kmalloc(sizeof (struct pci_resource),
+- GFP_KERNEL);
+- if (!t_mem_node)
+- return -ENOMEM;
+-
+- if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
+- (!disable || (save_command & PCI_COMMAND_MEMORY))) {
+- prefetchable = 0;
+- mem_node = t_mem_node;
+- res_type_str++;
+- } else
+- p_mem_node = t_mem_node;
+-
+- base = base & 0xFFFFFFF0L;
+- base = (~base) + 1;
+-
+- switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
+- case PCI_BASE_ADDRESS_MEM_TYPE_32:
+- if (prefetchable) {
+- p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
+- p_mem_node->length = (ulong)base;
+- dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
+- res_type_str,
+- p_mem_node->base,
+- p_mem_node->length);
+-
+- p_mem_node->next = func->p_mem_head;
+- func->p_mem_head = p_mem_node;
+- } else {
+- mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
+- mem_node->length = (ulong)base;
+- dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
+- res_type_str,
+- mem_node->base,
+- mem_node->length);
+-
+- mem_node->next = func->mem_head;
+- func->mem_head = mem_node;
+- }
+- break;
+- case PCI_BASE_ADDRESS_MEM_TYPE_64:
+- pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
+- base64 = temp_register2;
+- base64 = (base64 << 32) | save_base;
+-
+- if (temp_register2) {
+- dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n",
+- res_type_str, temp_register2, (u32)base64);
+- base64 &= 0x00000000FFFFFFFFL;
+- }
+-
+- if (prefetchable) {
+- p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
+- p_mem_node->length = base;
+- dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
+- res_type_str,
+- p_mem_node->base,
+- p_mem_node->length);
+-
+- p_mem_node->next = func->p_mem_head;
+- func->p_mem_head = p_mem_node;
+- } else {
+- mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
+- mem_node->length = base;
+- dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
+- res_type_str,
+- mem_node->base,
+- mem_node->length);
+-
+- mem_node->next = func->mem_head;
+- func->mem_head = mem_node;
+- }
+- cloop += 4;
+- break;
+- default:
+- dbg("asur: reserved BAR type=0x%x\n",
+- temp_register);
+- break;
+- }
+- }
+- } /* End of base register loop */
+- } else { /* Some other unknown header type */
+- dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n",
+- func->bus, func->device);
+- }
+-
+- /* find the next device in this slot */
+- if (!disable)
+- break;
+- func = pciehp_slot_find(func->bus, func->device, index++);
+- }
+-
+- return 0;
+-}
+-
+-
+-/**
+- * kfree_resource_list: release memory of all list members
+- * @res: resource list to free
+- */
+-static inline void
+-return_resource_list(struct pci_resource **func, struct pci_resource **res)
+-{
+- struct pci_resource *node;
+- struct pci_resource *t_node;
+-
+- node = *func;
+- *func = NULL;
+- while (node) {
+- t_node = node->next;
+- return_resource(res, node);
+- node = t_node;
+- }
+-}
+-
+-/*
+- * pciehp_return_board_resources
+- *
+- * this routine returns all resources allocated to a board to
+- * the available pool.
+- *
+- * returns 0 if success
+- */
+-int pciehp_return_board_resources(struct pci_func * func,
+- struct resource_lists * resources)
+-{
+- int rc;
+-
+- dbg("%s\n", __FUNCTION__);
+-
+- if (!func)
+- return 1;
+-
+- return_resource_list(&(func->io_head),&(resources->io_head));
+- return_resource_list(&(func->mem_head),&(resources->mem_head));
+- return_resource_list(&(func->p_mem_head),&(resources->p_mem_head));
+- return_resource_list(&(func->bus_head),&(resources->bus_head));
+-
+- rc = pciehp_resource_sort_and_combine(&(resources->mem_head));
+- rc |= pciehp_resource_sort_and_combine(&(resources->p_mem_head));
+- rc |= pciehp_resource_sort_and_combine(&(resources->io_head));
+- rc |= pciehp_resource_sort_and_combine(&(resources->bus_head));
+-
+- return rc;
+-}
+-
+-/**
+- * kfree_resource_list: release memory of all list members
+- * @res: resource list to free
+- */
+-static inline void
+-kfree_resource_list(struct pci_resource **r)
+-{
+- struct pci_resource *res, *tres;
+-
+- res = *r;
+- *r = NULL;
+-
+- while (res) {
+- tres = res;
+- res = res->next;
+- kfree(tres);
+- }
+-}
+-
+-/**
+- * pciehp_destroy_resource_list: put node back in the resource list
+- * @resources: list to put nodes back
+- */
+-void pciehp_destroy_resource_list(struct resource_lists * resources)
+-{
+- kfree_resource_list(&(resources->io_head));
+- kfree_resource_list(&(resources->mem_head));
+- kfree_resource_list(&(resources->p_mem_head));
+- kfree_resource_list(&(resources->bus_head));
+-}
+-
+-/**
+- * pciehp_destroy_board_resources: put node back in the resource list
+- * @resources: list to put nodes back
+- */
+-void pciehp_destroy_board_resources(struct pci_func * func)
+-{
+- kfree_resource_list(&(func->io_head));
+- kfree_resource_list(&(func->mem_head));
+- kfree_resource_list(&(func->p_mem_head));
+- kfree_resource_list(&(func->bus_head));
+-}
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehprm_acpi.c 2005-10-27 22:11:49.000000000 -0700
++++ gregkh-2.6/drivers/pci/hotplug/pciehprm_acpi.c 2005-11-02 10:54:23.000000000 -0800
+@@ -35,9 +35,6 @@
+ #include <linux/pci-acpi.h>
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+-#ifdef CONFIG_IA64
+-#include <asm/iosapic.h>
+-#endif
+ #include <acpi/acpi.h>
+ #include <acpi/acpi_bus.h>
+ #include <acpi/actypes.h>
+@@ -84,10 +81,6 @@
+ int dev;
+ int fun;
+ u32 sun;
+- struct pci_resource *mem_head;
+- struct pci_resource *p_mem_head;
+- struct pci_resource *io_head;
+- struct pci_resource *bus_head;
+ void *slot_ops; /* _STA, _EJx, etc */
+ struct slot *slot;
+ }; /* per func */
+@@ -104,14 +97,6 @@
+ int bus; /* pdev->subordinate->number */
+ struct acpi__hpp *_hpp;
+ struct acpi_php_slot *slots;
+- struct pci_resource *tmem_head; /* total from crs */
+- struct pci_resource *tp_mem_head; /* total from crs */
+- struct pci_resource *tio_head; /* total from crs */
+- struct pci_resource *tbus_head; /* total from crs */
+- struct pci_resource *mem_head; /* available */
+- struct pci_resource *p_mem_head; /* available */
+- struct pci_resource *io_head; /* available */
+- struct pci_resource *bus_head; /* available */
+ int scanned;
+ int type;
+ };
+@@ -268,485 +253,6 @@
+ return oshp_run_status;
+ }
+
+-static acpi_status acpi_evaluate_crs(
+- acpi_handle handle,
+- struct acpi_resource **retbuf
+- )
+-{
+- acpi_status status;
+- struct acpi_buffer crsbuf;
+- u8 *path_name = acpi_path_name(handle);
+-
+- crsbuf.length = 0;
+- crsbuf.pointer = NULL;
+-
+- status = acpi_get_current_resources (handle, &crsbuf);
+-
+- switch (status) {
+- case AE_BUFFER_OVERFLOW:
+- break; /* found */
+- case AE_NOT_FOUND:
+- dbg("acpi_pciehprm:%s _CRS not found\n", path_name);
+- return status;
+- default:
+- err ("acpi_pciehprm:%s _CRS fail=0x%x\n", path_name, status);
+- return status;
+- }
+-
+- crsbuf.pointer = kmalloc (crsbuf.length, GFP_KERNEL);
+- if (!crsbuf.pointer) {
+- err ("acpi_pciehprm: alloc %ld bytes for %s _CRS fail\n", (ulong)crsbuf.length, path_name);
+- return AE_NO_MEMORY;
+- }
+-
+- status = acpi_get_current_resources (handle, &crsbuf);
+- if (ACPI_FAILURE(status)) {
+- err("acpi_pciehprm: %s _CRS fail=0x%x.\n", path_name, status);
+- kfree(crsbuf.pointer);
+- return status;
+- }
+-
+- *retbuf = crsbuf.pointer;
+-
+- return status;
+-}
+-
+-static void free_pci_resource ( struct pci_resource *aprh)
+-{
+- struct pci_resource *res, *next;
+-
+- for (res = aprh; res; res = next) {
+- next = res->next;
+- kfree(res);
+- }
+-}
+-
+-static void print_pci_resource ( struct pci_resource *aprh)
+-{
+- struct pci_resource *res;
+-
+- for (res = aprh; res; res = res->next)
+- dbg(" base= 0x%x length= 0x%x\n", res->base, res->length);
+-}
+-
+-static void print_slot_resources( struct acpi_php_slot *aps)
+-{
+- if (aps->bus_head) {
+- dbg(" BUS Resources:\n");
+- print_pci_resource (aps->bus_head);
+- }
+-
+- if (aps->io_head) {
+- dbg(" IO Resources:\n");
+- print_pci_resource (aps->io_head);
+- }
+-
+- if (aps->mem_head) {
+- dbg(" MEM Resources:\n");
+- print_pci_resource (aps->mem_head);
+- }
+-
+- if (aps->p_mem_head) {
+- dbg(" PMEM Resources:\n");
+- print_pci_resource (aps->p_mem_head);
+- }
+-}
+-
+-static void print_pci_resources( struct acpi_bridge *ab)
+-{
+- if (ab->tbus_head) {
+- dbg(" Total BUS Resources:\n");
+- print_pci_resource (ab->tbus_head);
+- }
+- if (ab->bus_head) {
+- dbg(" BUS Resources:\n");
+- print_pci_resource (ab->bus_head);
+- }
+-
+- if (ab->tio_head) {
+- dbg(" Total IO Resources:\n");
+- print_pci_resource (ab->tio_head);
+- }
+- if (ab->io_head) {
+- dbg(" IO Resources:\n");
+- print_pci_resource (ab->io_head);
+- }
+-
+- if (ab->tmem_head) {
+- dbg(" Total MEM Resources:\n");
+- print_pci_resource (ab->tmem_head);
+- }
+- if (ab->mem_head) {
+- dbg(" MEM Resources:\n");
+- print_pci_resource (ab->mem_head);
+- }
+-
+- if (ab->tp_mem_head) {
+- dbg(" Total PMEM Resources:\n");
+- print_pci_resource (ab->tp_mem_head);
+- }
+- if (ab->p_mem_head) {
+- dbg(" PMEM Resources:\n");
+- print_pci_resource (ab->p_mem_head);
+- }
+- if (ab->_hpp) {
+- dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size);
+- dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer);
+- dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr);
+- dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr);
+- }
+-}
+-
+-static int pciehprm_delete_resource(
+- struct pci_resource **aprh,
+- ulong base,
+- ulong size)
+-{
+- struct pci_resource *res;
+- struct pci_resource *prevnode;
+- struct pci_resource *split_node;
+- ulong tbase;
+-
+- pciehp_resource_sort_and_combine(aprh);
+-
+- for (res = *aprh; res; res = res->next) {
+- if (res->base > base)
+- continue;
+-
+- if ((res->base + res->length) < (base + size))
+- continue;
+-
+- if (res->base < base) {
+- tbase = base;
+-
+- if ((res->length - (tbase - res->base)) < size)
+- continue;
+-
+- split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+- if (!split_node)
+- return -ENOMEM;
+-
+- split_node->base = res->base;
+- split_node->length = tbase - res->base;
+- res->base = tbase;
+- res->length -= split_node->length;
+-
+- split_node->next = res->next;
+- res->next = split_node;
+- }
+-
+- if (res->length >= size) {
+- split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+- if (!split_node)
+- return -ENOMEM;
+-
+- split_node->base = res->base + size;
+- split_node->length = res->length - size;
+- res->length = size;
+-
+- split_node->next = res->next;
+- res->next = split_node;
+- }
+-
+- if (*aprh == res) {
+- *aprh = res->next;
+- } else {
+- prevnode = *aprh;
+- while (prevnode->next != res)
+- prevnode = prevnode->next;
+-
+- prevnode->next = res->next;
+- }
+- res->next = NULL;
+- kfree(res);
+- break;
+- }
+-
+- return 0;
+-}
+-
+-static int pciehprm_delete_resources(
+- struct pci_resource **aprh,
+- struct pci_resource *this
+- )
+-{
+- struct pci_resource *res;
+-
+- for (res = this; res; res = res->next)
+- pciehprm_delete_resource(aprh, res->base, res->length);
+-
+- return 0;
+-}
+-
+-static int pciehprm_add_resource(
+- struct pci_resource **aprh,
+- ulong base,
+- ulong size)
+-{
+- struct pci_resource *res;
+-
+- for (res = *aprh; res; res = res->next) {
+- if ((res->base + res->length) == base) {
+- res->length += size;
+- size = 0L;
+- break;
+- }
+- if (res->next == *aprh)
+- break;
+- }
+-
+- if (size) {
+- res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+- if (!res) {
+- err ("acpi_pciehprm: alloc for res fail\n");
+- return -ENOMEM;
+- }
+- memset(res, 0, sizeof (struct pci_resource));
+-
+- res->base = base;
+- res->length = size;
+- res->next = *aprh;
+- *aprh = res;
+- }
+-
+- return 0;
+-}
+-
+-static int pciehprm_add_resources(
+- struct pci_resource **aprh,
+- struct pci_resource *this
+- )
+-{
+- struct pci_resource *res;
+- int rc = 0;
+-
+- for (res = this; res && !rc; res = res->next)
+- rc = pciehprm_add_resource(aprh, res->base, res->length);
+-
+- return rc;
+-}
+-
+-static void acpi_parse_io (
+- struct acpi_bridge *ab,
+- union acpi_resource_data *data
+- )
+-{
+- struct acpi_resource_io *dataio;
+- dataio = (struct acpi_resource_io *) data;
+-
+- dbg("Io Resource\n");
+- dbg(" %d bit decode\n", ACPI_DECODE_16 == dataio->io_decode ? 16:10);
+- dbg(" Range minimum base: %08X\n", dataio->min_base_address);
+- dbg(" Range maximum base: %08X\n", dataio->max_base_address);
+- dbg(" Alignment: %08X\n", dataio->alignment);
+- dbg(" Range Length: %08X\n", dataio->range_length);
+-}
+-
+-static void acpi_parse_fixed_io (
+- struct acpi_bridge *ab,
+- union acpi_resource_data *data
+- )
+-{
+- struct acpi_resource_fixed_io *datafio;
+- datafio = (struct acpi_resource_fixed_io *) data;
+-
+- dbg("Fixed Io Resource\n");
+- dbg(" Range base address: %08X", datafio->base_address);
+- dbg(" Range length: %08X", datafio->range_length);
+-}
+-
+-static void acpi_parse_address16_32 (
+- struct acpi_bridge *ab,
+- union acpi_resource_data *data,
+- acpi_resource_type id
+- )
+-{
+- /*
+- * acpi_resource_address16 == acpi_resource_address32
+- * acpi_resource_address16 *data16 = (acpi_resource_address16 *) data;
+- */
+- struct acpi_resource_address32 *data32 = (struct acpi_resource_address32 *) data;
+- struct pci_resource **aprh, **tprh;
+-
+- if (id == ACPI_RSTYPE_ADDRESS16)
+- dbg("acpi_pciehprm:16-Bit Address Space Resource\n");
+- else
+- dbg("acpi_pciehprm:32-Bit Address Space Resource\n");
+-
+- switch (data32->resource_type) {
+- case ACPI_MEMORY_RANGE:
+- dbg(" Resource Type: Memory Range\n");
+- aprh = &ab->mem_head;
+- tprh = &ab->tmem_head;
+-
+- switch (data32->attribute.memory.cache_attribute) {
+- case ACPI_NON_CACHEABLE_MEMORY:
+- dbg(" Type Specific: Noncacheable memory\n");
+- break;
+- case ACPI_CACHABLE_MEMORY:
+- dbg(" Type Specific: Cacheable memory\n");
+- break;
+- case ACPI_WRITE_COMBINING_MEMORY:
+- dbg(" Type Specific: Write-combining memory\n");
+- break;
+- case ACPI_PREFETCHABLE_MEMORY:
+- aprh = &ab->p_mem_head;
+- dbg(" Type Specific: Prefetchable memory\n");
+- break;
+- default:
+- dbg(" Type Specific: Invalid cache attribute\n");
+- break;
+- }
+-
+- dbg(" Type Specific: Read%s\n", ACPI_READ_WRITE_MEMORY == data32->attribute.memory.read_write_attribute ? "/Write":" Only");
+- break;
+-
+- case ACPI_IO_RANGE:
+- dbg(" Resource Type: I/O Range\n");
+- aprh = &ab->io_head;
+- tprh = &ab->tio_head;
+-
+- switch (data32->attribute.io.range_attribute) {
+- case ACPI_NON_ISA_ONLY_RANGES:
+- dbg(" Type Specific: Non-ISA Io Addresses\n");
+- break;
+- case ACPI_ISA_ONLY_RANGES:
+- dbg(" Type Specific: ISA Io Addresses\n");
+- break;
+- case ACPI_ENTIRE_RANGE:
+- dbg(" Type Specific: ISA and non-ISA Io Addresses\n");
+- break;
+- default:
+- dbg(" Type Specific: Invalid range attribute\n");
+- break;
+- }
+- break;
+-
+- case ACPI_BUS_NUMBER_RANGE:
+- dbg(" Resource Type: Bus Number Range(fixed)\n");
+- /* fixup to be compatible with the rest of php driver */
+- data32->min_address_range++;
+- data32->address_length--;
+- aprh = &ab->bus_head;
+- tprh = &ab->tbus_head;
+- break;
+- default:
+- dbg(" Resource Type: Invalid resource type. Exiting.\n");
+- return;
+- }
+-
+- dbg(" Resource %s\n", ACPI_CONSUMER == data32->producer_consumer ? "Consumer":"Producer");
+- dbg(" %s decode\n", ACPI_SUB_DECODE == data32->decode ? "Subtractive":"Positive");
+- dbg(" Min address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->min_address_fixed ? "":"not");
+- dbg(" Max address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->max_address_fixed ? "":"not");
+- dbg(" Granularity: %08X\n", data32->granularity);
+- dbg(" Address range min: %08X\n", data32->min_address_range);
+- dbg(" Address range max: %08X\n", data32->max_address_range);
+- dbg(" Address translation offset: %08X\n", data32->address_translation_offset);
+- dbg(" Address Length: %08X\n", data32->address_length);
+-
+- if (0xFF != data32->resource_source.index) {
+- dbg(" Resource Source Index: %X\n", data32->resource_source.index);
+- /* dbg(" Resource Source: %s\n", data32->resource_source.string_ptr); */
+- }
+-
+- pciehprm_add_resource(aprh, data32->min_address_range, data32->address_length);
+-}
+-
+-static acpi_status acpi_parse_crs(
+- struct acpi_bridge *ab,
+- struct acpi_resource *crsbuf
+- )
+-{
+- acpi_status status = AE_OK;
+- struct acpi_resource *resource = crsbuf;
+- u8 count = 0;
+- u8 done = 0;
+-
+- while (!done) {
+- dbg("acpi_pciehprm: PCI bus 0x%x Resource structure %x.\n", ab->bus, count++);
+- switch (resource->id) {
+- case ACPI_RSTYPE_IRQ:
+- dbg("Irq -------- Resource\n");
+- break;
+- case ACPI_RSTYPE_DMA:
+- dbg("DMA -------- Resource\n");
+- break;
+- case ACPI_RSTYPE_START_DPF:
+- dbg("Start DPF -------- Resource\n");
+- break;
+- case ACPI_RSTYPE_END_DPF:
+- dbg("End DPF -------- Resource\n");
+- break;
+- case ACPI_RSTYPE_IO:
+- acpi_parse_io (ab, &resource->data);
+- break;
+- case ACPI_RSTYPE_FIXED_IO:
+- acpi_parse_fixed_io (ab, &resource->data);
+- break;
+- case ACPI_RSTYPE_VENDOR:
+- dbg("Vendor -------- Resource\n");
+- break;
+- case ACPI_RSTYPE_END_TAG:
+- dbg("End_tag -------- Resource\n");
+- done = 1;
+- break;
+- case ACPI_RSTYPE_MEM24:
+- dbg("Mem24 -------- Resource\n");
+- break;
+- case ACPI_RSTYPE_MEM32:
+- dbg("Mem32 -------- Resource\n");
+- break;
+- case ACPI_RSTYPE_FIXED_MEM32:
+- dbg("Fixed Mem32 -------- Resource\n");
+- break;
+- case ACPI_RSTYPE_ADDRESS16:
+- acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS16);
+- break;
+- case ACPI_RSTYPE_ADDRESS32:
+- acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS32);
+- break;
+- case ACPI_RSTYPE_ADDRESS64:
+- info("Address64 -------- Resource unparsed\n");
+- break;
+- case ACPI_RSTYPE_EXT_IRQ:
+- dbg("Ext Irq -------- Resource\n");
+- break;
+- default:
+- dbg("Invalid -------- resource type 0x%x\n", resource->id);
+- break;
+- }
+-
+- resource = (struct acpi_resource *) ((char *)resource + resource->length);
+- }
+-
+- return status;
+-}
+-
+-static acpi_status acpi_get_crs( struct acpi_bridge *ab)
+-{
+- acpi_status status;
+- struct acpi_resource *crsbuf;
+-
+- status = acpi_evaluate_crs(ab->handle, &crsbuf);
+- if (ACPI_SUCCESS(status)) {
+- status = acpi_parse_crs(ab, crsbuf);
+- kfree(crsbuf);
+-
+- pciehp_resource_sort_and_combine(&ab->bus_head);
+- pciehp_resource_sort_and_combine(&ab->io_head);
+- pciehp_resource_sort_and_combine(&ab->mem_head);
+- pciehp_resource_sort_and_combine(&ab->p_mem_head);
+-
+- pciehprm_add_resources (&ab->tbus_head, ab->bus_head);
+- pciehprm_add_resources (&ab->tio_head, ab->io_head);
+- pciehprm_add_resources (&ab->tmem_head, ab->mem_head);
+- pciehprm_add_resources (&ab->tp_mem_head, ab->p_mem_head);
+- }
+-
+- return status;
+-}
+-
+ /* find acpi_bridge downword from ab. */
+ static struct acpi_bridge *
+ find_acpi_bridge_by_bus(
+@@ -1064,14 +570,6 @@
+ ab->scanned = 0;
+ ab->type = BRIDGE_TYPE_HOST;
+
+- /* get root pci bridge's current resources */
+- status = acpi_get_crs(ab);
+- if (ACPI_FAILURE(status)) {
+- err("acpi_pciehprm:%s evaluate _CRS fail=0x%x\n", path_name, status);
+- kfree(ab);
+- return NULL;
+- }
+-
+ status = pci_osc_control_set (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
+ if (ACPI_FAILURE(status)) {
+ err("%s: status %x\n", __FUNCTION__, status);
+@@ -1179,11 +677,6 @@
+ {
+ dbg(" free a php func of slot(0x%02x) on PCI b:d:f=0x%02x:%02x:%02x\n", aps->sun, aps->bus, aps->dev, aps->fun);
+
+- free_pci_resource (aps->io_head);
+- free_pci_resource (aps->bus_head);
+- free_pci_resource (aps->mem_head);
+- free_pci_resource (aps->p_mem_head);
+-
+ kfree(aps);
+ }
+
+@@ -1208,15 +701,6 @@
+ free_a_slot(aps);
+ }
+
+- free_pci_resource (ab->io_head);
+- free_pci_resource (ab->tio_head);
+- free_pci_resource (ab->bus_head);
+- free_pci_resource (ab->tbus_head);
+- free_pci_resource (ab->mem_head);
+- free_pci_resource (ab->tmem_head);
+- free_pci_resource (ab->p_mem_head);
+- free_pci_resource (ab->tp_mem_head);
+-
+ kfree(ab);
+ }
+
+@@ -1266,48 +750,6 @@
+ return slot_num;
+ }
+
+-static int print_acpi_resources (struct acpi_bridge *ab)
+-{
+- struct acpi_php_slot *aps;
+- int i;
+-
+- switch (ab->type) {
+- case BRIDGE_TYPE_HOST:
+- dbg("PCI HOST Bridge (%x) [%s]\n", ab->bus, acpi_path_name(ab->handle));
+- break;
+- case BRIDGE_TYPE_P2P:
+- dbg("PCI P2P Bridge (%x-%x) [%s]\n", ab->pbus, ab->bus, acpi_path_name(ab->handle));
+- break;
+- };
+-
+- print_pci_resources (ab);
+-
+- for ( i = -1, aps = ab->slots; aps; aps = aps->next) {
+- if (aps->dev == i)
+- continue;
+- dbg(" Slot sun(%x) s:b:d:f(%02x:%02x:%02x:%02x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);
+- print_slot_resources(aps);
+- i = aps->dev;
+- }
+-
+- if (ab->child)
+- print_acpi_resources (ab->child);
+-
+- if (ab->next)
+- print_acpi_resources (ab->next);
+-
+- return 0;
+-}
+-
+-int pciehprm_print_pirt(void)
+-{
+- dbg("PCIEHPRM ACPI Slots\n");
+- if (acpi_bridges_head)
+- print_acpi_resources (acpi_bridges_head);
+-
+- return 0;
+-}
+-
+ static struct acpi_php_slot * get_acpi_slot (
+ struct acpi_bridge *ab,
+ u32 sun
+@@ -1349,288 +791,6 @@
+ }
+ #endif
+
+-static void pciehprm_dump_func_res( struct pci_func *fun)
+-{
+- struct pci_func *func = fun;
+-
+- if (func->bus_head) {
+- dbg(": BUS Resources:\n");
+- print_pci_resource (func->bus_head);
+- }
+- if (func->io_head) {
+- dbg(": IO Resources:\n");
+- print_pci_resource (func->io_head);
+- }
+- if (func->mem_head) {
+- dbg(": MEM Resources:\n");
+- print_pci_resource (func->mem_head);
+- }
+- if (func->p_mem_head) {
+- dbg(": PMEM Resources:\n");
+- print_pci_resource (func->p_mem_head);
+- }
+-}
+-
+-static void pciehprm_dump_ctrl_res( struct controller *ctlr)
+-{
+- struct controller *ctrl = ctlr;
+-
+- if (ctrl->bus_head) {
+- dbg(": BUS Resources:\n");
+- print_pci_resource (ctrl->bus_head);
+- }
+- if (ctrl->io_head) {
+- dbg(": IO Resources:\n");
+- print_pci_resource (ctrl->io_head);
+- }
+- if (ctrl->mem_head) {
+- dbg(": MEM Resources:\n");
+- print_pci_resource (ctrl->mem_head);
+- }
+- if (ctrl->p_mem_head) {
+- dbg(": PMEM Resources:\n");
+- print_pci_resource (ctrl->p_mem_head);
+- }
+-}
+-
+-static int pciehprm_get_used_resources (
+- struct controller *ctrl,
+- struct pci_func *func
+- )
+-{
+- return pciehp_save_used_resources (ctrl, func, !DISABLE_CARD);
+-}
+-
+-static int configure_existing_function(
+- struct controller *ctrl,
+- struct pci_func *func
+- )
+-{
+- int rc;
+-
+- /* see how much resources the func has used. */
+- rc = pciehprm_get_used_resources (ctrl, func);
+-
+- if (!rc) {
+- /* subtract the resources used by the func from ctrl resources */
+- rc = pciehprm_delete_resources (&ctrl->bus_head, func->bus_head);
+- rc |= pciehprm_delete_resources (&ctrl->io_head, func->io_head);
+- rc |= pciehprm_delete_resources (&ctrl->mem_head, func->mem_head);
+- rc |= pciehprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head);
+- if (rc)
+- warn("aCEF: cannot del used resources\n");
+- } else
+- err("aCEF: cannot get used resources\n");
+-
+- return rc;
+-}
+-
+-static int bind_pci_resources_to_slots ( struct controller *ctrl)
+-{
+- struct pci_func *func, new_func;
+- int busn = ctrl->slot_bus;
+- int devn, funn;
+- u32 vid;
+-
+- for (devn = 0; devn < 32; devn++) {
+- for (funn = 0; funn < 8; funn++) {
+- /*
+- if (devn == ctrl->device && funn == ctrl->function)
+- continue;
+- */
+- /* find out if this entry is for an occupied slot */
+- vid = 0xFFFFFFFF;
+- pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid);
+-
+- if (vid != 0xFFFFFFFF) {
+- dbg("%s: vid = %x\n", __FUNCTION__, vid);
+- func = pciehp_slot_find(busn, devn, funn);
+- if (!func) {
+- memset(&new_func, 0, sizeof(struct pci_func));
+- new_func.bus = busn;
+- new_func.device = devn;
+- new_func.function = funn;
+- new_func.is_a_board = 1;
+- configure_existing_function(ctrl, &new_func);
+- pciehprm_dump_func_res(&new_func);
+- } else {
+- configure_existing_function(ctrl, func);
+- pciehprm_dump_func_res(func);
+- }
+- dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
+- }
+- }
+- }
+-
+- return 0;
+-}
+-
+-static int bind_pci_resources(
+- struct controller *ctrl,
+- struct acpi_bridge *ab
+- )
+-{
+- int status = 0;
+-
+- if (ab->bus_head) {
+- dbg("bapr: BUS Resources add on PCI 0x%x\n", ab->bus);
+- status = pciehprm_add_resources (&ctrl->bus_head, ab->bus_head);
+- if (pciehprm_delete_resources (&ab->bus_head, ctrl->bus_head))
+- warn("bapr: cannot sub BUS Resource on PCI 0x%x\n", ab->bus);
+- if (status) {
+- err("bapr: BUS Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
+- return status;
+- }
+- } else
+- info("bapr: No BUS Resource on PCI 0x%x.\n", ab->bus);
+-
+- if (ab->io_head) {
+- dbg("bapr: IO Resources add on PCI 0x%x\n", ab->bus);
+- status = pciehprm_add_resources (&ctrl->io_head, ab->io_head);
+- if (pciehprm_delete_resources (&ab->io_head, ctrl->io_head))
+- warn("bapr: cannot sub IO Resource on PCI 0x%x\n", ab->bus);
+- if (status) {
+- err("bapr: IO Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
+- return status;
+- }
+- } else
+- info("bapr: No IO Resource on PCI 0x%x.\n", ab->bus);
+-
+- if (ab->mem_head) {
+- dbg("bapr: MEM Resources add on PCI 0x%x\n", ab->bus);
+- status = pciehprm_add_resources (&ctrl->mem_head, ab->mem_head);
+- if (pciehprm_delete_resources (&ab->mem_head, ctrl->mem_head))
+- warn("bapr: cannot sub MEM Resource on PCI 0x%x\n", ab->bus);
+- if (status) {
+- err("bapr: MEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
+- return status;
+- }
+- } else
+- info("bapr: No MEM Resource on PCI 0x%x.\n", ab->bus);
+-
+- if (ab->p_mem_head) {
+- dbg("bapr: PMEM Resources add on PCI 0x%x\n", ab->bus);
+- status = pciehprm_add_resources (&ctrl->p_mem_head, ab->p_mem_head);
+- if (pciehprm_delete_resources (&ab->p_mem_head, ctrl->p_mem_head))
+- warn("bapr: cannot sub PMEM Resource on PCI 0x%x\n", ab->bus);
+- if (status) {
+- err("bapr: PMEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
+- return status;
+- }
+- } else
+- info("bapr: No PMEM Resource on PCI 0x%x.\n", ab->bus);
+-
+- return status;
+-}
+-
+-static int no_pci_resources( struct acpi_bridge *ab)
+-{
+- return !(ab->p_mem_head || ab->mem_head || ab->io_head || ab->bus_head);
+-}
+-
+-static int find_pci_bridge_resources (
+- struct controller *ctrl,
+- struct acpi_bridge *ab
+- )
+-{
+- int rc = 0;
+- struct pci_func func;
+-
+- memset(&func, 0, sizeof(struct pci_func));
+-
+- func.bus = ab->pbus;
+- func.device = ab->pdevice;
+- func.function = ab->pfunction;
+- func.is_a_board = 1;
+-
+- /* Get used resources for this PCI bridge */
+- rc = pciehp_save_used_resources (ctrl, &func, !DISABLE_CARD);
+-
+- ab->io_head = func.io_head;
+- ab->mem_head = func.mem_head;
+- ab->p_mem_head = func.p_mem_head;
+- ab->bus_head = func.bus_head;
+- if (ab->bus_head)
+- pciehprm_delete_resource(&ab->bus_head, ctrl->pci_dev->subordinate->number, 1);
+-
+- return rc;
+-}
+-
+-static int get_pci_resources_from_bridge(
+- struct controller *ctrl,
+- struct acpi_bridge *ab
+- )
+-{
+- int rc = 0;
+-
+- dbg("grfb: Get Resources for PCI 0x%x from actual PCI bridge 0x%x.\n", ctrl->bus, ab->bus);
+-
+- rc = find_pci_bridge_resources (ctrl, ab);
+-
+- pciehp_resource_sort_and_combine(&ab->bus_head);
+- pciehp_resource_sort_and_combine(&ab->io_head);
+- pciehp_resource_sort_and_combine(&ab->mem_head);
+- pciehp_resource_sort_and_combine(&ab->p_mem_head);
+-
+- pciehprm_add_resources (&ab->tbus_head, ab->bus_head);
+- pciehprm_add_resources (&ab->tio_head, ab->io_head);
+- pciehprm_add_resources (&ab->tmem_head, ab->mem_head);
+- pciehprm_add_resources (&ab->tp_mem_head, ab->p_mem_head);
+-
+- return rc;
+-}
+-
+-static int get_pci_resources(
+- struct controller *ctrl,
+- struct acpi_bridge *ab
+- )
+-{
+- int rc = 0;
+-
+- if (no_pci_resources(ab)) {
+- dbg("spbr:PCI 0x%x has no resources. Get parent resources.\n", ab->bus);
+- rc = get_pci_resources_from_bridge(ctrl, ab);
+- }
+-
+- return rc;
+-}
+-
+-/*
+- * Get resources for this ctrl.
+- * 1. get total resources from ACPI _CRS or bridge (this ctrl)
+- * 2. find used resources of existing adapters
+- * 3. subtract used resources from total resources
+- */
+-int pciehprm_find_available_resources( struct controller *ctrl)
+-{
+- int rc = 0;
+- struct acpi_bridge *ab;
+-
+- ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->pci_dev->subordinate->number);
+- if (!ab) {
+- err("pfar:cannot locate acpi bridge of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number);
+- return -1;
+- }
+- if (no_pci_resources(ab)) {
+- rc = get_pci_resources(ctrl, ab);
+- if (rc) {
+- err("pfar:cannot get pci resources of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number);
+- return -1;
+- }
+- }
+-
+- rc = bind_pci_resources(ctrl, ab);
+- dbg("pfar:pre-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number);
+- pciehprm_dump_ctrl_res(ctrl);
+-
+- bind_pci_resources_to_slots (ctrl);
+-
+- dbg("pfar:post-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number);
+- pciehprm_dump_ctrl_res(ctrl);
+-
+- return rc;
+-}
+-
+ int pciehprm_set_hpp(
+ struct controller *ctrl,
+ struct pci_func *func,
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehprm_nonacpi.c 2005-11-02 09:25:02.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehprm_nonacpi.c 2005-11-02 10:56:32.000000000 -0800
+@@ -34,12 +34,7 @@
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <linux/slab.h>
+-
+ #include <asm/uaccess.h>
+-#ifdef CONFIG_IA64
+-#include <asm/iosapic.h>
+-#endif
+-
+ #include "pciehp.h"
+ #include "pciehprm.h"
+ #include "pciehprm_nonacpi.h"
+@@ -50,11 +45,6 @@
+ return;
+ }
+
+-int pciehprm_print_pirt(void)
+-{
+- return 0;
+-}
+-
+ int pciehprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
+ {
+
+@@ -62,343 +52,6 @@
+ return 0;
+ }
+
+-
+-static void print_pci_resource ( struct pci_resource *aprh)
+-{
+- struct pci_resource *res;
+-
+- for (res = aprh; res; res = res->next)
+- dbg(" base= 0x%x length= 0x%x\n", res->base, res->length);
+-}
+-
+-
+-static void phprm_dump_func_res( struct pci_func *fun)
+-{
+- struct pci_func *func = fun;
+-
+- if (func->bus_head) {
+- dbg(": BUS Resources:\n");
+- print_pci_resource (func->bus_head);
+- }
+- if (func->io_head) {
+- dbg(": IO Resources:\n");
+- print_pci_resource (func->io_head);
+- }
+- if (func->mem_head) {
+- dbg(": MEM Resources:\n");
+- print_pci_resource (func->mem_head);
+- }
+- if (func->p_mem_head) {
+- dbg(": PMEM Resources:\n");
+- print_pci_resource (func->p_mem_head);
+- }
+-}
+-
+-static int phprm_get_used_resources (
+- struct controller *ctrl,
+- struct pci_func *func
+- )
+-{
+- return pciehp_save_used_resources (ctrl, func, !DISABLE_CARD);
+-}
+-
+-static int phprm_delete_resource(
+- struct pci_resource **aprh,
+- ulong base,
+- ulong size)
+-{
+- struct pci_resource *res;
+- struct pci_resource *prevnode;
+- struct pci_resource *split_node;
+- ulong tbase;
+-
+- pciehp_resource_sort_and_combine(aprh);
+-
+- for (res = *aprh; res; res = res->next) {
+- if (res->base > base)
+- continue;
+-
+- if ((res->base + res->length) < (base + size))
+- continue;
+-
+- if (res->base < base) {
+- tbase = base;
+-
+- if ((res->length - (tbase - res->base)) < size)
+- continue;
+-
+- split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+- if (!split_node)
+- return -ENOMEM;
+-
+- split_node->base = res->base;
+- split_node->length = tbase - res->base;
+- res->base = tbase;
+- res->length -= split_node->length;
+-
+- split_node->next = res->next;
+- res->next = split_node;
+- }
+-
+- if (res->length >= size) {
+- split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+- if (!split_node)
+- return -ENOMEM;
+-
+- split_node->base = res->base + size;
+- split_node->length = res->length - size;
+- res->length = size;
+-
+- split_node->next = res->next;
+- res->next = split_node;
+- }
+-
+- if (*aprh == res) {
+- *aprh = res->next;
+- } else {
+- prevnode = *aprh;
+- while (prevnode->next != res)
+- prevnode = prevnode->next;
+-
+- prevnode->next = res->next;
+- }
+- res->next = NULL;
+- kfree(res);
+- break;
+- }
+-
+- return 0;
+-}
+-
+-
+-static int phprm_delete_resources(
+- struct pci_resource **aprh,
+- struct pci_resource *this
+- )
+-{
+- struct pci_resource *res;
+-
+- for (res = this; res; res = res->next)
+- phprm_delete_resource(aprh, res->base, res->length);
+-
+- return 0;
+-}
+-
+-
+-static int configure_existing_function(
+- struct controller *ctrl,
+- struct pci_func *func
+- )
+-{
+- int rc;
+-
+- /* see how much resources the func has used. */
+- rc = phprm_get_used_resources (ctrl, func);
+-
+- if (!rc) {
+- /* subtract the resources used by the func from ctrl resources */
+- rc = phprm_delete_resources (&ctrl->bus_head, func->bus_head);
+- rc |= phprm_delete_resources (&ctrl->io_head, func->io_head);
+- rc |= phprm_delete_resources (&ctrl->mem_head, func->mem_head);
+- rc |= phprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head);
+- if (rc)
+- warn("aCEF: cannot del used resources\n");
+- } else
+- err("aCEF: cannot get used resources\n");
+-
+- return rc;
+-}
+-
+-static int pciehprm_delete_resource(
+- struct pci_resource **aprh,
+- ulong base,
+- ulong size)
+-{
+- struct pci_resource *res;
+- struct pci_resource *prevnode;
+- struct pci_resource *split_node;
+- ulong tbase;
+-
+- pciehp_resource_sort_and_combine(aprh);
+-
+- for (res = *aprh; res; res = res->next) {
+- if (res->base > base)
+- continue;
+-
+- if ((res->base + res->length) < (base + size))
+- continue;
+-
+- if (res->base < base) {
+- tbase = base;
+-
+- if ((res->length - (tbase - res->base)) < size)
+- continue;
+-
+- split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+- if (!split_node)
+- return -ENOMEM;
+-
+- split_node->base = res->base;
+- split_node->length = tbase - res->base;
+- res->base = tbase;
+- res->length -= split_node->length;
+-
+- split_node->next = res->next;
+- res->next = split_node;
+- }
+-
+- if (res->length >= size) {
+- split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+- if (!split_node)
+- return -ENOMEM;
+-
+- split_node->base = res->base + size;
+- split_node->length = res->length - size;
+- res->length = size;
+-
+- split_node->next = res->next;
+- res->next = split_node;
+- }
+-
+- if (*aprh == res) {
+- *aprh = res->next;
+- } else {
+- prevnode = *aprh;
+- while (prevnode->next != res)
+- prevnode = prevnode->next;
+-
+- prevnode->next = res->next;
+- }
+- res->next = NULL;
+- kfree(res);
+- break;
+- }
+-
+- return 0;
+-}
+-
+-static int bind_pci_resources_to_slots ( struct controller *ctrl)
+-{
+- struct pci_func *func, new_func;
+- int busn = ctrl->slot_bus;
+- int devn, funn;
+- u32 vid;
+-
+- for (devn = 0; devn < 32; devn++) {
+- for (funn = 0; funn < 8; funn++) {
+- /*
+- if (devn == ctrl->device && funn == ctrl->function)
+- continue;
+- */
+- /* find out if this entry is for an occupied slot */
+- vid = 0xFFFFFFFF;
+-
+- pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid);
+-
+- if (vid != 0xFFFFFFFF) {
+- dbg("%s: vid = %x bus %x dev %x fun %x\n", __FUNCTION__,
+- vid, busn, devn, funn);
+- func = pciehp_slot_find(busn, devn, funn);
+- dbg("%s: func = %p\n", __FUNCTION__,func);
+- if (!func) {
+- memset(&new_func, 0, sizeof(struct pci_func));
+- new_func.bus = busn;
+- new_func.device = devn;
+- new_func.function = funn;
+- new_func.is_a_board = 1;
+- configure_existing_function(ctrl, &new_func);
+- phprm_dump_func_res(&new_func);
+- } else {
+- configure_existing_function(ctrl, func);
+- phprm_dump_func_res(func);
+- }
+- dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
+- }
+- }
+- }
+-
+- return 0;
+-}
+-
+-static void phprm_dump_ctrl_res( struct controller *ctlr)
+-{
+- struct controller *ctrl = ctlr;
+-
+- if (ctrl->bus_head) {
+- dbg(": BUS Resources:\n");
+- print_pci_resource (ctrl->bus_head);
+- }
+- if (ctrl->io_head) {
+- dbg(": IO Resources:\n");
+- print_pci_resource (ctrl->io_head);
+- }
+- if (ctrl->mem_head) {
+- dbg(": MEM Resources:\n");
+- print_pci_resource (ctrl->mem_head);
+- }
+- if (ctrl->p_mem_head) {
+- dbg(": PMEM Resources:\n");
+- print_pci_resource (ctrl->p_mem_head);
+- }
+-}
+-
+-/*
+- * phprm_find_available_resources
+- *
+- * Finds available memory, IO, and IRQ resources for programming
+- * devices which may be added to the system
+- * this function is for hot plug ADD!
+- *
+- * returns 0 if success
+- */
+-int pciehprm_find_available_resources(struct controller *ctrl)
+-{
+- struct pci_func func;
+- u32 rc;
+-
+- memset(&func, 0, sizeof(struct pci_func));
+-
+- func.bus = ctrl->bus;
+- func.device = ctrl->device;
+- func.function = ctrl->function;
+- func.is_a_board = 1;
+-
+- /* Get resources for this PCI bridge */
+- rc = pciehp_save_used_resources (ctrl, &func, !DISABLE_CARD);
+- dbg("%s: pciehp_save_used_resources rc = %d\n", __FUNCTION__, rc);
+-
+- if (func.mem_head)
+- func.mem_head->next = ctrl->mem_head;
+- ctrl->mem_head = func.mem_head;
+-
+- if (func.p_mem_head)
+- func.p_mem_head->next = ctrl->p_mem_head;
+- ctrl->p_mem_head = func.p_mem_head;
+-
+- if (func.io_head)
+- func.io_head->next = ctrl->io_head;
+- ctrl->io_head = func.io_head;
+-
+- if(func.bus_head)
+- func.bus_head->next = ctrl->bus_head;
+- ctrl->bus_head = func.bus_head;
+-
+- if (ctrl->bus_head)
+- pciehprm_delete_resource(&ctrl->bus_head, ctrl->pci_dev->subordinate->number, 1);
+-
+- dbg("%s:pre-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus);
+- phprm_dump_ctrl_res(ctrl);
+-
+- dbg("%s: before bind_pci_resources_to slots\n", __FUNCTION__);
+-
+- bind_pci_resources_to_slots (ctrl);
+-
+- dbg("%s:post-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus);
+- phprm_dump_ctrl_res(ctrl);
+-
+- return (rc);
+-}
+-
+ int pciehprm_set_hpp(
+ struct controller *ctrl,
+ struct pci_func *func,
diff --git a/pci/pci-pciehp-02.patch b/pci/pci-pciehp-02.patch
new file mode 100644
index 0000000000000..b131d059fcb73
--- /dev/null
+++ b/pci/pci-pciehp-02.patch
@@ -0,0 +1,1309 @@
+From owner-linux-pci@atrey.karlin.mff.cuni.cz Mon Oct 31 16:32:18 2005
+Message-Id: <20051101002122.973467729@csdlinux-2.jf.intel.com>
+Date: Mon, 31 Oct 2005 16:20:07 -0800
+From: rajesh.shah@intel.com
+To: kristen.c.accardi@intel.com, gregkh@suse.de
+Cc: akpm@osdl.org, rajesh.shah@intel.com
+Subject: [patch 2/8] pciehp: reduce dependence on ACPI
+Content-Disposition: inline; filename=pciehp-reduce-acpi-dependence
+
+Reduce the PCI Express hotplug driver's dependence on ACPI.
+We don't walk the acpi namespace anymore to build a list of
+bridges and devices. We go to ACPI only to run the _OSC or
+_OSHP methods to transition control of hotplug hardware from
+system BIOS to the hotplug driver, and to run the _HPP
+method to get hotplug device parameters like cache line size,
+latency timer and SERR/PERR enable from BIOS.
+
+Note that one of the side effects of this patch is that pciehp
+does not automatically enable the hot-added device or its DMA
+bus mastering capability now. It expects the device driver to
+do that. This may break some drivers and we will have to fix
+them as they are reported.
+
+Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+ drivers/pci/hotplug/pciehp.h | 11
+ drivers/pci/hotplug/pciehp_core.c | 20
+ drivers/pci/hotplug/pciehp_ctrl.c | 1
+ drivers/pci/hotplug/pciehp_hpc.c | 4
+ drivers/pci/hotplug/pciehprm.h | 52 --
+ drivers/pci/hotplug/pciehprm_acpi.c | 838 ++-------------------------------
+ drivers/pci/hotplug/pciehprm_nonacpi.c | 107 ----
+ drivers/pci/hotplug/pciehprm_nonacpi.h | 56 --
+ 8 files changed, 96 insertions(+), 993 deletions(-)
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp.h 2005-11-02 10:57:01.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp.h 2005-11-02 10:57:08.000000000 -0800
+@@ -49,6 +49,13 @@
+ #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
+ #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
+
++struct hotplug_params {
++ u8 cache_line_size;
++ u8 latency_timer;
++ u8 enable_serr;
++ u8 enable_perr;
++};
++
+ struct pci_func {
+ struct pci_func *next;
+ u8 bus;
+@@ -199,6 +206,10 @@
+ extern int pciehp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot);
+ extern int pciehp_configure_device (struct slot *ctrl);
+ extern int pciehp_unconfigure_device (struct pci_func* func);
++extern int get_hp_hw_control_from_firmware(struct pci_dev *dev);
++extern void get_hp_params_from_firmware(struct pci_dev *dev,
++ struct hotplug_params *hpp);
++
+
+
+ /* Global variables */
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_core.c 2005-11-02 10:57:01.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_core.c 2005-11-02 10:57:08.000000000 -0800
+@@ -39,7 +39,6 @@
+ #include <linux/init.h>
+ #include <asm/uaccess.h>
+ #include "pciehp.h"
+-#include "pciehprm.h"
+ #include <linux/interrupt.h>
+
+ /* Global variables */
+@@ -381,6 +380,7 @@
+ dbg("%s: DRV_thread pid = %d\n", __FUNCTION__, current->pid);
+
+ pdev = dev->port;
++ ctrl->pci_dev = pdev;
+
+ rc = pcie_init(ctrl, dev,
+ (php_intr_callback_t) pciehp_handle_attention_button,
+@@ -392,8 +392,6 @@
+ goto err_out_free_ctrl;
+ }
+
+- ctrl->pci_dev = pdev;
+-
+ pci_set_drvdata(pdev, ctrl);
+
+ ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL);
+@@ -609,18 +607,14 @@
+ if (retval)
+ goto error_hpc_init;
+
+- retval = pciehprm_init(PCI);
+- if (!retval) {
+- retval = pcie_port_service_register(&hpdriver_portdrv);
+- dbg("pcie_port_service_register = %d\n", retval);
+- info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+- if (retval)
+- dbg("%s: Failure to register service\n", __FUNCTION__);
+- }
++ retval = pcie_port_service_register(&hpdriver_portdrv);
++ dbg("pcie_port_service_register = %d\n", retval);
++ info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
++ if (retval)
++ dbg("%s: Failure to register service\n", __FUNCTION__);
+
+ error_hpc_init:
+ if (retval) {
+- pciehprm_cleanup();
+ pciehp_event_stop_thread();
+ };
+
+@@ -632,8 +626,6 @@
+ dbg("unload_pciehpd()\n");
+ unload_pciehpd();
+
+- pciehprm_cleanup();
+-
+ dbg("pcie_port_service_unregister\n");
+ pcie_port_service_unregister(&hpdriver_portdrv);
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_ctrl.c 2005-11-02 10:57:01.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_ctrl.c 2005-11-02 10:57:08.000000000 -0800
+@@ -40,7 +40,6 @@
+ #include <linux/pci.h>
+ #include "../pci.h"
+ #include "pciehp.h"
+-#include "pciehprm.h"
+
+ static void interrupt_event_handler(struct controller *ctrl);
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_hpc.c 2005-11-02 10:57:01.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_hpc.c 2005-11-02 10:57:08.000000000 -0800
+@@ -1470,6 +1470,10 @@
+ }
+ dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word);
+
++ rc = get_hp_hw_control_from_firmware(ctrl->pci_dev);
++ if (rc)
++ goto abort_free_ctlr;
++
+ /* Add this HPC instance into the HPC list */
+ spin_lock(&list_lock);
+ if (php_ctlr_list_head == 0) {
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehprm.h 2005-11-02 10:57:01.000000000 -0800
++++ /dev/null 1970-01-01 00:00:00.000000000 +0000
+@@ -1,52 +0,0 @@
+-/*
+- * PCIEHPRM : PCIEHP Resource Manager for ACPI/non-ACPI platform
+- *
+- * Copyright (C) 1995,2001 Compaq Computer Corporation
+- * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
+- * Copyright (C) 2001 IBM Corp.
+- * Copyright (C) 2003-2004 Intel Corporation
+- *
+- * All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or (at
+- * your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+- * NON INFRINGEMENT. See the GNU General Public License for more
+- * details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- *
+- * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
+- *
+- */
+-
+-#ifndef _PCIEHPRM_H_
+-#define _PCIEHPRM_H_
+-
+-#ifdef CONFIG_HOTPLUG_PCI_PCIE_PHPRM_NONACPI
+-#include "pciehprm_nonacpi.h"
+-#endif
+-
+-int pciehprm_init(enum php_ctlr_type ct);
+-void pciehprm_cleanup(void);
+-int pciehprm_print_pirt(void);
+-int pciehprm_find_available_resources(struct controller *ctrl);
+-int pciehprm_set_hpp(struct controller *ctrl, struct pci_func *func, u8 card_type);
+-void pciehprm_enable_card(struct controller *ctrl, struct pci_func *func, u8 card_type);
+-
+-#ifdef DEBUG
+-#define RES_CHECK(this, bits) \
+- { if (((this) & (bits - 1))) \
+- printk("%s:%d ERR: potential res loss!\n", __FUNCTION__, __LINE__); }
+-#else
+-#define RES_CHECK(this, bits)
+-#endif
+-
+-#endif /* _PCIEHPRM_H_ */
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehprm_acpi.c 2005-11-02 10:57:01.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehprm_acpi.c 2005-11-02 10:57:08.000000000 -0800
+@@ -39,70 +39,11 @@
+ #include <acpi/acpi_bus.h>
+ #include <acpi/actypes.h>
+ #include "pciehp.h"
+-#include "pciehprm.h"
+-
+-#define PCI_MAX_BUS 0x100
+-#define ACPI_STA_DEVICE_PRESENT 0x01
+
+ #define METHOD_NAME__SUN "_SUN"
+ #define METHOD_NAME__HPP "_HPP"
+ #define METHOD_NAME_OSHP "OSHP"
+
+-/* Status code for running acpi method to gain native control */
+-#define NC_NOT_RUN 0
+-#define OSC_NOT_EXIST 1
+-#define OSC_RUN_FAILED 2
+-#define OSHP_NOT_EXIST 3
+-#define OSHP_RUN_FAILED 4
+-#define NC_RUN_SUCCESS 5
+-
+-#define PHP_RES_BUS 0xA0
+-#define PHP_RES_IO 0xA1
+-#define PHP_RES_MEM 0xA2
+-#define PHP_RES_PMEM 0xA3
+-
+-#define BRIDGE_TYPE_P2P 0x00
+-#define BRIDGE_TYPE_HOST 0x01
+-
+-/* this should go to drivers/acpi/include/ */
+-struct acpi__hpp {
+- u8 cache_line_size;
+- u8 latency_timer;
+- u8 enable_serr;
+- u8 enable_perr;
+-};
+-
+-struct acpi_php_slot {
+- struct acpi_php_slot *next;
+- struct acpi_bridge *bridge;
+- acpi_handle handle;
+- int seg;
+- int bus;
+- int dev;
+- int fun;
+- u32 sun;
+- void *slot_ops; /* _STA, _EJx, etc */
+- struct slot *slot;
+-}; /* per func */
+-
+-struct acpi_bridge {
+- struct acpi_bridge *parent;
+- struct acpi_bridge *next;
+- struct acpi_bridge *child;
+- acpi_handle handle;
+- int seg;
+- int pbus; /* pdev->bus->number */
+- int pdevice; /* PCI_SLOT(pdev->devfn) */
+- int pfunction; /* PCI_DEVFN(pdev->devfn) */
+- int bus; /* pdev->subordinate->number */
+- struct acpi__hpp *_hpp;
+- struct acpi_php_slot *slots;
+- int scanned;
+- int type;
+-};
+-
+-static struct acpi_bridge *acpi_bridges_head;
+-
+ static u8 * acpi_path_name( acpi_handle handle)
+ {
+ acpi_status status;
+@@ -118,85 +59,43 @@
+ return path_name;
+ }
+
+-static void acpi_get__hpp ( struct acpi_bridge *ab);
+-static int acpi_run_oshp ( struct acpi_bridge *ab);
+-static int osc_run_status = NC_NOT_RUN;
+-static int oshp_run_status = NC_NOT_RUN;
+-
+-static int acpi_add_slot_to_php_slots(
+- struct acpi_bridge *ab,
+- int bus_num,
+- acpi_handle handle,
+- u32 adr,
+- u32 sun
+- )
+-{
+- struct acpi_php_slot *aps;
+- static long samesun = -1;
+-
+- aps = (struct acpi_php_slot *) kmalloc (sizeof(struct acpi_php_slot), GFP_KERNEL);
+- if (!aps) {
+- err ("acpi_pciehprm: alloc for aps fail\n");
+- return -1;
+- }
+- memset(aps, 0, sizeof(struct acpi_php_slot));
+-
+- aps->handle = handle;
+- aps->bus = bus_num;
+- aps->dev = (adr >> 16) & 0xffff;
+- aps->fun = adr & 0xffff;
+- aps->sun = sun;
+-
+- aps->next = ab->slots; /* cling to the bridge */
+- aps->bridge = ab;
+- ab->slots = aps;
+-
+- ab->scanned += 1;
+- if (!ab->_hpp)
+- acpi_get__hpp(ab);
+-
+- if (osc_run_status == OSC_NOT_EXIST)
+- oshp_run_status = acpi_run_oshp(ab);
+-
+- if (sun != samesun) {
+- info("acpi_pciehprm: Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n",
+- aps->sun, ab->seg, aps->bus, aps->dev, aps->fun);
+- samesun = sun;
+- }
+- return 0;
+-}
+-
+-static void acpi_get__hpp ( struct acpi_bridge *ab)
++static acpi_status
++acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
+ {
+ acpi_status status;
+ u8 nui[4];
+ struct acpi_buffer ret_buf = { 0, NULL};
+ union acpi_object *ext_obj, *package;
+- u8 *path_name = acpi_path_name(ab->handle);
++ u8 *path_name = acpi_path_name(handle);
+ int i, len = 0;
+
+ /* get _hpp */
+- status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf);
++ status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
+ switch (status) {
+ case AE_BUFFER_OVERFLOW:
+ ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
+ if (!ret_buf.pointer) {
+- err ("acpi_pciehprm:%s alloc for _HPP fail\n", path_name);
+- return;
++ err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
++ path_name);
++ return AE_NO_MEMORY;
+ }
+- status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf);
++ status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
++ NULL, &ret_buf);
+ if (ACPI_SUCCESS(status))
+ break;
+ default:
+ if (ACPI_FAILURE(status)) {
+- err("acpi_pciehprm:%s _HPP fail=0x%x\n", path_name, status);
+- return;
++ dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
++ path_name, status);
++ return status;
+ }
+ }
+
+ ext_obj = (union acpi_object *) ret_buf.pointer;
+ if (ext_obj->type != ACPI_TYPE_PACKAGE) {
+- err ("acpi_pciehprm:%s _HPP obj not a package\n", path_name);
++ err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
++ path_name);
++ status = AE_ERROR;
+ goto free_and_return;
+ }
+
+@@ -209,689 +108,94 @@
+ nui[i] = (u8)ext_obj->integer.value;
+ break;
+ default:
+- err ("acpi_pciehprm:%s _HPP obj type incorrect\n", path_name);
++ err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
++ path_name);
++ status = AE_ERROR;
+ goto free_and_return;
+ }
+ }
+
+- ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL);
+- if (!ab->_hpp) {
+- err ("acpi_pciehprm:%s alloc for _HPP failed\n", path_name);
+- goto free_and_return;
+- }
+- memset(ab->_hpp, 0, sizeof(struct acpi__hpp));
+-
+- ab->_hpp->cache_line_size = nui[0];
+- ab->_hpp->latency_timer = nui[1];
+- ab->_hpp->enable_serr = nui[2];
+- ab->_hpp->enable_perr = nui[3];
+-
+- dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size);
+- dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer);
+- dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr);
+- dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr);
++ hpp->cache_line_size = nui[0];
++ hpp->latency_timer = nui[1];
++ hpp->enable_serr = nui[2];
++ hpp->enable_perr = nui[3];
++
++ dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
++ dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
++ dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
++ dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
+
+ free_and_return:
+ kfree(ret_buf.pointer);
++ return status;
+ }
+
+-static int acpi_run_oshp ( struct acpi_bridge *ab)
++static acpi_status acpi_run_oshp(acpi_handle handle)
+ {
+ acpi_status status;
+- u8 *path_name = acpi_path_name(ab->handle);
++ u8 *path_name = acpi_path_name(handle);
+
+ /* run OSHP */
+- status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, NULL);
++ status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
+ if (ACPI_FAILURE(status)) {
+- err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status);
+- oshp_run_status = (status == AE_NOT_FOUND) ? OSHP_NOT_EXIST : OSHP_RUN_FAILED;
++ err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
++ status);
+ } else {
+- oshp_run_status = NC_RUN_SUCCESS;
+- dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status);
+- dbg("acpi_pciehprm:%s oshp_run_status =0x%x\n", path_name, oshp_run_status);
++ dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
+ }
+- return oshp_run_status;
++ return status;
+ }
+
+-/* find acpi_bridge downword from ab. */
+-static struct acpi_bridge *
+-find_acpi_bridge_by_bus(
+- struct acpi_bridge *ab,
+- int seg,
+- int bus /* pdev->subordinate->number */
+- )
++int get_hp_hw_control_from_firmware(struct pci_dev *dev)
+ {
+- struct acpi_bridge *lab = NULL;
+-
+- if (!ab)
+- return NULL;
+-
+- if ((ab->bus == bus) && (ab->seg == seg))
+- return ab;
+-
+- if (ab->child)
+- lab = find_acpi_bridge_by_bus(ab->child, seg, bus);
+-
+- if (!lab)
+- if (ab->next)
+- lab = find_acpi_bridge_by_bus(ab->next, seg, bus);
+-
+- return lab;
+-}
+-
+-/*
+- * Build a device tree of ACPI PCI Bridges
+- */
+-static void pciehprm_acpi_register_a_bridge (
+- struct acpi_bridge **head,
+- struct acpi_bridge *pab, /* parent bridge to which child bridge is added */
+- struct acpi_bridge *cab /* child bridge to add */
+- )
+-{
+- struct acpi_bridge *lpab;
+- struct acpi_bridge *lcab;
+-
+- lpab = find_acpi_bridge_by_bus(*head, pab->seg, pab->bus);
+- if (!lpab) {
+- if (!(pab->type & BRIDGE_TYPE_HOST))
+- warn("PCI parent bridge s:b(%x:%x) not in list.\n", pab->seg, pab->bus);
+- pab->next = *head;
+- *head = pab;
+- lpab = pab;
+- }
+-
+- if ((cab->type & BRIDGE_TYPE_HOST) && (pab == cab))
+- return;
+-
+- lcab = find_acpi_bridge_by_bus(*head, cab->seg, cab->bus);
+- if (lcab) {
+- if ((pab->bus != lcab->parent->bus) || (lcab->bus != cab->bus))
+- err("PCI child bridge s:b(%x:%x) in list with diff parent.\n", cab->seg, cab->bus);
+- return;
+- } else
+- lcab = cab;
+-
+- lcab->parent = lpab;
+- lcab->next = lpab->child;
+- lpab->child = lcab;
+-}
+-
+-static acpi_status pciehprm_acpi_build_php_slots_callback(
+- acpi_handle handle,
+- u32 Level,
+- void *context,
+- void **retval
+- )
+-{
+- ulong bus_num;
+- ulong seg_num;
+- ulong sun, adr;
+- ulong padr = 0;
+- acpi_handle phandle = NULL;
+- struct acpi_bridge *pab = (struct acpi_bridge *)context;
+- struct acpi_bridge *lab;
+- acpi_status status;
+- u8 *path_name = acpi_path_name(handle);
+-
+- /* get _SUN */
+- status = acpi_evaluate_integer(handle, METHOD_NAME__SUN, NULL, &sun);
+- switch(status) {
+- case AE_NOT_FOUND:
+- return AE_OK;
+- default:
+- if (ACPI_FAILURE(status)) {
+- err("acpi_pciehprm:%s _SUN fail=0x%x\n", path_name, status);
+- return status;
+- }
+- }
+-
+- /* get _ADR. _ADR must exist if _SUN exists */
+- status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
+- if (ACPI_FAILURE(status)) {
+- err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status);
+- return status;
+- }
+-
+- dbg("acpi_pciehprm:%s sun=0x%08x adr=0x%08x\n", path_name, (u32)sun, (u32)adr);
+-
+- status = acpi_get_parent(handle, &phandle);
+- if (ACPI_FAILURE(status)) {
+- err("acpi_pciehprm:%s get_parent fail=0x%x\n", path_name, status);
+- return (status);
+- }
+-
+- bus_num = pab->bus;
+- seg_num = pab->seg;
++ acpi_status status;
++ /*
++ * Per PCI firmware specification, we should run the ACPI _OSC
++ * method to get control of hotplug hardware before using it
++ */
++ /* Fixme: run _OSC for a specific host bridge, not all of them */
++ status = pci_osc_control_set(OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
+
+- if (pab->bus == bus_num) {
+- lab = pab;
+- } else {
+- dbg("WARN: pab is not parent\n");
+- lab = find_acpi_bridge_by_bus(pab, seg_num, bus_num);
+- if (!lab) {
+- dbg("acpi_pciehprm: alloc new P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
+- lab = (struct acpi_bridge *)kmalloc(sizeof(struct acpi_bridge), GFP_KERNEL);
+- if (!lab) {
+- err("acpi_pciehprm: alloc for ab fail\n");
+- return AE_NO_MEMORY;
+- }
+- memset(lab, 0, sizeof(struct acpi_bridge));
+-
+- lab->handle = phandle;
+- lab->pbus = pab->bus;
+- lab->pdevice = (int)(padr >> 16) & 0xffff;
+- lab->pfunction = (int)(padr & 0xffff);
+- lab->bus = (int)bus_num;
+- lab->scanned = 0;
+- lab->type = BRIDGE_TYPE_P2P;
+-
+- pciehprm_acpi_register_a_bridge (&acpi_bridges_head, pab, lab);
+- } else
+- dbg("acpi_pciehprm: found P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
++ /* Fixme: fail native hotplug if _OSC does not exist for root ports */
++ if (status == AE_NOT_FOUND) {
++ /*
++ * Some older BIOS's don't support _OSC but support
++ * OSHP to do the same thing
++ */
++ acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev));
++ if (handle)
++ status = acpi_run_oshp(handle);
+ }
+-
+- acpi_add_slot_to_php_slots(lab, (int)bus_num, handle, (u32)adr, (u32)sun);
+-
+- return (status);
+-}
+-
+-static int pciehprm_acpi_build_php_slots(
+- struct acpi_bridge *ab,
+- u32 depth
+- )
+-{
+- acpi_status status;
+- u8 *path_name = acpi_path_name(ab->handle);
+-
+- /* Walk down this pci bridge to get _SUNs if any behind P2P */
+- status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
+- ab->handle,
+- depth,
+- pciehprm_acpi_build_php_slots_callback,
+- ab,
+- NULL );
+ if (ACPI_FAILURE(status)) {
+- dbg("acpi_pciehprm:%s walk for _SUN on pci bridge seg:bus(%x:%x) fail=0x%x\n", path_name, ab->seg, ab->bus, status);
++ err("Cannot get control of hotplug hardware\n");
+ return -1;
+ }
+
++ dbg("Sucess getting control of hotplug hardware\n");
+ return 0;
+ }
+
+-static void build_a_bridge(
+- struct acpi_bridge *pab,
+- struct acpi_bridge *ab
+- )
+-{
+- u8 *path_name = acpi_path_name(ab->handle);
+-
+- pciehprm_acpi_register_a_bridge (&acpi_bridges_head, pab, ab);
+-
+- switch (ab->type) {
+- case BRIDGE_TYPE_HOST:
+- dbg("acpi_pciehprm: Registered PCI HOST Bridge(%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
+- ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
+- break;
+- case BRIDGE_TYPE_P2P:
+- dbg("acpi_pciehprm: Registered PCI P2P Bridge(%02x-%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
+- ab->pbus, ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
+- break;
+- };
+-
+- /* build any immediate PHP slots under this pci bridge */
+- pciehprm_acpi_build_php_slots(ab, 1);
+-}
+-
+-static struct acpi_bridge * add_p2p_bridge(
+- acpi_handle handle,
+- struct acpi_bridge *pab, /* parent */
+- ulong adr
+- )
+-{
+- struct acpi_bridge *ab;
+- struct pci_dev *pdev;
+- ulong devnum, funcnum;
+- u8 *path_name = acpi_path_name(handle);
+-
+- ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
+- if (!ab) {
+- err("acpi_pciehprm: alloc for ab fail\n");
+- return NULL;
+- }
+- memset(ab, 0, sizeof(struct acpi_bridge));
+-
+- devnum = (adr >> 16) & 0xffff;
+- funcnum = adr & 0xffff;
+-
+- pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
+- if (!pdev || !pdev->subordinate) {
+- err("acpi_pciehprm:%s is not a P2P Bridge\n", path_name);
+- kfree(ab);
+- return NULL;
+- }
+-
+- ab->handle = handle;
+- ab->seg = pab->seg;
+- ab->pbus = pab->bus; /* or pdev->bus->number */
+- ab->pdevice = devnum; /* or PCI_SLOT(pdev->devfn) */
+- ab->pfunction = funcnum; /* or PCI_FUNC(pdev->devfn) */
+- ab->bus = pdev->subordinate->number;
+- ab->scanned = 0;
+- ab->type = BRIDGE_TYPE_P2P;
+-
+- dbg("acpi_pciehprm: P2P(%x-%x) on pci=b:d:f(%x:%x:%x) acpi=b:d:f(%x:%x:%x) [%s]\n",
+- pab->bus, ab->bus, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+- pab->bus, (u32)devnum, (u32)funcnum, path_name);
+-
+- build_a_bridge(pab, ab);
+-
+- return ab;
+-}
+-
+-static acpi_status scan_p2p_bridge(
+- acpi_handle handle,
+- u32 Level,
+- void *context,
+- void **retval
+- )
+-{
+- struct acpi_bridge *pab = (struct acpi_bridge *)context;
+- struct acpi_bridge *ab;
+- acpi_status status;
+- ulong adr = 0;
+- u8 *path_name = acpi_path_name(handle);
+- ulong devnum, funcnum;
+- struct pci_dev *pdev;
+-
+- /* get device, function */
+- status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
+- if (ACPI_FAILURE(status)) {
+- if (status != AE_NOT_FOUND)
+- err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status);
+- return AE_OK;
+- }
+-
+- devnum = (adr >> 16) & 0xffff;
+- funcnum = adr & 0xffff;
+-
+- pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
+- if (!pdev)
+- return AE_OK;
+- if (!pdev->subordinate)
+- return AE_OK;
+-
+- ab = add_p2p_bridge(handle, pab, adr);
+- if (ab) {
+- status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
+- handle,
+- (u32)1,
+- scan_p2p_bridge,
+- ab,
+- NULL);
+- if (ACPI_FAILURE(status))
+- dbg("acpi_pciehprm:%s find_p2p fail=0x%x\n", path_name, status);
+- }
+-
+- return AE_OK;
+-}
+-
+-static struct acpi_bridge * add_host_bridge(
+- acpi_handle handle,
+- ulong segnum,
+- ulong busnum
+- )
+-{
+- ulong adr = 0;
+- acpi_status status;
+- struct acpi_bridge *ab;
+- u8 *path_name = acpi_path_name(handle);
+-
+- /* get device, function: host br adr is always 0000 though. */
+- status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
+- if (ACPI_FAILURE(status)) {
+- err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status);
+- return NULL;
+- }
+- dbg("acpi_pciehprm: ROOT PCI seg(0x%x)bus(0x%x)dev(0x%x)func(0x%x) [%s]\n", (u32)segnum,
+- (u32)busnum, (u32)(adr >> 16) & 0xffff, (u32)adr & 0xffff, path_name);
+-
+- ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
+- if (!ab) {
+- err("acpi_pciehprm: alloc for ab fail\n");
+- return NULL;
+- }
+- memset(ab, 0, sizeof(struct acpi_bridge));
+-
+- ab->handle = handle;
+- ab->seg = (int)segnum;
+- ab->bus = ab->pbus = (int)busnum;
+- ab->pdevice = (int)(adr >> 16) & 0xffff;
+- ab->pfunction = (int)(adr & 0xffff);
+- ab->scanned = 0;
+- ab->type = BRIDGE_TYPE_HOST;
+-
+- status = pci_osc_control_set (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
+- if (ACPI_FAILURE(status)) {
+- err("%s: status %x\n", __FUNCTION__, status);
+- osc_run_status = (status == AE_NOT_FOUND) ? OSC_NOT_EXIST : OSC_RUN_FAILED;
+- } else {
+- osc_run_status = NC_RUN_SUCCESS;
+- }
+- dbg("%s: osc_run_status %x\n", __FUNCTION__, osc_run_status);
+-
+- build_a_bridge(ab, ab);
+-
+- return ab;
+-}
+-
+-static acpi_status acpi_scan_from_root_pci_callback (
+- acpi_handle handle,
+- u32 Level,
+- void *context,
+- void **retval
+- )
++void get_hp_params_from_firmware(struct pci_dev *dev,
++ struct hotplug_params *hpp)
+ {
+- ulong segnum = 0;
+- ulong busnum = 0;
+- acpi_status status;
+- struct acpi_bridge *ab;
+- u8 *path_name = acpi_path_name(handle);
+-
+- /* get bus number of this pci root bridge */
+- status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &segnum);
+- if (ACPI_FAILURE(status)) {
+- if (status != AE_NOT_FOUND) {
+- err("acpi_pciehprm:%s evaluate _SEG fail=0x%x\n", path_name, status);
+- return status;
+- }
+- segnum = 0;
+- }
+-
+- /* get bus number of this pci root bridge */
+- status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, &busnum);
+- if (ACPI_FAILURE(status)) {
+- err("acpi_pciehprm:%s evaluate _BBN fail=0x%x\n", path_name, status);
+- return (status);
+- }
+-
+- ab = add_host_bridge(handle, segnum, busnum);
+- if (ab) {
+- status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
+- handle,
+- 1,
+- scan_p2p_bridge,
+- ab,
+- NULL);
+- if (ACPI_FAILURE(status))
+- dbg("acpi_pciehprm:%s find_p2p fail=0x%x\n", path_name, status);
+- }
+-
+- return AE_OK;
+-}
+-
+-static int pciehprm_acpi_scan_pci (void)
+-{
+- acpi_status status;
++ acpi_status status = AE_NOT_FOUND;
++ struct pci_dev *pdev = dev;
+
+ /*
+- * TBD: traverse LDM device tree with the help of
+- * unified ACPI augmented for php device population.
++ * _HPP settings apply to all child buses, until another _HPP is
++ * encountered. If we don't find an _HPP for the input pci dev,
++ * look for it in the parent device scope since that would apply to
++ * this pci dev. If we don't find any _HPP, use hardcoded defaults
+ */
+- status = acpi_get_devices ( PCI_ROOT_HID_STRING,
+- acpi_scan_from_root_pci_callback,
+- NULL,
+- NULL );
+- if (ACPI_FAILURE(status)) {
+- err("acpi_pciehprm:get_device PCI ROOT HID fail=0x%x\n", status);
+- return -1;
+- }
+-
+- return 0;
+-}
+-
+-int pciehprm_init(enum php_ctlr_type ctlr_type)
+-{
+- int rc;
+-
+- if (ctlr_type != PCI)
+- return -ENODEV;
+-
+- dbg("pciehprm ACPI init <enter>\n");
+- acpi_bridges_head = NULL;
+-
+- /* construct PCI bus:device tree of acpi_handles */
+- rc = pciehprm_acpi_scan_pci();
+- if (rc)
+- return rc;
+-
+- if ((oshp_run_status != NC_RUN_SUCCESS) && (osc_run_status != NC_RUN_SUCCESS)) {
+- err("Fails to gain control of native hot-plug\n");
+- rc = -ENODEV;
+- }
+-
+- dbg("pciehprm ACPI init %s\n", (rc)?"fail":"success");
+- return rc;
+-}
+-
+-static void free_a_slot(struct acpi_php_slot *aps)
+-{
+- dbg(" free a php func of slot(0x%02x) on PCI b:d:f=0x%02x:%02x:%02x\n", aps->sun, aps->bus, aps->dev, aps->fun);
+-
+- kfree(aps);
+-}
+-
+-static void free_a_bridge( struct acpi_bridge *ab)
+-{
+- struct acpi_php_slot *aps, *next;
+-
+- switch (ab->type) {
+- case BRIDGE_TYPE_HOST:
+- dbg("Free ACPI PCI HOST Bridge(%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
+- ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
+- break;
+- case BRIDGE_TYPE_P2P:
+- dbg("Free ACPI PCI P2P Bridge(%x-%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
+- ab->pbus, ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
+- break;
+- };
+-
+- /* free slots first */
+- for (aps = ab->slots; aps; aps = next) {
+- next = aps->next;
+- free_a_slot(aps);
+- }
+-
+- kfree(ab);
+-}
+-
+-static void pciehprm_free_bridges ( struct acpi_bridge *ab)
+-{
+- if (!ab)
+- return;
+-
+- if (ab->child)
+- pciehprm_free_bridges (ab->child);
+-
+- if (ab->next)
+- pciehprm_free_bridges (ab->next);
+-
+- free_a_bridge(ab);
+-}
+-
+-void pciehprm_cleanup(void)
+-{
+- pciehprm_free_bridges (acpi_bridges_head);
+-}
+-
+-static int get_number_of_slots (
+- struct acpi_bridge *ab,
+- int selfonly
+- )
+-{
+- struct acpi_php_slot *aps;
+- int prev_slot = -1;
+- int slot_num = 0;
+-
+- for ( aps = ab->slots; aps; aps = aps->next)
+- if (aps->dev != prev_slot) {
+- prev_slot = aps->dev;
+- slot_num++;
+- }
+-
+- if (ab->child)
+- slot_num += get_number_of_slots (ab->child, 0);
+-
+- if (selfonly)
+- return slot_num;
+-
+- if (ab->next)
+- slot_num += get_number_of_slots (ab->next, 0);
+-
+- return slot_num;
+-}
+-
+-static struct acpi_php_slot * get_acpi_slot (
+- struct acpi_bridge *ab,
+- u32 sun
+- )
+-{
+- struct acpi_php_slot *aps = NULL;
+-
+- for ( aps = ab->slots; aps; aps = aps->next)
+- if (aps->sun == sun)
+- return aps;
+-
+- if (!aps && ab->child) {
+- aps = (struct acpi_php_slot *)get_acpi_slot (ab->child, sun);
+- if (aps)
+- return aps;
+- }
+-
+- if (!aps && ab->next) {
+- aps = (struct acpi_php_slot *)get_acpi_slot (ab->next, sun);
+- if (aps)
+- return aps;
+- }
+-
+- return aps;
+-
+-}
+-
+-#if 0
+-void * pciehprm_get_slot(struct slot *slot)
+-{
+- struct acpi_bridge *ab = acpi_bridges_head;
+- struct acpi_php_slot *aps = get_acpi_slot (ab, slot->number);
+-
+- aps->slot = slot;
+-
+- dbg("Got acpi slot sun(%x): s:b:d:f(%x:%x:%x:%x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);
+-
+- return (void *)aps;
+-}
+-#endif
+-
+-int pciehprm_set_hpp(
+- struct controller *ctrl,
+- struct pci_func *func,
+- u8 card_type
+- )
+-{
+- struct acpi_bridge *ab;
+- struct pci_bus lpci_bus, *pci_bus;
+- int rc = 0;
+- unsigned int devfn;
+- u8 cls= 0x08; /* default cache line size */
+- u8 lt = 0x40; /* default latency timer */
+- u8 ep = 0;
+- u8 es = 0;
+-
+- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+- pci_bus = &lpci_bus;
+- pci_bus->number = func->bus;
+- devfn = PCI_DEVFN(func->device, func->function);
+-
+- ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);
+-
+- if (ab) {
+- if (ab->_hpp) {
+- lt = (u8)ab->_hpp->latency_timer;
+- cls = (u8)ab->_hpp->cache_line_size;
+- ep = (u8)ab->_hpp->enable_perr;
+- es = (u8)ab->_hpp->enable_serr;
+- } else
+- dbg("_hpp: no _hpp for B/D/F=%#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
+- } else
+- dbg("_hpp: no acpi bridge for B/D/F = %#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
+-
+-
+- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
+- /* set subordinate Latency Timer */
+- rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, lt);
++ while (pdev && (ACPI_FAILURE(status))) {
++ acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
++ if (!handle)
++ break;
++ status = acpi_run_hpp(handle, hpp);
++ if (!(pdev->bus->parent))
++ break;
++ /* Check if a parent object supports _HPP */
++ pdev = pdev->bus->parent->self;
+ }
+-
+- /* set base Latency Timer */
+- rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, lt);
+- dbg(" set latency timer =0x%02x: %x\n", lt, rc);
+-
+- rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, cls);
+- dbg(" set cache_line_size=0x%02x: %x\n", cls, rc);
+-
+- return rc;
+ }
+
+-void pciehprm_enable_card(
+- struct controller *ctrl,
+- struct pci_func *func,
+- u8 card_type)
+-{
+- u16 command, cmd, bcommand, bcmd;
+- struct pci_bus lpci_bus, *pci_bus;
+- struct acpi_bridge *ab;
+- unsigned int devfn;
+- int rc;
+-
+- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+- pci_bus = &lpci_bus;
+- pci_bus->number = func->bus;
+- devfn = PCI_DEVFN(func->device, func->function);
+-
+- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &cmd);
+-
+- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
+- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcmd);
+- }
+-
+- command = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
+- | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+- bcommand = bcmd | PCI_BRIDGE_CTL_NO_ISA;
+-
+- ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);
+- if (ab) {
+- if (ab->_hpp) {
+- if (ab->_hpp->enable_perr) {
+- command |= PCI_COMMAND_PARITY;
+- bcommand |= PCI_BRIDGE_CTL_PARITY;
+- } else {
+- command &= ~PCI_COMMAND_PARITY;
+- bcommand &= ~PCI_BRIDGE_CTL_PARITY;
+- }
+- if (ab->_hpp->enable_serr) {
+- command |= PCI_COMMAND_SERR;
+- bcommand |= PCI_BRIDGE_CTL_SERR;
+- } else {
+- command &= ~PCI_COMMAND_SERR;
+- bcommand &= ~PCI_BRIDGE_CTL_SERR;
+- }
+- } else
+- dbg("no _hpp for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
+- } else
+- dbg("no acpi bridge for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
+-
+- if (command != cmd) {
+- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
+- }
+- if ((card_type == PCI_HEADER_TYPE_BRIDGE) && (bcommand != bcmd)) {
+- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
+- }
+-}
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehprm_nonacpi.c 2005-11-02 10:57:01.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehprm_nonacpi.c 2005-11-02 10:57:08.000000000 -0800
+@@ -36,15 +36,9 @@
+ #include <linux/slab.h>
+ #include <asm/uaccess.h>
+ #include "pciehp.h"
+-#include "pciehprm.h"
+ #include "pciehprm_nonacpi.h"
+
+
+-void pciehprm_cleanup(void)
+-{
+- return;
+-}
+-
+ int pciehprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
+ {
+
+@@ -52,106 +46,13 @@
+ return 0;
+ }
+
+-int pciehprm_set_hpp(
+- struct controller *ctrl,
+- struct pci_func *func,
+- u8 card_type)
+-{
+- u32 rc;
+- u8 temp_byte;
+- struct pci_bus lpci_bus, *pci_bus;
+- unsigned int devfn;
+- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+- pci_bus = &lpci_bus;
+- pci_bus->number = func->bus;
+- devfn = PCI_DEVFN(func->device, func->function);
+-
+- temp_byte = 0x40; /* hard coded value for LT */
+- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
+- /* set subordinate Latency Timer */
+- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);
+-
+- if (rc) {
+- dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__,
+- func->bus, func->device, func->function);
+- return rc;
+- }
+- }
+-
+- /* set base Latency Timer */
+- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
+-
+- if (rc) {
+- dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
+- return rc;
+- }
+-
+- /* set Cache Line size */
+- temp_byte = 0x08; /* hard coded value for CLS */
+-
+- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
+-
+- if (rc) {
+- dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
+- }
+-
+- /* set enable_perr */
+- /* set enable_serr */
+-
+- return rc;
+-}
+-
+-void pciehprm_enable_card(
+- struct controller *ctrl,
+- struct pci_func *func,
+- u8 card_type)
++void get_hp_params_from_firmware(struct pci_dev *dev,
++ struct hotplug_params *hpp)
+ {
+- u16 command, bcommand;
+- struct pci_bus lpci_bus, *pci_bus;
+- unsigned int devfn;
+- int rc;
+-
+- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+- pci_bus = &lpci_bus;
+- pci_bus->number = func->bus;
+- devfn = PCI_DEVFN(func->device, func->function);
+-
+- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
+-
+- command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR
+- | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
+- | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+-
+- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
+-
+- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
+-
+- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
+-
+- bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR
+- | PCI_BRIDGE_CTL_NO_ISA;
+-
+- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
+- }
++ return;
+ }
+
+-static int legacy_pciehprm_init_pci(void)
++int get_hp_hw_control_from_firmware(struct pci_dev *dev)
+ {
+ return 0;
+ }
+-
+-int pciehprm_init(enum php_ctlr_type ctrl_type)
+-{
+- int retval;
+-
+- switch (ctrl_type) {
+- case PCI:
+- retval = legacy_pciehprm_init_pci();
+- break;
+- default:
+- retval = -ENODEV;
+- break;
+- }
+-
+- return retval;
+-}
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehprm_nonacpi.h 2005-11-02 10:57:01.000000000 -0800
++++ /dev/null 1970-01-01 00:00:00.000000000 +0000
+@@ -1,56 +0,0 @@
+-/*
+- * PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
+- *
+- * Copyright (C) 1995,2001 Compaq Computer Corporation
+- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+- * Copyright (C) 2001 IBM Corp.
+- * Copyright (C) 2003-2004 Intel Corporation
+- *
+- * All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or (at
+- * your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+- * NON INFRINGEMENT. See the GNU General Public License for more
+- * details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- *
+- * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
+- *
+- */
+-
+-#ifndef _PCIEHPRM_NONACPI_H_
+-#define _PCIEHPRM_NONACPI_H_
+-
+-struct irq_info {
+- u8 bus, devfn; /* bus, device and function */
+- struct {
+- u8 link; /* IRQ line ID, chipset dependent, 0=not routed */
+- u16 bitmap; /* Available IRQs */
+- } __attribute__ ((packed)) irq[4];
+- u8 slot; /* slot number, 0=onboard */
+- u8 rfu;
+-} __attribute__ ((packed));
+-
+-struct irq_routing_table {
+- u32 signature; /* PIRQ_SIGNATURE should be here */
+- u16 version; /* PIRQ_VERSION */
+- u16 size; /* Table size in bytes */
+- u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */
+- u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */
+- u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */
+- u32 miniport_data; /* Crap */
+- u8 rfu[11];
+- u8 checksum; /* Modulo 256 checksum must give zero */
+- struct irq_info slots[0];
+-} __attribute__ ((packed));
+-
+-#endif /* _PCIEHPRM_NONACPI_H_ */
diff --git a/pci/pci-pciehp-03.patch b/pci/pci-pciehp-03.patch
new file mode 100644
index 0000000000000..a75e787306ac0
--- /dev/null
+++ b/pci/pci-pciehp-03.patch
@@ -0,0 +1,1144 @@
+From owner-linux-pci@atrey.karlin.mff.cuni.cz Mon Oct 31 16:31:55 2005
+Message-Id: <20051101002123.283015130@csdlinux-2.jf.intel.com>
+Date: Mon, 31 Oct 2005 16:20:08 -0800
+From: rajesh.shah@intel.com
+To: kristen.c.accardi@intel.com, gregkh@suse.de
+Cc: akpm@osdl.org, rajesh.shah@intel.com
+Subject: [patch 3/8] pciehp: remove redundant data structures
+Content-Disposition: inline; filename=pciehp-remove-redundant-data-structures
+
+State information is currently stored in per-slot as well as
+per-pci-function data structures in pciehp. There's a lot of
+overlap in the information kept, and some of it is never used.
+This patch consolidates the state information to per-slot and
+eliminates unused data structures. The biggest change is to
+eliminate the pci_func structure and the code around managing
+its lists.
+
+Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+ drivers/pci/hotplug/pciehp.h | 30 --
+ drivers/pci/hotplug/pciehp_core.c | 29 --
+ drivers/pci/hotplug/pciehp_ctrl.c | 391 +++-----------------------------------
+ drivers/pci/hotplug/pciehp_pci.c | 349 ++-------------------------------
+ 4 files changed, 65 insertions(+), 734 deletions(-)
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp.h 2005-11-02 10:57:10.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp.h 2005-11-02 10:57:11.000000000 -0800
+@@ -56,25 +56,11 @@
+ u8 enable_perr;
+ };
+
+-struct pci_func {
+- struct pci_func *next;
+- u8 bus;
+- u8 device;
+- u8 function;
+- u8 is_a_board;
+- u16 status;
+- u8 configured;
+- u8 switch_save;
+- u8 presence_save;
+- u16 reserved2;
+- u32 config_space[0x20];
+- struct pci_dev* pci_dev;
+-};
+-
+ struct slot {
+ struct slot *next;
+ u8 bus;
+ u8 device;
++ u16 status;
+ u32 number;
+ u8 is_a_board;
+ u8 configured;
+@@ -177,9 +163,6 @@
+ * error Messages
+ */
+ #define msg_initialization_err "Initialization failure, error=%d\n"
+-#define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n"
+-#define msg_HPC_non_pcie "The PCI hot plug controller is not supported by this driver.\n"
+-#define msg_HPC_not_supported "This system is not supported by this version of pciephd module. Upgrade to a newer version of pciehpd\n"
+ #define msg_button_on "PCI slot #%d - powering on due to button press.\n"
+ #define msg_button_off "PCI slot #%d - powering off due to button press.\n"
+ #define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n"
+@@ -188,8 +171,6 @@
+ /* controller functions */
+ extern int pciehp_event_start_thread (void);
+ extern void pciehp_event_stop_thread (void);
+-extern struct pci_func *pciehp_slot_create (unsigned char busnumber);
+-extern struct pci_func *pciehp_slot_find (unsigned char bus, unsigned char device, unsigned char index);
+ extern int pciehp_enable_slot (struct slot *slot);
+ extern int pciehp_disable_slot (struct slot *slot);
+
+@@ -200,12 +181,8 @@
+ /* extern void long_delay (int delay); */
+
+ /* pci functions */
+-extern int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
+-/*extern int pciehp_get_bus_dev (struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/
+-extern int pciehp_save_config (struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
+-extern int pciehp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot);
+-extern int pciehp_configure_device (struct slot *ctrl);
+-extern int pciehp_unconfigure_device (struct pci_func* func);
++extern int pciehp_configure_device (struct slot *p_slot);
++extern int pciehp_unconfigure_device (struct slot *p_slot);
+ extern int get_hp_hw_control_from_firmware(struct pci_dev *dev);
+ extern void get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp);
+@@ -214,7 +191,6 @@
+
+ /* Global variables */
+ extern struct controller *pciehp_ctrl_list;
+-extern struct pci_func *pciehp_slot_list[256];
+
+ /* Inline functions */
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_core.c 2005-11-02 10:57:10.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_core.c 2005-11-02 10:57:11.000000000 -0800
+@@ -46,7 +46,6 @@
+ int pciehp_poll_mode;
+ int pciehp_poll_time;
+ struct controller *pciehp_ctrl_list;
+-struct pci_func *pciehp_slot_list[256];
+
+ #define DRIVER_VERSION "0.4"
+ #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
+@@ -422,15 +421,6 @@
+ first_device_num = ctrl->slot_device_offset;
+ num_ctlr_slots = ctrl->num_slots;
+
+- /* Store PCI Config Space for all devices on this bus */
+- dbg("%s: Before calling pciehp_save_config, ctrl->bus %x,ctrl->slot_bus %x\n",
+- __FUNCTION__,ctrl->bus, ctrl->slot_bus);
+- rc = pciehp_save_config(ctrl, ctrl->slot_bus, num_ctlr_slots, first_device_num);
+- if (rc) {
+- err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc);
+- goto err_out_free_ctrl_bus;
+- }
+-
+ ctrl->add_support = 1;
+
+ /* Setup the slot information structures */
+@@ -491,7 +481,6 @@
+
+ static int pcie_start_thread(void)
+ {
+- int loop;
+ int retval = 0;
+
+ dbg("Initialize + Start the notification/polling mechanism \n");
+@@ -502,20 +491,11 @@
+ return retval;
+ }
+
+- dbg("Initialize slot lists\n");
+- /* One slot list for each bus in the system */
+- for (loop = 0; loop < 256; loop++) {
+- pciehp_slot_list[loop] = NULL;
+- }
+-
+ return retval;
+ }
+
+ static void __exit unload_pciehpd(void)
+ {
+- struct pci_func *next;
+- struct pci_func *TempSlot;
+- int loop;
+ struct controller *ctrl;
+ struct controller *tctrl;
+
+@@ -534,15 +514,6 @@
+ kfree(tctrl);
+ }
+
+- for (loop = 0; loop < 256; loop++) {
+- next = pciehp_slot_list[loop];
+- while (next != NULL) {
+- TempSlot = next;
+- next = next->next;
+- kfree(TempSlot);
+- }
+- }
+-
+ /* Stop the notification mechanism */
+ pciehp_event_stop_thread();
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_ctrl.c 2005-11-02 10:57:10.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_ctrl.c 2005-11-02 10:57:11.000000000 -0800
+@@ -55,19 +55,16 @@
+ struct slot *p_slot;
+ u8 rc = 0;
+ u8 getstatus;
+- struct pci_func *func;
+ struct event_info *taskInfo;
+
+ /* Attention Button Change */
+ dbg("pciehp: Attention button interrupt received.\n");
+
+- func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+-
+ /* This is the structure that tells the worker thread what to do */
+ taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+ p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
++ p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+ p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+
+ ctrl->next_event = (ctrl->next_event + 1) % 10;
+@@ -112,14 +109,11 @@
+ struct slot *p_slot;
+ u8 rc = 0;
+ u8 getstatus;
+- struct pci_func *func;
+ struct event_info *taskInfo;
+
+ /* Switch Change */
+ dbg("pciehp: Switch interrupt received.\n");
+
+- func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+-
+ /* This is the structure that tells the worker thread
+ * what to do
+ */
+@@ -129,7 +123,7 @@
+
+ rc++;
+ p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
++ p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+ p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+
+ if (getstatus) {
+@@ -137,14 +131,14 @@
+ * Switch opened
+ */
+ info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
+- func->switch_save = 0;
++ p_slot->switch_save = 0;
+ taskInfo->event_type = INT_SWITCH_OPEN;
+ } else {
+ /*
+ * Switch closed
+ */
+ info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
+- func->switch_save = 0x10;
++ p_slot->switch_save = 0x10;
+ taskInfo->event_type = INT_SWITCH_CLOSE;
+ }
+
+@@ -159,14 +153,11 @@
+ struct controller *ctrl = (struct controller *) inst_id;
+ struct slot *p_slot;
+ u8 rc = 0;
+- struct pci_func *func;
+ struct event_info *taskInfo;
+
+ /* Presence Change */
+ dbg("pciehp: Presence/Notify input change.\n");
+
+- func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+-
+ /* This is the structure that tells the worker thread
+ * what to do
+ */
+@@ -180,8 +171,8 @@
+ /* Switch is open, assume a presence change
+ * Save the presence state
+ */
+- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+- if (func->presence_save) {
++ p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
++ if (p_slot->presence_save) {
+ /*
+ * Card Present
+ */
+@@ -206,14 +197,11 @@
+ struct controller *ctrl = (struct controller *) inst_id;
+ struct slot *p_slot;
+ u8 rc = 0;
+- struct pci_func *func;
+ struct event_info *taskInfo;
+
+ /* power fault */
+ dbg("pciehp: Power fault interrupt received.\n");
+
+- func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+-
+ /* this is the structure that tells the worker thread
+ * what to do
+ */
+@@ -229,7 +217,7 @@
+ * power fault Cleared
+ */
+ info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
+- func->status = 0x00;
++ p_slot->status = 0x00;
+ taskInfo->event_type = INT_POWER_FAULT_CLEAR;
+ } else {
+ /*
+@@ -238,7 +226,7 @@
+ info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
+ taskInfo->event_type = INT_POWER_FAULT;
+ /* set power fault status for this board */
+- func->status = 0xFF;
++ p_slot->status = 0xFF;
+ info("power fault bit %x set\n", hp_slot);
+ }
+ if (rc)
+@@ -247,187 +235,6 @@
+ return rc;
+ }
+
+-/**
+- * pciehp_slot_create - Creates a node and adds it to the proper bus.
+- * @busnumber - bus where new node is to be located
+- *
+- * Returns pointer to the new node or NULL if unsuccessful
+- */
+-struct pci_func *pciehp_slot_create(u8 busnumber)
+-{
+- struct pci_func *new_slot;
+- struct pci_func *next;
+- dbg("%s: busnumber %x\n", __FUNCTION__, busnumber);
+- new_slot = kmalloc(sizeof(struct pci_func), GFP_KERNEL);
+-
+- if (new_slot == NULL)
+- return new_slot;
+-
+- memset(new_slot, 0, sizeof(struct pci_func));
+-
+- new_slot->next = NULL;
+- new_slot->configured = 1;
+-
+- if (pciehp_slot_list[busnumber] == NULL) {
+- pciehp_slot_list[busnumber] = new_slot;
+- } else {
+- next = pciehp_slot_list[busnumber];
+- while (next->next != NULL)
+- next = next->next;
+- next->next = new_slot;
+- }
+- return new_slot;
+-}
+-
+-
+-/**
+- * slot_remove - Removes a node from the linked list of slots.
+- * @old_slot: slot to remove
+- *
+- * Returns 0 if successful, !0 otherwise.
+- */
+-static int slot_remove(struct pci_func * old_slot)
+-{
+- struct pci_func *next;
+-
+- if (old_slot == NULL)
+- return 1;
+-
+- next = pciehp_slot_list[old_slot->bus];
+-
+- if (next == NULL)
+- return 1;
+-
+- if (next == old_slot) {
+- pciehp_slot_list[old_slot->bus] = old_slot->next;
+- kfree(old_slot);
+- return 0;
+- }
+-
+- while ((next->next != old_slot) && (next->next != NULL)) {
+- next = next->next;
+- }
+-
+- if (next->next == old_slot) {
+- next->next = old_slot->next;
+- kfree(old_slot);
+- return 0;
+- } else
+- return 2;
+-}
+-
+-
+-/**
+- * bridge_slot_remove - Removes a node from the linked list of slots.
+- * @bridge: bridge to remove
+- *
+- * Returns 0 if successful, !0 otherwise.
+- */
+-static int bridge_slot_remove(struct pci_func *bridge)
+-{
+- u8 subordinateBus, secondaryBus;
+- u8 tempBus;
+- struct pci_func *next;
+-
+- if (bridge == NULL)
+- return 1;
+-
+- secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF;
+- subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF;
+-
+- for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {
+- next = pciehp_slot_list[tempBus];
+-
+- while (!slot_remove(next)) {
+- next = pciehp_slot_list[tempBus];
+- }
+- }
+-
+- next = pciehp_slot_list[bridge->bus];
+-
+- if (next == NULL) {
+- return 1;
+- }
+-
+- if (next == bridge) {
+- pciehp_slot_list[bridge->bus] = bridge->next;
+- kfree(bridge);
+- return 0;
+- }
+-
+- while ((next->next != bridge) && (next->next != NULL)) {
+- next = next->next;
+- }
+-
+- if (next->next == bridge) {
+- next->next = bridge->next;
+- kfree(bridge);
+- return 0;
+- } else
+- return 2;
+-}
+-
+-
+-/**
+- * pciehp_slot_find - Looks for a node by bus, and device, multiple functions accessed
+- * @bus: bus to find
+- * @device: device to find
+- * @index: is 0 for first function found, 1 for the second...
+- *
+- * Returns pointer to the node if successful, %NULL otherwise.
+- */
+-struct pci_func *pciehp_slot_find(u8 bus, u8 device, u8 index)
+-{
+- int found = -1;
+- struct pci_func *func;
+-
+- func = pciehp_slot_list[bus];
+- dbg("%s: bus %x device %x index %x\n",
+- __FUNCTION__, bus, device, index);
+- if (func != NULL) {
+- dbg("%s: func-> bus %x device %x function %x pci_dev %p\n",
+- __FUNCTION__, func->bus, func->device, func->function,
+- func->pci_dev);
+- } else
+- dbg("%s: func == NULL\n", __FUNCTION__);
+-
+- if ((func == NULL) || ((func->device == device) && (index == 0)))
+- return func;
+-
+- if (func->device == device)
+- found++;
+-
+- while (func->next != NULL) {
+- func = func->next;
+-
+- dbg("%s: In while loop, func-> bus %x device %x function %x pci_dev %p\n",
+- __FUNCTION__, func->bus, func->device, func->function,
+- func->pci_dev);
+- if (func->device == device)
+- found++;
+- dbg("%s: while loop, found %d, index %d\n", __FUNCTION__,
+- found, index);
+-
+- if ((found == index) || (func->function == index)) {
+- dbg("%s: Found bus %x dev %x func %x\n", __FUNCTION__,
+- func->bus, func->device, func->function);
+- return func;
+- }
+- }
+-
+- return NULL;
+-}
+-
+-static int is_bridge(struct pci_func * func)
+-{
+- /* Check the header type */
+- if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01)
+- return 1;
+- else
+- return 0;
+-}
+-
+-
+ /* The following routines constitute the bulk of the
+ hotplug controller logic
+ */
+@@ -472,17 +279,16 @@
+ * Configures board
+ *
+ */
+-static u32 board_added(struct pci_func * func, struct controller * ctrl)
++static u32 board_added(struct slot *p_slot)
+ {
+ u8 hp_slot;
+ u32 temp_register = 0xFFFFFFFF;
+ u32 rc = 0;
+- struct slot *p_slot;
++ struct controller *ctrl = p_slot->ctrl;
+
+- p_slot = pciehp_find_slot(ctrl, func->device);
+- hp_slot = func->device - ctrl->slot_device_offset;
++ hp_slot = p_slot->device - ctrl->slot_device_offset;
+
+- dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
++ dbg("%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, p_slot->device, ctrl->slot_device_offset, hp_slot);
+
+ /* Wait for exclusive access to hardware */
+ down(&ctrl->crit_sect);
+@@ -522,15 +328,15 @@
+ return rc;
+ }
+
+- dbg("%s: func status = %x\n", __FUNCTION__, func->status);
++ dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status);
+
+ /* Check for a power fault */
+- if (func->status == 0xFF) {
++ if (p_slot->status == 0xFF) {
+ /* power fault occurred, but it was benign */
+ temp_register = 0xFFFFFFFF;
+ dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register);
+ rc = POWER_FAILURE;
+- func->status = 0;
++ p_slot->status = 0;
+ goto err_exit;
+ }
+
+@@ -541,10 +347,9 @@
+ goto err_exit;
+ }
+
+- pciehp_save_slot_config(ctrl, func);
+- func->status = 0;
+- func->switch_save = 0x10;
+- func->is_a_board = 0x01;
++ p_slot->status = 0;
++ p_slot->switch_save = 0x10;
++ p_slot->is_a_board = 0x01;
+
+ /*
+ * Some PCI Express root ports require fixup after hot-plug operation.
+@@ -575,30 +380,27 @@
+ * remove_board - Turns off slot and LED's
+ *
+ */
+-static u32 remove_board(struct pci_func *func, struct controller *ctrl)
++static u32 remove_board(struct slot *p_slot)
+ {
+ u8 device;
+ u8 hp_slot;
+ u32 rc;
+- struct slot *p_slot;
+-
+- if (func == NULL)
+- return 1;
++ struct controller *ctrl = p_slot->ctrl;
+
+- if (pciehp_unconfigure_device(func))
++ if (pciehp_unconfigure_device(p_slot))
+ return 1;
+
+- device = func->device;
++ device = p_slot->device;
+
+- hp_slot = func->device - ctrl->slot_device_offset;
++ hp_slot = p_slot->device - ctrl->slot_device_offset;
+ p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+ dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
+
+ /* Change status to shutdown */
+- if (func->is_a_board)
+- func->status = 0x01;
+- func->configured = 0;
++ if (p_slot->is_a_board)
++ p_slot->status = 0x01;
++ p_slot->configured = 0;
+
+ /* Wait for exclusive access to hardware */
+ down(&ctrl->crit_sect);
+@@ -626,35 +428,8 @@
+ /* Done with exclusive hardware access */
+ up(&ctrl->crit_sect);
+
+- if (ctrl->add_support) {
+- while (func) {
+- if (is_bridge(func)) {
+- dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n",
+- ctrl->seg, func->bus, func->device, func->function);
+- bridge_slot_remove(func);
+- } else {
+- dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n",
+- ctrl->seg, func->bus, func->device, func->function);
+- slot_remove(func);
+- }
+-
+- func = pciehp_slot_find(ctrl->slot_bus, device, 0);
+- }
+-
+- /* Setup slot structure with entry for empty slot */
+- func = pciehp_slot_create(ctrl->slot_bus);
+-
+- if (func == NULL) {
+- return 1;
+- }
+-
+- func->bus = ctrl->slot_bus;
+- func->device = device;
+- func->function = 0;
+- func->configured = 0;
+- func->switch_save = 0x10;
+- func->is_a_board = 0;
+- }
++ p_slot->switch_save = 0x10;
++ p_slot->is_a_board = 0;
+
+ return 0;
+ }
+@@ -851,7 +626,6 @@
+ {
+ int loop = 0;
+ int change = 1;
+- struct pci_func *func;
+ u8 hp_slot;
+ u8 getstatus;
+ struct slot *p_slot;
+@@ -863,11 +637,9 @@
+ if (ctrl->event_queue[loop].event_type != 0) {
+ hp_slot = ctrl->event_queue[loop].hp_slot;
+
+- func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+-
+ p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+- dbg("hp_slot %d, func %p, p_slot %p\n", hp_slot, func, p_slot);
++ dbg("hp_slot %d, p_slot %p\n", hp_slot, p_slot);
+
+ if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) {
+ dbg("button cancel\n");
+@@ -1015,13 +787,6 @@
+ {
+ u8 getstatus = 0;
+ int rc;
+- struct pci_func *func;
+-
+- func = pciehp_slot_find(p_slot->bus, p_slot->device, 0);
+- if (!func) {
+- dbg("%s: Error! slot NULL\n", __FUNCTION__);
+- return 1;
+- }
+
+ /* Check to see if (latch closed, card present, power off) */
+ down(&p_slot->ctrl->crit_sect);
+@@ -1051,45 +816,21 @@
+ }
+ up(&p_slot->ctrl->crit_sect);
+
+- slot_remove(func);
+-
+- func = pciehp_slot_create(p_slot->bus);
+- if (func == NULL)
+- return 1;
+-
+- func->bus = p_slot->bus;
+- func->device = p_slot->device;
+- func->function = 0;
+- func->configured = 0;
+- func->is_a_board = 1;
++ p_slot->configured = 0;
++ p_slot->is_a_board = 1;
+
+ /* We have to save the presence info for these slots */
+- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
++ p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+ p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+- func->switch_save = !getstatus? 0x10:0;
++ p_slot->switch_save = !getstatus? 0x10:0;
+
+- rc = board_added(func, p_slot->ctrl);
++ rc = board_added(p_slot);
+ if (rc) {
+- if (is_bridge(func))
+- bridge_slot_remove(func);
+- else
+- slot_remove(func);
+-
+- /* Setup slot structure with entry for empty slot */
+- func = pciehp_slot_create(p_slot->bus);
+- if (func == NULL)
+- return 1; /* Out of memory */
+-
+- func->bus = p_slot->bus;
+- func->device = p_slot->device;
+- func->function = 0;
+- func->configured = 0;
+- func->is_a_board = 1;
+-
+ /* We have to save the presence info for these slots */
+- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
++ p_slot->hpc_ops->get_adapter_status(p_slot,
++ &(p_slot->presence_save));
+ p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+- func->switch_save = !getstatus? 0x10:0;
++ p_slot->switch_save = !getstatus? 0x10:0;
+ }
+
+ if (p_slot)
+@@ -1101,14 +842,8 @@
+
+ int pciehp_disable_slot(struct slot *p_slot)
+ {
+- u8 class_code, header_type, BCR;
+- u8 index = 0;
+ u8 getstatus = 0;
+- u32 rc = 0;
+ int ret = 0;
+- unsigned int devfn;
+- struct pci_bus *pci_bus = p_slot->ctrl->pci_dev->subordinate;
+- struct pci_func *func;
+
+ if (!p_slot->ctrl)
+ return 1;
+@@ -1145,54 +880,8 @@
+
+ up(&p_slot->ctrl->crit_sect);
+
+- func = pciehp_slot_find(p_slot->bus, p_slot->device, index++);
+-
+- /* Make sure there are no video controllers here
+- * for all func of p_slot
+- */
+- while (func && !rc) {
+- pci_bus->number = func->bus;
+- devfn = PCI_DEVFN(func->device, func->function);
+-
+- /* Check the Class Code */
+- rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
+- if (rc)
+- return rc;
+-
+- if (class_code == PCI_BASE_CLASS_DISPLAY) {
+- /* Display/Video adapter (not supported) */
+- rc = REMOVE_NOT_SUPPORTED;
+- } else {
+- /* See if it's a bridge */
+- rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
+- if (rc)
+- return rc;
+-
+- /* If it's a bridge, check the VGA Enable bit */
+- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+- rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR);
+- if (rc)
+- return rc;
+-
+- /* If the VGA Enable bit is set, remove isn't supported */
+- if (BCR & PCI_BRIDGE_CTL_VGA) {
+- rc = REMOVE_NOT_SUPPORTED;
+- }
+- }
+- }
+-
+- func = pciehp_slot_find(p_slot->bus, p_slot->device, index++);
+- }
+-
+- func = pciehp_slot_find(p_slot->bus, p_slot->device, 0);
+- if ((func != NULL) && !rc) {
+- rc = remove_board(func, p_slot->ctrl);
+- } else if (!rc)
+- rc = 1;
+-
+- if (p_slot)
+- update_slot_info(p_slot);
+-
+- return rc;
++ ret = remove_board(p_slot);
++ update_slot_info(p_slot);
++ return ret;
+ }
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_pci.c 2005-11-02 10:57:00.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_pci.c 2005-11-02 10:57:11.000000000 -0800
+@@ -101,346 +101,41 @@
+ return 0;
+ }
+
+-int pciehp_unconfigure_device(struct pci_func* func)
++int pciehp_unconfigure_device(struct slot *p_slot)
+ {
+ int rc = 0;
+ int j;
+- struct pci_bus *pbus;
++ u8 bctl = 0;
+
+- dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus,
+- func->device, func->function);
+- pbus = func->pci_dev->bus;
++ dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus,
++ p_slot->device);
+
+ for (j=0; j<8 ; j++) {
+- struct pci_dev* temp = pci_find_slot(func->bus,
+- (func->device << 3) | j);
+- if (temp) {
+- pci_remove_bus_device(temp);
++ struct pci_dev* temp = pci_find_slot(p_slot->bus,
++ (p_slot->device << 3) | j);
++ if (!temp)
++ continue;
++ if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
++ err("Cannot remove display device %s\n",
++ pci_name(temp));
++ continue;
+ }
++ if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
++ pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
++ if (bctl & PCI_BRIDGE_CTL_VGA) {
++ err("Cannot remove display device %s\n",
++ pci_name(temp));
++ continue;
++ }
++ }
++ pci_remove_bus_device(temp);
+ }
+ /*
+ * Some PCI Express root ports require fixup after hot-plug operation.
+ */
+ if (pcie_mch_quirk)
+- pci_fixup_device(pci_fixup_final, pbus->self);
++ pci_fixup_device(pci_fixup_final, p_slot->ctrl->pci_dev);
+
+ return rc;
+ }
+
+-/*
+- * pciehp_save_config
+- *
+- * Reads configuration for all slots in a PCI bus and saves info.
+- *
+- * Note: For non-hot plug busses, the slot # saved is the device #
+- *
+- * returns 0 if success
+- */
+-int pciehp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num)
+-{
+- int rc;
+- u8 class_code;
+- u8 header_type;
+- u32 ID;
+- u8 secondary_bus;
+- struct pci_func *new_slot;
+- int sub_bus;
+- int max_functions;
+- int function;
+- u8 DevError;
+- int device = 0;
+- int cloop = 0;
+- int stop_it;
+- int index;
+- int is_hot_plug = num_ctlr_slots || first_device_num;
+- struct pci_bus lpci_bus, *pci_bus;
+- int FirstSupported, LastSupported;
+-
+- dbg("%s: Enter\n", __FUNCTION__);
+-
+- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
+- pci_bus = &lpci_bus;
+-
+- dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__,
+- num_ctlr_slots, first_device_num);
+-
+- /* Decide which slots are supported */
+- if (is_hot_plug) {
+- /*********************************
+- * is_hot_plug is the slot mask
+- *********************************/
+- FirstSupported = first_device_num;
+- LastSupported = FirstSupported + num_ctlr_slots - 1;
+- } else {
+- FirstSupported = 0;
+- LastSupported = 0x1F;
+- }
+-
+- dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported,
+- LastSupported);
+-
+- /* Save PCI configuration space for all devices in supported slots */
+- dbg("%s: pci_bus->number = %x\n", __FUNCTION__, pci_bus->number);
+- pci_bus->number = busnumber;
+- dbg("%s: bus = %x, dev = %x\n", __FUNCTION__, busnumber, device);
+- for (device = FirstSupported; device <= LastSupported; device++) {
+- ID = 0xFFFFFFFF;
+- rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0),
+- PCI_VENDOR_ID, &ID);
+-
+- if (ID != 0xFFFFFFFF) { /* device in slot */
+- dbg("%s: ID = %x\n", __FUNCTION__, ID);
+- rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
+- 0x0B, &class_code);
+- if (rc)
+- return rc;
+-
+- rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
+- PCI_HEADER_TYPE, &header_type);
+- if (rc)
+- return rc;
+-
+- dbg("class_code = %x, header_type = %x\n", class_code, header_type);
+-
+- /* If multi-function device, set max_functions to 8 */
+- if (header_type & 0x80)
+- max_functions = 8;
+- else
+- max_functions = 1;
+-
+- function = 0;
+-
+- do {
+- DevError = 0;
+- dbg("%s: In do loop\n", __FUNCTION__);
+-
+- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* P-P Bridge */
+- /* Recurse the subordinate bus
+- * get the subordinate bus number
+- */
+- rc = pci_bus_read_config_byte(pci_bus,
+- PCI_DEVFN(device, function),
+- PCI_SECONDARY_BUS, &secondary_bus);
+- if (rc) {
+- return rc;
+- } else {
+- sub_bus = (int) secondary_bus;
+-
+- /* Save secondary bus cfg spc with this recursive call. */
+- rc = pciehp_save_config(ctrl, sub_bus, 0, 0);
+- if (rc)
+- return rc;
+- }
+- }
+-
+- index = 0;
+- new_slot = pciehp_slot_find(busnumber, device, index++);
+-
+- dbg("%s: new_slot = %p bus %x dev %x fun %x\n",
+- __FUNCTION__, new_slot, busnumber, device, index-1);
+-
+- while (new_slot && (new_slot->function != (u8) function)) {
+- new_slot = pciehp_slot_find(busnumber, device, index++);
+- dbg("%s: while loop, new_slot = %p bus %x dev %x fun %x\n",
+- __FUNCTION__, new_slot, busnumber, device, index-1);
+- }
+- if (!new_slot) {
+- /* Setup slot structure. */
+- new_slot = pciehp_slot_create(busnumber);
+- dbg("%s: if, new_slot = %p bus %x dev %x fun %x\n",
+- __FUNCTION__, new_slot, busnumber, device, function);
+-
+- if (new_slot == NULL)
+- return(1);
+- }
+-
+- new_slot->bus = (u8) busnumber;
+- new_slot->device = (u8) device;
+- new_slot->function = (u8) function;
+- new_slot->is_a_board = 1;
+- new_slot->switch_save = 0x10;
+- /* In case of unsupported board */
+- new_slot->status = DevError;
+- new_slot->pci_dev = pci_find_slot(new_slot->bus,
+- (new_slot->device << 3) | new_slot->function);
+- dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev);
+-
+- for (cloop = 0; cloop < 0x20; cloop++) {
+- rc = pci_bus_read_config_dword(pci_bus,
+- PCI_DEVFN(device, function),
+- cloop << 2,
+- (u32 *) &(new_slot->config_space [cloop]));
+- /* dbg("new_slot->config_space[%x] = %x\n",
+- cloop, new_slot->config_space[cloop]); */
+- if (rc)
+- return rc;
+- }
+-
+- function++;
+-
+- stop_it = 0;
+-
+- /* this loop skips to the next present function
+- * reading in Class Code and Header type.
+- */
+-
+- while ((function < max_functions)&&(!stop_it)) {
+- dbg("%s: In while loop \n", __FUNCTION__);
+- rc = pci_bus_read_config_dword(pci_bus,
+- PCI_DEVFN(device, function),
+- PCI_VENDOR_ID, &ID);
+-
+- if (ID == 0xFFFFFFFF) { /* nothing there. */
+- function++;
+- dbg("Nothing there\n");
+- } else { /* Something there */
+- rc = pci_bus_read_config_byte(pci_bus,
+- PCI_DEVFN(device, function),
+- 0x0B, &class_code);
+- if (rc)
+- return rc;
+-
+- rc = pci_bus_read_config_byte(pci_bus,
+- PCI_DEVFN(device, function),
+- PCI_HEADER_TYPE, &header_type);
+- if (rc)
+- return rc;
+-
+- dbg("class_code = %x, header_type = %x\n", class_code, header_type);
+- stop_it++;
+- }
+- }
+-
+- } while (function < max_functions);
+- /* End of IF (device in slot?) */
+- } else if (is_hot_plug) {
+- /* Setup slot structure with entry for empty slot */
+- new_slot = pciehp_slot_create(busnumber);
+-
+- if (new_slot == NULL) {
+- return(1);
+- }
+- dbg("new_slot = %p, bus = %x, dev = %x, fun = %x\n", new_slot,
+- new_slot->bus, new_slot->device, new_slot->function);
+-
+- new_slot->bus = (u8) busnumber;
+- new_slot->device = (u8) device;
+- new_slot->function = 0;
+- new_slot->is_a_board = 0;
+- new_slot->presence_save = 0;
+- new_slot->switch_save = 0;
+- }
+- } /* End of FOR loop */
+-
+- dbg("%s: Exit\n", __FUNCTION__);
+- return(0);
+-}
+-
+-
+-/*
+- * pciehp_save_slot_config
+- *
+- * Saves configuration info for all PCI devices in a given slot
+- * including subordinate busses.
+- *
+- * returns 0 if success
+- */
+-int pciehp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot)
+-{
+- int rc;
+- u8 class_code;
+- u8 header_type;
+- u32 ID;
+- u8 secondary_bus;
+- int sub_bus;
+- int max_functions;
+- int function;
+- int cloop = 0;
+- int stop_it;
+- struct pci_bus lpci_bus, *pci_bus;
+- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
+- pci_bus = &lpci_bus;
+- pci_bus->number = new_slot->bus;
+-
+- ID = 0xFFFFFFFF;
+-
+- pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0),
+- PCI_VENDOR_ID, &ID);
+-
+- if (ID != 0xFFFFFFFF) { /* device in slot */
+- pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
+- 0x0B, &class_code);
+-
+- pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
+- PCI_HEADER_TYPE, &header_type);
+-
+- if (header_type & 0x80) /* Multi-function device */
+- max_functions = 8;
+- else
+- max_functions = 1;
+-
+- function = 0;
+-
+- do {
+- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
+- /* Recurse the subordinate bus */
+- pci_bus_read_config_byte(pci_bus,
+- PCI_DEVFN(new_slot->device, function),
+- PCI_SECONDARY_BUS, &secondary_bus);
+-
+- sub_bus = (int) secondary_bus;
+-
+- /* Save the config headers for the secondary bus. */
+- rc = pciehp_save_config(ctrl, sub_bus, 0, 0);
+-
+- if (rc)
+- return rc;
+-
+- } /* End of IF */
+-
+- new_slot->status = 0;
+-
+- for (cloop = 0; cloop < 0x20; cloop++) {
+- pci_bus_read_config_dword(pci_bus,
+- PCI_DEVFN(new_slot->device, function),
+- cloop << 2,
+- (u32 *) &(new_slot->config_space [cloop]));
+- }
+-
+- function++;
+-
+- stop_it = 0;
+-
+- /* this loop skips to the next present function
+- * reading in the Class Code and the Header type.
+- */
+-
+- while ((function < max_functions) && (!stop_it)) {
+- pci_bus_read_config_dword(pci_bus,
+- PCI_DEVFN(new_slot->device, function),
+- PCI_VENDOR_ID, &ID);
+-
+- if (ID == 0xFFFFFFFF) { /* nothing there. */
+- function++;
+- } else { /* Something there */
+- pci_bus_read_config_byte(pci_bus,
+- PCI_DEVFN(new_slot->device, function),
+- 0x0B, &class_code);
+-
+- pci_bus_read_config_byte(pci_bus,
+- PCI_DEVFN(new_slot->device, function),
+- PCI_HEADER_TYPE, &header_type);
+-
+- stop_it++;
+- }
+- }
+-
+- } while (function < max_functions);
+- } /* End of IF (device in slot?) */
+- else {
+- return 2;
+- }
+-
+- return 0;
+-}
+-
diff --git a/pci/pci-pciehp-04.patch b/pci/pci-pciehp-04.patch
new file mode 100644
index 0000000000000..ca65298894f6e
--- /dev/null
+++ b/pci/pci-pciehp-04.patch
@@ -0,0 +1,487 @@
+From owner-linux-pci@atrey.karlin.mff.cuni.cz Mon Oct 31 16:31:25 2005
+Message-Id: <20051101002123.615058591@csdlinux-2.jf.intel.com>
+Date: Mon, 31 Oct 2005 16:20:09 -0800
+From: rajesh.shah@intel.com
+To: kristen.c.accardi@intel.com, gregkh@suse.de
+Cc: akpm@osdl.org, rajesh.shah@intel.com
+Subject: [patch 4/8] pciehp: miscellaneous cleanups
+Content-Disposition: inline; filename=pciehp-misc-cleanups
+
+Remove un-necessary header includes, remove dead code, remove
+some hardcoded constants...
+
+Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+ drivers/pci/hotplug/pciehp.h | 44 ++++++++++++-------------
+ drivers/pci/hotplug/pciehp_core.c | 14 --------
+ drivers/pci/hotplug/pciehp_ctrl.c | 56 +++++++--------------------------
+ drivers/pci/hotplug/pciehp_hpc.c | 38 ++--------------------
+ drivers/pci/hotplug/pciehp_pci.c | 4 --
+ drivers/pci/hotplug/pciehprm_acpi.c | 6 ---
+ drivers/pci/hotplug/pciehprm_nonacpi.c | 12 -------
+ 7 files changed, 41 insertions(+), 133 deletions(-)
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp.h 2005-11-02 10:57:13.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp.h 2005-11-02 10:57:16.000000000 -0800
+@@ -32,8 +32,6 @@
+ #include <linux/types.h>
+ #include <linux/pci.h>
+ #include <linux/delay.h>
+-#include <asm/semaphore.h>
+-#include <asm/io.h>
+ #include <linux/pcieport_if.h>
+ #include "pci_hotplug.h"
+
+@@ -62,13 +60,7 @@
+ u8 device;
+ u16 status;
+ u32 number;
+- u8 is_a_board;
+- u8 configured;
+ u8 state;
+- u8 switch_save;
+- u8 presence_save;
+- u32 capabilities;
+- u16 reserved2;
+ struct timer_list task_event;
+ u8 hp_slot;
+ struct controller *ctrl;
+@@ -82,27 +74,42 @@
+ u8 hp_slot;
+ };
+
++typedef u8(*php_intr_callback_t) (u8 hp_slot, void *instance_id);
++
++struct php_ctlr_state_s {
++ struct php_ctlr_state_s *pnext;
++ struct pci_dev *pci_dev;
++ unsigned int irq;
++ unsigned long flags; /* spinlock's */
++ u32 slot_device_offset;
++ u32 num_slots;
++ struct timer_list int_poll_timer; /* Added for poll event */
++ php_intr_callback_t attention_button_callback;
++ php_intr_callback_t switch_change_callback;
++ php_intr_callback_t presence_change_callback;
++ php_intr_callback_t power_fault_callback;
++ void *callback_instance_id;
++ struct ctrl_reg *creg; /* Ptr to controller register space */
++};
++
++#define MAX_EVENTS 10
+ struct controller {
+ struct controller *next;
+ struct semaphore crit_sect; /* critical section semaphore */
+- void *hpc_ctlr_handle; /* HPC controller handle */
++ struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */
+ int num_slots; /* Number of slots on ctlr */
+ int slot_num_inc; /* 1 or -1 */
+ struct pci_dev *pci_dev;
+ struct pci_bus *pci_bus;
+- struct event_info event_queue[10];
++ struct event_info event_queue[MAX_EVENTS];
+ struct slot *slot;
+ struct hpc_ops *hpc_ops;
+ wait_queue_head_t queue; /* sleep & wake process */
+ u8 next_event;
+- u8 seg;
+ u8 bus;
+ u8 device;
+ u8 function;
+- u8 rev;
+ u8 slot_device_offset;
+- u8 add_support;
+- enum pci_bus_speed speed;
+ u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */
+ u8 slot_bus; /* Bus where the slots handled by this controller sit */
+ u8 ctrlcap;
+@@ -250,14 +257,7 @@
+ ACPI
+ };
+
+-typedef u8(*php_intr_callback_t) (unsigned int change_id, void *instance_id);
+-
+-int pcie_init(struct controller *ctrl, struct pcie_device *dev,
+- php_intr_callback_t attention_button_callback,
+- php_intr_callback_t switch_change_callback,
+- php_intr_callback_t presence_change_callback,
+- php_intr_callback_t power_fault_callback);
+-
++int pcie_init(struct controller *ctrl, struct pcie_device *dev);
+
+ /* This has no meaning for PCI Express, as there is only 1 slot per port */
+ int pcie_get_ctlr_slot_config(struct controller *ctrl,
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_core.c 2005-11-02 10:57:13.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_core.c 2005-11-02 10:57:16.000000000 -0800
+@@ -27,17 +27,11 @@
+ *
+ */
+
+-#include <linux/config.h>
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+ #include <linux/kernel.h>
+ #include <linux/types.h>
+-#include <linux/proc_fs.h>
+-#include <linux/slab.h>
+-#include <linux/workqueue.h>
+ #include <linux/pci.h>
+-#include <linux/init.h>
+-#include <asm/uaccess.h>
+ #include "pciehp.h"
+ #include <linux/interrupt.h>
+
+@@ -381,11 +375,7 @@
+ pdev = dev->port;
+ ctrl->pci_dev = pdev;
+
+- rc = pcie_init(ctrl, dev,
+- (php_intr_callback_t) pciehp_handle_attention_button,
+- (php_intr_callback_t) pciehp_handle_switch_change,
+- (php_intr_callback_t) pciehp_handle_presence_change,
+- (php_intr_callback_t) pciehp_handle_power_fault);
++ rc = pcie_init(ctrl, dev);
+ if (rc) {
+ dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME);
+ goto err_out_free_ctrl;
+@@ -421,8 +411,6 @@
+ first_device_num = ctrl->slot_device_offset;
+ num_ctlr_slots = ctrl->num_slots;
+
+- ctrl->add_support = 1;
+-
+ /* Setup the slot information structures */
+ rc = init_slots(ctrl);
+ if (rc) {
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_ctrl.c 2005-11-02 10:57:13.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_ctrl.c 2005-11-02 10:57:16.000000000 -0800
+@@ -27,15 +27,9 @@
+ *
+ */
+
+-#include <linux/config.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/types.h>
+-#include <linux/slab.h>
+-#include <linux/workqueue.h>
+-#include <linux/interrupt.h>
+-#include <linux/delay.h>
+-#include <linux/wait.h>
+ #include <linux/smp_lock.h>
+ #include <linux/pci.h>
+ #include "../pci.h"
+@@ -64,10 +58,9 @@
+ taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+ p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+- p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+ p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+
+- ctrl->next_event = (ctrl->next_event + 1) % 10;
++ ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
+ taskInfo->hp_slot = hp_slot;
+
+ rc++;
+@@ -118,12 +111,11 @@
+ * what to do
+ */
+ taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+- ctrl->next_event = (ctrl->next_event + 1) % 10;
++ ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
+ taskInfo->hp_slot = hp_slot;
+
+ rc++;
+ p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+- p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+ p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+
+ if (getstatus) {
+@@ -131,14 +123,12 @@
+ * Switch opened
+ */
+ info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
+- p_slot->switch_save = 0;
+ taskInfo->event_type = INT_SWITCH_OPEN;
+ } else {
+ /*
+ * Switch closed
+ */
+ info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
+- p_slot->switch_save = 0x10;
+ taskInfo->event_type = INT_SWITCH_CLOSE;
+ }
+
+@@ -152,7 +142,7 @@
+ {
+ struct controller *ctrl = (struct controller *) inst_id;
+ struct slot *p_slot;
+- u8 rc = 0;
++ u8 presence_save, rc = 0;
+ struct event_info *taskInfo;
+
+ /* Presence Change */
+@@ -162,7 +152,7 @@
+ * what to do
+ */
+ taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+- ctrl->next_event = (ctrl->next_event + 1) % 10;
++ ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
+ taskInfo->hp_slot = hp_slot;
+
+ rc++;
+@@ -171,8 +161,8 @@
+ /* Switch is open, assume a presence change
+ * Save the presence state
+ */
+- p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+- if (p_slot->presence_save) {
++ p_slot->hpc_ops->get_adapter_status(p_slot, &presence_save);
++ if (presence_save) {
+ /*
+ * Card Present
+ */
+@@ -206,7 +196,7 @@
+ * what to do
+ */
+ taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+- ctrl->next_event = (ctrl->next_event + 1) % 10;
++ ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
+ taskInfo->hp_slot = hp_slot;
+
+ rc++;
+@@ -279,11 +269,10 @@
+ * Configures board
+ *
+ */
+-static u32 board_added(struct slot *p_slot)
++static int board_added(struct slot *p_slot)
+ {
+ u8 hp_slot;
+- u32 temp_register = 0xFFFFFFFF;
+- u32 rc = 0;
++ int rc = 0;
+ struct controller *ctrl = p_slot->ctrl;
+
+ hp_slot = p_slot->device - ctrl->slot_device_offset;
+@@ -333,8 +322,6 @@
+ /* Check for a power fault */
+ if (p_slot->status == 0xFF) {
+ /* power fault occurred, but it was benign */
+- temp_register = 0xFFFFFFFF;
+- dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register);
+ rc = POWER_FAILURE;
+ p_slot->status = 0;
+ goto err_exit;
+@@ -348,8 +335,6 @@
+ }
+
+ p_slot->status = 0;
+- p_slot->switch_save = 0x10;
+- p_slot->is_a_board = 0x01;
+
+ /*
+ * Some PCI Express root ports require fixup after hot-plug operation.
+@@ -380,11 +365,11 @@
+ * remove_board - Turns off slot and LED's
+ *
+ */
+-static u32 remove_board(struct slot *p_slot)
++static int remove_board(struct slot *p_slot)
+ {
+ u8 device;
+ u8 hp_slot;
+- u32 rc;
++ int rc;
+ struct controller *ctrl = p_slot->ctrl;
+
+ if (pciehp_unconfigure_device(p_slot))
+@@ -398,9 +383,7 @@
+ dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
+
+ /* Change status to shutdown */
+- if (p_slot->is_a_board)
+- p_slot->status = 0x01;
+- p_slot->configured = 0;
++ p_slot->status = 0x01;
+
+ /* Wait for exclusive access to hardware */
+ down(&ctrl->crit_sect);
+@@ -428,9 +411,6 @@
+ /* Done with exclusive hardware access */
+ up(&ctrl->crit_sect);
+
+- p_slot->switch_save = 0x10;
+- p_slot->is_a_board = 0;
+-
+ return 0;
+ }
+
+@@ -633,7 +613,7 @@
+ while (change) {
+ change = 0;
+
+- for (loop = 0; loop < 10; loop++) {
++ for (loop = 0; loop < MAX_EVENTS; loop++) {
+ if (ctrl->event_queue[loop].event_type != 0) {
+ hp_slot = ctrl->event_queue[loop].hp_slot;
+
+@@ -816,21 +796,11 @@
+ }
+ up(&p_slot->ctrl->crit_sect);
+
+- p_slot->configured = 0;
+- p_slot->is_a_board = 1;
+-
+- /* We have to save the presence info for these slots */
+- p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+ p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+- p_slot->switch_save = !getstatus? 0x10:0;
+
+ rc = board_added(p_slot);
+ if (rc) {
+- /* We have to save the presence info for these slots */
+- p_slot->hpc_ops->get_adapter_status(p_slot,
+- &(p_slot->presence_save));
+ p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+- p_slot->switch_save = !getstatus? 0x10:0;
+ }
+
+ if (p_slot)
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_hpc.c 2005-11-02 10:57:10.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_hpc.c 2005-11-02 10:57:16.000000000 -0800
+@@ -27,16 +27,10 @@
+ *
+ */
+
+-#include <linux/config.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/types.h>
+-#include <linux/slab.h>
+-#include <linux/vmalloc.h>
+-#include <linux/interrupt.h>
+-#include <linux/spinlock.h>
+ #include <linux/pci.h>
+-#include <asm/system.h>
+ #include "../pci.h"
+ #include "pciehp.h"
+
+@@ -217,23 +211,6 @@
+ #define MRL_STATE 0x0020
+ #define PRSN_STATE 0x0040
+
+-struct php_ctlr_state_s {
+- struct php_ctlr_state_s *pnext;
+- struct pci_dev *pci_dev;
+- unsigned int irq;
+- unsigned long flags; /* spinlock's */
+- u32 slot_device_offset;
+- u32 num_slots;
+- struct timer_list int_poll_timer; /* Added for poll event */
+- php_intr_callback_t attention_button_callback;
+- php_intr_callback_t switch_change_callback;
+- php_intr_callback_t presence_change_callback;
+- php_intr_callback_t power_fault_callback;
+- void *callback_instance_id;
+- struct ctrl_reg *creg; /* Ptr to controller register space */
+-};
+-
+-
+ static spinlock_t hpc_event_lock;
+
+ DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */
+@@ -1248,12 +1225,7 @@
+ .check_lnk_status = hpc_check_lnk_status,
+ };
+
+-int pcie_init(struct controller * ctrl,
+- struct pcie_device *dev,
+- php_intr_callback_t attention_button_callback,
+- php_intr_callback_t switch_change_callback,
+- php_intr_callback_t presence_change_callback,
+- php_intr_callback_t power_fault_callback)
++int pcie_init(struct controller * ctrl, struct pcie_device *dev)
+ {
+ struct php_ctlr_state_s *php_ctlr, *p;
+ void *instance_id = ctrl;
+@@ -1362,10 +1334,10 @@
+ dbg("HPC interrupt = %d\n", php_ctlr->irq);
+
+ /* Save interrupt callback info */
+- php_ctlr->attention_button_callback = attention_button_callback;
+- php_ctlr->switch_change_callback = switch_change_callback;
+- php_ctlr->presence_change_callback = presence_change_callback;
+- php_ctlr->power_fault_callback = power_fault_callback;
++ php_ctlr->attention_button_callback = pciehp_handle_attention_button;
++ php_ctlr->switch_change_callback = pciehp_handle_switch_change;
++ php_ctlr->presence_change_callback = pciehp_handle_presence_change;
++ php_ctlr->power_fault_callback = pciehp_handle_power_fault;
+ php_ctlr->callback_instance_id = instance_id;
+
+ /* return PCI Controller Info */
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_pci.c 2005-11-02 10:57:13.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_pci.c 2005-11-02 10:57:16.000000000 -0800
+@@ -27,13 +27,9 @@
+ *
+ */
+
+-#include <linux/config.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/types.h>
+-#include <linux/slab.h>
+-#include <linux/workqueue.h>
+-#include <linux/proc_fs.h>
+ #include <linux/pci.h>
+ #include "../pci.h"
+ #include "pciehp.h"
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehprm_acpi.c 2005-11-02 10:57:10.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehprm_acpi.c 2005-11-02 10:57:16.000000000 -0800
+@@ -24,18 +24,12 @@
+ *
+ */
+
+-#include <linux/config.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/types.h>
+ #include <linux/pci.h>
+-#include <linux/init.h>
+ #include <linux/acpi.h>
+-#include <linux/efi.h>
+ #include <linux/pci-acpi.h>
+-#include <asm/uaccess.h>
+-#include <asm/system.h>
+-#include <acpi/acpi.h>
+ #include <acpi/acpi_bus.h>
+ #include <acpi/actypes.h>
+ #include "pciehp.h"
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehprm_nonacpi.c 2005-11-02 10:57:10.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehprm_nonacpi.c 2005-11-02 10:58:13.000000000 -0800
+@@ -27,24 +27,12 @@
+ *
+ */
+
+-#include <linux/config.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/types.h>
+ #include <linux/pci.h>
+-#include <linux/init.h>
+ #include <linux/slab.h>
+-#include <asm/uaccess.h>
+ #include "pciehp.h"
+-#include "pciehprm_nonacpi.h"
+-
+-
+-int pciehprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
+-{
+-
+- *sun = (u8) (ctrl->first_slot);
+- return 0;
+-}
+
+ void get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp)
diff --git a/pci/pci-pciehp-05.patch b/pci/pci-pciehp-05.patch
new file mode 100644
index 0000000000000..f930358ce9a0b
--- /dev/null
+++ b/pci/pci-pciehp-05.patch
@@ -0,0 +1,533 @@
+From owner-linux-pci@atrey.karlin.mff.cuni.cz Mon Oct 31 16:32:33 2005
+Message-Id: <20051101002123.950096242@csdlinux-2.jf.intel.com>
+Date: Mon, 31 Oct 2005 16:20:10 -0800
+From: rajesh.shah@intel.com
+To: kristen.c.accardi@intel.com, gregkh@suse.de
+Cc: akpm@osdl.org, rajesh.shah@intel.com
+Subject: [patch 5/8] pciehp: reduce debug message verbosity
+Content-Disposition: inline; filename=pciehp-reduce-dbg-verbosity
+
+Reduce the number of debug messages generated if pciehp debug is
+enabled. I tried to restrict this to removing debug messages that
+are either early-driver-debug type messages, or print information
+that can be inferred through other debug prints.
+
+Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+ drivers/pci/hotplug/pciehp.h | 5 ---
+ drivers/pci/hotplug/pciehp_core.c | 9 -----
+ drivers/pci/hotplug/pciehp_ctrl.c | 24 +++++++--------
+ drivers/pci/hotplug/pciehp_hpc.c | 59 ++++++++++----------------------------
+ 4 files changed, 28 insertions(+), 69 deletions(-)
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp.h 2005-11-02 10:58:29.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp.h 2005-11-02 10:58:33.000000000 -0800
+@@ -207,12 +207,9 @@
+
+ p_slot = ctrl->slot;
+
+- dbg("p_slot = %p\n", p_slot);
+-
+ while (p_slot && (p_slot->device != device)) {
+ tmp_slot = p_slot;
+ p_slot = p_slot->next;
+- dbg("In while loop, p_slot = %p\n", p_slot);
+ }
+ if (p_slot == NULL) {
+ err("ERROR: pciehp_find_slot device=0x%x\n", device);
+@@ -228,7 +225,6 @@
+
+ DECLARE_WAITQUEUE(wait, current);
+
+- dbg("%s : start\n", __FUNCTION__);
+ add_wait_queue(&ctrl->queue, &wait);
+ if (!pciehp_poll_mode)
+ /* Sleep for up to 1 second */
+@@ -240,7 +236,6 @@
+ if (signal_pending(current))
+ retval = -EINTR;
+
+- dbg("%s : end\n", __FUNCTION__);
+ return retval;
+ }
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_core.c 2005-11-02 10:58:29.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_core.c 2005-11-02 10:58:33.000000000 -0800
+@@ -106,8 +106,6 @@
+ u32 slot_number;
+ int result = -ENOMEM;
+
+- dbg("%s\n",__FUNCTION__);
+-
+ number_of_slots = ctrl->num_slots;
+ slot_device = ctrl->slot_device_offset;
+ slot_number = ctrl->first_slot;
+@@ -362,7 +360,6 @@
+ u8 value;
+ struct pci_dev *pdev;
+
+- dbg("%s: Called by hp_drv\n", __FUNCTION__);
+ ctrl = kmalloc(sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl) {
+ err("%s : out of memory\n", __FUNCTION__);
+@@ -370,8 +367,6 @@
+ }
+ memset(ctrl, 0, sizeof(struct controller));
+
+- dbg("%s: DRV_thread pid = %d\n", __FUNCTION__, current->pid);
+-
+ pdev = dev->port;
+ ctrl->pci_dev = pdev;
+
+@@ -389,7 +384,6 @@
+ rc = -ENOMEM;
+ goto err_out_unmap_mmio_region;
+ }
+- dbg("%s: ctrl->pci_bus %p\n", __FUNCTION__, ctrl->pci_bus);
+ memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus));
+ ctrl->bus = pdev->bus->number; /* ctrl bus */
+ ctrl->slot_bus = pdev->subordinate->number; /* bus controlled by this HPC */
+@@ -419,7 +413,6 @@
+ }
+
+ t_slot = pciehp_find_slot(ctrl, first_device_num);
+- dbg("%s: t_slot %p\n", __FUNCTION__, t_slot);
+
+ /* Finish setting up the hot plug ctrl device */
+ ctrl->next_event = 0;
+@@ -436,7 +429,6 @@
+ down(&ctrl->crit_sect);
+
+ t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
+- dbg("%s: adpater value %x\n", __FUNCTION__, value);
+
+ if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
+ rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
+@@ -585,7 +577,6 @@
+ dbg("unload_pciehpd()\n");
+ unload_pciehpd();
+
+- dbg("pcie_port_service_unregister\n");
+ pcie_port_service_unregister(&hpdriver_portdrv);
+
+ info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_ctrl.c 2005-11-02 10:58:29.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_ctrl.c 2005-11-02 10:58:33.000000000 -0800
+@@ -277,7 +277,9 @@
+
+ hp_slot = p_slot->device - ctrl->slot_device_offset;
+
+- dbg("%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, p_slot->device, ctrl->slot_device_offset, hp_slot);
++ dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n",
++ __FUNCTION__, p_slot->device,
++ ctrl->slot_device_offset, hp_slot);
+
+ /* Wait for exclusive access to hardware */
+ down(&ctrl->crit_sect);
+@@ -305,9 +307,7 @@
+ up(&ctrl->crit_sect);
+
+ /* Wait for ~1 second */
+- dbg("%s: before long_delay\n", __FUNCTION__);
+ wait_for_ctrl_irq (ctrl);
+- dbg("%s: afterlong_delay\n", __FUNCTION__);
+
+ /* Check link training status */
+ rc = p_slot->hpc_ops->check_lnk_status(ctrl);
+@@ -444,13 +444,15 @@
+ p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+ if (getstatus) {
+ p_slot->state = POWEROFF_STATE;
+- dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
++ dbg("%s: disabling bus:device(%x:%x)\n", __FUNCTION__,
++ p_slot->bus, p_slot->device);
+
+ pciehp_disable_slot(p_slot);
+ p_slot->state = STATIC_STATE;
+ } else {
+ p_slot->state = POWERON_STATE;
+- dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
++ dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__,
++ p_slot->bus, p_slot->device);
+
+ if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
+ /* Wait for exclusive access to hardware */
+@@ -492,13 +494,15 @@
+ p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
+ if (!getstatus) {
+ p_slot->state = POWEROFF_STATE;
+- dbg("In removing board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
++ dbg("%s: removing bus:device(%x:%x)\n",
++ __FUNCTION__, p_slot->bus, p_slot->device);
+
+ pciehp_disable_slot(p_slot);
+ p_slot->state = STATIC_STATE;
+ } else {
+ p_slot->state = POWERON_STATE;
+- dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
++ dbg("%s: adding bus:device(%x:%x)\n",
++ __FUNCTION__, p_slot->bus, p_slot->device);
+
+ if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
+ /* Wait for exclusive access to hardware */
+@@ -564,7 +568,6 @@
+ err ("Can't start up our event thread\n");
+ return -1;
+ }
+- dbg("Our event thread pid = %d\n", pid);
+ return 0;
+ }
+
+@@ -572,9 +575,7 @@
+ void pciehp_event_stop_thread(void)
+ {
+ event_finished = 1;
+- dbg("event_thread finish command given\n");
+ up(&event_semaphore);
+- dbg("wait for event_thread to exit\n");
+ down(&event_exit);
+ }
+
+@@ -619,8 +620,6 @@
+
+ p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+- dbg("hp_slot %d, p_slot %p\n", hp_slot, p_slot);
+-
+ if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) {
+ dbg("button cancel\n");
+ del_timer(&p_slot->task_event);
+@@ -712,7 +711,6 @@
+ p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
+ p_slot->task_event.data = (unsigned long) p_slot;
+
+- dbg("add_timer p_slot = %p\n", (void *) p_slot);
+ add_timer(&p_slot->task_event);
+ }
+ }
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_hpc.c 2005-11-02 10:58:29.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_hpc.c 2005-11-02 10:58:33.000000000 -0800
+@@ -274,7 +274,6 @@
+
+ DBG_ENTER_ROUTINE
+
+- dbg("%s : Enter\n", __FUNCTION__);
+ if (!php_ctlr) {
+ err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+ return -1;
+@@ -285,7 +284,6 @@
+ err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
+ return retval;
+ }
+- dbg("%s : hp_register_read_word SLOT_STATUS %x\n", __FUNCTION__, slot_status);
+
+ if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) {
+ /* After 1 sec and CMD_COMPLETED still not set, just proceed forward to issue
+@@ -293,14 +291,11 @@
+ dbg("%s : CMD_COMPLETED not clear after 1 sec.\n", __FUNCTION__);
+ }
+
+- dbg("%s: Before hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd);
+ retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), cmd | CMD_CMPL_INTR_ENABLE);
+ if (retval) {
+ err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
+ return retval;
+ }
+- dbg("%s : hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd | CMD_CMPL_INTR_ENABLE);
+- dbg("%s : Exit\n", __FUNCTION__);
+
+ DBG_LEAVE_ROUTINE
+ return retval;
+@@ -516,7 +511,8 @@
+ u16 slot_ctrl;
+ int rc = 0;
+
+- dbg("%s: \n", __FUNCTION__);
++ DBG_ENTER_ROUTINE
++
+ if (!php_ctlr) {
+ err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+ return -1;
+@@ -532,7 +528,6 @@
+ err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+ return rc;
+ }
+- dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
+
+ switch (value) {
+ case 0 : /* turn off */
+@@ -553,6 +548,7 @@
+ pcie_write_cmd(slot, slot_cmd);
+ dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
+
++ DBG_LEAVE_ROUTINE
+ return rc;
+ }
+
+@@ -564,7 +560,8 @@
+ u16 slot_ctrl;
+ int rc = 0;
+
+- dbg("%s: \n", __FUNCTION__);
++ DBG_ENTER_ROUTINE
++
+ if (!php_ctlr) {
+ err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+ return ;
+@@ -581,7 +578,6 @@
+ err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+ return;
+ }
+- dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
+ slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100;
+ if (!pciehp_poll_mode)
+ slot_cmd = slot_cmd | HP_INTR_ENABLE;
+@@ -589,6 +585,7 @@
+ pcie_write_cmd(slot, slot_cmd);
+
+ dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
++ DBG_LEAVE_ROUTINE
+ return;
+ }
+
+@@ -599,7 +596,8 @@
+ u16 slot_ctrl;
+ int rc = 0;
+
+- dbg("%s: \n", __FUNCTION__);
++ DBG_ENTER_ROUTINE
++
+ if (!php_ctlr) {
+ err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+ return ;
+@@ -616,7 +614,6 @@
+ err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+ return;
+ }
+- dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
+
+ slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300;
+
+@@ -625,6 +622,7 @@
+ pcie_write_cmd(slot, slot_cmd);
+ dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
+
++ DBG_LEAVE_ROUTINE
+ return;
+ }
+
+@@ -635,7 +633,8 @@
+ u16 slot_ctrl;
+ int rc = 0;
+
+- dbg("%s: \n", __FUNCTION__);
++ DBG_ENTER_ROUTINE
++
+ if (!php_ctlr) {
+ err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+ return ;
+@@ -652,7 +651,6 @@
+ err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+ return;
+ }
+- dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
+
+ slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200;
+
+@@ -661,6 +659,7 @@
+ pcie_write_cmd(slot, slot_cmd);
+
+ dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
++ DBG_LEAVE_ROUTINE
+ return;
+ }
+
+@@ -757,7 +756,6 @@
+ int retval = 0;
+
+ DBG_ENTER_ROUTINE
+- dbg("%s: \n", __FUNCTION__);
+
+ if (!php_ctlr) {
+ err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+@@ -776,8 +774,6 @@
+ err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+ return retval;
+ }
+- dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base),
+- slot_ctrl);
+
+ slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON;
+
+@@ -806,7 +802,6 @@
+ int retval = 0;
+
+ DBG_ENTER_ROUTINE
+- dbg("%s: \n", __FUNCTION__);
+
+ if (!php_ctlr) {
+ err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+@@ -825,8 +820,6 @@
+ err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+ return retval;
+ }
+- dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base),
+- slot_ctrl);
+
+ slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF;
+
+@@ -901,7 +894,6 @@
+ return IRQ_NONE;
+ }
+
+- dbg("%s: Set Mask Hot-plug Interrupt Enable\n", __FUNCTION__);
+ dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
+ temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;
+
+@@ -910,7 +902,6 @@
+ err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
+ return IRQ_NONE;
+ }
+- dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
+
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
+ if (rc) {
+@@ -926,14 +917,12 @@
+ err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
+ return IRQ_NONE;
+ }
+- dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word);
+ }
+
+ if (intr_loc & CMD_COMPLETED) {
+ /*
+ * Command Complete Interrupt Pending
+ */
+- dbg("%s: In Command Complete Interrupt Pending\n", __FUNCTION__);
+ wake_up_interruptible(&ctrl->queue);
+ }
+
+@@ -966,7 +955,6 @@
+ }
+
+ dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__);
+- dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
+ temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
+
+ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word);
+@@ -974,14 +962,12 @@
+ err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
+ return IRQ_NONE;
+ }
+- dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
+
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
+ if (rc) {
+ err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
+ return IRQ_NONE;
+ }
+- dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status);
+
+ /* Clear command complete interrupt caused by this write */
+ temp_word = 0x1F;
+@@ -1254,8 +1240,8 @@
+ pdev = dev->port;
+ php_ctlr->pci_dev = pdev; /* save pci_dev in context */
+
+- dbg("%s: pdev->vendor %x pdev->device %x\n", __FUNCTION__,
+- pdev->vendor, pdev->device);
++ dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
++ __FUNCTION__, pdev->vendor, pdev->device);
+
+ saved_cap_base = pcie_cap_base;
+
+@@ -1312,8 +1298,6 @@
+ first = 0;
+ }
+
+- dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number,
+- PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq);
+ for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
+ if (pci_resource_len(pdev, rc) > 0)
+ dbg("pci resource[%d] start=0x%lx(len=0x%lx)\n", rc,
+@@ -1331,7 +1315,6 @@
+
+ /* find the IRQ */
+ php_ctlr->irq = dev->irq;
+- dbg("HPC interrupt = %d\n", php_ctlr->irq);
+
+ /* Save interrupt callback info */
+ php_ctlr->attention_button_callback = pciehp_handle_attention_button;
+@@ -1359,15 +1342,12 @@
+ err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
+ goto abort_free_ctlr;
+ }
+- dbg("%s : Mask HPIE hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, temp_word);
+
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
+ if (rc) {
+ err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
+ goto abort_free_ctlr;
+ }
+- dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base)
+- , slot_status);
+
+ temp_word = 0x1F; /* Clear all events */
+ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
+@@ -1375,7 +1355,6 @@
+ err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
+ goto abort_free_ctlr;
+ }
+- dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word);
+
+ if (pciehp_poll_mode) {/* Install interrupt polling code */
+ /* Install and start the interrupt polling timer */
+@@ -1391,13 +1370,14 @@
+ }
+ }
+
++ dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
++ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq);
++
+ rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
+ if (rc) {
+ err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+ goto abort_free_ctlr;
+ }
+- dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), temp_word);
+- dbg("%s: slot_cap %x\n", __FUNCTION__, slot_cap);
+
+ intr_enable = intr_enable | PRSN_DETECT_ENABLE;
+
+@@ -1417,7 +1397,6 @@
+ } else {
+ temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
+ }
+- dbg("%s: temp_word %x\n", __FUNCTION__, temp_word);
+
+ /* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */
+ rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
+@@ -1425,14 +1404,11 @@
+ err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
+ goto abort_free_ctlr;
+ }
+- dbg("%s : Unmask HPIE hp_register_write_word SLOT_CTRL with %x\n", __FUNCTION__, temp_word);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
+ if (rc) {
+ err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
+ goto abort_free_ctlr;
+ }
+- dbg("%s: Unmask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__,
+- SLOT_STATUS(ctrl->cap_base), slot_status);
+
+ temp_word = 0x1F; /* Clear all events */
+ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
+@@ -1440,7 +1416,6 @@
+ err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
+ goto abort_free_ctlr;
+ }
+- dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word);
+
+ rc = get_hp_hw_control_from_firmware(ctrl->pci_dev);
+ if (rc)
diff --git a/pci/pci-pciehp-06.patch b/pci/pci-pciehp-06.patch
new file mode 100644
index 0000000000000..250387b5f9efc
--- /dev/null
+++ b/pci/pci-pciehp-06.patch
@@ -0,0 +1,108 @@
+From owner-linux-pci@atrey.karlin.mff.cuni.cz Mon Oct 31 16:31:09 2005
+Message-Id: <20051101002124.233201779@csdlinux-2.jf.intel.com>
+Date: Mon, 31 Oct 2005 16:20:11 -0800
+From: rajesh.shah@intel.com
+To: kristen.c.accardi@intel.com, gregkh@suse.de
+Cc: akpm@osdl.org, rajesh.shah@intel.com
+Subject: [patch 6/8] pciehp: request control of each hotplug controller individually
+Content-Disposition: inline; filename=acpi-make-osc-call-per-handle
+
+This patch tweaks the way pciehp requests control of the hotplug
+hardware from BIOS. It now tries to invoke the ACPI _OSC method
+for a specific hotplug controller only, rather than walking the
+entire acpi namespace invoking all possible _OSC methods under
+all host bridges. This allows us to gain control of each hotplug
+controller individually, even if BIOS fails to give us control of
+some other hotplug controller in the system.
+
+Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+ drivers/pci/hotplug/pciehprm_acpi.c | 9 ++++-----
+ drivers/pci/pci-acpi.c | 11 +++--------
+ include/linux/pci-acpi.h | 5 +++--
+ 3 files changed, 10 insertions(+), 15 deletions(-)
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehprm_acpi.c 2005-11-02 10:58:29.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehprm_acpi.c 2005-11-02 10:58:35.000000000 -0800
+@@ -143,12 +143,13 @@
+ int get_hp_hw_control_from_firmware(struct pci_dev *dev)
+ {
+ acpi_status status;
++ acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev));
+ /*
+ * Per PCI firmware specification, we should run the ACPI _OSC
+ * method to get control of hotplug hardware before using it
+ */
+- /* Fixme: run _OSC for a specific host bridge, not all of them */
+- status = pci_osc_control_set(OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
++ status = pci_osc_control_set(handle,
++ OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
+
+ /* Fixme: fail native hotplug if _OSC does not exist for root ports */
+ if (status == AE_NOT_FOUND) {
+@@ -156,9 +157,7 @@
+ * Some older BIOS's don't support _OSC but support
+ * OSHP to do the same thing
+ */
+- acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev));
+- if (handle)
+- status = acpi_run_oshp(handle);
++ status = acpi_run_oshp(handle);
+ }
+ if (ACPI_FAILURE(status)) {
+ err("Cannot get control of hotplug hardware\n");
+--- gregkh-2.6.orig/drivers/pci/pci-acpi.c 2005-08-28 16:41:01.000000000 -0700
++++ gregkh-2.6/drivers/pci/pci-acpi.c 2005-11-02 10:58:35.000000000 -0800
+@@ -91,9 +91,7 @@
+ static acpi_status
+ acpi_run_osc (
+ acpi_handle handle,
+- u32 level,
+- void *context,
+- void **retval )
++ void *context)
+ {
+ acpi_status status;
+ struct acpi_object_list input;
+@@ -184,7 +182,7 @@
+ *
+ * Attempt to take control from Firmware on requested control bits.
+ **/
+-acpi_status pci_osc_control_set(u32 flags)
++acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
+ {
+ acpi_status status;
+ u32 ctrlset;
+@@ -198,10 +196,7 @@
+ return AE_SUPPORT;
+ }
+ ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset;
+- status = acpi_get_devices ( PCI_ROOT_HID_STRING,
+- acpi_run_osc,
+- ctrlset_buf,
+- NULL );
++ status = acpi_run_osc(handle, ctrlset_buf);
+ if (ACPI_FAILURE (status)) {
+ ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset;
+ }
+--- gregkh-2.6.orig/include/linux/pci-acpi.h 2005-08-28 16:41:01.000000000 -0700
++++ gregkh-2.6/include/linux/pci-acpi.h 2005-11-02 10:58:35.000000000 -0800
+@@ -47,14 +47,15 @@
+ OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL)
+
+ #ifdef CONFIG_ACPI
+-extern acpi_status pci_osc_control_set(u32 flags);
++extern acpi_status pci_osc_control_set(acpi_handle handle, u32 flags);
+ extern acpi_status pci_osc_support_set(u32 flags);
+ #else
+ #if !defined(acpi_status)
+ typedef u32 acpi_status;
+ #define AE_ERROR (acpi_status) (0x0001)
+ #endif
+-static inline acpi_status pci_osc_control_set(u32 flags) {return AE_ERROR;}
++static inline acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
++{return AE_ERROR;}
+ static inline acpi_status pci_osc_support_set(u32 flags) {return AE_ERROR;}
+ #endif
+
diff --git a/pci/pci-pciehp-07.patch b/pci/pci-pciehp-07.patch
new file mode 100644
index 0000000000000..d9ae30b9ccaf0
--- /dev/null
+++ b/pci/pci-pciehp-07.patch
@@ -0,0 +1,221 @@
+From owner-linux-pci@atrey.karlin.mff.cuni.cz Mon Oct 31 16:31:40 2005
+Message-Id: <20051101002124.495349454@csdlinux-2.jf.intel.com>
+Date: Mon, 31 Oct 2005 16:20:12 -0800
+From: rajesh.shah@intel.com
+To: kristen.c.accardi@intel.com, gregkh@suse.de
+Cc: akpm@osdl.org, rajesh.shah@intel.com
+Subject: [patch 7/8] pciehp: clean-up how we request control of hotplug hardware
+Content-Disposition: inline; filename=pciehp-fix-osc-oshp
+
+This patch further tweaks how we request control of hotplug
+controller hardware from BIOS. We first search the ACPI namespace
+corresponding to a specific hotplug controller looking for an
+_OSC or OSHP method. On failure, we successively move to the
+ACPI parent object, till we hit the highest level host bridge
+in the hierarchy. This allows for different types of BIOS's
+which place the _OSC/OSHP methods at various places in the acpi
+namespace, while still not encroaching on the namespace of
+some other root level host bridge.
+
+This patch also introduces a new load time option (pciehp_force)
+that allows us to bypass all _OSC/OSHP checking. Not supporting
+these methods seems to be be the most common ACPI firmware problem
+we've run into. This will still _not_ allow the pciehp driver to
+work correctly if the BIOS really doesn't support pciehp (i.e. if
+it doesn't generate a hotplug interrupt). Use this option with
+caution. Some BIOS's may deliberately not build any _OSC/OSHP
+methods to make sure it retains control the hotplug hardware.
+Using the pciehp_force parameter for such systems can lead to
+two separate entities trying to control the same hardware.
+
+Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+ drivers/acpi/glue.c | 1
+ drivers/pci/hotplug/pciehp.h | 1
+ drivers/pci/hotplug/pciehp_core.c | 3 +
+ drivers/pci/hotplug/pciehp_hpc.c | 11 +++-
+ drivers/pci/hotplug/pciehprm_acpi.c | 92 +++++++++++++++++++++++++++++-------
+ 5 files changed, 89 insertions(+), 19 deletions(-)
+
+--- gregkh-2.6.orig/drivers/acpi/glue.c 2005-10-27 22:11:39.000000000 -0700
++++ gregkh-2.6/drivers/acpi/glue.c 2005-11-02 10:58:38.000000000 -0800
+@@ -203,6 +203,7 @@
+ acpi_get_devices(PCI_ROOT_HID_STRING, find_pci_rootbridge, &find, NULL);
+ return find.handle;
+ }
++EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle);
+
+ /* Get device's handler per its address under its parent */
+ struct acpi_find_child {
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp.h 2005-11-02 10:58:34.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp.h 2005-11-02 10:58:38.000000000 -0800
+@@ -40,6 +40,7 @@
+ extern int pciehp_poll_mode;
+ extern int pciehp_poll_time;
+ extern int pciehp_debug;
++extern int pciehp_force;
+
+ /*#define dbg(format, arg...) do { if (pciehp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/
+ #define dbg(format, arg...) do { if (pciehp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0)
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_core.c 2005-11-02 10:58:34.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_core.c 2005-11-02 10:58:38.000000000 -0800
+@@ -39,6 +39,7 @@
+ int pciehp_debug;
+ int pciehp_poll_mode;
+ int pciehp_poll_time;
++int pciehp_force;
+ struct controller *pciehp_ctrl_list;
+
+ #define DRIVER_VERSION "0.4"
+@@ -52,9 +53,11 @@
+ module_param(pciehp_debug, bool, 0644);
+ module_param(pciehp_poll_mode, bool, 0644);
+ module_param(pciehp_poll_time, int, 0644);
++module_param(pciehp_force, bool, 0644);
+ MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not");
+ MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not");
+ MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds");
++MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing");
+
+ #define PCIE_MODULE_NAME "pciehp"
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_hpc.c 2005-11-02 10:58:34.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_hpc.c 2005-11-02 10:58:38.000000000 -0800
+@@ -1417,9 +1417,14 @@
+ goto abort_free_ctlr;
+ }
+
+- rc = get_hp_hw_control_from_firmware(ctrl->pci_dev);
+- if (rc)
+- goto abort_free_ctlr;
++ if (pciehp_force) {
++ dbg("Bypassing BIOS check for pciehp use on %s\n",
++ pci_name(ctrl->pci_dev));
++ } else {
++ rc = get_hp_hw_control_from_firmware(ctrl->pci_dev);
++ if (rc)
++ goto abort_free_ctlr;
++ }
+
+ /* Add this HPC instance into the HPC list */
+ spin_lock(&list_lock);
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehprm_acpi.c 2005-11-02 10:58:37.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehprm_acpi.c 2005-11-02 10:58:38.000000000 -0800
+@@ -132,7 +132,7 @@
+ /* run OSHP */
+ status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
+ if (ACPI_FAILURE(status)) {
+- err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
++ dbg("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
+ status);
+ } else {
+ dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
+@@ -140,32 +140,92 @@
+ return status;
+ }
+
++static int is_root_bridge(acpi_handle handle)
++{
++ acpi_status status;
++ struct acpi_device_info *info;
++ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
++ int i;
++
++ status = acpi_get_object_info(handle, &buffer);
++ if (ACPI_SUCCESS(status)) {
++ info = buffer.pointer;
++ if ((info->valid & ACPI_VALID_HID) &&
++ !strcmp(PCI_ROOT_HID_STRING,
++ info->hardware_id.value)) {
++ acpi_os_free(buffer.pointer);
++ return 1;
++ }
++ if (info->valid & ACPI_VALID_CID) {
++ for (i=0; i < info->compatibility_id.count; i++) {
++ if (!strcmp(PCI_ROOT_HID_STRING,
++ info->compatibility_id.id[i].value)) {
++ acpi_os_free(buffer.pointer);
++ return 1;
++ }
++ }
++ }
++ }
++ return 0;
++}
++
+ int get_hp_hw_control_from_firmware(struct pci_dev *dev)
+ {
+ acpi_status status;
+- acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev));
++ acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
++ struct pci_dev *pdev = dev;
++ u8 *path_name;
+ /*
+ * Per PCI firmware specification, we should run the ACPI _OSC
+- * method to get control of hotplug hardware before using it
++ * method to get control of hotplug hardware before using it.
++ * If an _OSC is missing, we look for an OSHP to do the same thing.
++ * To handle different BIOS behavior, we look for _OSC and OSHP
++ * within the scope of the hotplug controller and its parents, upto
++ * the host bridge under which this controller exists.
+ */
+- status = pci_osc_control_set(handle,
+- OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
+-
+- /* Fixme: fail native hotplug if _OSC does not exist for root ports */
+- if (status == AE_NOT_FOUND) {
++ while (!handle) {
+ /*
+- * Some older BIOS's don't support _OSC but support
+- * OSHP to do the same thing
++ * This hotplug controller was not listed in the ACPI name
++ * space at all. Try to get acpi handle of parent pci bus.
+ */
+- status = acpi_run_oshp(handle);
++ if (!pdev || !pdev->bus->parent)
++ break;
++ dbg("Could not find %s in acpi namespace, trying parent\n",
++ pci_name(pdev));
++ if (!pdev->bus->parent->self)
++ /* Parent must be a host bridge */
++ handle = acpi_get_pci_rootbridge_handle(
++ pci_domain_nr(pdev->bus->parent),
++ pdev->bus->parent->number);
++ else
++ handle = DEVICE_ACPI_HANDLE(
++ &(pdev->bus->parent->self->dev));
++ pdev = pdev->bus->parent->self;
+ }
+- if (ACPI_FAILURE(status)) {
+- err("Cannot get control of hotplug hardware\n");
+- return -1;
++
++ while (handle) {
++ path_name = acpi_path_name(handle);
++ dbg("Trying to get hotplug control for %s \n", path_name);
++ status = pci_osc_control_set(handle,
++ OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
++ if (status == AE_NOT_FOUND)
++ status = acpi_run_oshp(handle);
++ if (ACPI_SUCCESS(status)) {
++ dbg("Gained control for hotplug HW for pci %s (%s)\n",
++ pci_name(dev), path_name);
++ return 0;
++ }
++ if (is_root_bridge(handle))
++ break;
++ chandle = handle;
++ status = acpi_get_parent(chandle, &handle);
++ if (ACPI_FAILURE(status))
++ break;
+ }
+
+- dbg("Sucess getting control of hotplug hardware\n");
+- return 0;
++ err("Cannot get control of hotplug hardware for pci %s\n",
++ pci_name(dev));
++ return -1;
+ }
+
+ void get_hp_params_from_firmware(struct pci_dev *dev,
diff --git a/pci/pci-pciehp-08.patch b/pci/pci-pciehp-08.patch
new file mode 100644
index 0000000000000..02438e6b61e19
--- /dev/null
+++ b/pci/pci-pciehp-08.patch
@@ -0,0 +1,48 @@
+From owner-linux-pci@atrey.karlin.mff.cuni.cz Mon Oct 31 16:32:31 2005
+Message-Id: <20051101002124.779002843@csdlinux-2.jf.intel.com>
+Date: Mon, 31 Oct 2005 16:20:13 -0800
+From: rajesh.shah@intel.com
+To: kristen.c.accardi@intel.com, gregkh@suse.de
+Cc: akpm@osdl.org, rajesh.shah@intel.com
+Subject: [patch 8/8] pciehp: fix handling of power faults during hotplug
+Content-Disposition: inline; filename=pciehp-fix-powerfault-handling
+
+The current pciehp implementation reports a power-fail error
+even if the condition has cleared by the time the corresponding
+interrupt handling code gets a chance to run. This patch
+fixes this problem.
+
+Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+ drivers/pci/hotplug/pciehp_hpc.c | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_hpc.c 2005-11-02 10:58:40.000000000 -0800
++++ gregkh-2.6/drivers/pci/hotplug/pciehp_hpc.c 2005-11-02 10:58:41.000000000 -0800
+@@ -481,7 +481,6 @@
+ u16 slot_status;
+ u8 pwr_fault;
+ int retval = 0;
+- u8 status;
+
+ DBG_ENTER_ROUTINE
+
+@@ -493,15 +492,13 @@
+ retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status);
+
+ if (retval) {
+- err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
++ err("%s : Cannot check for power fault\n", __FUNCTION__);
+ return retval;
+ }
+ pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1);
+- status = (pwr_fault != 1) ? 1 : 0;
+
+ DBG_LEAVE_ROUTINE
+- /* Note: Logic 0 => fault */
+- return status;
++ return pwr_fault;
+ }
+
+ static int hpc_set_attention_status(struct slot *slot, u8 value)