diff options
Diffstat (limited to 'drivers/acpi/pci_root.c')
-rw-r--r-- | drivers/acpi/pci_root.c | 263 |
1 files changed, 154 insertions, 109 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 7928d4dc7056..0ac546d5e53f 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -45,9 +45,9 @@ | |||
45 | ACPI_MODULE_NAME("pci_root"); | 45 | ACPI_MODULE_NAME("pci_root"); |
46 | #define ACPI_PCI_ROOT_CLASS "pci_bridge" | 46 | #define ACPI_PCI_ROOT_CLASS "pci_bridge" |
47 | #define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" | 47 | #define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" |
48 | static int acpi_pci_root_add(struct acpi_device *device); | 48 | static int acpi_pci_root_add(struct acpi_device *device, |
49 | static int acpi_pci_root_remove(struct acpi_device *device, int type); | 49 | const struct acpi_device_id *not_used); |
50 | static int acpi_pci_root_start(struct acpi_device *device); | 50 | static void acpi_pci_root_remove(struct acpi_device *device); |
51 | 51 | ||
52 | #define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \ | 52 | #define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \ |
53 | | OSC_ACTIVE_STATE_PWR_SUPPORT \ | 53 | | OSC_ACTIVE_STATE_PWR_SUPPORT \ |
@@ -58,17 +58,11 @@ static const struct acpi_device_id root_device_ids[] = { | |||
58 | {"PNP0A03", 0}, | 58 | {"PNP0A03", 0}, |
59 | {"", 0}, | 59 | {"", 0}, |
60 | }; | 60 | }; |
61 | MODULE_DEVICE_TABLE(acpi, root_device_ids); | ||
62 | 61 | ||
63 | static struct acpi_driver acpi_pci_root_driver = { | 62 | static struct acpi_scan_handler pci_root_handler = { |
64 | .name = "pci_root", | ||
65 | .class = ACPI_PCI_ROOT_CLASS, | ||
66 | .ids = root_device_ids, | 63 | .ids = root_device_ids, |
67 | .ops = { | 64 | .attach = acpi_pci_root_add, |
68 | .add = acpi_pci_root_add, | 65 | .detach = acpi_pci_root_remove, |
69 | .remove = acpi_pci_root_remove, | ||
70 | .start = acpi_pci_root_start, | ||
71 | }, | ||
72 | }; | 66 | }; |
73 | 67 | ||
74 | /* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */ | 68 | /* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */ |
@@ -109,24 +103,6 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) | |||
109 | } | 103 | } |
110 | EXPORT_SYMBOL(acpi_pci_unregister_driver); | 104 | EXPORT_SYMBOL(acpi_pci_unregister_driver); |
111 | 105 | ||
112 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) | ||
113 | { | ||
114 | struct acpi_pci_root *root; | ||
115 | acpi_handle handle = NULL; | ||
116 | |||
117 | mutex_lock(&acpi_pci_root_lock); | ||
118 | list_for_each_entry(root, &acpi_pci_roots, node) | ||
119 | if ((root->segment == (u16) seg) && | ||
120 | (root->secondary.start == (u16) bus)) { | ||
121 | handle = root->device->handle; | ||
122 | break; | ||
123 | } | ||
124 | mutex_unlock(&acpi_pci_root_lock); | ||
125 | return handle; | ||
126 | } | ||
127 | |||
128 | EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); | ||
129 | |||
130 | /** | 106 | /** |
131 | * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge | 107 | * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge |
132 | * @handle - the ACPI CA node in question. | 108 | * @handle - the ACPI CA node in question. |
@@ -188,21 +164,6 @@ static acpi_status try_get_root_bridge_busnr(acpi_handle handle, | |||
188 | return AE_OK; | 164 | return AE_OK; |
189 | } | 165 | } |
190 | 166 | ||
191 | static void acpi_pci_bridge_scan(struct acpi_device *device) | ||
192 | { | ||
193 | int status; | ||
194 | struct acpi_device *child = NULL; | ||
195 | |||
196 | if (device->flags.bus_address) | ||
197 | if (device->parent && device->parent->ops.bind) { | ||
198 | status = device->parent->ops.bind(device); | ||
199 | if (!status) { | ||
200 | list_for_each_entry(child, &device->children, node) | ||
201 | acpi_pci_bridge_scan(child); | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | |||
206 | static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766"; | 167 | static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766"; |
207 | 168 | ||
208 | static acpi_status acpi_pci_run_osc(acpi_handle handle, | 169 | static acpi_status acpi_pci_run_osc(acpi_handle handle, |
@@ -445,14 +406,14 @@ out: | |||
445 | } | 406 | } |
446 | EXPORT_SYMBOL(acpi_pci_osc_control_set); | 407 | EXPORT_SYMBOL(acpi_pci_osc_control_set); |
447 | 408 | ||
448 | static int acpi_pci_root_add(struct acpi_device *device) | 409 | static int acpi_pci_root_add(struct acpi_device *device, |
410 | const struct acpi_device_id *not_used) | ||
449 | { | 411 | { |
450 | unsigned long long segment, bus; | 412 | unsigned long long segment, bus; |
451 | acpi_status status; | 413 | acpi_status status; |
452 | int result; | 414 | int result; |
453 | struct acpi_pci_root *root; | 415 | struct acpi_pci_root *root; |
454 | acpi_handle handle; | 416 | struct acpi_pci_driver *driver; |
455 | struct acpi_device *child; | ||
456 | u32 flags, base_flags; | 417 | u32 flags, base_flags; |
457 | bool is_osc_granted = false; | 418 | bool is_osc_granted = false; |
458 | 419 | ||
@@ -506,16 +467,6 @@ static int acpi_pci_root_add(struct acpi_device *device) | |||
506 | acpi_device_name(device), acpi_device_bid(device), | 467 | acpi_device_name(device), acpi_device_bid(device), |
507 | root->segment, &root->secondary); | 468 | root->segment, &root->secondary); |
508 | 469 | ||
509 | /* | ||
510 | * PCI Routing Table | ||
511 | * ----------------- | ||
512 | * Evaluate and parse _PRT, if exists. | ||
513 | */ | ||
514 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); | ||
515 | if (ACPI_SUCCESS(status)) | ||
516 | result = acpi_pci_irq_add_prt(device->handle, root->segment, | ||
517 | root->secondary.start); | ||
518 | |||
519 | root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle); | 470 | root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle); |
520 | 471 | ||
521 | /* | 472 | /* |
@@ -603,21 +554,6 @@ static int acpi_pci_root_add(struct acpi_device *device) | |||
603 | goto out_del_root; | 554 | goto out_del_root; |
604 | } | 555 | } |
605 | 556 | ||
606 | /* | ||
607 | * Attach ACPI-PCI Context | ||
608 | * ----------------------- | ||
609 | * Thus binding the ACPI and PCI devices. | ||
610 | */ | ||
611 | result = acpi_pci_bind_root(device); | ||
612 | if (result) | ||
613 | goto out_del_root; | ||
614 | |||
615 | /* | ||
616 | * Scan and bind all _ADR-Based Devices | ||
617 | */ | ||
618 | list_for_each_entry(child, &device->children, node) | ||
619 | acpi_pci_bridge_scan(child); | ||
620 | |||
621 | /* ASPM setting */ | 557 | /* ASPM setting */ |
622 | if (is_osc_granted) { | 558 | if (is_osc_granted) { |
623 | if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) | 559 | if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) |
@@ -632,26 +568,10 @@ static int acpi_pci_root_add(struct acpi_device *device) | |||
632 | if (device->wakeup.flags.run_wake) | 568 | if (device->wakeup.flags.run_wake) |
633 | device_set_run_wake(root->bus->bridge, true); | 569 | device_set_run_wake(root->bus->bridge, true); |
634 | 570 | ||
635 | return 0; | 571 | if (system_state != SYSTEM_BOOTING) { |
636 | 572 | pcibios_resource_survey_bus(root->bus); | |
637 | out_del_root: | ||
638 | mutex_lock(&acpi_pci_root_lock); | ||
639 | list_del(&root->node); | ||
640 | mutex_unlock(&acpi_pci_root_lock); | ||
641 | |||
642 | acpi_pci_irq_del_prt(root->segment, root->secondary.start); | ||
643 | end: | ||
644 | kfree(root); | ||
645 | return result; | ||
646 | } | ||
647 | |||
648 | static int acpi_pci_root_start(struct acpi_device *device) | ||
649 | { | ||
650 | struct acpi_pci_root *root = acpi_driver_data(device); | ||
651 | struct acpi_pci_driver *driver; | ||
652 | |||
653 | if (system_state != SYSTEM_BOOTING) | ||
654 | pci_assign_unassigned_bus_resources(root->bus); | 573 | pci_assign_unassigned_bus_resources(root->bus); |
574 | } | ||
655 | 575 | ||
656 | mutex_lock(&acpi_pci_root_lock); | 576 | mutex_lock(&acpi_pci_root_lock); |
657 | list_for_each_entry(driver, &acpi_pci_drivers, node) | 577 | list_for_each_entry(driver, &acpi_pci_drivers, node) |
@@ -664,14 +584,20 @@ static int acpi_pci_root_start(struct acpi_device *device) | |||
664 | pci_enable_bridges(root->bus); | 584 | pci_enable_bridges(root->bus); |
665 | 585 | ||
666 | pci_bus_add_devices(root->bus); | 586 | pci_bus_add_devices(root->bus); |
587 | return 1; | ||
588 | |||
589 | out_del_root: | ||
590 | mutex_lock(&acpi_pci_root_lock); | ||
591 | list_del(&root->node); | ||
592 | mutex_unlock(&acpi_pci_root_lock); | ||
667 | 593 | ||
668 | return 0; | 594 | end: |
595 | kfree(root); | ||
596 | return result; | ||
669 | } | 597 | } |
670 | 598 | ||
671 | static int acpi_pci_root_remove(struct acpi_device *device, int type) | 599 | static void acpi_pci_root_remove(struct acpi_device *device) |
672 | { | 600 | { |
673 | acpi_status status; | ||
674 | acpi_handle handle; | ||
675 | struct acpi_pci_root *root = acpi_driver_data(device); | 601 | struct acpi_pci_root *root = acpi_driver_data(device); |
676 | struct acpi_pci_driver *driver; | 602 | struct acpi_pci_driver *driver; |
677 | 603 | ||
@@ -686,31 +612,150 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) | |||
686 | device_set_run_wake(root->bus->bridge, false); | 612 | device_set_run_wake(root->bus->bridge, false); |
687 | pci_acpi_remove_bus_pm_notifier(device); | 613 | pci_acpi_remove_bus_pm_notifier(device); |
688 | 614 | ||
689 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); | ||
690 | if (ACPI_SUCCESS(status)) | ||
691 | acpi_pci_irq_del_prt(root->segment, root->secondary.start); | ||
692 | |||
693 | pci_remove_root_bus(root->bus); | 615 | pci_remove_root_bus(root->bus); |
694 | 616 | ||
695 | mutex_lock(&acpi_pci_root_lock); | 617 | mutex_lock(&acpi_pci_root_lock); |
696 | list_del(&root->node); | 618 | list_del(&root->node); |
697 | mutex_unlock(&acpi_pci_root_lock); | 619 | mutex_unlock(&acpi_pci_root_lock); |
698 | kfree(root); | 620 | kfree(root); |
699 | return 0; | ||
700 | } | 621 | } |
701 | 622 | ||
702 | static int __init acpi_pci_root_init(void) | 623 | void __init acpi_pci_root_init(void) |
703 | { | 624 | { |
704 | acpi_hest_init(); | 625 | acpi_hest_init(); |
705 | 626 | ||
706 | if (acpi_pci_disabled) | 627 | if (!acpi_pci_disabled) { |
707 | return 0; | 628 | pci_acpi_crs_quirks(); |
629 | acpi_scan_add_handler(&pci_root_handler); | ||
630 | } | ||
631 | } | ||
632 | /* Support root bridge hotplug */ | ||
633 | |||
634 | static void handle_root_bridge_insertion(acpi_handle handle) | ||
635 | { | ||
636 | struct acpi_device *device; | ||
708 | 637 | ||
709 | pci_acpi_crs_quirks(); | 638 | if (!acpi_bus_get_device(handle, &device)) { |
710 | if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) | 639 | printk(KERN_DEBUG "acpi device exists...\n"); |
711 | return -ENODEV; | 640 | return; |
641 | } | ||
712 | 642 | ||
713 | return 0; | 643 | if (acpi_bus_scan(handle)) |
644 | printk(KERN_ERR "cannot add bridge to acpi list\n"); | ||
714 | } | 645 | } |
715 | 646 | ||
716 | subsys_initcall(acpi_pci_root_init); | 647 | static void handle_root_bridge_removal(struct acpi_device *device) |
648 | { | ||
649 | struct acpi_eject_event *ej_event; | ||
650 | |||
651 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); | ||
652 | if (!ej_event) { | ||
653 | /* Inform firmware the hot-remove operation has error */ | ||
654 | (void) acpi_evaluate_hotplug_ost(device->handle, | ||
655 | ACPI_NOTIFY_EJECT_REQUEST, | ||
656 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, | ||
657 | NULL); | ||
658 | return; | ||
659 | } | ||
660 | |||
661 | ej_event->device = device; | ||
662 | ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; | ||
663 | |||
664 | acpi_bus_hot_remove_device(ej_event); | ||
665 | } | ||
666 | |||
667 | static void _handle_hotplug_event_root(struct work_struct *work) | ||
668 | { | ||
669 | struct acpi_pci_root *root; | ||
670 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER }; | ||
671 | struct acpi_hp_work *hp_work; | ||
672 | acpi_handle handle; | ||
673 | u32 type; | ||
674 | |||
675 | hp_work = container_of(work, struct acpi_hp_work, work); | ||
676 | handle = hp_work->handle; | ||
677 | type = hp_work->type; | ||
678 | |||
679 | root = acpi_pci_find_root(handle); | ||
680 | |||
681 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | ||
682 | |||
683 | switch (type) { | ||
684 | case ACPI_NOTIFY_BUS_CHECK: | ||
685 | /* bus enumerate */ | ||
686 | printk(KERN_DEBUG "%s: Bus check notify on %s\n", __func__, | ||
687 | (char *)buffer.pointer); | ||
688 | if (!root) | ||
689 | handle_root_bridge_insertion(handle); | ||
690 | |||
691 | break; | ||
692 | |||
693 | case ACPI_NOTIFY_DEVICE_CHECK: | ||
694 | /* device check */ | ||
695 | printk(KERN_DEBUG "%s: Device check notify on %s\n", __func__, | ||
696 | (char *)buffer.pointer); | ||
697 | if (!root) | ||
698 | handle_root_bridge_insertion(handle); | ||
699 | break; | ||
700 | |||
701 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
702 | /* request device eject */ | ||
703 | printk(KERN_DEBUG "%s: Device eject notify on %s\n", __func__, | ||
704 | (char *)buffer.pointer); | ||
705 | if (root) | ||
706 | handle_root_bridge_removal(root->device); | ||
707 | break; | ||
708 | default: | ||
709 | printk(KERN_WARNING "notify_handler: unknown event type 0x%x for %s\n", | ||
710 | type, (char *)buffer.pointer); | ||
711 | break; | ||
712 | } | ||
713 | |||
714 | kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ | ||
715 | kfree(buffer.pointer); | ||
716 | } | ||
717 | |||
718 | static void handle_hotplug_event_root(acpi_handle handle, u32 type, | ||
719 | void *context) | ||
720 | { | ||
721 | alloc_acpi_hp_work(handle, type, context, | ||
722 | _handle_hotplug_event_root); | ||
723 | } | ||
724 | |||
725 | static acpi_status __init | ||
726 | find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
727 | { | ||
728 | acpi_status status; | ||
729 | char objname[64]; | ||
730 | struct acpi_buffer buffer = { .length = sizeof(objname), | ||
731 | .pointer = objname }; | ||
732 | int *count = (int *)context; | ||
733 | |||
734 | if (!acpi_is_root_bridge(handle)) | ||
735 | return AE_OK; | ||
736 | |||
737 | (*count)++; | ||
738 | |||
739 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | ||
740 | |||
741 | status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | ||
742 | handle_hotplug_event_root, NULL); | ||
743 | if (ACPI_FAILURE(status)) | ||
744 | printk(KERN_DEBUG "acpi root: %s notify handler is not installed, exit status: %u\n", | ||
745 | objname, (unsigned int)status); | ||
746 | else | ||
747 | printk(KERN_DEBUG "acpi root: %s notify handler is installed\n", | ||
748 | objname); | ||
749 | |||
750 | return AE_OK; | ||
751 | } | ||
752 | |||
753 | void __init acpi_pci_root_hp_init(void) | ||
754 | { | ||
755 | int num = 0; | ||
756 | |||
757 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
758 | ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL); | ||
759 | |||
760 | printk(KERN_DEBUG "Found %d acpi root devices\n", num); | ||
761 | } | ||