aboutsummaryrefslogtreecommitdiffstats
path: root/pci
diff options
context:
space:
mode:
authorGreg KH <greg@press.(none)>2005-10-14 17:23:05 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2005-10-14 17:23:05 -0700
commite4b0d747f3d3f5264a70c6260d4147106e8df458 (patch)
tree5221e81474a2520ae553995a371db2f8a52c25cc /pci
parent97f0358110694370d21c8e927c1106908361ddc2 (diff)
downloadpatches-e4b0d747f3d3f5264a70c6260d4147106e8df458.tar.gz
more new patches
Diffstat (limited to 'pci')
-rw-r--r--pci/shpc-01-shpc-use-pci-core.patch4387
-rw-r--r--pci/shpc-02-remove-redundant-res-display.patch99
-rw-r--r--pci/shpc-03-reduce-acpi-dependence.patch1357
-rw-r--r--pci/shpc-04-probe-bail-early.patch54
-rw-r--r--pci/shpc-05-dont-save-pci-configs.patch483
-rw-r--r--pci/shpc-06-remove-redundant-data-structures.patch852
-rw-r--r--pci/shpc-07--misc-cleanup.patch619
-rw-r--r--pci/shpc-08-reduce-dbg-verbosity.patch331
-rw-r--r--pci/shpc-09-remove-sysfs-files-on-unload.patch53
9 files changed, 8235 insertions, 0 deletions
diff --git a/pci/shpc-01-shpc-use-pci-core.patch b/pci/shpc-01-shpc-use-pci-core.patch
new file mode 100644
index 0000000000000..665206e095e3f
--- /dev/null
+++ b/pci/shpc-01-shpc-use-pci-core.patch
@@ -0,0 +1,4387 @@
+From rshah1@unix-os.sc.intel.com Thu Oct 13 13:21:23 2005
+Message-Id: <20051013190820.268763669@csdlinux-2.jf.intel.com>
+Date: Thu, 13 Oct 2005 12:05:36 -0700
+From: rajesh.shah@intel.com
+To: kristen.c.accardi@intel.com, gregkh@suse.de
+Cc: david.keck@amd.com, akpm@osdl.org, Rajesh Shah <rajesh.shah@intel.com>
+Subject: [patch 1/9] shpchp: use the PCI core for hotplug resource management
+Content-Disposition: inline; filename=shpc-01-shpc-use-pci-core.patch
+
+This patch converts the standard hotplug controller driver to use
+the PCI core for resource management. This eliminates a whole lot
+of duplicated code, and integrates shpchp in 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/shpchp.h | 57 -
+ drivers/pci/hotplug/shpchp_core.c | 36
+ drivers/pci/hotplug/shpchp_ctrl.c | 1624 ---------------------------------
+ drivers/pci/hotplug/shpchp_pci.c | 482 +--------
+ drivers/pci/hotplug/shpchp_sysfs.c | 121 +-
+ drivers/pci/hotplug/shpchprm.h | 12
+ drivers/pci/hotplug/shpchprm_acpi.c | 851 -----------------
+ drivers/pci/hotplug/shpchprm_legacy.c | 294 -----
+ drivers/pci/hotplug/shpchprm_legacy.h | 113 --
+ drivers/pci/hotplug/shpchprm_nonacpi.c | 278 -----
+ drivers/pci/hotplug/shpchprm_nonacpi.h | 56 -
+ 11 files changed, 168 insertions(+), 3756 deletions(-)
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp.h
++++ gregkh-2.6/drivers/pci/hotplug/shpchp.h
+@@ -63,14 +63,7 @@ struct pci_func {
+ u8 switch_save;
+ u8 presence_save;
+ u8 pwr_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;
+ };
+
+@@ -96,12 +89,6 @@ struct slot {
+ 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;
+@@ -113,10 +100,6 @@ struct controller {
+ 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];
+@@ -139,20 +122,6 @@ struct controller {
+ u16 vendor_id;
+ };
+
+-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 AMD SHPC ID */
+ #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450
+
+@@ -197,7 +166,6 @@ struct resource_lists {
+ #define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n"
+ #define msg_HPC_non_shpc "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 shpcphd mdoule. Upgrade to a newer version of shpchpd\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"
+@@ -207,7 +175,6 @@ struct resource_lists {
+ extern void shpchp_create_ctrl_files (struct controller *ctrl);
+
+ /* controller functions */
+-extern int shpchprm_find_available_resources(struct controller *ctrl);
+ extern int shpchp_event_start_thread(void);
+ extern void shpchp_event_stop_thread(void);
+ extern struct pci_func *shpchp_slot_create(unsigned char busnumber);
+@@ -220,19 +187,10 @@ extern u8 shpchp_handle_switch_change(u8
+ extern u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id);
+ extern u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id);
+
+-/* resource functions */
+-extern int shpchp_resource_sort_and_combine(struct pci_resource **head);
+-
+ /* pci functions */
+-extern int shpchp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
+-/*extern int shpchp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/
+ extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
+-extern int shpchp_save_used_resources(struct controller *ctrl, struct pci_func * func, int flag);
+ extern int shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot);
+-extern void shpchp_destroy_board_resources(struct pci_func * func);
+-extern int shpchp_return_board_resources(struct pci_func * func, struct resource_lists * resources);
+-extern void shpchp_destroy_resource_list(struct resource_lists * resources);
+-extern int shpchp_configure_device(struct controller* ctrl, struct pci_func* func);
++extern int shpchp_configure_device(struct slot *p_slot);
+ extern int shpchp_unconfigure_device(struct pci_func* func);
+
+
+@@ -240,10 +198,6 @@ extern int shpchp_unconfigure_device(str
+ extern struct controller *shpchp_ctrl_list;
+ extern struct pci_func *shpchp_slot_list[256];
+
+-/* These are added to support AMD shpc */
+-extern u8 shpchp_nic_irq;
+-extern u8 shpchp_disk_irq;
+-
+ struct ctrl_reg {
+ volatile u32 base_offset;
+ volatile u32 slot_avail1;
+@@ -398,15 +352,6 @@ static inline int wait_for_ctrl_irq (str
+ 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/shpchp_core.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_core.c
+@@ -418,16 +418,8 @@ static int shpc_probe(struct pci_dev *pd
+ goto err_out_free_ctrl_bus;
+ }
+
+- /* Get IO, memory, and IRQ resources for new devices */
+- rc = shpchprm_find_available_resources(ctrl);
+- ctrl->add_support = !rc;
++ ctrl->add_support = 1;
+
+- if (rc) {
+- dbg("shpchprm_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) {
+@@ -497,18 +489,6 @@ static int shpc_start_thread(void)
+ return retval;
+ }
+
+-static inline void __exit
+-free_shpchp_res(struct pci_resource *res)
+-{
+- struct pci_resource *tres;
+-
+- while (res) {
+- tres = res;
+- res = res->next;
+- kfree(tres);
+- }
+-}
+-
+ static void __exit unload_shpchpd(void)
+ {
+ struct pci_func *next;
+@@ -522,11 +502,6 @@ static void __exit unload_shpchpd(void)
+ while (ctrl) {
+ cleanup_slots(ctrl);
+
+- free_shpchp_res(ctrl->io_head);
+- free_shpchp_res(ctrl->mem_head);
+- free_shpchp_res(ctrl->p_mem_head);
+- free_shpchp_res(ctrl->bus_head);
+-
+ kfree (ctrl->pci_bus);
+
+ dbg("%s: calling release_ctlr\n", __FUNCTION__);
+@@ -541,11 +516,6 @@ static void __exit unload_shpchpd(void)
+ for (loop = 0; loop < 256; loop++) {
+ next = shpchp_slot_list[loop];
+ while (next != NULL) {
+- free_shpchp_res(next->io_head);
+- free_shpchp_res(next->mem_head);
+- free_shpchp_res(next->p_mem_head);
+- free_shpchp_res(next->bus_head);
+-
+ TempSlot = next;
+ next = next->next;
+ kfree(TempSlot);
+@@ -607,9 +577,7 @@ error_hpc_init:
+ if (retval) {
+ shpchprm_cleanup();
+ shpchp_event_stop_thread();
+- } else
+- shpchprm_print_pirt();
+-
++ }
+ return retval;
+ }
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_ctrl.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_ctrl.c
+@@ -38,13 +38,10 @@
+ #include <linux/wait.h>
+ #include <linux/smp_lock.h>
+ #include <linux/pci.h>
++#include "../pci.h"
+ #include "shpchp.h"
+ #include "shpchprm.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) */
+@@ -52,9 +49,6 @@ static struct semaphore event_exit; /*
+ static int event_finished;
+ static unsigned long pushbutton_pending; /* = 0 */
+
+-u8 shpchp_disk_irq;
+-u8 shpchp_nic_irq;
+-
+ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id)
+ {
+ struct controller *ctrl = (struct controller *) inst_id;
+@@ -260,624 +254,6 @@ u8 shpchp_handle_power_fault(u8 hp_slot,
+ return rc;
+ }
+
+-
+-/*
+- * sort_by_size
+- *
+- * Sorts nodes on the list by their length.
+- * Smallest first.
+- *
+- */
+-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
+- *
+- * Returns zero or one node of resources that aren't in use
+- *
+- */
+-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 = shpchp_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(*split_node), 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;
+- node->next = NULL;
+- } else {
+- prevnode = *head;
+- while (prevnode->next != node)
+- prevnode = prevnode->next;
+-
+- prevnode->next = node->next;
+- node->next = NULL;
+- }
+-
+- return(node);
+-}
+-
+-
+-/*
+- * do_bridge_resource_split
+- *
+- * Returns zero or one node of resources that aren't in use
+- *
+- */
+-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 = shpchp_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 ( shpchp_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(*split_node), 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(*split_node), 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 (shpchp_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(*split_node), 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(*split_node), 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(*split_node),
+- 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 ( shpchp_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(*split_node), 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(*split_node), 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);
+-}
+-
+-
+-/*
+- * shpchp_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 shpchp_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);
+-}
+-
+-
+ /**
+ * shpchp_slot_create - Creates a node and adds it to the proper bus.
+ * @busnumber - bus where new node is to be located
+@@ -933,7 +309,6 @@ static int slot_remove(struct pci_func *
+
+ if (next == old_slot) {
+ shpchp_slot_list[old_slot->bus] = old_slot->next;
+- shpchp_destroy_board_resources(old_slot);
+ kfree(old_slot);
+ return(0);
+ }
+@@ -944,7 +319,6 @@ static int slot_remove(struct pci_func *
+
+ if (next->next == old_slot) {
+ next->next = old_slot->next;
+- shpchp_destroy_board_resources(old_slot);
+ kfree(old_slot);
+ return(0);
+ } else
+@@ -1120,12 +494,8 @@ static u32 board_added(struct pci_func *
+ {
+ u8 hp_slot;
+ u8 slots_not_empty = 0;
+- int index;
+- u32 temp_register = 0xFFFFFFFF;
+- u32 retval, rc = 0;
+- struct pci_func *new_func = NULL;
++ u32 rc = 0;
+ struct slot *p_slot;
+- struct resource_lists res_lists;
+ enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed;
+ u8 pi, mode;
+
+@@ -1328,135 +698,65 @@ static u32 board_added(struct pci_func *
+ /* Check for a power fault */
+ if (func->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);
++ dbg("%s: power fault\n", __FUNCTION__);
+ 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;
+-
+- shpchp_resource_sort_and_combine(&(ctrl->mem_head));
+- shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
+- shpchp_resource_sort_and_combine(&(ctrl->io_head));
+- shpchp_resource_sort_and_combine(&(ctrl->bus_head));
+-
+- if (rc) {
+- /* Wait for exclusive access to hardware */
+- down(&ctrl->crit_sect);
+-
+- /* turn off slot, turn on Amber LED, turn off Green LED */
+- retval = p_slot->hpc_ops->slot_disable(p_slot);
+- if (retval) {
+- err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
+- /* Done with exclusive hardware access */
+- up(&ctrl->crit_sect);
+- return retval;
+- }
+- /* Wait for the command to complete */
+- wait_for_ctrl_irq (ctrl);
++ if (shpchp_configure_device(p_slot)) {
++ err("Cannot add device at 0x%x:0x%x\n", p_slot->bus,
++ p_slot->device);
++ goto err_exit;
++ }
+
+- retval = p_slot->hpc_ops->check_cmd_status(ctrl);
+- if (retval) {
+- err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, retval);
+- /* Done with exclusive hardware access */
+- up(&ctrl->crit_sect);
+- return retval;
+- }
++ shpchp_save_slot_config(ctrl, func);
+
+- /* Done with exclusive hardware access */
+- up(&ctrl->crit_sect);
++ func->status = 0;
++ func->switch_save = 0x10;
++ func->is_a_board = 0x01;
++ func->pwr_save = 1;
+
+- return(rc);
+- }
+- shpchp_save_slot_config(ctrl, func);
++ /* Wait for exclusive access to hardware */
++ down(&ctrl->crit_sect);
+
+- func->status = 0;
+- func->switch_save = 0x10;
+- func->is_a_board = 0x01;
+- func->pwr_save = 1;
++ p_slot->hpc_ops->green_led_on(p_slot);
+
+- /* Next, we will instantiate the linux pci_dev structures
+- * (with appropriate driver notification, if already present)
+- */
+- index = 0;
+- do {
+- new_func = shpchp_slot_find(ctrl->slot_bus, func->device, index++);
+- if (new_func && !new_func->pci_dev) {
+- dbg("%s:call pci_hp_configure_dev\n", __FUNCTION__);
+- shpchp_configure_device(ctrl, new_func);
+- }
+- } while (new_func);
+-
+- /* Wait for exclusive access to hardware */
+- down(&ctrl->crit_sect);
++ /* Wait for the command to complete */
++ wait_for_ctrl_irq (ctrl);
+
+- p_slot->hpc_ops->green_led_on(p_slot);
++ /* Done with exclusive hardware access */
++ up(&ctrl->crit_sect);
+
+- /* Wait for the command to complete */
+- wait_for_ctrl_irq (ctrl);
++ return 0;
+
++err_exit:
++ /* Wait for exclusive access to hardware */
++ down(&ctrl->crit_sect);
+
++ /* turn off slot, turn on Amber LED, turn off Green LED */
++ rc = p_slot->hpc_ops->slot_disable(p_slot);
++ if (rc) {
++ err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
+ /* Done with exclusive hardware access */
+ up(&ctrl->crit_sect);
++ return rc;
++ }
++ /* Wait for the command to complete */
++ wait_for_ctrl_irq (ctrl);
+
+- } else {
+- /* Wait for exclusive access to hardware */
+- down(&ctrl->crit_sect);
+-
+- /* turn off slot, turn on Amber LED, turn off Green LED */
+- rc = p_slot->hpc_ops->slot_disable(p_slot);
+- if (rc) {
+- err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
+- /* Done with exclusive hardware access */
+- up(&ctrl->crit_sect);
+- return rc;
+- }
+- /* Wait for the command to complete */
+- wait_for_ctrl_irq (ctrl);
+-
+- rc = p_slot->hpc_ops->check_cmd_status(ctrl);
+- if (rc) {
+- err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc);
+- /* Done with exclusive hardware access */
+- up(&ctrl->crit_sect);
+- return rc;
+- }
+-
++ rc = p_slot->hpc_ops->check_cmd_status(ctrl);
++ if (rc) {
++ err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc);
+ /* Done with exclusive hardware access */
+ up(&ctrl->crit_sect);
+-
+- return(rc);
++ return rc;
+ }
+- return 0;
++
++ /* Done with exclusive hardware access */
++ up(&ctrl->crit_sect);
++
++ return(rc);
+ }
+
+
+@@ -1466,13 +766,9 @@ static u32 board_added(struct pci_func *
+ */
+ 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)
+@@ -1488,27 +784,6 @@ static u32 remove_board(struct pci_func
+
+ 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 = shpchp_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 = shpchp_save_used_resources(ctrl, func, DISABLE_CARD);
+- }
+ /* Change status to shutdown */
+ if (func->is_a_board)
+ func->status = 0x01;
+@@ -1551,26 +826,6 @@ static u32 remove_board(struct pci_func
+
+ 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);
+-
+- shpchp_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;
+-
+- shpchp_resource_sort_and_combine(&(ctrl->mem_head));
+- shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
+- shpchp_resource_sort_and_combine(&(ctrl->io_head));
+- shpchp_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);
+@@ -2050,798 +1305,3 @@ int shpchp_disable_slot (struct slot *p_
+ 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 = shpchp_slot_find(new_slot->bus, new_slot->device, index++);
+-
+- if (new_slot)
+- shpchp_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 = shpchp_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 configure_new_device\n");
+-
+- return 0;
+-}
+-
+-
+-/*
+- * Configuration logic that involves the hotplug data structures and
+- * their bookkeeping
+- */
+-
+-
+-/**
+- * 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 device;
+- u8 class_code;
+- u16 temp_word;
+- u32 rc;
+- u32 temp_register;
+- u32 base;
+- 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 pci_bus lpci_bus, *pci_bus;
+- struct resource_lists temp_resources;
+-#if defined(CONFIG_X86_64)
+- u8 IRQ=0;
+-#endif
+-
+- 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;
+-
+- if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
+- /* 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 = shpchprm_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(*hold_bus_node), GFP_KERNEL);
+- hold_IO_node = kmalloc(sizeof(*hold_IO_node), GFP_KERNEL);
+- hold_mem_node = kmalloc(sizeof(*hold_mem_node), GFP_KERNEL);
+- hold_p_mem_node = kmalloc(sizeof(*hold_p_mem_node), 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.
+- */
+- 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 = (u32)(mem_node->base >> 16);
+- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+-
+- RES_CHECK(mem_node->base + mem_node->length - 1, 16);
+- temp_word = (u32)((mem_node->base + mem_node->length - 1) >> 16);
+- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+- } else {
+- temp_word = 0xFFFF;
+- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+-
+- temp_word = 0x0000;
+- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+-
+- kfree(hold_mem_node);
+- hold_mem_node = NULL;
+- }
+-
+- /* 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.
+- */
+- if (p_mem_node) {
+- memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource));
+- p_mem_node->next = NULL;
+-
+- /* set Pre Mem base and Limit registers */
+- RES_CHECK(p_mem_node->base, 16);
+- temp_word = (u32)(p_mem_node->base >> 16);
+- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
+-
+- RES_CHECK(p_mem_node->base + p_mem_node->length - 1, 16);
+- temp_word = (u32)((p_mem_node->base + p_mem_node->length - 1) >> 16);
+- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+- } else {
+- temp_word = 0xFFFF;
+- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
+-
+- temp_word = 0x0000;
+- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+-
+- kfree(hold_p_mem_node);
+- hold_p_mem_node = NULL;
+- }
+-
+- /* 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 = shpchp_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) {
+- shpchp_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 = shpchp_set_irq(func->bus, func->device,
+- 0x0A + cloop, irqs.interrupt[cloop]);
+- if (rc) {
+- shpchp_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 = (u32)((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 = (u32)((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 = (u32)((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 = (u32)((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
+- */
+-
+- shpchprm_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);
+- } 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 */
+-
+-#if defined(CONFIG_X86_64)
+- /* Figure out which interrupt pin this function uses */
+- rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_INTERRUPT_PIN, &temp_byte);
+-
+- /* If this function needs an interrupt and we are behind a bridge
+- and the pin is tied to something that's alread mapped,
+- set this one the same
+- */
+- if (temp_byte && resources->irqs &&
+- (resources->irqs->valid_INT &
+- (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) {
+- /* We have to share with something already set up */
+- IRQ = resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03];
+- } else {
+- /* Program IRQ based on card type */
+- rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
+-
+- if (class_code == PCI_BASE_CLASS_STORAGE) {
+- IRQ = shpchp_disk_irq;
+- } else {
+- IRQ = shpchp_nic_irq;
+- }
+- }
+-
+- /* IRQ Line */
+- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ);
+-
+- if (!behind_bridge) {
+- rc = shpchp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ);
+- if (rc)
+- return(1);
+- } else {
+- /* TBD - this code may also belong in the other clause of this If statement */
+- resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03] = IRQ;
+- resources->irqs->valid_INT |= 0x01 << (temp_byte + resources->irqs->barber_pole - 1) & 0x03;
+- }
+-#endif
+- /* 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 = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL);
+- if (rc)
+- return rc;
+-
+- shpchprm_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/shpchp_pci.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_pci.c
+@@ -37,46 +37,69 @@
+ #include <linux/pci.h>
+ #include "../pci.h"
+ #include "shpchp.h"
+-#ifndef CONFIG_IA64
+-#include "../../../arch/i386/pci/pci.h" /* horrible hack showing how processor dependant we are... */
+-#endif
+
+-int shpchp_configure_device (struct controller* ctrl, struct pci_func* func)
++int shpchp_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) {
+- num = pci_scan_slot(ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function));
+- if (num) {
+- dbg("%s: subordiante %p number %x\n", __FUNCTION__, ctrl->pci_dev->subordinate,
+- ctrl->pci_dev->subordinate->number);
+- 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 shpchp_unconfigure_device(struct pci_func* func)
+ {
+ int rc = 0;
+@@ -95,44 +118,6 @@ int shpchp_unconfigure_device(struct pci
+ return rc;
+ }
+
+-/*
+- * shpchp_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 shpchp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
+-{
+-#if defined(CONFIG_X86) && !defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_64)
+- 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 */
+
+
+@@ -447,364 +432,3 @@ int shpchp_save_slot_config(struct contr
+ return 0;
+ }
+
+-
+-/*
+- * shpchp_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 shpchp_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 = shpchp_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 = shpchp_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;
+- }
+-}
+-
+-/*
+- * shpchp_return_board_resources
+- *
+- * this routine returns all resources allocated to a board to
+- * the available pool.
+- *
+- * returns 0 if success
+- */
+-int shpchp_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 = shpchp_resource_sort_and_combine(&(resources->mem_head));
+- rc |= shpchp_resource_sort_and_combine(&(resources->p_mem_head));
+- rc |= shpchp_resource_sort_and_combine(&(resources->io_head));
+- rc |= shpchp_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);
+- }
+-}
+-
+-/**
+- * shpchp_destroy_resource_list: put node back in the resource list
+- * @resources: list to put nodes back
+- */
+-void shpchp_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));
+-}
+-
+-/**
+- * shpchp_destroy_board_resources: put node back in the resource list
+- * @resources: list to put nodes back
+- */
+-void shpchp_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/shpchp_sysfs.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_sysfs.c
+@@ -40,43 +40,49 @@
+
+ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf)
+ {
+- struct pci_dev *pci_dev;
+- struct controller *ctrl;
++ struct pci_dev *pdev;
+ char * out = buf;
+- int index;
+- struct pci_resource *res;
++ int index, busnr;
++ struct resource *res;
++ struct pci_bus *bus;
+
+- pci_dev = container_of (dev, struct pci_dev, dev);
+- ctrl = pci_get_drvdata(pci_dev);
++ pdev = container_of (dev, struct pci_dev, dev);
++ bus = pdev->subordinate;
+
+ out += sprintf(buf, "Free resources: memory\n");
+- index = 11;
+- res = ctrl->mem_head;
+- while (res && index--) {
+- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+- res = res->next;
++ for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) {
++ res = bus->resource[index];
++ if (res && (res->flags & IORESOURCE_MEM) &&
++ !(res->flags & IORESOURCE_PREFETCH)) {
++ out += sprintf(out, "start = %8.8lx, length = %8.8lx\n",
++ res->start, (res->end - res->start));
++ }
+ }
+ out += sprintf(out, "Free resources: prefetchable memory\n");
+- index = 11;
+- res = ctrl->p_mem_head;
+- while (res && index--) {
+- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+- res = res->next;
++ for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) {
++ res = bus->resource[index];
++ if (res && (res->flags & IORESOURCE_MEM) &&
++ (res->flags & IORESOURCE_PREFETCH)) {
++ out += sprintf(out, "start = %8.8lx, length = %8.8lx\n",
++ res->start, (res->end - res->start));
++ }
+ }
+ out += sprintf(out, "Free resources: IO\n");
+- index = 11;
+- res = ctrl->io_head;
+- while (res && index--) {
+- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+- res = res->next;
++ for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) {
++ res = bus->resource[index];
++ if (res && (res->flags & IORESOURCE_IO)) {
++ out += sprintf(out, "start = %8.8lx, length = %8.8lx\n",
++ res->start, (res->end - res->start));
++ }
+ }
+ out += sprintf(out, "Free resources: bus numbers\n");
+- index = 11;
+- res = ctrl->bus_head;
+- while (res && index--) {
+- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+- res = res->next;
++ for (busnr = bus->secondary; busnr <= bus->subordinate; busnr++) {
++ if (!pci_find_bus(pci_domain_nr(bus), busnr))
++ break;
+ }
++ if (busnr < bus->subordinate)
++ out += sprintf(out, "start = %8.8x, length = %8.8x\n",
++ busnr, (bus->subordinate - busnr));
+
+ return out - buf;
+ }
+@@ -84,16 +90,16 @@ static DEVICE_ATTR (ctrl, S_IRUGO, show_
+
+ static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char *buf)
+ {
+- struct pci_dev *pci_dev;
++ struct pci_dev *pdev, *fdev;
+ struct controller *ctrl;
+ char * out = buf;
+ int index;
+- struct pci_resource *res;
++ struct resource *res;
+ struct pci_func *new_slot;
+ struct slot *slot;
+
+- pci_dev = container_of (dev, struct pci_dev, dev);
+- ctrl = pci_get_drvdata(pci_dev);
++ pdev = container_of (dev, struct pci_dev, dev);
++ ctrl = pci_get_drvdata(pdev);
+
+ slot=ctrl->slot;
+
+@@ -101,34 +107,47 @@ static ssize_t show_dev (struct device *
+ new_slot = shpchp_slot_find(slot->bus, slot->device, 0);
+ if (!new_slot)
+ break;
++ fdev = new_slot->pci_dev;
++ if (!fdev)
++ break;
+ out += sprintf(out, "assigned resources: memory\n");
+- index = 11;
+- res = new_slot->mem_head;
+- while (res && index--) {
+- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+- res = res->next;
++ for (index=0; index <= PCI_NUM_RESOURCES; index++) {
++ res = &(fdev->resource[index]);
++ if (res && (res->flags & IORESOURCE_MEM) &&
++ !(res->flags & IORESOURCE_PREFETCH)) {
++ out += sprintf(out,
++ "start = %8.8lx, length = %8.8lx\n",
++ res->start, (res->end - res->start));
++ }
+ }
+ out += sprintf(out, "assigned resources: prefetchable memory\n");
+- index = 11;
+- res = new_slot->p_mem_head;
+- while (res && index--) {
+- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+- res = res->next;
++ for (index=0; index <= PCI_NUM_RESOURCES; index++) {
++ res = &(fdev->resource[index]);
++ if (res && (res->flags & (IORESOURCE_MEM |
++ IORESOURCE_PREFETCH))) {
++ out += sprintf(out,
++ "start = %8.8lx, length = %8.8lx\n",
++ res->start, (res->end - res->start));
++ }
+ }
+ out += sprintf(out, "assigned resources: IO\n");
+- index = 11;
+- res = new_slot->io_head;
+- while (res && index--) {
+- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+- res = res->next;
++ for (index=0; index <= PCI_NUM_RESOURCES; index++) {
++ res = &(fdev->resource[index]);
++ if (res && (res->flags & IORESOURCE_IO)) {
++ out += sprintf(out,
++ "start = %8.8lx, length = %8.8lx\n",
++ res->start, (res->end - res->start));
++ }
+ }
+ out += sprintf(out, "assigned resources: bus numbers\n");
+- index = 11;
+- res = new_slot->bus_head;
+- while (res && index--) {
+- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+- res = res->next;
+- }
++ if (fdev->subordinate)
++ out += sprintf(out, "start = %8.8x, length = %8.8x\n",
++ fdev->subordinate->secondary,
++ (fdev->subordinate->subordinate -
++ fdev->subordinate->secondary));
++ else
++ out += sprintf(out, "start = %8.8x, length = %8.8x\n",
++ fdev->bus->number, 1);
+ slot=slot->next;
+ }
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchprm.h
++++ gregkh-2.6/drivers/pci/hotplug/shpchprm.h
+@@ -32,24 +32,12 @@
+
+ #ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY
+ #include "shpchprm_legacy.h"
+-#else
+-#include "shpchprm_nonacpi.h"
+ #endif
+
+ int shpchprm_init(enum php_ctlr_type ct);
+ void shpchprm_cleanup(void);
+-int shpchprm_print_pirt(void);
+-int shpchprm_find_available_resources(struct controller *ctrl);
+ int shpchprm_set_hpp(struct controller *ctrl, struct pci_func *func, u8 card_type);
+ void shpchprm_enable_card(struct controller *ctrl, struct pci_func *func, u8 card_type);
+ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum);
+
+-#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 /* _SHPCHPRM_H_ */
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchprm_acpi.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchprm_acpi.c
+@@ -34,9 +34,6 @@
+ #include <linux/efi.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>
+@@ -75,10 +72,6 @@ struct acpi_php_slot {
+ 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 */
+@@ -95,14 +88,6 @@ struct acpi_bridge {
+ 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;
+ };
+@@ -252,485 +237,6 @@ static void acpi_run_oshp ( struct acpi_
+ return;
+ }
+
+-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_shpchprm:%s _CRS not found\n", path_name);
+- return status;
+- default:
+- err ("acpi_shpchprm:%s _CRS fail=0x%x\n", path_name, status);
+- return status;
+- }
+-
+- crsbuf.pointer = kmalloc (crsbuf.length, GFP_KERNEL);
+- if (!crsbuf.pointer) {
+- err ("acpi_shpchprm: 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_shpchprm: %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 shpchprm_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;
+-
+- shpchp_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 shpchprm_delete_resources(
+- struct pci_resource **aprh,
+- struct pci_resource *this
+- )
+-{
+- struct pci_resource *res;
+-
+- for (res = this; res; res = res->next)
+- shpchprm_delete_resource(aprh, res->base, res->length);
+-
+- return 0;
+-}
+-
+-static int shpchprm_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_shpchprm: 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 shpchprm_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 = shpchprm_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_shpchprm:16-Bit Address Space Resource\n");
+- else
+- dbg("acpi_shpchprm: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); */
+- }
+-
+- shpchprm_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_shpchprm: 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);
+-
+- shpchp_resource_sort_and_combine(&ab->bus_head);
+- shpchp_resource_sort_and_combine(&ab->io_head);
+- shpchp_resource_sort_and_combine(&ab->mem_head);
+- shpchp_resource_sort_and_combine(&ab->p_mem_head);
+-
+- shpchprm_add_resources (&ab->tbus_head, ab->bus_head);
+- shpchprm_add_resources (&ab->tio_head, ab->io_head);
+- shpchprm_add_resources (&ab->tmem_head, ab->mem_head);
+- shpchprm_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(
+@@ -1047,13 +553,6 @@ static struct acpi_bridge * add_host_bri
+ 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_shpchprm:%s evaluate _CRS fail=0x%x\n", path_name, status);
+- kfree(ab);
+- return NULL;
+- }
+ build_a_bridge(ab, ab);
+
+ return ab;
+@@ -1147,11 +646,6 @@ static void free_a_slot(struct acpi_php_
+ {
+ 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);
+ }
+
+@@ -1176,15 +670,6 @@ static void free_a_bridge( struct acpi_b
+ 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);
+ }
+
+@@ -1234,47 +719,6 @@ static int get_number_of_slots (
+ 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 shpchprm_print_pirt(void)
+-{
+- dbg("SHPCHPRM 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
+@@ -1302,265 +746,6 @@ static struct acpi_php_slot * get_acpi_s
+
+ }
+
+-#if 0
+-static void * shpchprm_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
+-
+-static void shpchprm_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 shpchprm_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 shpchprm_get_used_resources (
+- struct controller *ctrl,
+- struct pci_func *func
+- )
+-{
+- return shpchp_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 = shpchprm_get_used_resources (ctrl, func);
+-
+- if (!rc) {
+- /* subtract the resources used by the func from ctrl resources */
+- rc = shpchprm_delete_resources (&ctrl->bus_head, func->bus_head);
+- rc |= shpchprm_delete_resources (&ctrl->io_head, func->io_head);
+- rc |= shpchprm_delete_resources (&ctrl->mem_head, func->mem_head);
+- rc |= shpchprm_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) {
+- func = shpchp_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);
+- shpchprm_dump_func_res(&new_func);
+- } else {
+- configure_existing_function(ctrl, func);
+- shpchprm_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 = shpchprm_add_resources (&ctrl->bus_head, ab->bus_head);
+- if (shpchprm_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 = shpchprm_add_resources (&ctrl->io_head, ab->io_head);
+- if (shpchprm_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 = shpchprm_add_resources (&ctrl->mem_head, ab->mem_head);
+- if (shpchprm_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 = shpchprm_add_resources (&ctrl->p_mem_head, ab->p_mem_head);
+- if (shpchprm_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 = shpchp_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)
+- shpchprm_delete_resource(&ab->bus_head, ctrl->bus, 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);
+-
+- shpchp_resource_sort_and_combine(&ab->bus_head);
+- shpchp_resource_sort_and_combine(&ab->io_head);
+- shpchp_resource_sort_and_combine(&ab->mem_head);
+- shpchp_resource_sort_and_combine(&ab->p_mem_head);
+-
+- shpchprm_add_resources (&ab->tbus_head, ab->bus_head);
+- shpchprm_add_resources (&ab->tio_head, ab->io_head);
+- shpchprm_add_resources (&ab->tmem_head, ab->mem_head);
+- shpchprm_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;
+-}
+-
+ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
+ {
+ int offset = devnum - ctrl->slot_device_offset;
+@@ -1570,42 +755,6 @@ int shpchprm_get_physical_slot_number(st
+ return 0;
+ }
+
+-/*
+- * 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 shpchprm_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);
+- shpchprm_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);
+- shpchprm_dump_ctrl_res(ctrl);
+-
+- return rc;
+-}
+-
+ int shpchprm_set_hpp(
+ struct controller *ctrl,
+ struct pci_func *func,
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchprm_legacy.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchprm_legacy.c
+@@ -34,25 +34,11 @@
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <asm/uaccess.h>
+-#ifdef CONFIG_IA64
+-#include <asm/iosapic.h>
+-#endif
+ #include "shpchp.h"
+ #include "shpchprm.h"
+-#include "shpchprm_legacy.h"
+-
+-static void __iomem *shpchp_rom_start;
+-static u16 unused_IRQ;
+
+ void shpchprm_cleanup(void)
+ {
+- if (shpchp_rom_start)
+- iounmap(shpchp_rom_start);
+-}
+-
+-int shpchprm_print_pirt(void)
+-{
+- return 0;
+ }
+
+ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
+@@ -63,280 +49,6 @@ int shpchprm_get_physical_slot_number(st
+ return 0;
+ }
+
+-/* Find the Hot Plug Resource Table in the specified region of memory */
+-static void __iomem *detect_HRT_floating_pointer(void __iomem *begin, void __iomem *end)
+-{
+- void __iomem *fp;
+- void __iomem *endp;
+- u8 temp1, temp2, temp3, temp4;
+- int status = 0;
+-
+- endp = (end - sizeof(struct hrt) + 1);
+-
+- for (fp = begin; fp <= endp; fp += 16) {
+- temp1 = readb(fp + SIG0);
+- temp2 = readb(fp + SIG1);
+- temp3 = readb(fp + SIG2);
+- temp4 = readb(fp + SIG3);
+- if (temp1 == '$' && temp2 == 'H' && temp3 == 'R' && temp4 == 'T') {
+- status = 1;
+- break;
+- }
+- }
+-
+- if (!status)
+- fp = NULL;
+-
+- dbg("Discovered Hotplug Resource Table at %p\n", fp);
+- return fp;
+-}
+-
+-/*
+- * shpchprm_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 shpchprm_find_available_resources(struct controller *ctrl)
+-{
+- u8 populated_slot;
+- u8 bridged_slot;
+- void __iomem *one_slot;
+- struct pci_func *func = NULL;
+- int i = 10, index = 0;
+- u32 temp_dword, rc;
+- ulong temp_ulong;
+- struct pci_resource *mem_node;
+- struct pci_resource *p_mem_node;
+- struct pci_resource *io_node;
+- struct pci_resource *bus_node;
+- void __iomem *rom_resource_table;
+- struct pci_bus lpci_bus, *pci_bus;
+- u8 cfgspc_irq, temp;
+-
+- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+- pci_bus = &lpci_bus;
+- rom_resource_table = detect_HRT_floating_pointer(shpchp_rom_start, shpchp_rom_start + 0xffff);
+- dbg("rom_resource_table = %p\n", rom_resource_table);
+- if (rom_resource_table == NULL)
+- return -ENODEV;
+-
+- /* Sum all resources and setup resource maps */
+- unused_IRQ = readl(rom_resource_table + UNUSED_IRQ);
+- dbg("unused_IRQ = %x\n", unused_IRQ);
+-
+- temp = 0;
+- while (unused_IRQ) {
+- if (unused_IRQ & 1) {
+- shpchp_disk_irq = temp;
+- break;
+- }
+- unused_IRQ = unused_IRQ >> 1;
+- temp++;
+- }
+-
+- dbg("shpchp_disk_irq= %d\n", shpchp_disk_irq);
+- unused_IRQ = unused_IRQ >> 1;
+- temp++;
+-
+- while (unused_IRQ) {
+- if (unused_IRQ & 1) {
+- shpchp_nic_irq = temp;
+- break;
+- }
+- unused_IRQ = unused_IRQ >> 1;
+- temp++;
+- }
+-
+- dbg("shpchp_nic_irq= %d\n", shpchp_nic_irq);
+- unused_IRQ = readl(rom_resource_table + PCIIRQ);
+-
+- temp = 0;
+-
+- pci_read_config_byte(ctrl->pci_dev, PCI_INTERRUPT_LINE, &cfgspc_irq);
+-
+- if (!shpchp_nic_irq) {
+- shpchp_nic_irq = cfgspc_irq;
+- }
+-
+- if (!shpchp_disk_irq) {
+- shpchp_disk_irq = cfgspc_irq;
+- }
+-
+- dbg("shpchp_disk_irq, shpchp_nic_irq= %d, %d\n", shpchp_disk_irq, shpchp_nic_irq);
+-
+- one_slot = rom_resource_table + sizeof(struct hrt);
+-
+- i = readb(rom_resource_table + NUMBER_OF_ENTRIES);
+- dbg("number_of_entries = %d\n", i);
+-
+- if (!readb(one_slot + SECONDARY_BUS))
+- return (1);
+-
+- dbg("dev|IO base|length|MEMbase|length|PM base|length|PB SB MB\n");
+-
+- while (i && readb(one_slot + SECONDARY_BUS)) {
+- u8 dev_func = readb(one_slot + DEV_FUNC);
+- u8 primary_bus = readb(one_slot + PRIMARY_BUS);
+- u8 secondary_bus = readb(one_slot + SECONDARY_BUS);
+- u8 max_bus = readb(one_slot + MAX_BUS);
+- u16 io_base = readw(one_slot + IO_BASE);
+- u16 io_length = readw(one_slot + IO_LENGTH);
+- u16 mem_base = readw(one_slot + MEM_BASE);
+- u16 mem_length = readw(one_slot + MEM_LENGTH);
+- u16 pre_mem_base = readw(one_slot + PRE_MEM_BASE);
+- u16 pre_mem_length = readw(one_slot + PRE_MEM_LENGTH);
+-
+- dbg("%2.2x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x |%2.2x %2.2x %2.2x\n",
+- dev_func, io_base, io_length, mem_base, mem_length, pre_mem_base, pre_mem_length,
+- primary_bus, secondary_bus, max_bus);
+-
+- /* If this entry isn't for our controller's bus, ignore it */
+- if (primary_bus != ctrl->slot_bus) {
+- i--;
+- one_slot += sizeof(struct slot_rt);
+- continue;
+- }
+- /* find out if this entry is for an occupied slot */
+- temp_dword = 0xFFFFFFFF;
+- pci_bus->number = primary_bus;
+- pci_bus_read_config_dword(pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword);
+-
+- dbg("temp_D_word = %x\n", temp_dword);
+-
+- if (temp_dword != 0xFFFFFFFF) {
+- index = 0;
+- func = shpchp_slot_find(primary_bus, dev_func >> 3, 0);
+-
+- while (func && (func->function != (dev_func & 0x07))) {
+- dbg("func = %p b:d:f(%x:%x:%x)\n", func, primary_bus, dev_func >> 3, index);
+- func = shpchp_slot_find(primary_bus, dev_func >> 3, index++);
+- }
+-
+- /* If we can't find a match, skip this table entry */
+- if (!func) {
+- i--;
+- one_slot += sizeof(struct slot_rt);
+- continue;
+- }
+- /* this may not work and shouldn't be used */
+- if (secondary_bus != primary_bus)
+- bridged_slot = 1;
+- else
+- bridged_slot = 0;
+-
+- populated_slot = 1;
+- } else {
+- populated_slot = 0;
+- bridged_slot = 0;
+- }
+- dbg("slot populated =%s \n", populated_slot?"yes":"no");
+-
+- /* If we've got a valid IO base, use it */
+-
+- temp_ulong = io_base + io_length;
+-
+- if ((io_base) && (temp_ulong <= 0x10000)) {
+- io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+- if (!io_node)
+- return -ENOMEM;
+-
+- io_node->base = (ulong)io_base;
+- io_node->length = (ulong)io_length;
+- dbg("found io_node(base, length) = %x, %x\n", io_node->base, io_node->length);
+-
+- if (!populated_slot) {
+- io_node->next = ctrl->io_head;
+- ctrl->io_head = io_node;
+- } else {
+- io_node->next = func->io_head;
+- func->io_head = io_node;
+- }
+- }
+-
+- /* If we've got a valid memory base, use it */
+- temp_ulong = mem_base + mem_length;
+- if ((mem_base) && (temp_ulong <= 0x10000)) {
+- mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+- if (!mem_node)
+- return -ENOMEM;
+-
+- mem_node->base = (ulong)mem_base << 16;
+- mem_node->length = (ulong)(mem_length << 16);
+- dbg("found mem_node(base, length) = %x, %x\n", mem_node->base, mem_node->length);
+-
+- if (!populated_slot) {
+- mem_node->next = ctrl->mem_head;
+- ctrl->mem_head = mem_node;
+- } else {
+- mem_node->next = func->mem_head;
+- func->mem_head = mem_node;
+- }
+- }
+-
+- /*
+- * If we've got a valid prefetchable memory base, and
+- * the base + length isn't greater than 0xFFFF
+- */
+- temp_ulong = pre_mem_base + pre_mem_length;
+- if ((pre_mem_base) && (temp_ulong <= 0x10000)) {
+- p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+- if (!p_mem_node)
+- return -ENOMEM;
+-
+- p_mem_node->base = (ulong)pre_mem_base << 16;
+- p_mem_node->length = (ulong)pre_mem_length << 16;
+- dbg("found p_mem_node(base, length) = %x, %x\n", p_mem_node->base, p_mem_node->length);
+-
+- if (!populated_slot) {
+- p_mem_node->next = ctrl->p_mem_head;
+- ctrl->p_mem_head = p_mem_node;
+- } else {
+- p_mem_node->next = func->p_mem_head;
+- func->p_mem_head = p_mem_node;
+- }
+- }
+-
+- /*
+- * If we've got a valid bus number, use it
+- * The second condition is to ignore bus numbers on
+- * populated slots that don't have PCI-PCI bridges
+- */
+- if (secondary_bus && (secondary_bus != primary_bus)) {
+- bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+- if (!bus_node)
+- return -ENOMEM;
+-
+- bus_node->base = (ulong)secondary_bus;
+- bus_node->length = (ulong)(max_bus - secondary_bus + 1);
+- dbg("found bus_node(base, length) = %x, %x\n", bus_node->base, bus_node->length);
+-
+- if (!populated_slot) {
+- bus_node->next = ctrl->bus_head;
+- ctrl->bus_head = bus_node;
+- } else {
+- bus_node->next = func->bus_head;
+- func->bus_head = bus_node;
+- }
+- }
+-
+- i--;
+- one_slot += sizeof(struct slot_rt);
+- }
+-
+- /* If all of the following fail, we don't have any resources for hot plug add */
+- rc = 1;
+- rc &= shpchp_resource_sort_and_combine(&(ctrl->mem_head));
+- rc &= shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
+- rc &= shpchp_resource_sort_and_combine(&(ctrl->io_head));
+- rc &= shpchp_resource_sort_and_combine(&(ctrl->bus_head));
+-
+- return (rc);
+-}
+-
+ int shpchprm_set_hpp(
+ struct controller *ctrl,
+ struct pci_func *func,
+@@ -413,12 +125,6 @@ void shpchprm_enable_card(
+
+ static int legacy_shpchprm_init_pci(void)
+ {
+- shpchp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN);
+- if (!shpchp_rom_start) {
+- err("Could not ioremap memory region for ROM\n");
+- return -EIO;
+- }
+-
+ return 0;
+ }
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchprm_legacy.h
++++ /dev/null
+@@ -1,113 +0,0 @@
+-/*
+- * SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform using HRT
+- *
+- * 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 _SHPCHPRM_LEGACY_H_
+-#define _SHPCHPRM_LEGACY_H_
+-
+-#define ROM_PHY_ADDR 0x0F0000
+-#define ROM_PHY_LEN 0x00FFFF
+-
+-struct slot_rt {
+- u8 dev_func;
+- u8 primary_bus;
+- u8 secondary_bus;
+- u8 max_bus;
+- u16 io_base;
+- u16 io_length;
+- u16 mem_base;
+- u16 mem_length;
+- u16 pre_mem_base;
+- u16 pre_mem_length;
+-} __attribute__ ((packed));
+-
+-/* offsets to the hotplug slot resource table registers based on the above structure layout */
+-enum slot_rt_offsets {
+- DEV_FUNC = offsetof(struct slot_rt, dev_func),
+- PRIMARY_BUS = offsetof(struct slot_rt, primary_bus),
+- SECONDARY_BUS = offsetof(struct slot_rt, secondary_bus),
+- MAX_BUS = offsetof(struct slot_rt, max_bus),
+- IO_BASE = offsetof(struct slot_rt, io_base),
+- IO_LENGTH = offsetof(struct slot_rt, io_length),
+- MEM_BASE = offsetof(struct slot_rt, mem_base),
+- MEM_LENGTH = offsetof(struct slot_rt, mem_length),
+- PRE_MEM_BASE = offsetof(struct slot_rt, pre_mem_base),
+- PRE_MEM_LENGTH = offsetof(struct slot_rt, pre_mem_length),
+-};
+-
+-struct hrt {
+- char sig0;
+- char sig1;
+- char sig2;
+- char sig3;
+- u16 unused_IRQ;
+- u16 PCIIRQ;
+- u8 number_of_entries;
+- u8 revision;
+- u16 reserved1;
+- u32 reserved2;
+-} __attribute__ ((packed));
+-
+-/* offsets to the hotplug resource table registers based on the above structure layout */
+-enum hrt_offsets {
+- SIG0 = offsetof(struct hrt, sig0),
+- SIG1 = offsetof(struct hrt, sig1),
+- SIG2 = offsetof(struct hrt, sig2),
+- SIG3 = offsetof(struct hrt, sig3),
+- UNUSED_IRQ = offsetof(struct hrt, unused_IRQ),
+- PCIIRQ = offsetof(struct hrt, PCIIRQ),
+- NUMBER_OF_ENTRIES = offsetof(struct hrt, number_of_entries),
+- REVISION = offsetof(struct hrt, revision),
+- HRT_RESERVED1 = offsetof(struct hrt, reserved1),
+- HRT_RESERVED2 = offsetof(struct hrt, reserved2),
+-};
+-
+-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 /* _SHPCHPRM_LEGACY_H_ */
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchprm_nonacpi.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchprm_nonacpi.c
+@@ -34,23 +34,14 @@
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <asm/uaccess.h>
+-#ifdef CONFIG_IA64
+-#include <asm/iosapic.h>
+-#endif
+ #include "shpchp.h"
+ #include "shpchprm.h"
+-#include "shpchprm_nonacpi.h"
+
+ void shpchprm_cleanup(void)
+ {
+ return;
+ }
+
+-int shpchprm_print_pirt(void)
+-{
+- return 0;
+-}
+-
+ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
+ {
+ int offset = devnum - ctrl->slot_device_offset;
+@@ -60,275 +51,6 @@ int shpchprm_get_physical_slot_number(st
+ 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 shpchp_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;
+-
+- shpchp_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 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) {
+- func = shpchp_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);
+- 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 shpchprm_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 = shpchp_save_used_resources (ctrl, &func, !DISABLE_CARD);
+- dbg("%s: shpchp_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)
+- phprm_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);
+- 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);
+-
+-
+- /* If all of the following fail, we don't have any resources for hot plug add */
+- rc = 1;
+- rc &= shpchp_resource_sort_and_combine(&(ctrl->mem_head));
+- rc &= shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
+- rc &= shpchp_resource_sort_and_combine(&(ctrl->io_head));
+- rc &= shpchp_resource_sort_and_combine(&(ctrl->bus_head));
+-
+- return (rc);
+-}
+-
+ int shpchprm_set_hpp(
+ struct controller *ctrl,
+ struct pci_func *func,
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchprm_nonacpi.h
++++ /dev/null
+@@ -1,56 +0,0 @@
+-/*
+- * SHPCHPRM 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 _SHPCHPRM_NONACPI_H_
+-#define _SHPCHPRM_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 /* _SHPCHPRM_NONACPI_H_ */
diff --git a/pci/shpc-02-remove-redundant-res-display.patch b/pci/shpc-02-remove-redundant-res-display.patch
new file mode 100644
index 0000000000000..ed7bbadcdfabc
--- /dev/null
+++ b/pci/shpc-02-remove-redundant-res-display.patch
@@ -0,0 +1,99 @@
+From rshah1@unix-os.sc.intel.com Thu Oct 13 13:21:12 2005
+Message-Id: <20051013190820.614626546@csdlinux-2.jf.intel.com>
+Date: Thu, 13 Oct 2005 12:05:37 -0700
+From: rajesh.shah@intel.com
+To: kristen.c.accardi@intel.com, gregkh@suse.de
+Cc: david.keck@amd.com, akpm@osdl.org, Rajesh Shah <rajesh.shah@intel.com>
+Subject: [patch 2/9] shpchp: remove redundant display of PCI device resources
+Content-Disposition: inline; filename=shpc-02-remove-redundant-res-display.patch
+
+Info about resources assigned to PCI devices is already available
+through sysfs and pci utilities. There's no need for shpchp to
+create another sysfs file to display the same information.
+
+Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/pci/hotplug/shpchp_sysfs.c | 68 -------------------------------------
+ 1 file changed, 68 deletions(-)
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_sysfs.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_sysfs.c
+@@ -88,75 +88,7 @@ static ssize_t show_ctrl (struct device
+ }
+ static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
+
+-static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct pci_dev *pdev, *fdev;
+- struct controller *ctrl;
+- char * out = buf;
+- int index;
+- struct resource *res;
+- struct pci_func *new_slot;
+- struct slot *slot;
+-
+- pdev = container_of (dev, struct pci_dev, dev);
+- ctrl = pci_get_drvdata(pdev);
+-
+- slot=ctrl->slot;
+-
+- while (slot) {
+- new_slot = shpchp_slot_find(slot->bus, slot->device, 0);
+- if (!new_slot)
+- break;
+- fdev = new_slot->pci_dev;
+- if (!fdev)
+- break;
+- out += sprintf(out, "assigned resources: memory\n");
+- for (index=0; index <= PCI_NUM_RESOURCES; index++) {
+- res = &(fdev->resource[index]);
+- if (res && (res->flags & IORESOURCE_MEM) &&
+- !(res->flags & IORESOURCE_PREFETCH)) {
+- out += sprintf(out,
+- "start = %8.8lx, length = %8.8lx\n",
+- res->start, (res->end - res->start));
+- }
+- }
+- out += sprintf(out, "assigned resources: prefetchable memory\n");
+- for (index=0; index <= PCI_NUM_RESOURCES; index++) {
+- res = &(fdev->resource[index]);
+- if (res && (res->flags & (IORESOURCE_MEM |
+- IORESOURCE_PREFETCH))) {
+- out += sprintf(out,
+- "start = %8.8lx, length = %8.8lx\n",
+- res->start, (res->end - res->start));
+- }
+- }
+- out += sprintf(out, "assigned resources: IO\n");
+- for (index=0; index <= PCI_NUM_RESOURCES; index++) {
+- res = &(fdev->resource[index]);
+- if (res && (res->flags & IORESOURCE_IO)) {
+- out += sprintf(out,
+- "start = %8.8lx, length = %8.8lx\n",
+- res->start, (res->end - res->start));
+- }
+- }
+- out += sprintf(out, "assigned resources: bus numbers\n");
+- if (fdev->subordinate)
+- out += sprintf(out, "start = %8.8x, length = %8.8x\n",
+- fdev->subordinate->secondary,
+- (fdev->subordinate->subordinate -
+- fdev->subordinate->secondary));
+- else
+- out += sprintf(out, "start = %8.8x, length = %8.8x\n",
+- fdev->bus->number, 1);
+- slot=slot->next;
+- }
+-
+- return out - buf;
+-}
+-static DEVICE_ATTR (dev, S_IRUGO, show_dev, NULL);
+-
+ void shpchp_create_ctrl_files (struct controller *ctrl)
+ {
+ device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
+- device_create_file (&ctrl->pci_dev->dev, &dev_attr_dev);
+ }
diff --git a/pci/shpc-03-reduce-acpi-dependence.patch b/pci/shpc-03-reduce-acpi-dependence.patch
new file mode 100644
index 0000000000000..585512d7e3390
--- /dev/null
+++ b/pci/shpc-03-reduce-acpi-dependence.patch
@@ -0,0 +1,1357 @@
+From rshah1@unix-os.sc.intel.com Thu Oct 13 13:21:05 2005
+Message-Id: <20051013190820.977830316@csdlinux-2.jf.intel.com>
+Date: Thu, 13 Oct 2005 12:05:38 -0700
+From: rajesh.shah@intel.com
+To: kristen.c.accardi@intel.com, gregkh@suse.de
+Cc: david.keck@amd.com, akpm@osdl.org, Rajesh Shah <rajesh.shah@intel.com>
+Subject: [patch 3/9] shpchp: reduce dependence on ACPI
+Content-Disposition: inline; filename=shpc-03-reduce-acpi-dependence
+
+Reduce the SHPC hotplug driver's dependence on ACPI. We don't
+walk the acpi namespace anymore to build a list of bridges and
+devices. The remaining interaction with ACPI is to run the
+_OSHP method to transition control of hotplug hardware from
+system BIOS to the shpc 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 shpchp
+does not enable the hot-added device or its DMA bus mastering
+automatically 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/shpchp.h | 12
+ drivers/pci/hotplug/shpchp_core.c | 13
+ drivers/pci/hotplug/shpchp_ctrl.c | 1
+ drivers/pci/hotplug/shpchp_hpc.c | 2
+ drivers/pci/hotplug/shpchp_pci.c | 52 ++
+ drivers/pci/hotplug/shpchprm.h | 43 -
+ drivers/pci/hotplug/shpchprm_acpi.c | 796 ++-------------------------------
+ drivers/pci/hotplug/shpchprm_legacy.c | 97 ----
+ drivers/pci/hotplug/shpchprm_nonacpi.c | 108 ----
+ 9 files changed, 139 insertions(+), 985 deletions(-)
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp.h
++++ gregkh-2.6/drivers/pci/hotplug/shpchp.h
+@@ -122,6 +122,13 @@ struct controller {
+ u16 vendor_id;
+ };
+
++struct hotplug_params {
++ u8 cache_line_size;
++ u8 latency_timer;
++ u8 enable_serr;
++ u8 enable_perr;
++};
++
+ /* Define AMD SHPC ID */
+ #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450
+
+@@ -192,6 +199,11 @@ extern int shpchp_save_config(struct con
+ extern int shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot);
+ extern int shpchp_configure_device(struct slot *p_slot);
+ extern int shpchp_unconfigure_device(struct pci_func* func);
++extern void 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);
++extern int shpchprm_get_physical_slot_number(struct controller *ctrl,
++ u32 *sun, u8 busnum, u8 devnum);
+
+
+ /* Global variables */
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_core.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_core.c
+@@ -39,7 +39,6 @@
+ #include <linux/init.h>
+ #include <asm/uaccess.h>
+ #include "shpchp.h"
+-#include "shpchprm.h"
+
+ /* Global variables */
+ int shpchp_debug;
+@@ -566,16 +565,12 @@ static int __init shpcd_init(void)
+ if (retval)
+ goto error_hpc_init;
+
+- retval = shpchprm_init(PCI);
+- if (!retval) {
+- retval = pci_register_driver(&shpc_driver);
+- dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
+- info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+- }
++ retval = pci_register_driver(&shpc_driver);
++ dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
++ info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+
+ error_hpc_init:
+ if (retval) {
+- shpchprm_cleanup();
+ shpchp_event_stop_thread();
+ }
+ return retval;
+@@ -586,8 +581,6 @@ static void __exit shpcd_cleanup(void)
+ dbg("unload_shpchpd()\n");
+ unload_shpchpd();
+
+- shpchprm_cleanup();
+-
+ dbg("pci_unregister_driver\n");
+ pci_unregister_driver(&shpc_driver);
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_ctrl.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_ctrl.c
+@@ -40,7 +40,6 @@
+ #include <linux/pci.h>
+ #include "../pci.h"
+ #include "shpchp.h"
+-#include "shpchprm.h"
+
+ static void interrupt_event_handler(struct controller *ctrl);
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_hpc.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_hpc.c
+@@ -1566,8 +1566,8 @@ int shpc_init(struct controller * ctrl,
+ err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq);
+ goto abort_free_ctlr;
+ }
+- /* Execute OSHP method here */
+ }
++ get_hp_hw_control_from_firmware(pdev);
+ dbg("%s: Before adding HPC to HPC list\n", __FUNCTION__);
+
+ /* Add this HPC instance into the HPC list */
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_pci.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_pci.c
+@@ -38,6 +38,55 @@
+ #include "../pci.h"
+ #include "shpchp.h"
+
++void program_fw_provided_values(struct pci_dev *dev)
++{
++ u16 pci_cmd, pci_bctl;
++ struct pci_dev *cdev;
++ struct hotplug_params hpp = {0x8, 0x40, 0, 0}; /* defaults */
++
++ /* Program hpp values for this device */
++ if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
++ (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
++ (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
++ return;
++
++ get_hp_params_from_firmware(dev, &hpp);
++
++ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size);
++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer);
++ pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
++ if (hpp.enable_serr)
++ pci_cmd |= PCI_COMMAND_SERR;
++ else
++ pci_cmd &= ~PCI_COMMAND_SERR;
++ if (hpp.enable_perr)
++ pci_cmd |= PCI_COMMAND_PARITY;
++ else
++ pci_cmd &= ~PCI_COMMAND_PARITY;
++ pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
++
++ /* Program bridge control value and child devices */
++ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
++ pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
++ hpp.latency_timer);
++ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
++ if (hpp.enable_serr)
++ pci_bctl |= PCI_BRIDGE_CTL_SERR;
++ else
++ pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
++ if (hpp.enable_perr)
++ pci_bctl |= PCI_BRIDGE_CTL_PARITY;
++ else
++ pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
++ pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);
++ if (dev->subordinate) {
++ list_for_each_entry(cdev, &dev->subordinate->devices,
++ bus_list)
++ program_fw_provided_values(cdev);
++ }
++ }
++}
++
+ int shpchp_configure_device(struct slot *p_slot)
+ {
+ struct pci_dev *dev;
+@@ -90,8 +139,7 @@ int shpchp_configure_device(struct slot
+ child->subordinate = pci_do_scan_bus(child);
+ pci_bus_size_bridges(child);
+ }
+- /* TBD: program firmware provided _HPP values */
+- /* program_fw_provided_values(dev); */
++ program_fw_provided_values(dev);
+ }
+
+ pci_bus_assign_resources(parent);
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchprm.h
++++ /dev/null
+@@ -1,43 +0,0 @@
+-/*
+- * SHPCHPRM : SHPCHP Resource Manager for ACPI/non-ACPI 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 _SHPCHPRM_H_
+-#define _SHPCHPRM_H_
+-
+-#ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY
+-#include "shpchprm_legacy.h"
+-#endif
+-
+-int shpchprm_init(enum php_ctlr_type ct);
+-void shpchprm_cleanup(void);
+-int shpchprm_set_hpp(struct controller *ctrl, struct pci_func *func, u8 card_type);
+-void shpchprm_enable_card(struct controller *ctrl, struct pci_func *func, u8 card_type);
+-int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum);
+-
+-#endif /* _SHPCHPRM_H_ */
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchprm_acpi.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchprm_acpi.c
+@@ -38,62 +38,11 @@
+ #include <acpi/acpi_bus.h>
+ #include <acpi/actypes.h>
+ #include "shpchp.h"
+-#include "shpchprm.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"
+
+-#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;
+@@ -109,82 +58,43 @@ static u8 * acpi_path_name( acpi_handle
+ return path_name;
+ }
+
+-static void acpi_get__hpp ( struct acpi_bridge *ab);
+-static void acpi_run_oshp ( struct acpi_bridge *ab);
+-
+-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_shpchprm: 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);
+-
+- acpi_run_oshp(ab);
+-
+- if (sun != samesun) {
+- info("acpi_shpchprm: 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_shpchprm:%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_shpchprm:%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_shpchprm:%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;
+ }
+
+@@ -197,553 +107,41 @@ static void acpi_get__hpp ( struct acpi_
+ nui[i] = (u8)ext_obj->integer.value;
+ break;
+ default:
+- err ("acpi_shpchprm:%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_shpchprm:%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 void acpi_run_oshp ( struct acpi_bridge *ab)
+-{
+- acpi_status status;
+- u8 *path_name = acpi_path_name(ab->handle);
+-
+- /* run OSHP */
+- status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, NULL);
+- if (ACPI_FAILURE(status)) {
+- err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status);
+- } else
+- dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status);
+- return;
+-}
+-
+-/* 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 */
+- )
+-{
+- 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 shpchprm_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 */
+- )
++static void acpi_run_oshp(acpi_handle handle)
+ {
+- 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 shpchprm_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_shpchprm:%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_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
+- return status;
+- }
+-
+- dbg("acpi_shpchprm:%s sun=0x%08x adr=0x%08x\n", path_name, (u32)sun, (u32)adr);
+-
+- status = acpi_get_parent(handle, &phandle);
++ /* run OSHP */
++ status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
+ if (ACPI_FAILURE(status)) {
+- err("acpi_shpchprm:%s get_parent fail=0x%x\n", path_name, status);
+- return (status);
+- }
+-
+- bus_num = pab->bus;
+- seg_num = pab->seg;
+-
+- if (pab->bus == bus_num) {
+- lab = pab;
++ err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
++ status);
+ } else {
+- dbg("WARN: pab is not parent\n");
+- lab = find_acpi_bridge_by_bus(pab, seg_num, bus_num);
+- if (!lab) {
+- dbg("acpi_shpchprm: 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_shpchprm: 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;
+-
+- shpchprm_acpi_register_a_bridge (&acpi_bridges_head, pab, lab);
+- } else
+- dbg("acpi_shpchprm: found P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
+- }
+-
+- acpi_add_slot_to_php_slots(lab, (int)bus_num, handle, (u32)adr, (u32)sun);
+- return (status);
+-}
+-
+-static int shpchprm_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,
+- shpchprm_acpi_build_php_slots_callback,
+- ab,
+- NULL );
+- if (ACPI_FAILURE(status)) {
+- dbg("acpi_shpchprm:%s walk for _SUN on pci bridge seg:bus(%x:%x) fail=0x%x\n", path_name, ab->seg, ab->bus, status);
+- return -1;
+- }
+-
+- return 0;
+-}
+-
+-static void build_a_bridge(
+- struct acpi_bridge *pab,
+- struct acpi_bridge *ab
+- )
+-{
+- u8 *path_name = acpi_path_name(ab->handle);
+-
+- shpchprm_acpi_register_a_bridge (&acpi_bridges_head, pab, ab);
+-
+- switch (ab->type) {
+- case BRIDGE_TYPE_HOST:
+- dbg("acpi_shpchprm: 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_shpchprm: 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 */
+- shpchprm_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_shpchprm: alloc for ab fail\n");
+- return NULL;
++ dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
+ }
+- 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_shpchprm:%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_shpchprm: 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_shpchprm:%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_shpchprm:%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_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
+- return NULL;
+- }
+- dbg("acpi_shpchprm: 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_shpchprm: 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;
+-
+- 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
+- )
+-{
+- 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_shpchprm:%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_shpchprm:%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_shpchprm:%s find_p2p fail=0x%x\n", path_name, status);
+- }
+-
+- return AE_OK;
+-}
+-
+-static int shpchprm_acpi_scan_pci (void)
+-{
+- acpi_status status;
+-
+- /*
+- * TBD: traverse LDM device tree with the help of
+- * unified ACPI augmented for php device population.
+- */
+- status = acpi_get_devices ( PCI_ROOT_HID_STRING,
+- acpi_scan_from_root_pci_callback,
+- NULL,
+- NULL );
+- if (ACPI_FAILURE(status)) {
+- err("acpi_shpchprm:get_device PCI ROOT HID fail=0x%x\n", status);
+- return -1;
+- }
+-
+- return 0;
+-}
+-
+-int shpchprm_init(enum php_ctlr_type ctlr_type)
+-{
+- int rc;
+-
+- if (ctlr_type != PCI)
+- return -ENODEV;
+-
+- dbg("shpchprm ACPI init <enter>\n");
+- acpi_bridges_head = NULL;
+-
+- /* construct PCI bus:device tree of acpi_handles */
+- rc = shpchprm_acpi_scan_pci();
+- if (rc)
+- return rc;
+-
+- dbg("shpchprm 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 shpchprm_free_bridges ( struct acpi_bridge *ab)
+-{
+- if (!ab)
+- return;
+-
+- if (ab->child)
+- shpchprm_free_bridges (ab->child);
+-
+- if (ab->next)
+- shpchprm_free_bridges (ab->next);
+-
+- free_a_bridge(ab);
+-}
+-
+-void shpchprm_cleanup(void)
+-{
+- shpchprm_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;
+-
+ }
+
+ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
+@@ -755,108 +153,40 @@ int shpchprm_get_physical_slot_number(st
+ return 0;
+ }
+
+-int shpchprm_set_hpp(
+- struct controller *ctrl,
+- struct pci_func *func,
+- u8 card_type
+- )
++void get_hp_hw_control_from_firmware(struct pci_dev *dev)
+ {
+- 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->slot_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);
+- }
+-
+- /* 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;
++ /*
++ * OSHP is an optional ACPI firmware control method. If present,
++ * we need to run it to inform BIOS that we will control SHPC
++ * hardware from now on.
++ */
++ acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev));
++ if (!handle)
++ return;
++ acpi_run_oshp(handle);
+ }
+
+-void shpchprm_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, 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, &command);
+-
+- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
+- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
+- }
++ acpi_status status = AE_NOT_FOUND;
++ struct pci_dev *pdev = dev;
+
+- cmd = command = command | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
+- | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+- bcmd = bcommand = bcommand | PCI_BRIDGE_CTL_NO_ISA;
+-
+- ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_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);
++ /*
++ * _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
++ */
++ 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;
+ }
+ }
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchprm_legacy.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchprm_legacy.c
+@@ -37,10 +37,6 @@
+ #include "shpchp.h"
+ #include "shpchprm.h"
+
+-void shpchprm_cleanup(void)
+-{
+-}
+-
+ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
+ {
+ int offset = devnum - ctrl->slot_device_offset;
+@@ -49,97 +45,14 @@ int shpchprm_get_physical_slot_number(st
+ return 0;
+ }
+
+-int shpchprm_set_hpp(
+- struct controller *ctrl,
+- struct pci_func *func,
+- u8 card_type)
++void get_hp_params_from_firmware(struct pci_dev *dev,
++ struct hotplug_params *hpp)
+ {
+- 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;
++ return;
+ }
+
+-void shpchprm_enable_card(
+- struct controller *ctrl,
+- struct pci_func *func,
+- u8 card_type)
++void get_hp_hw_control_from_firmware(struct pci_dev *dev)
+ {
+- 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);
+- }
+-}
+-
+-static int legacy_shpchprm_init_pci(void)
+-{
+- return 0;
++ return;
+ }
+
+-int shpchprm_init(enum php_ctlr_type ctrl_type)
+-{
+- int retval;
+-
+- switch (ctrl_type) {
+- case PCI:
+- retval = legacy_shpchprm_init_pci();
+- break;
+- default:
+- retval = -ENODEV;
+- break;
+- }
+-
+- return retval;
+-}
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchprm_nonacpi.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchprm_nonacpi.c
+@@ -37,11 +37,6 @@
+ #include "shpchp.h"
+ #include "shpchprm.h"
+
+-void shpchprm_cleanup(void)
+-{
+- return;
+-}
+-
+ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
+ {
+ int offset = devnum - ctrl->slot_device_offset;
+@@ -51,106 +46,13 @@ int shpchprm_get_physical_slot_number(st
+ return 0;
+ }
+
+-int shpchprm_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 shpchprm_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);
+- }
+-}
+-
+-static int legacy_shpchprm_init_pci(void)
+-{
+- return 0;
++ return;
+ }
+
+-int shpchprm_init(enum php_ctlr_type ctrl_type)
++void get_hp_hw_control_from_firmware(struct pci_dev *dev)
+ {
+- int retval;
+-
+- switch (ctrl_type) {
+- case PCI:
+- retval = legacy_shpchprm_init_pci();
+- break;
+- default:
+- retval = -ENODEV;
+- break;
+- }
+-
+- return retval;
++ return;
+ }
diff --git a/pci/shpc-04-probe-bail-early.patch b/pci/shpc-04-probe-bail-early.patch
new file mode 100644
index 0000000000000..8f5da7e66d650
--- /dev/null
+++ b/pci/shpc-04-probe-bail-early.patch
@@ -0,0 +1,54 @@
+From rshah1@unix-os.sc.intel.com Thu Oct 13 13:21:00 2005
+Message-Id: <20051013190821.278182580@csdlinux-2.jf.intel.com>
+Date: Thu, 13 Oct 2005 12:05:39 -0700
+From: rajesh.shah@intel.com
+To: kristen.c.accardi@intel.com, gregkh@suse.de
+Cc: david.keck@amd.com, akpm@osdl.org, Rajesh Shah <rajesh.shah@intel.com>
+Subject: [patch 4/9] shpchp: detect SHPC capability before doing a lot of work
+Content-Disposition: inline; filename=shpc-04-probe-bail-early.patch
+
+The shpc driver registers its probe function for all pci-pci
+bridges in the system. Not all of them will be shpc capable, so
+look for this capability early in the probe function and return
+if there's no work to do on this bridge. The old shpc driver
+did some initialization work on all bridges before detecting
+that shpc is not supported and unwinds the work it's already done
+in that case.
+
+Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/pci/hotplug/shpchp_core.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_core.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_core.c
+@@ -351,6 +351,17 @@ static int get_cur_bus_speed (struct hot
+ return 0;
+ }
+
++static int is_shpc_capable(struct pci_dev *dev)
++{
++ if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device ==
++ PCI_DEVICE_ID_AMD_GOLAM_7450))
++ return 1;
++ if (pci_find_capability(dev, PCI_CAP_ID_SHPC))
++ return 1;
++
++ return 0;
++}
++
+ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ int rc;
+@@ -359,6 +370,9 @@ static int shpc_probe(struct pci_dev *pd
+ int first_device_num; /* first PCI device number supported by this SHPC */
+ int num_ctlr_slots; /* number of slots supported by this SHPC */
+
++ if (!is_shpc_capable(pdev))
++ return -ENODEV;
++
+ ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
+ if (!ctrl) {
+ err("%s : out of memory\n", __FUNCTION__);
diff --git a/pci/shpc-05-dont-save-pci-configs.patch b/pci/shpc-05-dont-save-pci-configs.patch
new file mode 100644
index 0000000000000..8e970bf3c9421
--- /dev/null
+++ b/pci/shpc-05-dont-save-pci-configs.patch
@@ -0,0 +1,483 @@
+From rshah1@unix-os.sc.intel.com Thu Oct 13 13:21:06 2005
+Message-Id: <20051013190821.552623698@csdlinux-2.jf.intel.com>
+Date: Thu, 13 Oct 2005 12:05:40 -0700
+From: rajesh.shah@intel.com
+To: kristen.c.accardi@intel.com, gregkh@suse.de
+Cc: david.keck@amd.com, akpm@osdl.org, Rajesh Shah <rajesh.shah@intel.com>
+Subject: [patch 5/9] shpchp: dont save PCI config for hotplug slots/devices
+Content-Disposition: inline; filename=shpc-05-dont-save-pci-configs.patch
+
+This patch eliminates saving the PCI config header for devices
+in hotplug capable slots. We now use the PCI core to get the
+specific parts of the config header as required.
+
+Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/pci/hotplug/shpchp.h | 1
+ drivers/pci/hotplug/shpchp_core.c | 7
+ drivers/pci/hotplug/shpchp_ctrl.c | 48 +++--
+ drivers/pci/hotplug/shpchp_pci.c | 314 --------------------------------------
+ 4 files changed, 32 insertions(+), 338 deletions(-)
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp.h
++++ gregkh-2.6/drivers/pci/hotplug/shpchp.h
+@@ -63,7 +63,6 @@ struct pci_func {
+ u8 switch_save;
+ u8 presence_save;
+ u8 pwr_save;
+- u32 config_space[0x20];
+ struct pci_dev* pci_dev;
+ };
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_core.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_core.c
+@@ -424,13 +424,6 @@ static int shpc_probe(struct pci_dev *pd
+ first_device_num = ctrl->slot_device_offset;
+ num_ctlr_slots = ctrl->num_slots;
+
+- /* Store PCI Config Space for all devices on this bus */
+- rc = shpchp_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 */
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_ctrl.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_ctrl.c
+@@ -328,21 +328,20 @@ static int slot_remove(struct pci_func *
+ /**
+ * bridge_slot_remove - Removes a node from the linked list of slots.
+ * @bridge: bridge to remove
++ * @secondaryBus: secondary PCI bus number for bridge being removed
++ * @subordinateBus: subordinate PCI bus number for bridge being removed
+ *
+ * Returns 0 if successful, !0 otherwise.
+ */
+-static int bridge_slot_remove(struct pci_func *bridge)
++static int bridge_slot_remove(struct pci_func *bridge, u8 secondaryBus,
++ u8 subordinateBus)
+ {
+- 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 = shpchp_slot_list[tempBus];
+
+@@ -410,16 +409,23 @@ struct pci_func *shpchp_slot_find(u8 bus
+ return(NULL);
+ }
+
+-static int is_bridge(struct pci_func * func)
++static int is_bridge(struct pci_func *func, struct controller *ctrl)
+ {
+- /* Check the header type */
+- if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01)
++ u8 hdr_type;
++ struct pci_bus *bus = ctrl->pci_dev->subordinate;
++
++ /*
++ * Note: device may have just been hot-added and not yet scanned
++ * by the pci core, so its pci_dev structure may not exist yet
++ */
++ pci_bus_read_config_byte(bus, PCI_DEVFN(func->device, func->function),
++ PCI_HEADER_TYPE, &hdr_type);
++ if ((hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE)
+ return 1;
+ else
+ return 0;
+ }
+
+-
+ /* The following routines constitute the bulk of the
+ hotplug controller logic
+ */
+@@ -709,8 +715,6 @@ static u32 board_added(struct pci_func *
+ goto err_exit;
+ }
+
+- shpchp_save_slot_config(ctrl, func);
+-
+ func->status = 0;
+ func->switch_save = 0x10;
+ func->is_a_board = 0x01;
+@@ -769,10 +773,18 @@ static u32 remove_board(struct pci_func
+ u8 hp_slot;
+ u32 rc;
+ struct slot *p_slot;
++ u8 secondary = 0, subordinate = 0;
++ int remove_bridge;
+
+ if (func == NULL)
+ return(1);
+
++ if ((remove_bridge = is_bridge(func, ctrl))) {
++ /* Stash away bus information before we destroy it */
++ secondary = func->pci_dev->subordinate->secondary;
++ subordinate = func->pci_dev->subordinate->subordinate;
++ }
++
+ if (shpchp_unconfigure_device(func))
+ return(1);
+
+@@ -825,10 +837,11 @@ static u32 remove_board(struct pci_func
+
+ if (ctrl->add_support) {
+ while (func) {
+- if (is_bridge(func)) {
++ if (remove_bridge) {
+ 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);
++ bridge_slot_remove(func, secondary,
++ subordinate);
+ } else
+ dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus,
+ func->device, func->function);
+@@ -1185,9 +1198,12 @@ int shpchp_enable_slot (struct slot *p_s
+
+ rc = board_added(func, p_slot->ctrl);
+ if (rc) {
+- if (is_bridge(func))
+- bridge_slot_remove(func);
+- else
++ if (is_bridge(func, p_slot->ctrl)) {
++ u8 secondary = func->pci_dev->subordinate->secondary;
++ u8 subordinate =
++ func->pci_dev->subordinate->subordinate;
++ bridge_slot_remove(func, secondary, subordinate);
++ } else
+ slot_remove(func);
+
+ /* Setup slot structure with entry for empty slot */
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_pci.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_pci.c
+@@ -166,317 +166,3 @@ int shpchp_unconfigure_device(struct pci
+ return rc;
+ }
+
+-/* More PCI configuration routines; this time centered around hotplug controller */
+-
+-
+-/*
+- * shpchp_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 shpchp_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 FirstSupported;
+- int LastSupported;
+- 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;
+-
+- dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__,
+- num_ctlr_slots, first_device_num);
+-
+- 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 */
+- pci_bus->number = busnumber;
+- 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 */
+- 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;
+-
+- 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 = shpchp_save_config(ctrl, sub_bus, 0, 0);
+- if (rc)
+- return rc;
+- }
+- }
+-
+- index = 0;
+- new_slot = shpchp_slot_find(busnumber, device, index++);
+-
+- dbg("new_slot = %p\n", new_slot);
+-
+- while (new_slot && (new_slot->function != (u8) function)) {
+- new_slot = shpchp_slot_find(busnumber, device, index++);
+- dbg("new_slot = %p\n", new_slot);
+- }
+- if (!new_slot) {
+- /* Setup slot structure. */
+- new_slot = shpchp_slot_create(busnumber);
+- dbg("new_slot = %p\n", new_slot);
+-
+- 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;
+- new_slot->pwr_save = 1;
+- /* 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)) {
+- 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 = shpchp_slot_create(busnumber);
+-
+- if (new_slot == NULL) {
+- return(1);
+- }
+- dbg("new_slot = %p\n", new_slot);
+-
+- 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 */
+-
+- return(0);
+-}
+-
+-
+-/*
+- * shpchp_save_slot_config
+- *
+- * Saves configuration info for all PCI devices in a given slot
+- * including subordinate busses.
+- *
+- * returns 0 if success
+- */
+-int shpchp_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 = shpchp_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/shpc-06-remove-redundant-data-structures.patch b/pci/shpc-06-remove-redundant-data-structures.patch
new file mode 100644
index 0000000000000..6fc1421c92284
--- /dev/null
+++ b/pci/shpc-06-remove-redundant-data-structures.patch
@@ -0,0 +1,852 @@
+From rshah1@unix-os.sc.intel.com Thu Oct 13 13:21:05 2005
+Message-Id: <20051013190821.836189267@csdlinux-2.jf.intel.com>
+Date: Thu, 13 Oct 2005 12:05:41 -0700
+From: rajesh.shah@intel.com
+To: kristen.c.accardi@intel.com, gregkh@suse.de
+Cc: david.keck@amd.com, akpm@osdl.org, Rajesh Shah <rajesh.shah@intel.com>
+Subject: [patch 6/9] shpchp: remove redundant data structures
+Content-Disposition: inline; filename=shpc-06-remove-redundant-data-structures.patch
+
+State information is currently stored in per-slot as well as
+per-pci-function data structures in shpchp. 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/shpchp.h | 35 ---
+ drivers/pci/hotplug/shpchp_core.c | 20 -
+ drivers/pci/hotplug/shpchp_ctrl.c | 405 +++-----------------------------------
+ drivers/pci/hotplug/shpchp_pci.c | 27 +-
+ 4 files changed, 63 insertions(+), 424 deletions(-)
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp.h
++++ gregkh-2.6/drivers/pci/hotplug/shpchp.h
+@@ -52,34 +52,18 @@ extern int shpchp_debug;
+ #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 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;
+- u8 pwr_save;
+- struct pci_dev* pci_dev;
+-};
+-
+ #define SLOT_MAGIC 0x67267321
+ struct slot {
+ u32 magic;
+ struct slot *next;
+ u8 bus;
+ u8 device;
++ u16 status;
+ u32 number;
+ u8 is_a_board;
+- u8 configured;
+ u8 state;
+- u8 switch_save;
+ u8 presence_save;
+- u32 capabilities;
+- u16 reserved2;
++ u8 pwr_save;
+ struct timer_list task_event;
+ u8 hp_slot;
+ struct controller *ctrl;
+@@ -106,19 +90,14 @@ struct controller {
+ 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 */
+ u8 slot_bus; /* Bus where the slots handled by this controller sit */
+- u8 push_flag;
+- u16 ctlrcap;
+- u16 vendor_id;
+ };
+
+ struct hotplug_params {
+@@ -169,13 +148,9 @@ struct hotplug_params {
+ * 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_shpc "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 shpcphd mdoule. Upgrade to a newer version of shpchpd\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"
+
+ /* sysfs functions for the hotplug controller info */
+ extern void shpchp_create_ctrl_files (struct controller *ctrl);
+@@ -183,8 +158,6 @@ extern void shpchp_create_ctrl_files (st
+ /* controller functions */
+ extern int shpchp_event_start_thread(void);
+ extern void shpchp_event_stop_thread(void);
+-extern struct pci_func *shpchp_slot_create(unsigned char busnumber);
+-extern struct pci_func *shpchp_slot_find(unsigned char bus, unsigned char device, unsigned char index);
+ extern int shpchp_enable_slot(struct slot *slot);
+ extern int shpchp_disable_slot(struct slot *slot);
+
+@@ -195,9 +168,8 @@ extern u8 shpchp_handle_power_fault(u8 h
+
+ /* pci functions */
+ extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
+-extern int shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot);
+ extern int shpchp_configure_device(struct slot *p_slot);
+-extern int shpchp_unconfigure_device(struct pci_func* func);
++extern int shpchp_unconfigure_device(struct slot *p_slot);
+ extern void 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);
+@@ -207,7 +179,6 @@ extern int shpchprm_get_physical_slot_nu
+
+ /* Global variables */
+ extern struct controller *shpchp_ctrl_list;
+-extern struct pci_func *shpchp_slot_list[256];
+
+ struct ctrl_reg {
+ volatile u32 base_offset;
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_core.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_core.c
+@@ -45,7 +45,6 @@ int shpchp_debug;
+ int shpchp_poll_mode;
+ int shpchp_poll_time;
+ struct controller *shpchp_ctrl_list; /* = NULL */
+-struct pci_func *shpchp_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>"
+@@ -475,7 +474,6 @@ err_out_none:
+
+ static int shpc_start_thread(void)
+ {
+- int loop;
+ int retval = 0;
+
+ dbg("Initialize + Start the notification/polling mechanism \n");
+@@ -486,20 +484,11 @@ static int shpc_start_thread(void)
+ return retval;
+ }
+
+- dbg("Initialize slot lists\n");
+- /* One slot list for each bus in the system */
+- for (loop = 0; loop < 256; loop++) {
+- shpchp_slot_list[loop] = NULL;
+- }
+-
+ return retval;
+ }
+
+ static void __exit unload_shpchpd(void)
+ {
+- struct pci_func *next;
+- struct pci_func *TempSlot;
+- int loop;
+ struct controller *ctrl;
+ struct controller *tctrl;
+
+@@ -519,15 +508,6 @@ static void __exit unload_shpchpd(void)
+ kfree(tctrl);
+ }
+
+- for (loop = 0; loop < 256; loop++) {
+- next = shpchp_slot_list[loop];
+- while (next != NULL) {
+- TempSlot = next;
+- next = next->next;
+- kfree(TempSlot);
+- }
+- }
+-
+ /* Stop the notification mechanism */
+ shpchp_event_stop_thread();
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_ctrl.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_ctrl.c
+@@ -54,19 +54,16 @@ u8 shpchp_handle_attention_button(u8 hp_
+ struct slot *p_slot;
+ u8 rc = 0;
+ u8 getstatus;
+- struct pci_func *func;
+ struct event_info *taskInfo;
+
+ /* Attention Button Change */
+ dbg("shpchp: Attention button interrupt received.\n");
+
+- func = shpchp_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 = shpchp_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;
+@@ -111,14 +108,11 @@ u8 shpchp_handle_switch_change(u8 hp_slo
+ struct slot *p_slot;
+ u8 rc = 0;
+ u8 getstatus;
+- struct pci_func *func;
+ struct event_info *taskInfo;
+
+ /* Switch Change */
+ dbg("shpchp: Switch interrupt received.\n");
+
+- func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+-
+ /* This is the structure that tells the worker thread
+ * what to do
+ */
+@@ -128,19 +122,18 @@ u8 shpchp_handle_switch_change(u8 hp_slo
+
+ rc++;
+ p_slot = shpchp_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);
+ dbg("%s: Card present %x Power status %x\n", __FUNCTION__,
+- func->presence_save, func->pwr_save);
++ p_slot->presence_save, p_slot->pwr_save);
+
+ if (getstatus) {
+ /*
+ * Switch opened
+ */
+ info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
+- func->switch_save = 0;
+ taskInfo->event_type = INT_SWITCH_OPEN;
+- if (func->pwr_save && func->presence_save) {
++ if (p_slot->pwr_save && p_slot->presence_save) {
+ taskInfo->event_type = INT_POWER_FAULT;
+ err("Surprise Removal of card\n");
+ }
+@@ -149,7 +142,6 @@ u8 shpchp_handle_switch_change(u8 hp_slo
+ * Switch closed
+ */
+ info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
+- func->switch_save = 0x10;
+ taskInfo->event_type = INT_SWITCH_CLOSE;
+ }
+
+@@ -165,14 +157,11 @@ u8 shpchp_handle_presence_change(u8 hp_s
+ struct slot *p_slot;
+ u8 rc = 0;
+ /*u8 temp_byte;*/
+- struct pci_func *func;
+ struct event_info *taskInfo;
+
+ /* Presence Change */
+ dbg("shpchp: Presence/Notify input change.\n");
+
+- func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+-
+ /* This is the structure that tells the worker thread
+ * what to do
+ */
+@@ -186,8 +175,8 @@ u8 shpchp_handle_presence_change(u8 hp_s
+ /*
+ * 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
+ */
+@@ -212,14 +201,11 @@ u8 shpchp_handle_power_fault(u8 hp_slot,
+ 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("shpchp: Power fault interrupt received.\n");
+
+- func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+-
+ /* This is the structure that tells the worker thread
+ * what to do
+ */
+@@ -235,7 +221,7 @@ u8 shpchp_handle_power_fault(u8 hp_slot,
+ * 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 {
+ /*
+@@ -244,7 +230,7 @@ u8 shpchp_handle_power_fault(u8 hp_slot,
+ 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)
+@@ -253,179 +239,6 @@ u8 shpchp_handle_power_fault(u8 hp_slot,
+ return rc;
+ }
+
+-/**
+- * shpchp_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 *shpchp_slot_create(u8 busnumber)
+-{
+- struct pci_func *new_slot;
+- struct pci_func *next;
+-
+- new_slot = kmalloc(sizeof(*new_slot), 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 (shpchp_slot_list[busnumber] == NULL) {
+- shpchp_slot_list[busnumber] = new_slot;
+- } else {
+- next = shpchp_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 = shpchp_slot_list[old_slot->bus];
+-
+- if (next == NULL) {
+- return(1);
+- }
+-
+- if (next == old_slot) {
+- shpchp_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
+- * @secondaryBus: secondary PCI bus number for bridge being removed
+- * @subordinateBus: subordinate PCI bus number for bridge being removed
+- *
+- * Returns 0 if successful, !0 otherwise.
+- */
+-static int bridge_slot_remove(struct pci_func *bridge, u8 secondaryBus,
+- u8 subordinateBus)
+-{
+- u8 tempBus;
+- struct pci_func *next;
+-
+- if (bridge == NULL)
+- return(1);
+-
+- for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {
+- next = shpchp_slot_list[tempBus];
+-
+- while (!slot_remove(next)) {
+- next = shpchp_slot_list[tempBus];
+- }
+- }
+-
+- next = shpchp_slot_list[bridge->bus];
+-
+- if (next == NULL) {
+- return(1);
+- }
+-
+- if (next == bridge) {
+- shpchp_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);
+-}
+-
+-
+-/**
+- * shpchp_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 *shpchp_slot_find(u8 bus, u8 device, u8 index)
+-{
+- int found = -1;
+- struct pci_func *func;
+-
+- func = shpchp_slot_list[bus];
+-
+- if ((func == NULL) || ((func->device == device) && (index == 0)))
+- return(func);
+-
+- if (func->device == device)
+- found++;
+-
+- while (func->next != NULL) {
+- func = func->next;
+-
+- if (func->device == device)
+- found++;
+-
+- if (found == index)
+- return(func);
+- }
+-
+- return(NULL);
+-}
+-
+-static int is_bridge(struct pci_func *func, struct controller *ctrl)
+-{
+- u8 hdr_type;
+- struct pci_bus *bus = ctrl->pci_dev->subordinate;
+-
+- /*
+- * Note: device may have just been hot-added and not yet scanned
+- * by the pci core, so its pci_dev structure may not exist yet
+- */
+- pci_bus_read_config_byte(bus, PCI_DEVFN(func->device, func->function),
+- PCI_HEADER_TYPE, &hdr_type);
+- if ((hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE)
+- return 1;
+- else
+- return 0;
+-}
+-
+ /* The following routines constitute the bulk of the
+ hotplug controller logic
+ */
+@@ -495,19 +308,20 @@ enum pci_bus_speed asp, enum pci_bus_spe
+ * Configures board
+ *
+ */
+-static u32 board_added(struct pci_func * func, struct controller * ctrl)
++static u32 board_added(struct slot *p_slot)
+ {
+ u8 hp_slot;
+ u8 slots_not_empty = 0;
+ u32 rc = 0;
+- struct slot *p_slot;
+ enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed;
+ u8 pi, mode;
++ struct controller *ctrl = p_slot->ctrl;
+
+- p_slot = shpchp_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);
+@@ -699,13 +513,13 @@ static u32 board_added(struct pci_func *
+ wait_for_ctrl_irq (ctrl);
+ dbg("%s: after long_delay\n", __FUNCTION__);
+
+- 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 */
+ dbg("%s: power fault\n", __FUNCTION__);
+ rc = POWER_FAILURE;
+- func->status = 0;
++ p_slot->status = 0;
+ goto err_exit;
+ }
+
+@@ -715,10 +529,9 @@ static u32 board_added(struct pci_func *
+ goto err_exit;
+ }
+
+- func->status = 0;
+- func->switch_save = 0x10;
+- func->is_a_board = 0x01;
+- func->pwr_save = 1;
++ p_slot->status = 0;
++ p_slot->is_a_board = 0x01;
++ p_slot->pwr_save = 1;
+
+ /* Wait for exclusive access to hardware */
+ down(&ctrl->crit_sect);
+@@ -767,38 +580,23 @@ err_exit:
+ * 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;
++ struct controller *ctrl = p_slot->ctrl;
+ u8 hp_slot;
+ u32 rc;
+- struct slot *p_slot;
+- u8 secondary = 0, subordinate = 0;
+- int remove_bridge;
+
+- if (func == NULL)
++ if (shpchp_unconfigure_device(p_slot))
+ return(1);
+
+- if ((remove_bridge = is_bridge(func, ctrl))) {
+- /* Stash away bus information before we destroy it */
+- secondary = func->pci_dev->subordinate->secondary;
+- subordinate = func->pci_dev->subordinate->subordinate;
+- }
+-
+- if (shpchp_unconfigure_device(func))
+- return(1);
+-
+- device = func->device;
+-
+- hp_slot = func->device - ctrl->slot_device_offset;
++ hp_slot = p_slot->device - ctrl->slot_device_offset;
+ p_slot = shpchp_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;
+
+ /* Wait for exclusive access to hardware */
+ down(&ctrl->crit_sect);
+@@ -835,36 +633,8 @@ static u32 remove_board(struct pci_func
+ /* Done with exclusive hardware access */
+ up(&ctrl->crit_sect);
+
+- if (ctrl->add_support) {
+- while (func) {
+- if (remove_bridge) {
+- 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, secondary,
+- subordinate);
+- } 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 = shpchp_slot_find(ctrl->slot_bus, device, 0);
+- }
+-
+- /* Setup slot structure with entry for empty slot */
+- func = shpchp_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->pwr_save = 0;
+- func->is_a_board = 0;
+- }
++ p_slot->pwr_save = 0;
++ p_slot->is_a_board = 0;
+
+ return 0;
+ }
+@@ -1006,7 +776,6 @@ static void interrupt_event_handler(stru
+ {
+ int loop = 0;
+ int change = 1;
+- struct pci_func *func;
+ u8 hp_slot;
+ u8 getstatus;
+ struct slot *p_slot;
+@@ -1021,11 +790,10 @@ static void interrupt_event_handler(stru
+ ctrl->event_queue[loop].event_type);
+ hp_slot = ctrl->event_queue[loop].hp_slot;
+
+- func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+-
+ p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+- dbg("%s: hp_slot %d, func %p, p_slot %p\n", __FUNCTION__, hp_slot, func, p_slot);
++ dbg("%s: hp_slot %d, p_slot %p\n",
++ __FUNCTION__, hp_slot, p_slot);
+
+ if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) {
+ dbg("%s: button cancel\n", __FUNCTION__);
+@@ -1147,13 +915,6 @@ int shpchp_enable_slot (struct slot *p_s
+ {
+ u8 getstatus = 0;
+ int rc;
+- struct pci_func *func;
+-
+- func = shpchp_slot_find(p_slot->bus, p_slot->device, 0);
+- if (!func) {
+- dbg("%s: Error! slot NULL\n", __FUNCTION__);
+- return -ENODEV;
+- }
+
+ /* Check to see if (latch closed, card present, power off) */
+ down(&p_slot->ctrl->crit_sect);
+@@ -1177,75 +938,35 @@ int shpchp_enable_slot (struct slot *p_s
+ }
+ up(&p_slot->ctrl->crit_sect);
+
+- slot_remove(func);
+-
+- func = shpchp_slot_create(p_slot->bus);
+- if (func == NULL)
+- return -ENOMEM;
+-
+- func->bus = p_slot->bus;
+- func->device = p_slot->device;
+- func->function = 0;
+- func->configured = 0;
+- func->is_a_board = 1;
++ 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_power_status(p_slot, &(func->pwr_save));
+- dbg("%s: func->pwr_save %x\n", __FUNCTION__, func->pwr_save);
++ p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
++ p_slot->hpc_ops->get_power_status(p_slot, &(p_slot->pwr_save));
++ dbg("%s: p_slot->pwr_save %x\n", __FUNCTION__, p_slot->pwr_save);
+ p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+- func->switch_save = !getstatus? 0x10:0;
+
+- rc = board_added(func, p_slot->ctrl);
++ rc = board_added(p_slot);
+ if (rc) {
+- if (is_bridge(func, p_slot->ctrl)) {
+- u8 secondary = func->pci_dev->subordinate->secondary;
+- u8 subordinate =
+- func->pci_dev->subordinate->subordinate;
+- bridge_slot_remove(func, secondary, subordinate);
+- } else
+- slot_remove(func);
+-
+- /* Setup slot structure with entry for empty slot */
+- func = shpchp_slot_create(p_slot->bus);
+- if (func == NULL)
+- return -ENOMEM; /* 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;
+ }
+
+- if (p_slot)
+- update_slot_info(p_slot);
+-
++ update_slot_info(p_slot);
+ return rc;
+ }
+
+
+ int shpchp_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;
+- struct pci_func *func;
+
+ if (!p_slot->ctrl)
+ return -ENODEV;
+
+- pci_bus = p_slot->ctrl->pci_dev->subordinate;
+-
+ /* Check to see if (latch closed, card present, power on) */
+ down(&p_slot->ctrl->crit_sect);
+
+@@ -1269,54 +990,8 @@ int shpchp_disable_slot (struct slot *p_
+ }
+ up(&p_slot->ctrl->crit_sect);
+
+- func = shpchp_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 -ENODEV;
+-
+- 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 -ENODEV;
+-
+- /* 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 -ENODEV;
+-
+- /* If the VGA Enable bit is set, remove isn't supported */
+- if (BCR & PCI_BRIDGE_CTL_VGA) {
+- rc = REMOVE_NOT_SUPPORTED;
+- }
+- }
+- }
+-
+- func = shpchp_slot_find(p_slot->bus, p_slot->device, index++);
+- }
+-
+- func = shpchp_slot_find(p_slot->bus, p_slot->device, 0);
+- if ((func != NULL) && !rc) {
+- rc = remove_board(func, p_slot->ctrl);
+- } else if (!rc)
+- rc = -ENODEV;
+-
+- if (p_slot)
+- update_slot_info(p_slot);
+-
++ rc = remove_board(p_slot);
++ update_slot_info(p_slot);
+ return rc;
+ }
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_pci.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_pci.c
+@@ -148,20 +148,33 @@ int shpchp_configure_device(struct slot
+ return 0;
+ }
+
+-int shpchp_unconfigure_device(struct pci_func* func)
++int shpchp_unconfigure_device(struct slot *p_slot)
+ {
+ int rc = 0;
+ int j;
++ u8 bctl = 0;
+
+- dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus,
+- func->device, func->function);
++ 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);
+ }
+ return rc;
+ }
diff --git a/pci/shpc-07--misc-cleanup.patch b/pci/shpc-07--misc-cleanup.patch
new file mode 100644
index 0000000000000..8d101ac80ee39
--- /dev/null
+++ b/pci/shpc-07--misc-cleanup.patch
@@ -0,0 +1,619 @@
+From rshah1@unix-os.sc.intel.com Thu Oct 13 13:21:22 2005
+Message-Id: <20051013190822.169818308@csdlinux-2.jf.intel.com>
+Date: Thu, 13 Oct 2005 12:05:42 -0700
+From: rajesh.shah@intel.com
+To: kristen.c.accardi@intel.com, gregkh@suse.de
+Cc: david.keck@amd.com, akpm@osdl.org, Rajesh Shah <rajesh.shah@intel.com>
+Subject: [patch 7/9] shpchp: miscellaneous cleanups
+Content-Disposition: inline; filename=shpc-07--misc-cleanup.patch
+
+Remove un-necessary header includes, remove dead code, remove
+some type casts, receive function return in the correct data
+type...
+
+Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/pci/hotplug/shpchp.h | 14 ---
+ drivers/pci/hotplug/shpchp_core.c | 12 ---
+ drivers/pci/hotplug/shpchp_ctrl.c | 31 +++-----
+ drivers/pci/hotplug/shpchp_hpc.c | 126 +++++++--------------------------
+ drivers/pci/hotplug/shpchp_pci.c | 4 -
+ drivers/pci/hotplug/shpchp_sysfs.c | 3
+ drivers/pci/hotplug/shpchprm_acpi.c | 6 -
+ drivers/pci/hotplug/shpchprm_legacy.c | 4 -
+ drivers/pci/hotplug/shpchprm_nonacpi.c | 3
+ 9 files changed, 46 insertions(+), 157 deletions(-)
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp.h
++++ gregkh-2.6/drivers/pci/hotplug/shpchp.h
+@@ -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 "pci_hotplug.h"
+
+ #if !defined(MODULE)
+@@ -80,7 +78,7 @@ struct event_info {
+ 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;
+@@ -234,7 +232,7 @@ enum ctrl_offsets {
+ SLOT11 = offsetof(struct ctrl_reg, slot11),
+ SLOT12 = offsetof(struct ctrl_reg, slot12),
+ };
+-typedef u8(*php_intr_callback_t) (unsigned int change_id, void *instance_id);
++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;
+@@ -347,11 +345,7 @@ enum php_ctlr_type {
+ ACPI
+ };
+
+-int shpc_init( struct controller *ctrl, struct pci_dev *pdev,
+- 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 shpc_init( struct controller *ctrl, struct pci_dev *pdev);
+
+ int shpc_get_ctlr_slot_config( struct controller *ctrl,
+ int *num_ctlr_slots,
+@@ -364,8 +358,6 @@ struct hpc_ops {
+ int (*power_on_slot ) (struct slot *slot);
+ int (*slot_enable ) (struct slot *slot);
+ int (*slot_disable ) (struct slot *slot);
+- int (*enable_all_slots) (struct slot *slot);
+- int (*pwr_on_all_slots) (struct slot *slot);
+ int (*set_bus_speed_mode) (struct slot *slot, enum pci_bus_speed speed);
+ int (*get_power_status) (struct slot *slot, u8 *status);
+ int (*get_attention_status) (struct slot *slot, u8 *status);
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_core.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_core.c
+@@ -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 "shpchp.h"
+
+ /* Global variables */
+@@ -381,11 +375,7 @@ static int shpc_probe(struct pci_dev *pd
+
+ dbg("DRV_thread pid = %d\n", current->pid);
+
+- rc = shpc_init(ctrl, pdev,
+- (php_intr_callback_t) shpchp_handle_attention_button,
+- (php_intr_callback_t) shpchp_handle_switch_change,
+- (php_intr_callback_t) shpchp_handle_presence_change,
+- (php_intr_callback_t) shpchp_handle_power_fault);
++ rc = shpc_init(ctrl, pdev);
+ if (rc) {
+ dbg("%s: controller initialization failed\n", SHPC_MODULE_NAME);
+ goto err_out_free_ctrl;
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_ctrl.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_ctrl.c
+@@ -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"
+@@ -242,9 +236,10 @@ u8 shpchp_handle_power_fault(u8 hp_slot,
+ /* The following routines constitute the bulk of the
+ hotplug controller logic
+ */
+-static u32 change_bus_speed(struct controller *ctrl, struct slot *p_slot, enum pci_bus_speed speed)
++static int change_bus_speed(struct controller *ctrl, struct slot *p_slot,
++ enum pci_bus_speed speed)
+ {
+- u32 rc = 0;
++ int rc = 0;
+
+ dbg("%s: change to speed %d\n", __FUNCTION__, speed);
+ down(&ctrl->crit_sect);
+@@ -266,10 +261,11 @@ static u32 change_bus_speed(struct contr
+ return rc;
+ }
+
+-static u32 fix_bus_speed(struct controller *ctrl, struct slot *pslot, u8 flag,
+-enum pci_bus_speed asp, enum pci_bus_speed bsp, enum pci_bus_speed msp)
++static int fix_bus_speed(struct controller *ctrl, struct slot *pslot,
++ u8 flag, enum pci_bus_speed asp, enum pci_bus_speed bsp,
++ enum pci_bus_speed msp)
+ {
+- u32 rc = 0;
++ int rc = 0;
+
+ if (flag != 0) { /* Other slots on the same bus are occupied */
+ if ( asp < bsp ) {
+@@ -308,11 +304,11 @@ enum pci_bus_speed asp, enum pci_bus_spe
+ * Configures board
+ *
+ */
+-static u32 board_added(struct slot *p_slot)
++static int board_added(struct slot *p_slot)
+ {
+ u8 hp_slot;
+ u8 slots_not_empty = 0;
+- u32 rc = 0;
++ int rc = 0;
+ enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed;
+ u8 pi, mode;
+ struct controller *ctrl = p_slot->ctrl;
+@@ -580,11 +576,11 @@ err_exit:
+ * remove_board - Turns off slot and LED's
+ *
+ */
+-static u32 remove_board(struct slot *p_slot)
++static int remove_board(struct slot *p_slot)
+ {
+ struct controller *ctrl = p_slot->ctrl;
+ u8 hp_slot;
+- u32 rc;
++ int rc;
+
+ if (shpchp_unconfigure_device(p_slot))
+ return(1);
+@@ -961,7 +957,6 @@ int shpchp_enable_slot (struct slot *p_s
+ int shpchp_disable_slot (struct slot *p_slot)
+ {
+ u8 getstatus = 0;
+- u32 rc = 0;
+ int ret = 0;
+
+ if (!p_slot->ctrl)
+@@ -990,8 +985,8 @@ int shpchp_disable_slot (struct slot *p_
+ }
+ up(&p_slot->ctrl->crit_sect);
+
+- rc = remove_board(p_slot);
++ ret = remove_board(p_slot);
+ update_slot_info(p_slot);
+- return rc;
++ return ret;
+ }
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_hpc.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_hpc.c
+@@ -27,17 +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/delay.h>
+ #include <linux/pci.h>
+-#include <asm/system.h>
+ #include "shpchp.h"
+
+ #ifdef DEBUG
+@@ -282,7 +275,7 @@ static void start_int_poll_timer(struct
+
+ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
+ {
+- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+ u16 cmd_status;
+ int retval = 0;
+ u16 temp_word;
+@@ -328,7 +321,7 @@ static int shpc_write_cmd(struct slot *s
+
+ static int hpc_check_cmd_status(struct controller *ctrl)
+ {
+- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
+ u16 cmd_status;
+ int retval = 0;
+
+@@ -368,7 +361,7 @@ static int hpc_check_cmd_status(struct c
+
+ static int hpc_get_attention_status(struct slot *slot, u8 *status)
+ {
+- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+ u32 slot_reg;
+ u16 slot_status;
+ u8 atten_led_state;
+@@ -408,7 +401,7 @@ static int hpc_get_attention_status(stru
+
+ static int hpc_get_power_status(struct slot * slot, u8 *status)
+ {
+- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+ u32 slot_reg;
+ u16 slot_status;
+ u8 slot_state;
+@@ -450,7 +443,7 @@ static int hpc_get_power_status(struct s
+
+ static int hpc_get_latch_status(struct slot *slot, u8 *status)
+ {
+- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+ u32 slot_reg;
+ u16 slot_status;
+
+@@ -473,7 +466,7 @@ static int hpc_get_latch_status(struct s
+
+ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
+ {
+- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+ u32 slot_reg;
+ u16 slot_status;
+ u8 card_state;
+@@ -496,7 +489,7 @@ static int hpc_get_adapter_status(struct
+
+ static int hpc_get_prog_int(struct slot *slot, u8 *prog_int)
+ {
+- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+
+ DBG_ENTER_ROUTINE
+
+@@ -513,7 +506,7 @@ static int hpc_get_prog_int(struct slot
+
+ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
+ {
+- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+ u32 slot_reg;
+ u16 slot_status, sec_bus_status;
+ u8 m66_cap, pcix_cap, pi;
+@@ -594,7 +587,7 @@ static int hpc_get_adapter_speed(struct
+
+ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
+ {
+- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+ u16 sec_bus_status;
+ u8 pi;
+ int retval = 0;
+@@ -623,7 +616,7 @@ static int hpc_get_mode1_ECC_cap(struct
+
+ static int hpc_query_power_fault(struct slot * slot)
+ {
+- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+ u32 slot_reg;
+ u16 slot_status;
+ u8 pwr_fault_state, status;
+@@ -647,7 +640,7 @@ static int hpc_query_power_fault(struct
+
+ static int hpc_set_attention_status(struct slot *slot, u8 value)
+ {
+- struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+ u8 slot_cmd = 0;
+ int rc = 0;
+
+@@ -683,7 +676,7 @@ static int hpc_set_attention_status(stru
+
+ static void hpc_set_green_led_on(struct slot *slot)
+ {
+- struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+ u8 slot_cmd;
+
+ if (!slot->ctrl->hpc_ctlr_handle) {
+@@ -705,7 +698,7 @@ static void hpc_set_green_led_on(struct
+
+ static void hpc_set_green_led_off(struct slot *slot)
+ {
+- struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+ u8 slot_cmd;
+
+ if (!slot->ctrl->hpc_ctlr_handle) {
+@@ -727,7 +720,7 @@ static void hpc_set_green_led_off(struct
+
+ static void hpc_set_green_led_blink(struct slot *slot)
+ {
+- struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+ u8 slot_cmd;
+
+ if (!slot->ctrl->hpc_ctlr_handle) {
+@@ -754,7 +747,7 @@ int shpc_get_ctlr_slot_config(struct con
+ int *updown, /* physical_slot_num increament: 1 or -1 */
+ int *flags)
+ {
+- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
+
+ DBG_ENTER_ROUTINE
+
+@@ -776,7 +769,7 @@ int shpc_get_ctlr_slot_config(struct con
+
+ static void hpc_release_ctlr(struct controller *ctrl)
+ {
+- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *p, *p_prev;
+
+ DBG_ENTER_ROUTINE
+@@ -828,7 +821,7 @@ DBG_LEAVE_ROUTINE
+
+ static int hpc_power_on_slot(struct slot * slot)
+ {
+- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+ u8 slot_cmd;
+ int retval = 0;
+
+@@ -859,7 +852,7 @@ static int hpc_power_on_slot(struct slot
+
+ static int hpc_slot_enable(struct slot * slot)
+ {
+- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+ u8 slot_cmd;
+ int retval = 0;
+
+@@ -890,7 +883,7 @@ static int hpc_slot_enable(struct slot *
+
+ static int hpc_slot_disable(struct slot * slot)
+ {
+- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+ u8 slot_cmd;
+ int retval = 0;
+
+@@ -920,51 +913,12 @@ static int hpc_slot_disable(struct slot
+ return retval;
+ }
+
+-static int hpc_enable_all_slots( struct slot *slot )
+-{
+- int retval = 0;
+-
+- DBG_ENTER_ROUTINE
+-
+- if (!slot->ctrl->hpc_ctlr_handle) {
+- err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+- return -1;
+- }
+-
+- retval = shpc_write_cmd(slot, 0, SET_ENABLE_ALL);
+- if (retval) {
+- err("%s: Write command failed!\n", __FUNCTION__);
+- return -1;
+- }
+-
+- DBG_LEAVE_ROUTINE
+-
+- return retval;
+-}
+-
+-static int hpc_pwr_on_all_slots(struct slot *slot)
+-{
+- int retval = 0;
+-
+- DBG_ENTER_ROUTINE
+-
+- retval = shpc_write_cmd(slot, 0, SET_PWR_ON_ALL);
+-
+- if (retval) {
+- err("%s: Write command failed!\n", __FUNCTION__);
+- return -1;
+- }
+-
+- DBG_LEAVE_ROUTINE
+- return retval;
+-}
+-
+ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
+ {
+ u8 slot_cmd;
+ u8 pi;
+ int retval = 0;
+- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+
+ DBG_ENTER_ROUTINE
+
+@@ -1184,7 +1138,7 @@ static irqreturn_t shpc_isr(int IRQ, voi
+
+ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
+ {
+- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+ enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
+ int retval = 0;
+ u8 pi;
+@@ -1253,7 +1207,7 @@ static int hpc_get_max_bus_speed (struct
+
+ static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value)
+ {
+- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
++ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+ enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
+ u16 sec_bus_status;
+ int retval = 0;
+@@ -1367,8 +1321,6 @@ static struct hpc_ops shpchp_hpc_ops = {
+ .power_on_slot = hpc_power_on_slot,
+ .slot_enable = hpc_slot_enable,
+ .slot_disable = hpc_slot_disable,
+- .enable_all_slots = hpc_enable_all_slots,
+- .pwr_on_all_slots = hpc_pwr_on_all_slots,
+ .set_bus_speed_mode = hpc_set_bus_speed_mode,
+ .set_attention_status = hpc_set_attention_status,
+ .get_power_status = hpc_get_power_status,
+@@ -1391,12 +1343,7 @@ static struct hpc_ops shpchp_hpc_ops = {
+ .check_cmd_status = hpc_check_cmd_status,
+ };
+
+-int shpc_init(struct controller * ctrl,
+- struct pci_dev * pdev,
+- 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 shpc_init(struct controller * ctrl, struct pci_dev * pdev)
+ {
+ struct php_ctlr_state_s *php_ctlr, *p;
+ void *instance_id = ctrl;
+@@ -1405,7 +1352,6 @@ int shpc_init(struct controller * ctrl,
+ static int first = 1;
+ u32 shpc_cap_offset, shpc_base_offset;
+ u32 tempdword, slot_reg;
+- u16 vendor_id, device_id;
+ u8 i;
+
+ DBG_ENTER_ROUTINE
+@@ -1422,21 +1368,8 @@ int shpc_init(struct controller * ctrl,
+
+ php_ctlr->pci_dev = pdev; /* save pci_dev in context */
+
+- rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
+- dbg("%s: Vendor ID: %x\n",__FUNCTION__, vendor_id);
+- if (rc) {
+- err("%s: unable to read PCI configuration data\n", __FUNCTION__);
+- goto abort_free_ctlr;
+- }
+-
+- rc = pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id);
+- dbg("%s: Device ID: %x\n",__FUNCTION__, device_id);
+- if (rc) {
+- err("%s: unable to read PCI configuration data\n", __FUNCTION__);
+- goto abort_free_ctlr;
+- }
+-
+- if ((vendor_id == PCI_VENDOR_ID_AMD) || (device_id == PCI_DEVICE_ID_AMD_GOLAM_7450)) {
++ if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
++ PCI_DEVICE_ID_AMD_GOLAM_7450)) {
+ shpc_base_offset = 0; /* amd shpc driver doesn't use this; assume 0 */
+ } else {
+ if ((shpc_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC)) == 0) {
+@@ -1514,11 +1447,10 @@ int shpc_init(struct controller * ctrl,
+ php_ctlr->irq = pdev->irq;
+ 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 = shpchp_handle_attention_button,
++ php_ctlr->switch_change_callback = shpchp_handle_switch_change;
++ php_ctlr->presence_change_callback = shpchp_handle_presence_change;
++ php_ctlr->power_fault_callback = shpchp_handle_power_fault;
+ php_ctlr->callback_instance_id = instance_id;
+
+ /* Return PCI Controller Info */
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_pci.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_pci.c
+@@ -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 "shpchp.h"
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_sysfs.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_sysfs.c
+@@ -26,12 +26,9 @@
+ *
+ */
+
+-#include <linux/config.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/types.h>
+-#include <linux/proc_fs.h>
+-#include <linux/workqueue.h>
+ #include <linux/pci.h>
+ #include "shpchp.h"
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchprm_acpi.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchprm_acpi.c
+@@ -24,16 +24,10 @@
+ *
+ */
+
+-#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 <asm/uaccess.h>
+-#include <asm/system.h>
+ #include <acpi/acpi.h>
+ #include <acpi/acpi_bus.h>
+ #include <acpi/actypes.h>
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchprm_legacy.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchprm_legacy.c
+@@ -27,15 +27,11 @@
+ *
+ */
+
+-#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 <asm/uaccess.h>
+ #include "shpchp.h"
+-#include "shpchprm.h"
+
+ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
+ {
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchprm_nonacpi.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchprm_nonacpi.c
+@@ -32,10 +32,7 @@
+ #include <linux/kernel.h>
+ #include <linux/types.h>
+ #include <linux/pci.h>
+-#include <linux/init.h>
+-#include <asm/uaccess.h>
+ #include "shpchp.h"
+-#include "shpchprm.h"
+
+ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
+ {
diff --git a/pci/shpc-08-reduce-dbg-verbosity.patch b/pci/shpc-08-reduce-dbg-verbosity.patch
new file mode 100644
index 0000000000000..e7d50cdeb00cf
--- /dev/null
+++ b/pci/shpc-08-reduce-dbg-verbosity.patch
@@ -0,0 +1,331 @@
+From rshah1@unix-os.sc.intel.com Thu Oct 13 13:21:06 2005
+Message-Id: <20051013190822.438265132@csdlinux-2.jf.intel.com>
+Date: Thu, 13 Oct 2005 12:05:43 -0700
+From: rajesh.shah@intel.com
+To: kristen.c.accardi@intel.com, gregkh@suse.de
+Cc: david.keck@amd.com, akpm@osdl.org, Rajesh Shah <rajesh.shah@intel.com>
+Subject: [patch 8/9] shpchp: reduce debug message verbosity
+Content-Disposition: inline; filename=shpc-08-reduce-dbg-verbosity.patch
+
+Reduce the number of debug messages generated if shpchp 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/shpchp.h | 6 ----
+ drivers/pci/hotplug/shpchp_core.c | 8 ------
+ drivers/pci/hotplug/shpchp_ctrl.c | 11 --------
+ drivers/pci/hotplug/shpchp_hpc.c | 47 +++++---------------------------------
+ 4 files changed, 7 insertions(+), 65 deletions(-)
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp.h
++++ gregkh-2.6/drivers/pci/hotplug/shpchp.h
+@@ -293,12 +293,9 @@ static inline struct slot *shpchp_find_s
+
+ 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: shpchp_find_slot device=0x%x\n", device);
+@@ -313,8 +310,6 @@ static inline int wait_for_ctrl_irq (str
+ DECLARE_WAITQUEUE(wait, current);
+ int retval = 0;
+
+- dbg("%s : start\n",__FUNCTION__);
+-
+ add_wait_queue(&ctrl->queue, &wait);
+
+ if (!shpchp_poll_mode) {
+@@ -328,7 +323,6 @@ static inline int wait_for_ctrl_irq (str
+ if (signal_pending(current))
+ retval = -EINTR;
+
+- dbg("%s : end\n", __FUNCTION__);
+ return retval;
+ }
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_core.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_core.c
+@@ -105,8 +105,6 @@ static int init_slots(struct controller
+ u32 slot_number, sun;
+ int result = -ENOMEM;
+
+- dbg("%s\n",__FUNCTION__);
+-
+ number_of_slots = ctrl->num_slots;
+ slot_device = ctrl->slot_device_offset;
+ slot_number = ctrl->first_slot;
+@@ -373,15 +371,12 @@ static int shpc_probe(struct pci_dev *pd
+ }
+ memset(ctrl, 0, sizeof(struct controller));
+
+- dbg("DRV_thread pid = %d\n", current->pid);
+-
+ rc = shpc_init(ctrl, pdev);
+ if (rc) {
+ dbg("%s: controller initialization failed\n", SHPC_MODULE_NAME);
+ goto err_out_free_ctrl;
+ }
+
+- dbg("%s: controller initialization success\n", __FUNCTION__);
+ ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */
+
+ pci_set_drvdata(pdev, ctrl);
+@@ -488,8 +483,6 @@ static void __exit unload_shpchpd(void)
+ cleanup_slots(ctrl);
+
+ kfree (ctrl->pci_bus);
+-
+- dbg("%s: calling release_ctlr\n", __FUNCTION__);
+ ctrl->hpc_ops->release_ctlr(ctrl);
+
+ tctrl = ctrl;
+@@ -558,7 +551,6 @@ static void __exit shpcd_cleanup(void)
+ dbg("unload_shpchpd()\n");
+ unload_shpchpd();
+
+- dbg("pci_unregister_driver\n");
+ pci_unregister_driver(&shpc_driver);
+
+ info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_ctrl.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_ctrl.c
+@@ -505,9 +505,7 @@ static int board_added(struct slot *p_sl
+ up(&ctrl->crit_sect);
+
+ /* Wait for ~1 second */
+- dbg("%s: before long_delay\n", __FUNCTION__);
+ wait_for_ctrl_irq (ctrl);
+- dbg("%s: after long_delay\n", __FUNCTION__);
+
+ dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status);
+ /* Check for a power fault */
+@@ -666,13 +664,11 @@ static void shpchp_pushbutton_thread (un
+ 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);
+
+ shpchp_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);
+
+ if (shpchp_enable_slot(p_slot)) {
+ /* Wait for exclusive access to hardware */
+@@ -734,7 +730,6 @@ int shpchp_event_start_thread (void)
+ err ("Can't start up our event thread\n");
+ return -1;
+ }
+- dbg("Our event thread pid = %d\n", pid);
+ return 0;
+ }
+
+@@ -742,9 +737,7 @@ int shpchp_event_start_thread (void)
+ void shpchp_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);
+ }
+
+@@ -776,7 +769,6 @@ static void interrupt_event_handler(stru
+ u8 getstatus;
+ struct slot *p_slot;
+
+- dbg("%s:\n", __FUNCTION__);
+ while (change) {
+ change = 0;
+
+@@ -788,9 +780,6 @@ static void interrupt_event_handler(stru
+
+ p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+- dbg("%s: hp_slot %d, p_slot %p\n",
+- __FUNCTION__, hp_slot, p_slot);
+-
+ if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) {
+ dbg("%s: button cancel\n", __FUNCTION__);
+ del_timer(&p_slot->task_event);
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_hpc.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_hpc.c
+@@ -313,7 +313,6 @@ static int shpc_write_cmd(struct slot *s
+ * command.
+ */
+ writew(temp_word, php_ctlr->creg + CMD);
+- dbg("%s: temp_word written %x\n", __FUNCTION__, temp_word);
+
+ DBG_LEAVE_ROUTINE
+ return retval;
+@@ -789,10 +788,8 @@ static void hpc_release_ctlr(struct cont
+ }
+ }
+ if (php_ctlr->pci_dev) {
+- dbg("%s: before calling iounmap & release_mem_region\n", __FUNCTION__);
+ iounmap(php_ctlr->creg);
+ release_mem_region(pci_resource_start(php_ctlr->pci_dev, 0), pci_resource_len(php_ctlr->pci_dev, 0));
+- dbg("%s: before calling iounmap & release_mem_region\n", __FUNCTION__);
+ php_ctlr->pci_dev = NULL;
+ }
+
+@@ -1043,18 +1040,13 @@ static irqreturn_t shpc_isr(int IRQ, voi
+
+ if (!intr_loc)
+ return IRQ_NONE;
+- dbg("%s: shpc_isr proceeds\n", __FUNCTION__);
+ dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc);
+
+ if(!shpchp_poll_mode) {
+ /* Mask Global Interrupt Mask - see implementation note on p. 139 */
+ /* of SHPC spec rev 1.0*/
+ temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+- dbg("%s: Before masking global interrupt, temp_dword = %x\n",
+- __FUNCTION__, temp_dword);
+ temp_dword |= 0x00000001;
+- dbg("%s: After masking global interrupt, temp_dword = %x\n",
+- __FUNCTION__, temp_dword);
+ writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+
+ intr_loc2 = readl(php_ctlr->creg + INTR_LOC);
+@@ -1068,11 +1060,7 @@ static irqreturn_t shpc_isr(int IRQ, voi
+ * Detect bit in Controller SERR-INT register
+ */
+ temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+- dbg("%s: Before clearing CCIP, temp_dword = %x\n",
+- __FUNCTION__, temp_dword);
+ temp_dword &= 0xfffeffff;
+- dbg("%s: After clearing CCIP, temp_dword = %x\n",
+- __FUNCTION__, temp_dword);
+ writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+ wake_up_interruptible(&ctrl->queue);
+ }
+@@ -1080,11 +1068,7 @@ static irqreturn_t shpc_isr(int IRQ, voi
+ if ((intr_loc = (intr_loc >> 1)) == 0) {
+ /* Unmask Global Interrupt Mask */
+ temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+- dbg("%s: 1-Before unmasking global interrupt, temp_dword = %x\n",
+- __FUNCTION__, temp_dword);
+ temp_dword &= 0xfffffffe;
+- dbg("%s: 1-After unmasking global interrupt, temp_dword = %x\n",
+- __FUNCTION__, temp_dword);
+ writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+
+ return IRQ_NONE;
+@@ -1094,11 +1078,9 @@ static irqreturn_t shpc_isr(int IRQ, voi
+ /* To find out which slot has interrupt pending */
+ if ((intr_loc >> hp_slot) & 0x01) {
+ temp_dword = readl(php_ctlr->creg + SLOT1 + (4*hp_slot));
+- dbg("%s: Slot %x with intr, temp_dword = %x\n",
+- __FUNCTION__, hp_slot, temp_dword);
++ dbg("%s: Slot %x with intr, slot register = %x\n",
++ __FUNCTION__, hp_slot, temp_dword);
+ temp_byte = (temp_dword >> 16) & 0xFF;
+- dbg("%s: Slot with intr, temp_byte = %x\n",
+- __FUNCTION__, temp_byte);
+ if ((php_ctlr->switch_change_callback) && (temp_byte & 0x08))
+ schedule_flag += php_ctlr->switch_change_callback(
+ hp_slot, php_ctlr->callback_instance_id);
+@@ -1114,8 +1096,6 @@ static irqreturn_t shpc_isr(int IRQ, voi
+
+ /* Clear all slot events */
+ temp_dword = 0xe01f3fff;
+- dbg("%s: Clearing slot events, temp_dword = %x\n",
+- __FUNCTION__, temp_dword);
+ writel(temp_dword, php_ctlr->creg + SLOT1 + (4*hp_slot));
+
+ intr_loc2 = readl(php_ctlr->creg + INTR_LOC);
+@@ -1125,11 +1105,7 @@ static irqreturn_t shpc_isr(int IRQ, voi
+ if (!shpchp_poll_mode) {
+ /* Unmask Global Interrupt Mask */
+ temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+- dbg("%s: 2-Before unmasking global interrupt, temp_dword = %x\n",
+- __FUNCTION__, temp_dword);
+ temp_dword &= 0xfffffffe;
+- dbg("%s: 2-After unmasking global interrupt, temp_dword = %x\n",
+- __FUNCTION__, temp_dword);
+ writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+ }
+
+@@ -1402,7 +1378,8 @@ int shpc_init(struct controller * ctrl,
+ err("%s : pci_read_config_dword failed\n", __FUNCTION__);
+ goto abort_free_ctlr;
+ }
+- dbg("%s: offset %d: tempdword %x\n", __FUNCTION__,i, tempdword);
++ dbg("%s: offset %d: value %x\n", __FUNCTION__,i,
++ tempdword);
+ }
+ }
+
+@@ -1411,13 +1388,6 @@ int shpc_init(struct controller * ctrl,
+ 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), pdev->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), shpc_base_offset %x\n", rc,
+- pci_resource_start(pdev, rc), pci_resource_len(pdev, rc), shpc_base_offset);
+-
+ info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor,
+ pdev->subsystem_device);
+
+@@ -1437,7 +1407,6 @@ int shpc_init(struct controller * ctrl,
+ goto abort_free_ctlr;
+ }
+ dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg);
+- dbg("%s: physical addr %p\n", __FUNCTION__, (void*)pci_resource_start(pdev, 0));
+
+ init_MUTEX(&ctrl->crit_sect);
+ /* Setup wait queue */
+@@ -1445,8 +1414,6 @@ int shpc_init(struct controller * ctrl,
+
+ /* Find the IRQ */
+ php_ctlr->irq = pdev->irq;
+- dbg("HPC interrupt = %d\n", php_ctlr->irq);
+-
+ php_ctlr->attention_button_callback = shpchp_handle_attention_button,
+ php_ctlr->switch_change_callback = shpchp_handle_switch_change;
+ php_ctlr->presence_change_callback = shpchp_handle_presence_change;
+@@ -1488,7 +1455,6 @@ int shpc_init(struct controller * ctrl,
+ if (rc) {
+ info("Can't get msi for the hotplug controller\n");
+ info("Use INTx for the hotplug controller\n");
+- dbg("%s: rc = %x\n", __FUNCTION__, rc);
+ } else
+ php_ctlr->irq = pdev->irq;
+
+@@ -1499,8 +1465,10 @@ int shpc_init(struct controller * ctrl,
+ goto abort_free_ctlr;
+ }
+ }
++ dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __FUNCTION__,
++ pdev->bus->number, PCI_SLOT(pdev->devfn),
++ PCI_FUNC(pdev->devfn), pdev->irq);
+ get_hp_hw_control_from_firmware(pdev);
+- dbg("%s: Before adding HPC to HPC list\n", __FUNCTION__);
+
+ /* Add this HPC instance into the HPC list */
+ spin_lock(&list_lock);
+@@ -1539,7 +1507,6 @@ int shpc_init(struct controller * ctrl,
+ dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
+ }
+
+- dbg("%s: Leaving shpc_init\n", __FUNCTION__);
+ DBG_LEAVE_ROUTINE
+ return 0;
+
diff --git a/pci/shpc-09-remove-sysfs-files-on-unload.patch b/pci/shpc-09-remove-sysfs-files-on-unload.patch
new file mode 100644
index 0000000000000..39adb2b040d37
--- /dev/null
+++ b/pci/shpc-09-remove-sysfs-files-on-unload.patch
@@ -0,0 +1,53 @@
+From rshah1@unix-os.sc.intel.com Thu Oct 13 13:21:12 2005
+Message-Id: <20051013190822.699063905@csdlinux-2.jf.intel.com>
+Date: Thu, 13 Oct 2005 12:05:44 -0700
+From: rajesh.shah@intel.com
+To: kristen.c.accardi@intel.com, gregkh@suse.de
+Cc: david.keck@amd.com, akpm@osdl.org, Rajesh Shah <rajesh.shah@intel.com>
+Subject: [patch 9/9] shpchp: fix oops at driver unload
+Content-Disposition: inline; filename=shpc-09-remove-sysfs-files-on-unload.patch
+
+At unload time, the shpchp driver does not remove sysfs files
+it had created in the driver's probe entry point. 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/shpchp.h | 1 +
+ drivers/pci/hotplug/shpchp_core.c | 1 +
+ drivers/pci/hotplug/shpchp_sysfs.c | 5 +++++
+ 3 files changed, 7 insertions(+)
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp.h
++++ gregkh-2.6/drivers/pci/hotplug/shpchp.h
+@@ -173,6 +173,7 @@ extern void get_hp_params_from_firmware(
+ struct hotplug_params *hpp);
+ extern int shpchprm_get_physical_slot_number(struct controller *ctrl,
+ u32 *sun, u8 busnum, u8 devnum);
++extern void shpchp_remove_ctrl_files(struct controller *ctrl);
+
+
+ /* Global variables */
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_core.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_core.c
+@@ -480,6 +480,7 @@ static void __exit unload_shpchpd(void)
+ ctrl = shpchp_ctrl_list;
+
+ while (ctrl) {
++ shpchp_remove_ctrl_files(ctrl);
+ cleanup_slots(ctrl);
+
+ kfree (ctrl->pci_bus);
+--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_sysfs.c
++++ gregkh-2.6/drivers/pci/hotplug/shpchp_sysfs.c
+@@ -89,3 +89,8 @@ void shpchp_create_ctrl_files (struct co
+ {
+ device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
+ }
++
++void shpchp_remove_ctrl_files(struct controller *ctrl)
++{
++ device_remove_file(&ctrl->pci_dev->dev, &dev_attr_ctrl);
++}