Skip to content

Commit 6299cf9

Browse files
westeribjorn-helgaas
authored andcommitted
PCI / ACPI: Enable wake automatically for power managed bridges
We enable power management automatically for bridges where pci_bridge_d3_possible() returns true. However, these bridges may have ACPI methods such as _DSW that need to be called before D3 entry. For example in Lenovo Thinkpad X1 Carbon 6th _DSW method is used to prepare D3cold for the PCIe root port hosting Thunderbolt chain. Because wake is not enabled _DSW method is never called and the port does not enter D3cold properly consuming more power than necessary. Users can work this around by writing "enabled" to "wakeup" sysfs file under the device in question but that is not something an ordinary user is expected to do. Since we already automatically enable power management for PCIe ports with ->bridge_d3 set extend that to enable wake for them as well, assuming the port has any ACPI wakeup related objects implemented in the namespace (adev->wakeup.flags.valid is true). This ensures the necessary ACPI methods get called at appropriate times and allows the root port in Thinkpad X1 Carbon 6th to go into D3cold. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent ac86e8e commit 6299cf9

File tree

1 file changed

+15
-1
lines changed

1 file changed

+15
-1
lines changed

drivers/pci/pci-acpi.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -762,19 +762,33 @@ static void pci_acpi_setup(struct device *dev)
762762
return;
763763

764764
device_set_wakeup_capable(dev, true);
765+
/*
766+
* For bridges that can do D3 we enable wake automatically (as
767+
* we do for the power management itself in that case). The
768+
* reason is that the bridge may have additional methods such as
769+
* _DSW that need to be called.
770+
*/
771+
if (pci_dev->bridge_d3)
772+
device_wakeup_enable(dev);
773+
765774
acpi_pci_wakeup(pci_dev, false);
766775
}
767776

768777
static void pci_acpi_cleanup(struct device *dev)
769778
{
770779
struct acpi_device *adev = ACPI_COMPANION(dev);
780+
struct pci_dev *pci_dev = to_pci_dev(dev);
771781

772782
if (!adev)
773783
return;
774784

775785
pci_acpi_remove_pm_notifier(adev);
776-
if (adev->wakeup.flags.valid)
786+
if (adev->wakeup.flags.valid) {
787+
if (pci_dev->bridge_d3)
788+
device_wakeup_disable(dev);
789+
777790
device_set_wakeup_capable(dev, false);
791+
}
778792
}
779793

780794
static bool pci_acpi_bus_match(struct device *dev)

0 commit comments

Comments
 (0)