Skip to content

systemd shouldn't try s3 followed by s2idle back to back #25151

@superm1

Description

@superm1

Component

No response

Is your feature request related to a problem? Please describe

I've noticed a few bug reports come through the amdgpu bug tracker that demonstrated an APU that prefers S3 (/sys/power/mem_sleep has deep) but in the suspend logs they end up using s2idle. This was an odd result to me.

At least on AMD APU platforms, the firmware can be configured for S3 (deep) or s2idle. The kernel exports the information in /sys/power/mem_sleep which one is the default.
On systems that support deep you'll see:

$ cat /sys/power/mem_sleep
s2idle [deep]

On systems that support s2idle you'll see:

$ cat /sys/power/mem_sleep
[s2idle]

s3
What is happening is that on systems that support deep, systemd attempts to suspend the system first by writing mem into /sys/power/state since that's specified first in the sleep config states:

sc->states[SLEEP_SUSPEND] = strv_new("mem", "standby", "freeze");

For $whatever_reasons that suspend fails. The kernel suspend routine is aborted, all the drivers try to clean up. Then systemd tries to run the next possible suspend routine.

STRV_FOREACH(state, states) {

If this succeeds the system isn't put into S3 and, and it certainly is still draining a ton of power. It's not really what the user expected.

Describe the solution you'd like

Right now systemd on systems that support s2idle is actually relying upon a kernel compatibility mode that writing mem into /sys/power/state will work the same, but the kernel internally examines /sys/power/mem_sleep to figure out whether to use s2idle or deep.

I'd like systemd to try no more than one mode on a given system. Perhaps this should be paired with the existing opened issue
#13451. A solution could be to try to read /sys/power/mem_sleep when reading the sleep config.

  • If that returns deep, then only populate the sleep config list with mem
  • If that returns s2idle then only populate the sleep config list with freeze
  • If that doesn't exist, do the current behavior (as it's probably an older kernel)

By making this change systemd will try at most onetime to suspend the system, and it will obey the user's intent by what was programmed to /sys/power/mem_sleep. This value is populated by the presence of the Low Power Idle bit in the FADT and/or the user overriding the value on the kernel command line.

Describe alternatives you've considered

I've sent a series to the kernel mailing list to propose removing s2idle mode on AMD systems when deep is offered since they're mutually exclusive. This was rejected as the point was the kernel should always support s2idle mode, even if it doesn't get devices to the deepest sleep state.

The systemd version you checked that didn't have the feature you are asking for

249

Metadata

Metadata

Assignees

No one assigned

    Labels

    RFE 🎁Request for Enhancement, i.e. a feature requestsleep

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions