diff options
Diffstat (limited to 'drivers/acpi/pci_root.c')
-rw-r--r-- | drivers/acpi/pci_root.c | 51 |
1 files changed, 14 insertions, 37 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d3874f425653..417876bce854 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -39,6 +39,8 @@ | |||
39 | #include <acpi/acpi_drivers.h> | 39 | #include <acpi/acpi_drivers.h> |
40 | #include <acpi/apei.h> | 40 | #include <acpi/apei.h> |
41 | 41 | ||
42 | #include "internal.h" | ||
43 | |||
42 | #define PREFIX "ACPI: " | 44 | #define PREFIX "ACPI: " |
43 | 45 | ||
44 | #define _COMPONENT ACPI_PCI_COMPONENT | 46 | #define _COMPONENT ACPI_PCI_COMPONENT |
@@ -590,39 +592,10 @@ static void handle_root_bridge_insertion(acpi_handle handle) | |||
590 | acpi_handle_err(handle, "cannot add bridge to acpi list\n"); | 592 | acpi_handle_err(handle, "cannot add bridge to acpi list\n"); |
591 | } | 593 | } |
592 | 594 | ||
593 | static void handle_root_bridge_removal(struct acpi_device *device) | 595 | static void hotplug_event_root(void *data, u32 type) |
594 | { | ||
595 | acpi_status status; | ||
596 | struct acpi_eject_event *ej_event; | ||
597 | |||
598 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); | ||
599 | if (!ej_event) { | ||
600 | /* Inform firmware the hot-remove operation has error */ | ||
601 | (void) acpi_evaluate_hotplug_ost(device->handle, | ||
602 | ACPI_NOTIFY_EJECT_REQUEST, | ||
603 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, | ||
604 | NULL); | ||
605 | return; | ||
606 | } | ||
607 | |||
608 | ej_event->device = device; | ||
609 | ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; | ||
610 | |||
611 | status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); | ||
612 | if (ACPI_FAILURE(status)) | ||
613 | kfree(ej_event); | ||
614 | } | ||
615 | |||
616 | static void _handle_hotplug_event_root(struct work_struct *work) | ||
617 | { | 596 | { |
597 | acpi_handle handle = data; | ||
618 | struct acpi_pci_root *root; | 598 | struct acpi_pci_root *root; |
619 | struct acpi_hp_work *hp_work; | ||
620 | acpi_handle handle; | ||
621 | u32 type; | ||
622 | |||
623 | hp_work = container_of(work, struct acpi_hp_work, work); | ||
624 | handle = hp_work->handle; | ||
625 | type = hp_work->type; | ||
626 | 599 | ||
627 | acpi_scan_lock_acquire(); | 600 | acpi_scan_lock_acquire(); |
628 | 601 | ||
@@ -652,9 +625,15 @@ static void _handle_hotplug_event_root(struct work_struct *work) | |||
652 | /* request device eject */ | 625 | /* request device eject */ |
653 | acpi_handle_printk(KERN_DEBUG, handle, | 626 | acpi_handle_printk(KERN_DEBUG, handle, |
654 | "Device eject notify on %s\n", __func__); | 627 | "Device eject notify on %s\n", __func__); |
655 | if (root) | 628 | if (!root) |
656 | handle_root_bridge_removal(root->device); | 629 | break; |
657 | break; | 630 | |
631 | get_device(&root->device->dev); | ||
632 | |||
633 | acpi_scan_lock_release(); | ||
634 | |||
635 | acpi_bus_device_eject(root->device, ACPI_NOTIFY_EJECT_REQUEST); | ||
636 | return; | ||
658 | default: | 637 | default: |
659 | acpi_handle_warn(handle, | 638 | acpi_handle_warn(handle, |
660 | "notify_handler: unknown event type 0x%x\n", | 639 | "notify_handler: unknown event type 0x%x\n", |
@@ -663,14 +642,12 @@ static void _handle_hotplug_event_root(struct work_struct *work) | |||
663 | } | 642 | } |
664 | 643 | ||
665 | acpi_scan_lock_release(); | 644 | acpi_scan_lock_release(); |
666 | kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ | ||
667 | } | 645 | } |
668 | 646 | ||
669 | static void handle_hotplug_event_root(acpi_handle handle, u32 type, | 647 | static void handle_hotplug_event_root(acpi_handle handle, u32 type, |
670 | void *context) | 648 | void *context) |
671 | { | 649 | { |
672 | alloc_acpi_hp_work(handle, type, context, | 650 | acpi_hotplug_execute(hotplug_event_root, handle, type); |
673 | _handle_hotplug_event_root); | ||
674 | } | 651 | } |
675 | 652 | ||
676 | static acpi_status __init | 653 | static acpi_status __init |