https://bugzilla.kernel.org/show_bug.cgi?id=220505

--- Comment #22 from tropicaal ([email protected]) ---
Alright, I can fairly confidently say *why* this happens, and it seems to be
due to Lenovo not implementing Microsoft's Modern Standby firmware
notifications in a spec-compliant way for this laptop.

For a rundown:

- The driver theoretically at fault here is drivers/acpi/x86/s2idle.c, where
acpi_sleep_run_lps0_dsm is invoked with Microsoft's DSM GUID for presumably
performing some extra modern standby operations on the PEP/SPMC that aren't
described by Intel's spec
https://uefi.org/sites/default/files/resources/Intel_ACPI_Low_Power_S0_Idle.pdf
(see section 3).
- The "_DSM" method on the PEP takes four arguments, wherein the first argument
is a GUID and the third argument is a function number. The meaning of the
function number changes depending on the GUID. Intel's GUID is
c4eb40a0-6cd2-11e2-bcfd-0800200c9a66 and Microsoft's GUID is
11e00d56-ce64-47ce-837b-1f898f9aa461. Looking at both the implementation and my
ACPICA trace, the kernel uses both GUIDs in the s2idle implementation.
- On this laptop, Microsoft's GUID branch will unconditionally call
\_SB.PC00.LPCB.EC0.UPHK with the function number (argument 2) of PEP _DSM which
performs power mangement operations on the EC. The kernel specifically invokes
these DSMs with Microsoft's GUID in this order:
    - On suspend: _DSM(Unknown, 1, 3, Unknown) -> UPHK(3), which sets DPLF to 0
and writes an EC command. At this point, some keyboard controls stop
responding.
    - On suspend: _DSM(Unknown, 1, 7, Unknown) -> UPHK(7), which is a noop for
UPHK.
    - On suspend: _DSM(Unknown, 1, 5, Unknown) -> UPHK(5), which sets a GPIO
pin on the EC low, presumably bringing it into a low power state. At this
point, the fans stop working.
    - On resume: _DSM(Unknown, 1, 6, Unknown) -> UPHK(6), which is a noop for
UPHK.
    - On resume: _DSM(Unknown, 1, 8, Unknown) -> UPHK(8), which appears to
update a timer value based on the RTC.
    - On resume: _DSM(Unknown, 1, 4, Unknown) -> UPHK(4), which presumably
undoes the effects of UPHK(3) based on the disassembly, but in practice seems
to be dependent on UPHK(9) to restore keyboard controls based on Jakob's
findings.
- So on sleep, the kernel calls DSM functions 3, 7, 5, and on resume calls
functions 6, 8, 4. Notably missing is DSM function 9, which undoes the work of
function 5 to wake the EC from low power, which we've already determined.

These _DSM calls are done by the aformentioned s2idle.c driver, where
3=ACPI_LPS0_SCREEN_OFF, 7=ACPI_LPS0_MS_ENTRY, 5=ACPI_LPS0_ENTRY, and
6=ACPI_LPS0_EXIT, 8=ACPI_LPS0_MS_EXIT, and 4=ACPI_LPS0_SCREEN_ON. So
ACPI_LPS0_SCREEN_OFF is what shuts off the keyboard controls and
ACPI_LPS0_ENTRY is what disables the EC functionality that never gets turned
back on in resume.

Once again, there is no mention anywhere of a function with an ID of 9, nor is
there any mention of it in Microsoft's specification
(https://learn.microsoft.com/en-us/windows-hardware/design/device-experiences/modern-standby-firmware-notifications),
yet the ACPI tables specifically implement and require a Function 9 to be
called to correctly wake the EC from its low power state. That's why this is
happening.

Now that we know exactly what's at fault here, bugging Lenovo might be worth a
shot even though they *technically* require a Windows reproduction.
Alternatively, I guess a patch could be implemented to call
acpi_sleep_run_lps0_dsm(9, lps0_dsm_func_mask_microsoft,
lps0_dsm_guid_microsoft) in acpi_s2idle_restore_early_lps0 specifically for
this model. I have some doubts this would be upstreamable though, given that
this is such a specific OEM quirk.

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are watching the assignee of the bug.

_______________________________________________
acpi-bugzilla mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/acpi-bugzilla

Reply via email to