Skip to content

Commit dcac86b

Browse files
committed
vga_switcheroo: Update PCI current_state on power change
When cutting power to a GPU and its integrated HDA controller, their cached current_state should be updated to D3cold to reflect reality. We currently rely on the DRM and HDA drivers to do that, however: - The HDA driver updates the current_state in azx_vs_set_state(), which will no longer be called with driver power control once we migrate to device links. (It will still be called with manual power control.) - If the HDA device is not bound, its current_state remains at D0 even though the GPU driver may decide to go to D3cold. - The DRM drivers update the current_state using pci_set_power_state() which can't put the device into a deeper power state than D3hot if the GPU is not deemed power-manageable by the platform (even though it *is* power-manageable by some nonstandard means, such as a _DSM). Centralize updating the current_state of the GPU and HDA controller in vga_switcheroo's ->runtime_suspend hook to overcome these deficiencies. The GPU and HDA controller are two functions of the same PCI device (VGA class device on function 0 and audio device on function 1) and no other PCI devices reside on the same bus since this is a PCIe point-to-point link, so we can just walk the bus and update the current_state of all devices. On ->runtime_resume, the HDA controller is in D0uninitialized state. Resume to D0active and then let it autosuspend as it sees fit. Note that vga_switcheroo_init_domain_pm_ops() is not supposed to be called by hybrid graphics laptops which power down the GPU via its root port's _PR3 resources and consequently vga_switcheroo_runtime_suspend() is not used. On those laptops, the root port is power-manageable by the platform (instead of by a nonstandard means) and the current_state is therefore updated by the PCI core through the following call chain: pci_set_power_state() __pci_complete_power_transition() pci_bus_set_current_state() Resuming to D0active happens through: pci_set_power_state() __pci_start_power_transition() pci_wakeup_bus() Cc: Dave Airlie <[email protected]> Cc: Ben Skeggs <[email protected]> Cc: Takashi Iwai <[email protected]> Cc: Alex Deucher <[email protected]> Cc: Bjorn Helgaas <[email protected]> Cc: Rafael J. Wysocki <[email protected]> Reviewed-by: Peter Wu <[email protected]> Tested-by: Kai Heng Feng <[email protected]> # AMD PowerXpress Tested-by: Mike Lothian <[email protected]> # AMD PowerXpress Tested-by: Denis Lisov <[email protected]> # Nvidia Optimus Tested-by: Peter Wu <[email protected]> # Nvidia Optimus Tested-by: Lukas Wunner <[email protected]> # MacBook Pro Signed-off-by: Lukas Wunner <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/8416958482c8c42d6f311ea5c1e5a65ccf21f5db.1520068884.git.lukas@wunner.de
1 parent 2a4d2c4 commit dcac86b

File tree

1 file changed

+2
-0
lines changed

1 file changed

+2
-0
lines changed

drivers/gpu/vga/vga_switcheroo.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,7 @@ static int vga_switcheroo_runtime_suspend(struct device *dev)
10221022
vgasr_priv.handler->switchto(VGA_SWITCHEROO_IGD);
10231023
mutex_unlock(&vgasr_priv.mux_hw_lock);
10241024
}
1025+
pci_bus_set_current_state(pdev->bus, PCI_D3cold);
10251026
vga_switcheroo_power_switch(pdev, VGA_SWITCHEROO_OFF);
10261027
mutex_unlock(&vgasr_mutex);
10271028
return 0;
@@ -1035,6 +1036,7 @@ static int vga_switcheroo_runtime_resume(struct device *dev)
10351036
mutex_lock(&vgasr_mutex);
10361037
vga_switcheroo_power_switch(pdev, VGA_SWITCHEROO_ON);
10371038
mutex_unlock(&vgasr_mutex);
1039+
pci_wakeup_bus(pdev->bus);
10381040
ret = dev->bus->pm->runtime_resume(dev);
10391041
if (ret)
10401042
return ret;

0 commit comments

Comments
 (0)