sleep: add SleepMemMode= setting for configuring /sys/power/mem_sleep
The setting is used when /sys/power/state is set to 'mem' (common for suspend) or /sys/power/disk is set to 'suspend' (hybrid-sleep). We default to kernel choice here, i.e. respect what's set through 'mem_sleep_default=' kernel cmdline option.
This commit is contained in:
@@ -54,6 +54,8 @@ SleepConfig* sleep_config_free(SleepConfig *sc) {
|
||||
strv_free(sc->modes[i]);
|
||||
}
|
||||
|
||||
strv_free(sc->mem_modes);
|
||||
|
||||
return mfree(sc);
|
||||
}
|
||||
|
||||
@@ -140,6 +142,8 @@ int parse_sleep_config(SleepConfig **ret) {
|
||||
{ "Sleep", "HybridSleepState", config_parse_warn_compat, DISABLED_LEGACY, NULL },
|
||||
{ "Sleep", "HybridSleepMode", config_parse_warn_compat, DISABLED_LEGACY, NULL },
|
||||
|
||||
{ "Sleep", "SleepMemMode", config_parse_sleep_mode, 0, &sc->mem_modes },
|
||||
|
||||
{ "Sleep", "HibernateDelaySec", config_parse_sec, 0, &sc->hibernate_delay_usec },
|
||||
{ "Sleep", "SuspendEstimationSec", config_parse_sec, 0, &sc->suspend_estimation_usec },
|
||||
{}
|
||||
@@ -344,6 +348,16 @@ static int sleep_supported_internal(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SLEEP_NEEDS_MEM_SLEEP(sleep_config, operation)) {
|
||||
r = sleep_mode_supported("/sys/power/mem_sleep", sleep_config->mem_modes);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
*ret_support = SLEEP_STATE_OR_MODE_NOT_SUPPORTED;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (SLEEP_OPERATION_IS_HIBERNATION(operation)) {
|
||||
r = sleep_mode_supported("/sys/power/disk", sleep_config->modes[operation]);
|
||||
if (r < 0)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "strv.h"
|
||||
#include "time-util.h"
|
||||
|
||||
typedef enum SleepOperation {
|
||||
@@ -28,7 +29,8 @@ typedef struct SleepConfig {
|
||||
bool allow[_SLEEP_OPERATION_MAX];
|
||||
|
||||
char **states[_SLEEP_OPERATION_CONFIG_MAX];
|
||||
char **modes[_SLEEP_OPERATION_CONFIG_MAX]; /* Power mode after writing hibernation image */
|
||||
char **modes[_SLEEP_OPERATION_CONFIG_MAX]; /* Power mode after writing hibernation image (/sys/power/disk) */
|
||||
char **mem_modes; /* /sys/power/mem_sleep */
|
||||
|
||||
usec_t hibernate_delay_usec;
|
||||
usec_t suspend_estimation_usec;
|
||||
@@ -39,6 +41,18 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(SleepConfig*, sleep_config_free);
|
||||
|
||||
int parse_sleep_config(SleepConfig **sleep_config);
|
||||
|
||||
static inline bool SLEEP_NEEDS_MEM_SLEEP(const SleepConfig *sc, SleepOperation operation) {
|
||||
assert(sc);
|
||||
assert(operation >= 0 && operation < _SLEEP_OPERATION_CONFIG_MAX);
|
||||
|
||||
/* As per https://docs.kernel.org/admin-guide/pm/sleep-states.html#basic-sysfs-interfaces-for-system-suspend-and-hibernation,
|
||||
* /sys/power/mem_sleep is honored if /sys/power/state is set to "mem" (common for suspend)
|
||||
* or /sys/power/disk is set to "suspend" (hybrid-sleep). */
|
||||
|
||||
return strv_contains(sc->states[operation], "mem") ||
|
||||
strv_contains(sc->modes[operation], "suspend");
|
||||
}
|
||||
|
||||
typedef enum SleepSupport {
|
||||
SLEEP_SUPPORTED,
|
||||
SLEEP_DISABLED, /* Disabled in SleepConfig.allow */
|
||||
|
||||
@@ -237,6 +237,12 @@ static int execute(
|
||||
if (state_fd < 0)
|
||||
return log_error_errno(errno, "Failed to open /sys/power/state: %m");
|
||||
|
||||
if (SLEEP_NEEDS_MEM_SLEEP(sleep_config, operation)) {
|
||||
r = write_mode("/sys/power/mem_sleep", sleep_config->mem_modes);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write mode to /sys/power/mem_sleep: %m");
|
||||
}
|
||||
|
||||
/* Configure hibernation settings if we are supposed to hibernate */
|
||||
if (SLEEP_OPERATION_IS_HIBERNATION(operation)) {
|
||||
_cleanup_(hibernation_device_done) HibernationDevice hibernation_device = {};
|
||||
|
||||
@@ -23,5 +23,6 @@
|
||||
#AllowHybridSleep=yes
|
||||
#SuspendState=mem standby freeze
|
||||
#HibernateMode=platform shutdown
|
||||
#SleepMemMode=
|
||||
#HibernateDelaySec=
|
||||
#SuspendEstimationSec=60min
|
||||
|
||||
Reference in New Issue
Block a user