Don't wake a runtime-suspended dGPU to service NVPCF/GPS ACPI notifies - #1181
Don't wake a runtime-suspended dGPU to service NVPCF/GPS ACPI notifies#1181ElXreno wants to merge 1 commit into
Conversation
…notifies On RTD3 laptops the dGPU is runtime-suspended (D3cold) while idle. Some platforms still deliver ACPI Notify() events for the NVPCF device and for GPS status changes while the GPU is suspended (for example around battery/AC transitions, or when the SBIOS pushes a thermal or power-limit hint). rm_acpi_nvpcf_notify() and RmHandleGPSStatusChange() both call os_ref_dynamic_power() unconditionally, resuming the GPU only to deliver an event that is meaningless while it is powered down. The GPU then re-suspends, and where the next notify arrives immediately it never settles in D3cold, cycling D0/D3cold and draining the battery (see NVIDIA#860, where users work around it by patching the ACPI tables to drop the Notify(NPCF, 0xC0)). Skip the work when the GPU is already runtime-suspended (NV_DYNAMIC_POWER_STATE_IDLE_INDICATED), the same guard that rm_pmu_perfmon_get_load() already uses. The NVPCF event is only consumed while the GPU is active, and GPS/SBIOS state is re-read on the next StateLoad, so no state is lost.
|
Possibly fixes: #905 There is in fact a Other commenters with different laptops have noticed similar issues. I myself with a 16APH8 have noticed the around 11-15 second consistent sleep/wake when no applications are using the dGPU. |
|
I have applied the patch to nvidia-open-dkms 610.43.03, on an ASUS Zephyrus G16 (RTX5080), and I can confirm it works. I have also set up a pacman hook, until this is merged into upstream. |
|
Interesting... I believe this will fix my issue where nvidia awakes periodically on battery. |
|
Thank you for working on this. I tested the NVPCF part on an ASUS ROG Zephyrus G14 GA403UI with an RTX 4070 Laptop GPU, NVIDIA driver 610.57.04, and Linux 7.1.6. I confirmed that suppressing NVPCF notifications while the GPU is runtime-suspended prevents the unnecessary wake. On my laptop, the firmware sends one notification per 1% of battery discharge. Without the guard, each notification wakes the GPU for approximately 20–22 seconds. Each wake consumed 110.4 ± 19.1 mWh. Since one occurs for every 1% discharged, approximately 17% of the observed battery drain was spent on these wakes while the NVIDIA GPU remained otherwise unused. On the tested laptop, provided the NVIDIA GPU remains otherwise unused, the patch reduces battery consumption by approximately 17%. However, I found one issue with dropping the notification rather than deferring it. The notification tells nvidia-powerd "the power limits changed, re-read them", and powerd never re-reads on its own. In my test I switched the platform profile while the GPU was suspended with notifications dropped: the GPU stayed capped at the old profile's 75 W instead of the new 90 W, even after it woke up, until the next battery-percent notification arrived. I implemented a variant that saves the notification and delivers it on the next resume instead: #1299. Same zero wakes on battery, but the limits always end up correct. I left GPS unchanged because I have not tested whether suppressing it is safe. |
On RTD3 laptops the discrete GPU sits in D3cold while idle. On some machines the platform keeps delivering ACPI
Notify()events (to the NVPCF device, and as GPS status changes) even while the GPU is suspended, for example around battery/AC transitions or when the SBIOS pushes a new thermal or power-limit hint.The two handlers that service those notifies,
rm_acpi_nvpcf_notify()andRmHandleGPSStatusChange(), both callos_ref_dynamic_power()unconditionally. That resumes the GPU purely to deliver an event that does nothing while it's powered down, and it then re-suspends. On a fair number of laptops the next notify lands right away, so the GPU never settles in D3cold. Folks in #860 describe it cycling D0/D3cold every ~11 seconds on battery, and the current workaround is to patch the ACPI tables to strip theNotify(NPCF, 0xC0).This skips the resume when the GPU is already runtime-suspended (
NV_DYNAMIC_POWER_STATE_IDLE_INDICATED), the same guardrm_pmu_perfmon_get_load()already uses a few functions away. Why it's safe:StateLoad, so a skipped sync is recovered when the GPU next powers uprm_power_source_change_event) and are left untouchedI traced the wake on an RTX 4060 mobile (ASUS TUF, open module):
With the guard in place the handlers still run, but the GPU stays in D3cold. Verified on 595.45.04 and 610.43.02.