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