aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/acpiphp_glue.c
diff options
context:
space:
mode:
authorRajesh Shah <rajesh.shah@intel.com>2005-04-28 03:25:54 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-06-28 00:52:42 -0400
commit364d5094a43ff2ceff3d19e40c4199771cb6cb8f (patch)
treebc3c70c12895d22aaa96dc27632df22f4ff9ac9e /drivers/pci/hotplug/acpiphp_glue.c
parent42f49a6ae5dca90cd0594475502bf1c43ff1dc07 (diff)
[PATCH] acpi hotplug: clean up notify handlers on acpiphp unload
A root bridge may not have directly attached hotpluggable slots under it. Instead, it may have p2p bridges with slots under it. In this case, we need to clean up the p2p bridges and slots properly too. Patch below applies on top of the original patch, and fixes this problem. Without this, acpiphp leaves behind notify handlers on module unload, and subsequent module load attempts don't work properly too. Patch was tested on an ia64 Tiger4 box. Signed-off-by: Rajesh Shah <rajesh.shah@intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/hotplug/acpiphp_glue.c')
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 41c3eb28b69d..2f72e50eca2f 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -487,18 +487,12 @@ static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
487 return NULL; 487 return NULL;
488} 488}
489 489
490static void remove_bridge(acpi_handle handle) 490static void cleanup_bridge(struct acpiphp_bridge *bridge)
491{ 491{
492 struct list_head *list, *tmp; 492 struct list_head *list, *tmp;
493 struct acpiphp_bridge *bridge;
494 struct acpiphp_slot *slot; 493 struct acpiphp_slot *slot;
495 acpi_status status; 494 acpi_status status;
496 495 acpi_handle handle = bridge->handle;
497 bridge = acpiphp_handle_to_bridge(handle);
498 if (!bridge) {
499 err("Could not find bridge for handle %p\n", handle);
500 return;
501 }
502 496
503 status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, 497 status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
504 handle_hotplug_event_bridge); 498 handle_hotplug_event_bridge);
@@ -529,6 +523,30 @@ static void remove_bridge(acpi_handle handle)
529 kfree(bridge); 523 kfree(bridge);
530} 524}
531 525
526static acpi_status
527cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
528{
529 struct acpiphp_bridge *bridge;
530
531 if (!(bridge = acpiphp_handle_to_bridge(handle)))
532 return AE_OK;
533 cleanup_bridge(bridge);
534 return AE_OK;
535}
536
537static void remove_bridge(acpi_handle handle)
538{
539 struct acpiphp_bridge *bridge;
540
541 bridge = acpiphp_handle_to_bridge(handle);
542 if (bridge) {
543 cleanup_bridge(bridge);
544 } else {
545 /* clean-up p2p bridges under this host bridge */
546 acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
547 (u32)1, cleanup_p2p_bridge, NULL, NULL);
548 }
549}
532 550
533static int power_on_slot(struct acpiphp_slot *slot) 551static int power_on_slot(struct acpiphp_slot *slot)
534{ 552{