[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>

authored by Rajesh Shah and committed by Greg Kroah-Hartman 364d5094 42f49a6a

+26 -8
+26 -8
drivers/pci/hotplug/acpiphp_glue.c
··· 487 487 return NULL; 488 488 } 489 489 490 - static void remove_bridge(acpi_handle handle) 490 + static void cleanup_bridge(struct acpiphp_bridge *bridge) 491 491 { 492 492 struct list_head *list, *tmp; 493 - struct acpiphp_bridge *bridge; 494 493 struct acpiphp_slot *slot; 495 494 acpi_status status; 496 - 497 - bridge = acpiphp_handle_to_bridge(handle); 498 - if (!bridge) { 499 - err("Could not find bridge for handle %p\n", handle); 500 - return; 501 - } 495 + acpi_handle handle = bridge->handle; 502 496 503 497 status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, 504 498 handle_hotplug_event_bridge); ··· 523 529 kfree(bridge); 524 530 } 525 531 532 + static acpi_status 533 + cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) 534 + { 535 + struct acpiphp_bridge *bridge; 536 + 537 + if (!(bridge = acpiphp_handle_to_bridge(handle))) 538 + return AE_OK; 539 + cleanup_bridge(bridge); 540 + return AE_OK; 541 + } 542 + 543 + static void remove_bridge(acpi_handle handle) 544 + { 545 + struct acpiphp_bridge *bridge; 546 + 547 + bridge = acpiphp_handle_to_bridge(handle); 548 + if (bridge) { 549 + cleanup_bridge(bridge); 550 + } else { 551 + /* clean-up p2p bridges under this host bridge */ 552 + acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 553 + (u32)1, cleanup_p2p_bridge, NULL, NULL); 554 + } 555 + } 526 556 527 557 static int power_on_slot(struct acpiphp_slot *slot) 528 558 {