diff options
Diffstat (limited to 'drivers/acpi/pci_root.c')
-rw-r--r-- | drivers/acpi/pci_root.c | 126 |
1 files changed, 12 insertions, 114 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 5b01bd6d5ea0..c1c4102e6478 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -35,9 +35,7 @@ | |||
35 | #include <linux/pci-aspm.h> | 35 | #include <linux/pci-aspm.h> |
36 | #include <linux/acpi.h> | 36 | #include <linux/acpi.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <acpi/acpi_bus.h> | 38 | #include <acpi/apei.h> /* for acpi_hest_init() */ |
39 | #include <acpi/acpi_drivers.h> | ||
40 | #include <acpi/apei.h> | ||
41 | 39 | ||
42 | #include "internal.h" | 40 | #include "internal.h" |
43 | 41 | ||
@@ -51,6 +49,12 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
51 | const struct acpi_device_id *not_used); | 49 | const struct acpi_device_id *not_used); |
52 | static void acpi_pci_root_remove(struct acpi_device *device); | 50 | static void acpi_pci_root_remove(struct acpi_device *device); |
53 | 51 | ||
52 | static int acpi_pci_root_scan_dependent(struct acpi_device *adev) | ||
53 | { | ||
54 | acpiphp_check_host_bridge(adev->handle); | ||
55 | return 0; | ||
56 | } | ||
57 | |||
54 | #define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \ | 58 | #define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \ |
55 | | OSC_PCI_ASPM_SUPPORT \ | 59 | | OSC_PCI_ASPM_SUPPORT \ |
56 | | OSC_PCI_CLOCK_PM_SUPPORT \ | 60 | | OSC_PCI_CLOCK_PM_SUPPORT \ |
@@ -66,7 +70,8 @@ static struct acpi_scan_handler pci_root_handler = { | |||
66 | .attach = acpi_pci_root_add, | 70 | .attach = acpi_pci_root_add, |
67 | .detach = acpi_pci_root_remove, | 71 | .detach = acpi_pci_root_remove, |
68 | .hotplug = { | 72 | .hotplug = { |
69 | .ignore = true, | 73 | .enabled = true, |
74 | .scan_dependent = acpi_pci_root_scan_dependent, | ||
70 | }, | 75 | }, |
71 | }; | 76 | }; |
72 | 77 | ||
@@ -630,116 +635,9 @@ static void acpi_pci_root_remove(struct acpi_device *device) | |||
630 | void __init acpi_pci_root_init(void) | 635 | void __init acpi_pci_root_init(void) |
631 | { | 636 | { |
632 | acpi_hest_init(); | 637 | acpi_hest_init(); |
633 | 638 | if (acpi_pci_disabled) | |
634 | if (!acpi_pci_disabled) { | ||
635 | pci_acpi_crs_quirks(); | ||
636 | acpi_scan_add_handler(&pci_root_handler); | ||
637 | } | ||
638 | } | ||
639 | /* Support root bridge hotplug */ | ||
640 | |||
641 | static void handle_root_bridge_insertion(acpi_handle handle) | ||
642 | { | ||
643 | struct acpi_device *device; | ||
644 | |||
645 | if (!acpi_bus_get_device(handle, &device)) { | ||
646 | dev_printk(KERN_DEBUG, &device->dev, | ||
647 | "acpi device already exists; ignoring notify\n"); | ||
648 | return; | 639 | return; |
649 | } | ||
650 | |||
651 | if (acpi_bus_scan(handle)) | ||
652 | acpi_handle_err(handle, "cannot add bridge to acpi list\n"); | ||
653 | } | ||
654 | |||
655 | static void hotplug_event_root(void *data, u32 type) | ||
656 | { | ||
657 | acpi_handle handle = data; | ||
658 | struct acpi_pci_root *root; | ||
659 | |||
660 | acpi_scan_lock_acquire(); | ||
661 | |||
662 | root = acpi_pci_find_root(handle); | ||
663 | |||
664 | switch (type) { | ||
665 | case ACPI_NOTIFY_BUS_CHECK: | ||
666 | /* bus enumerate */ | ||
667 | acpi_handle_printk(KERN_DEBUG, handle, | ||
668 | "Bus check notify on %s\n", __func__); | ||
669 | if (root) | ||
670 | acpiphp_check_host_bridge(handle); | ||
671 | else | ||
672 | handle_root_bridge_insertion(handle); | ||
673 | |||
674 | break; | ||
675 | |||
676 | case ACPI_NOTIFY_DEVICE_CHECK: | ||
677 | /* device check */ | ||
678 | acpi_handle_printk(KERN_DEBUG, handle, | ||
679 | "Device check notify on %s\n", __func__); | ||
680 | if (!root) | ||
681 | handle_root_bridge_insertion(handle); | ||
682 | break; | ||
683 | |||
684 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
685 | /* request device eject */ | ||
686 | acpi_handle_printk(KERN_DEBUG, handle, | ||
687 | "Device eject notify on %s\n", __func__); | ||
688 | if (!root) | ||
689 | break; | ||
690 | |||
691 | get_device(&root->device->dev); | ||
692 | |||
693 | acpi_scan_lock_release(); | ||
694 | |||
695 | acpi_bus_device_eject(root->device, ACPI_NOTIFY_EJECT_REQUEST); | ||
696 | return; | ||
697 | default: | ||
698 | acpi_handle_warn(handle, | ||
699 | "notify_handler: unknown event type 0x%x\n", | ||
700 | type); | ||
701 | break; | ||
702 | } | ||
703 | |||
704 | acpi_scan_lock_release(); | ||
705 | } | ||
706 | |||
707 | static void handle_hotplug_event_root(acpi_handle handle, u32 type, | ||
708 | void *context) | ||
709 | { | ||
710 | acpi_hotplug_execute(hotplug_event_root, handle, type); | ||
711 | } | ||
712 | |||
713 | static acpi_status __init | ||
714 | find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
715 | { | ||
716 | acpi_status status; | ||
717 | int *count = (int *)context; | ||
718 | |||
719 | if (!acpi_is_root_bridge(handle)) | ||
720 | return AE_OK; | ||
721 | |||
722 | (*count)++; | ||
723 | |||
724 | status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | ||
725 | handle_hotplug_event_root, NULL); | ||
726 | if (ACPI_FAILURE(status)) | ||
727 | acpi_handle_printk(KERN_DEBUG, handle, | ||
728 | "notify handler is not installed, exit status: %u\n", | ||
729 | (unsigned int)status); | ||
730 | else | ||
731 | acpi_handle_printk(KERN_DEBUG, handle, | ||
732 | "notify handler is installed\n"); | ||
733 | |||
734 | return AE_OK; | ||
735 | } | ||
736 | |||
737 | void __init acpi_pci_root_hp_init(void) | ||
738 | { | ||
739 | int num = 0; | ||
740 | |||
741 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
742 | ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL); | ||
743 | 640 | ||
744 | printk(KERN_DEBUG "Found %d acpi root devices\n", num); | 641 | pci_acpi_crs_quirks(); |
642 | acpi_scan_add_handler_with_hotplug(&pci_root_handler, "pci_root"); | ||
745 | } | 643 | } |