• Lukas Wunner's avatar
    PCI: Make pci_wakeup_bus() & pci_bus_set_current_state() public · 2a4d2c42
    Lukas Wunner authored
    There are PCI devices which are power-manageable by a nonstandard means,
    such as a custom ACPI method.  One example are discrete GPUs in hybrid
    graphics laptops, another are Thunderbolt controllers in Macs.
    
    Such devices can't be put into D3cold with pci_set_power_state() because
    pci_platform_power_transition() fails with -ENODEV.  Instead they're put
    into D3hot by pci_set_power_state() and subsequently into D3cold by
    invoking the nonstandard means.  However as a consequence the cached
    current_state is incorrectly left at D3hot.
    
    What we need to do is walk the hierarchy below such a PCI device on
    powerdown and update the current_state to D3cold.  On powerup the PCI
    device itself and the hierarchy below it is in D0uninitialized, so we
    need to walk the hierarchy again and wake all devices, causing them to
    be put into D0active and then letting them autosuspend as they see fit.
    
    To this end make pci_wakeup_bus() & pci_bus_set_current_state() public
    so PCI drivers don't have to reinvent the wheel.
    
    Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
    Acked-by: default avatarBjorn Helgaas <bhelgaas@google.com>
    Signed-off-by: default avatarLukas Wunner <lukas@wunner.de>
    Link: https://patchwork.freedesktop.org/patch/msgid/2962443259e7faec577274b4ef8c54aad66f9a94.1520068884.git.lukas@wunner.de
    2a4d2c42
pci.c 148 KB