aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/pci_root.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/pci_root.c')
-rw-r--r--drivers/acpi/pci_root.c126
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);
52static void acpi_pci_root_remove(struct acpi_device *device); 50static void acpi_pci_root_remove(struct acpi_device *device);
53 51
52static 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)
630void __init acpi_pci_root_init(void) 635void __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
641static 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
655static 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
707static 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
713static acpi_status __init
714find_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
737void __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}