diff options
Diffstat (limited to 'drivers/pci/pci-acpi.c')
-rw-r--r-- | drivers/pci/pci-acpi.c | 63 |
1 files changed, 62 insertions, 1 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index c2ab57705043..2a4aa6468579 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -519,6 +519,46 @@ static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev) | |||
519 | return PCI_POWER_ERROR; | 519 | return PCI_POWER_ERROR; |
520 | } | 520 | } |
521 | 521 | ||
522 | static struct acpi_device *acpi_pci_find_companion(struct device *dev); | ||
523 | |||
524 | static bool acpi_pci_bridge_d3(struct pci_dev *dev) | ||
525 | { | ||
526 | const struct fwnode_handle *fwnode; | ||
527 | struct acpi_device *adev; | ||
528 | struct pci_dev *root; | ||
529 | u8 val; | ||
530 | |||
531 | if (!dev->is_hotplug_bridge) | ||
532 | return false; | ||
533 | |||
534 | /* | ||
535 | * Look for a special _DSD property for the root port and if it | ||
536 | * is set we know the hierarchy behind it supports D3 just fine. | ||
537 | */ | ||
538 | root = pci_find_pcie_root_port(dev); | ||
539 | if (!root) | ||
540 | return false; | ||
541 | |||
542 | adev = ACPI_COMPANION(&root->dev); | ||
543 | if (root == dev) { | ||
544 | /* | ||
545 | * It is possible that the ACPI companion is not yet bound | ||
546 | * for the root port so look it up manually here. | ||
547 | */ | ||
548 | if (!adev && !pci_dev_is_added(root)) | ||
549 | adev = acpi_pci_find_companion(&root->dev); | ||
550 | } | ||
551 | |||
552 | if (!adev) | ||
553 | return false; | ||
554 | |||
555 | fwnode = acpi_fwnode_handle(adev); | ||
556 | if (fwnode_property_read_u8(fwnode, "HotPlugSupportInD3", &val)) | ||
557 | return false; | ||
558 | |||
559 | return val == 1; | ||
560 | } | ||
561 | |||
522 | static bool acpi_pci_power_manageable(struct pci_dev *dev) | 562 | static bool acpi_pci_power_manageable(struct pci_dev *dev) |
523 | { | 563 | { |
524 | struct acpi_device *adev = ACPI_COMPANION(&dev->dev); | 564 | struct acpi_device *adev = ACPI_COMPANION(&dev->dev); |
@@ -548,6 +588,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
548 | error = -EBUSY; | 588 | error = -EBUSY; |
549 | break; | 589 | break; |
550 | } | 590 | } |
591 | /* Fall through */ | ||
551 | case PCI_D0: | 592 | case PCI_D0: |
552 | case PCI_D1: | 593 | case PCI_D1: |
553 | case PCI_D2: | 594 | case PCI_D2: |
@@ -635,6 +676,7 @@ static bool acpi_pci_need_resume(struct pci_dev *dev) | |||
635 | } | 676 | } |
636 | 677 | ||
637 | static const struct pci_platform_pm_ops acpi_pci_platform_pm = { | 678 | static const struct pci_platform_pm_ops acpi_pci_platform_pm = { |
679 | .bridge_d3 = acpi_pci_bridge_d3, | ||
638 | .is_manageable = acpi_pci_power_manageable, | 680 | .is_manageable = acpi_pci_power_manageable, |
639 | .set_state = acpi_pci_set_power_state, | 681 | .set_state = acpi_pci_set_power_state, |
640 | .get_state = acpi_pci_get_power_state, | 682 | .get_state = acpi_pci_get_power_state, |
@@ -751,10 +793,15 @@ static void pci_acpi_setup(struct device *dev) | |||
751 | { | 793 | { |
752 | struct pci_dev *pci_dev = to_pci_dev(dev); | 794 | struct pci_dev *pci_dev = to_pci_dev(dev); |
753 | struct acpi_device *adev = ACPI_COMPANION(dev); | 795 | struct acpi_device *adev = ACPI_COMPANION(dev); |
796 | int node; | ||
754 | 797 | ||
755 | if (!adev) | 798 | if (!adev) |
756 | return; | 799 | return; |
757 | 800 | ||
801 | node = acpi_get_node(adev->handle); | ||
802 | if (node != NUMA_NO_NODE) | ||
803 | set_dev_node(dev, node); | ||
804 | |||
758 | pci_acpi_optimize_delay(pci_dev, adev->handle); | 805 | pci_acpi_optimize_delay(pci_dev, adev->handle); |
759 | 806 | ||
760 | pci_acpi_add_pm_notifier(adev, pci_dev); | 807 | pci_acpi_add_pm_notifier(adev, pci_dev); |
@@ -762,19 +809,33 @@ static void pci_acpi_setup(struct device *dev) | |||
762 | return; | 809 | return; |
763 | 810 | ||
764 | device_set_wakeup_capable(dev, true); | 811 | device_set_wakeup_capable(dev, true); |
812 | /* | ||
813 | * For bridges that can do D3 we enable wake automatically (as | ||
814 | * we do for the power management itself in that case). The | ||
815 | * reason is that the bridge may have additional methods such as | ||
816 | * _DSW that need to be called. | ||
817 | */ | ||
818 | if (pci_dev->bridge_d3) | ||
819 | device_wakeup_enable(dev); | ||
820 | |||
765 | acpi_pci_wakeup(pci_dev, false); | 821 | acpi_pci_wakeup(pci_dev, false); |
766 | } | 822 | } |
767 | 823 | ||
768 | static void pci_acpi_cleanup(struct device *dev) | 824 | static void pci_acpi_cleanup(struct device *dev) |
769 | { | 825 | { |
770 | struct acpi_device *adev = ACPI_COMPANION(dev); | 826 | struct acpi_device *adev = ACPI_COMPANION(dev); |
827 | struct pci_dev *pci_dev = to_pci_dev(dev); | ||
771 | 828 | ||
772 | if (!adev) | 829 | if (!adev) |
773 | return; | 830 | return; |
774 | 831 | ||
775 | pci_acpi_remove_pm_notifier(adev); | 832 | pci_acpi_remove_pm_notifier(adev); |
776 | if (adev->wakeup.flags.valid) | 833 | if (adev->wakeup.flags.valid) { |
834 | if (pci_dev->bridge_d3) | ||
835 | device_wakeup_disable(dev); | ||
836 | |||
777 | device_set_wakeup_capable(dev, false); | 837 | device_set_wakeup_capable(dev, false); |
838 | } | ||
778 | } | 839 | } |
779 | 840 | ||
780 | static bool pci_acpi_bus_match(struct device *dev) | 841 | static bool pci_acpi_bus_match(struct device *dev) |