[systemd-devel] [PATCH] Add support for Intel Rapid Start

Bastien Nocera hadess at hadess.net
Sun Oct 13 12:50:59 PDT 2013


Instead of using the kernel's hybrid sleep, use the firmware for
laptops that support Intel Rapid Start, as explained in:
http://mjg59.dreamwidth.org/26022.html
and implemented in:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/log/drivers/platform/x86/intel-rst.c
---
 src/shared/sleep-config.c | 28 ++++++++++++++++++++++++++--
 src/shared/sleep-config.h |  1 +
 src/sleep/sleep.c         |  3 +++
 3 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c
index d068bfc..c5551fc 100644
--- a/src/shared/sleep-config.c
+++ b/src/shared/sleep-config.c
@@ -250,6 +250,26 @@ static bool enough_memory_for_hibernation(void) {
         return r;
 }
 
+/* Check whether Intel Rapid Start Technology is supported:
+ * http://mjg59.dreamwidth.org/26022.html */
+bool has_rapid_start(void) {
+        int r;
+        _cleanup_free_ char *p = NULL;
+
+        r = read_one_line_file("/sys/bus/acpi/devices/INT3392:00/wakeup_events", &p);
+        if (r < 0)
+                return false;
+
+        /* We only support rapid start if we have both values set:
+         * 1: Wake to enter hibernation when the wakeup timer expires
+         * 2: Wake to enter hibernation when the battery reaches a
+         * critical level */
+        if (p[0] == '3' && p[1] == '\0')
+                return true;
+
+        return false;
+}
+
 int can_sleep(const char *verb) {
         _cleanup_strv_free_ char **modes = NULL, **states = NULL;
         int r;
@@ -262,8 +282,12 @@ int can_sleep(const char *verb) {
         if (r < 0)
                 return false;
 
-        if (!can_sleep_state(states) || !can_sleep_disk(modes))
+        if (!can_sleep_state(states) || !can_sleep_disk(modes) || !has_rapid_start())
                 return false;
 
-        return streq(verb, "suspend") || enough_memory_for_hibernation();
+        if streq(verb, "suspend")
+                return true;
+        if (streq (verb, "hybrid-sleep"))
+                return enough_memory_for_hibernation() || has_rapid_start();
+        return enough_memory_for_hibernation();
 }
diff --git a/src/shared/sleep-config.h b/src/shared/sleep-config.h
index 51d2dec..4fb418f 100644
--- a/src/shared/sleep-config.h
+++ b/src/shared/sleep-config.h
@@ -24,3 +24,4 @@ int parse_sleep_config(const char *verb, char ***modes, char ***states);
 int can_sleep(const char *verb);
 int can_sleep_disk(char **types);
 int can_sleep_state(char **types);
+bool has_rapid_start(void);
diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c
index a56ab89..264f2c4 100644
--- a/src/sleep/sleep.c
+++ b/src/sleep/sleep.c
@@ -211,6 +211,9 @@ int main(int argc, char *argv[]) {
         if (r <= 0)
                 goto finish;
 
+        if (has_rapid_start () && streq(arg_verb, "hybrid-sleep"))
+                arg_verb = "suspend";
+
         r = parse_sleep_config(arg_verb, &modes, &states);
         if (r < 0)
                 goto finish;
-- 
1.8.3.1




More information about the systemd-devel mailing list