aboutsummaryrefslogtreecommitdiffstats
path: root/pci/acpiphp-slot-management-fix-v4.patch
diff options
context:
space:
mode:
Diffstat (limited to 'pci/acpiphp-slot-management-fix-v4.patch')
-rw-r--r--pci/acpiphp-slot-management-fix-v4.patch343
1 files changed, 343 insertions, 0 deletions
diff --git a/pci/acpiphp-slot-management-fix-v4.patch b/pci/acpiphp-slot-management-fix-v4.patch
new file mode 100644
index 0000000000000..f21d89bbb10c6
--- /dev/null
+++ b/pci/acpiphp-slot-management-fix-v4.patch
@@ -0,0 +1,343 @@
+From kristen.c.accardi@intel.com Thu Feb 23 17:59:56 2006
+From: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com>
+Subject: [patch 5/5] acpiphp - slot management fix - V4
+To: greg@kroah.com
+Date: Thu, 23 Feb 2006 17:56:08 -0800
+Message-Id: <1140746168.11750.79.camel@whizzy>
+
+From: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com>
+
+o This patch removes IDs (for slots management).
+o This patch removes the slot register/unregister processes
+ from the init/exit phases. Instead, adds these processes
+ in the bridge add/cleanup phases.
+o Currently, this change doesn't have any meanings. But
+ these changes are needed to support p2p bridge(with
+ hotplug slot)
+
+Signed-off-by: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com>
+Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/pci/hotplug/acpiphp.h | 8 --
+ drivers/pci/hotplug/acpiphp_core.c | 127 +++++++++++++++++--------------------
+ drivers/pci/hotplug/acpiphp_glue.c | 48 ++++++-------
+ 3 files changed, 86 insertions(+), 97 deletions(-)
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/acpiphp.h
++++ gregkh-2.6/drivers/pci/hotplug/acpiphp.h
+@@ -60,10 +60,7 @@ struct acpiphp_slot;
+ * struct slot - slot information for each *physical* slot
+ */
+ struct slot {
+- u8 number;
+ struct hotplug_slot *hotplug_slot;
+- struct list_head slot_list;
+-
+ struct acpiphp_slot *acpi_slot;
+ };
+
+@@ -119,9 +116,9 @@ struct acpiphp_slot {
+ struct acpiphp_bridge *bridge; /* parent */
+ struct list_head funcs; /* one slot may have different
+ objects (i.e. for each function) */
++ struct slot *slot;
+ struct mutex crit_sect;
+
+- u32 id; /* slot id (serial #) for hotplug core */
+ u8 device; /* pci device# */
+
+ u32 sun; /* ACPI _SUN (slot unique number) */
+@@ -229,12 +226,13 @@ struct acpiphp_dock_station {
+ /* acpiphp_core.c */
+ extern int acpiphp_register_attention(struct acpiphp_attention_info*info);
+ extern int acpiphp_unregister_attention(struct acpiphp_attention_info *info);
++extern int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot);
++extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot);
+
+ /* acpiphp_glue.c */
+ extern int acpiphp_glue_init (void);
+ extern void acpiphp_glue_exit (void);
+ extern int acpiphp_get_num_slots (void);
+-extern struct acpiphp_slot *get_slot_from_id (int id);
+ typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);
+ void handle_hotplug_event_func(acpi_handle, u32, void*);
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/acpiphp_core.c
++++ gregkh-2.6/drivers/pci/hotplug/acpiphp_core.c
+@@ -44,8 +44,6 @@
+ #include "pci_hotplug.h"
+ #include "acpiphp.h"
+
+-static LIST_HEAD(slot_list);
+-
+ #define MY_NAME "acpiphp"
+
+ static int debug;
+@@ -341,62 +339,53 @@ static void release_slot(struct hotplug_
+ kfree(slot);
+ }
+
+-/**
+- * init_slots - initialize 'struct slot' structures for each slot
+- *
+- */
+-static int __init init_slots(void)
++/* callback routine to initialize 'struct slot' for each slot */
++int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
+ {
+ struct slot *slot;
++ struct hotplug_slot *hotplug_slot;
++ struct hotplug_slot_info *hotplug_slot_info;
+ int retval = -ENOMEM;
+- int i;
+
+- for (i = 0; i < num_slots; ++i) {
+- slot = kmalloc(sizeof(struct slot), GFP_KERNEL);
+- if (!slot)
+- goto error;
+- memset(slot, 0, sizeof(struct slot));
+-
+- slot->hotplug_slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
+- if (!slot->hotplug_slot)
+- goto error_slot;
+- memset(slot->hotplug_slot, 0, sizeof(struct hotplug_slot));
+-
+- slot->hotplug_slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
+- if (!slot->hotplug_slot->info)
+- goto error_hpslot;
+- memset(slot->hotplug_slot->info, 0, sizeof(struct hotplug_slot_info));
+-
+- slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
+- if (!slot->hotplug_slot->name)
+- goto error_info;
+-
+- slot->number = i;
+-
+- slot->hotplug_slot->private = slot;
+- slot->hotplug_slot->release = &release_slot;
+- slot->hotplug_slot->ops = &acpi_hotplug_slot_ops;
+-
+- slot->acpi_slot = get_slot_from_id(i);
+- slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot);
+- slot->hotplug_slot->info->attention_status = 0;
+- slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot);
+- slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot);
+- slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
+- slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN;
+-
+- make_slot_name(slot);
+-
+- retval = pci_hp_register(slot->hotplug_slot);
+- if (retval) {
+- err("pci_hp_register failed with error %d\n", retval);
+- goto error_name;
+- }
+-
+- /* add slot to our internal list */
+- list_add(&slot->slot_list, &slot_list);
+- info("Slot [%s] registered\n", slot->hotplug_slot->name);
+- }
++ slot = kzalloc(sizeof(*slot), GFP_KERNEL);
++ if (!slot)
++ goto error;
++
++ slot->hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
++ if (!slot->hotplug_slot)
++ goto error_slot;
++
++ slot->hotplug_slot->info = kzalloc(sizeof(*hotplug_slot_info),
++ GFP_KERNEL);
++ if (!slot->hotplug_slot->info)
++ goto error_hpslot;
++
++ slot->hotplug_slot->name = kzalloc(SLOT_NAME_SIZE, GFP_KERNEL);
++ if (!slot->hotplug_slot->name)
++ goto error_info;
++
++ slot->hotplug_slot->private = slot;
++ slot->hotplug_slot->release = &release_slot;
++ slot->hotplug_slot->ops = &acpi_hotplug_slot_ops;
++
++ slot->acpi_slot = acpiphp_slot;
++ slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot);
++ slot->hotplug_slot->info->attention_status = 0;
++ slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot);
++ slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot);
++ slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
++ slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN;
++
++ acpiphp_slot->slot = slot;
++ make_slot_name(slot);
++
++ retval = pci_hp_register(slot->hotplug_slot);
++ if (retval) {
++ err("pci_hp_register failed with error %d\n", retval);
++ goto error_name;
++ }
++
++ info("Slot [%s] registered\n", slot->hotplug_slot->name);
+
+ return 0;
+ error_name:
+@@ -412,17 +401,16 @@ error:
+ }
+
+
+-static void __exit cleanup_slots (void)
++void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
+ {
+- struct list_head *tmp, *n;
+- struct slot *slot;
++ struct slot *slot = acpiphp_slot->slot;
++ int retval = 0;
+
+- list_for_each_safe (tmp, n, &slot_list) {
+- /* memory will be freed in release_slot callback */
+- slot = list_entry(tmp, struct slot, slot_list);
+- list_del(&slot->slot_list);
+- pci_hp_deregister(slot->hotplug_slot);
+- }
++ info ("Slot [%s] unregistered\n", slot->hotplug_slot->name);
++
++ retval = pci_hp_deregister(slot->hotplug_slot);
++ if (retval)
++ err("pci_hp_deregister failed with error %d\n", retval);
+ }
+
+
+@@ -439,16 +427,21 @@ static int __init acpiphp_init(void)
+
+ /* read all the ACPI info from the system */
+ retval = init_acpi();
+- if (retval && !(docking_station))
+- return retval;
+
+- return init_slots();
++ /* if we have found a docking station, we should
++ * go ahead and load even if init_acpi has found
++ * no slots. This handles the case when the _DCK
++ * method not defined under the actual dock bridge
++ */
++ if (docking_station)
++ return 0;
++ else
++ return retval;
+ }
+
+
+ static void __exit acpiphp_exit(void)
+ {
+- cleanup_slots();
+ /* deallocate internal data structures etc. */
+ acpiphp_glue_exit();
+
+--- gregkh-2.6.orig/drivers/pci/hotplug/acpiphp_glue.c
++++ gregkh-2.6/drivers/pci/hotplug/acpiphp_glue.c
+@@ -128,8 +128,7 @@ register_slot(acpi_handle handle, u32 lv
+ acpi_handle tmp;
+ acpi_status status = AE_OK;
+ unsigned long adr, sun;
+- int device, function;
+- static int num_slots = 0; /* XXX if we support I/O node hotplug... */
++ int device, function, retval;
+
+ status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
+
+@@ -198,7 +197,6 @@ register_slot(acpi_handle handle, u32 lv
+
+ memset(slot, 0, sizeof(struct acpiphp_slot));
+ slot->bridge = bridge;
+- slot->id = num_slots++;
+ slot->device = device;
+ slot->sun = sun;
+ INIT_LIST_HEAD(&slot->funcs);
+@@ -212,6 +210,11 @@ register_slot(acpi_handle handle, u32 lv
+ dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n",
+ slot->sun, pci_domain_nr(bridge->pci_bus),
+ bridge->pci_bus->number, slot->device);
++ retval = acpiphp_register_hotplug_slot(slot);
++ if (retval) {
++ warn("acpiphp_register_hotplug_slot failed(err code = 0x%x)\n", retval);
++ goto err_exit;
++ }
+ }
+
+ newfunc->slot = slot;
+@@ -253,6 +256,14 @@ register_slot(acpi_handle handle, u32 lv
+ status = AE_OK;
+
+ return status;
++
++ err_exit:
++ bridge->nr_slots--;
++ bridge->slots = slot->next;
++ kfree(slot);
++ kfree(newfunc);
++
++ return AE_OK;
+ }
+
+
+@@ -335,9 +346,16 @@ static void init_bridge_misc(struct acpi
+ /* decode ACPI 2.0 _HPP (hot plug parameters) */
+ decode_hpp(bridge);
+
++ /* must be added to the list prior to calling register_slot */
++ list_add(&bridge->list, &bridge_list);
++
+ /* register all slot objects under this bridge */
+ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,
+ register_slot, bridge, NULL);
++ if (ACPI_FAILURE(status)) {
++ list_del(&bridge->list);
++ return;
++ }
+
+ /* install notify handler */
+ if (bridge->type != BRIDGE_TYPE_HOST) {
+@@ -350,8 +368,6 @@ static void init_bridge_misc(struct acpi
+ err("failed to register interrupt notify handler\n");
+ }
+ }
+-
+- list_add(&bridge->list, &bridge_list);
+ }
+
+
+@@ -555,6 +571,8 @@ static void cleanup_bridge(struct acpiph
+ list_del(list);
+ kfree(func);
+ }
++ acpiphp_unregister_hotplug_slot(slot);
++ list_del(&slot->funcs);
+ kfree(slot);
+ slot = next;
+ }
+@@ -1521,26 +1539,6 @@ static int acpiphp_for_each_slot(acpiphp
+ }
+ #endif
+
+-/* search matching slot from id */
+-struct acpiphp_slot *get_slot_from_id(int id)
+-{
+- struct list_head *node;
+- struct acpiphp_bridge *bridge;
+- struct acpiphp_slot *slot;
+-
+- list_for_each (node, &bridge_list) {
+- bridge = (struct acpiphp_bridge *)node;
+- for (slot = bridge->slots; slot; slot = slot->next)
+- if (slot->id == id)
+- return slot;
+- }
+-
+- /* should never happen! */
+- err("%s: no object for id %d\n", __FUNCTION__, id);
+- WARN_ON(1);
+- return NULL;
+-}
+-
+
+ /**
+ * acpiphp_enable_slot - power on slot