Linux Power Management development
 help / color / mirror / Atom feed
From: Antheas Kapenekakis <lkml@antheas.dev>
To: linux-pm@vger.kernel.org
Cc: platform-driver-x86@vger.kernel.org,
	dri-devel@lists.freedesktop.org,
	Mario Limonciello <mario.limonciello@amd.com>,
	Hans de Goede <hdegoede@redhat.com>,
	Kyle Gospodnetich <me@kylegospodneti.ch>,
	Antheas Kapenekakis <lkml@antheas.dev>
Subject: [RFC 13/13] PM: standby: Add sysfs attribute for modern standby transitions
Date: Thu, 21 Nov 2024 18:22:38 +0100	[thread overview]
Message-ID: <20241121172239.119590-14-lkml@antheas.dev> (raw)
In-Reply-To: <20241121172239.119590-1-lkml@antheas.dev>

Add a sysfs attribute to allow informing the kernel about the current
standby state, those being: "active", "screen_off", "sleep", and
"resume" (to prepare turning the display on). The final modern
standby state DRIPS is omitted, as that is entered during the kernel
suspend process and userspace will never see it.

Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
---
 Documentation/ABI/testing/sysfs-power | 34 ++++++++++++
 kernel/power/main.c                   | 75 +++++++++++++++++++++++++++
 2 files changed, 109 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power
index a3942b1036e2..eff13980cc7c 100644
--- a/Documentation/ABI/testing/sysfs-power
+++ b/Documentation/ABI/testing/sysfs-power
@@ -39,6 +39,40 @@ Description:
 		See Documentation/admin-guide/pm/sleep-states.rst for more
 		information.
 
+What:		/sys/power/standby
+Date:		November 2024
+Contact:	Antheas Kapenekakis <lkml@antheas.dev>
+Description:
+		The /sys/power/standby file controls the standby state of the
+		system. Modern S0ix capable systems can enter a set of low power
+		states while the kernel is still active. Transitioning into those
+		states may 1) deactivate tertiary hardware, and 2) change the
+		presentation of the device (e.g., pulse the suspend light, turn
+		off the keyboard backlight).
+
+		Available states are "active" (fully active), "screen-off" (fully
+		active but all displays of the system are off; virtual and real),
+		"sleep" (major userspace components have been frozen; light
+		background tasks may still run; this state may affect the power
+		envelope of the device). The final state is DRIPS or LSP0, where
+		the kernel suspends, and is entered by writing "mem" to
+		/sys/power/state. There is a secondary sleep state called "resume"
+		that can only be entered from "sleep" and is used in certain
+		devices to boost the Power Limit (PLx) while remaining in sleep
+		to hasten preparing for transitioning to "active".
+
+		Writing one of the above strings to this file causes the system
+		to transition into the corresponding state, by firing the
+		corresponding firmware notifications during the transition.
+
+		DRIPS or LSP0 (i.e., mem "s2idle") can only be entered from the
+		"sleep" state. If the kernel is asked to transition to DRIPS from
+		a different state, it will transition to "sleep" and then suspend.
+		On wakeup, the kernel will transition back to the previous state.
+
+		See Documentation/admin-guide/pm/standby-states.rst for more
+		information.
+
 What:		/sys/power/disk
 Date:		September 2006
 Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 6254814d4817..4377fdaf4a8d 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -748,6 +748,80 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
 
 power_attr(state);
 
+#ifdef CONFIG_SUSPEND
+/*
+ * standby - control system s2idle standby state.
+ *
+ * show() returns available standby states, which may be "active", "screen_off",
+ * "sleep" and "resume" (still in sleep but preparing to turn on display).
+ * See Documentation/admin-guide/pm/standby-states.rst for a description of
+ * what they mean.
+ *
+ * store() accepts one of those strings, translates it into the proper
+ * enumerated value, and initiates a transition to that standby state.
+ *
+ * When the system suspends, it will first enter the state "sleep", suspend,
+ * and then restore the last state before entering "sleep". I.e., if userspace
+ * is not S0ix-aware, the transitions expected by Modern Standby devices will
+ * always be performed.
+ */
+static ssize_t standby_show(struct kobject *kobj, struct kobj_attribute *attr,
+			  char *buf)
+{
+	char *s = buf;
+	standby_state_t i;
+	standby_state_t curr = pm_standby_state();
+
+	if (curr < 0)
+		return -EBUSY;
+
+	for (i = PM_STANDBY_MIN; i < PM_STANDBY_MAX; i++)
+		if (standby_states[i])
+			s += sprintf(s, curr == i ? "[%s] " : "%s ", standby_states[i]);
+
+	if (s != buf)
+		/* convert the last space to a newline */
+		*(s - 1) = '\n';
+	return (s - buf);
+}
+
+static standby_state_t decode_standby_state(const char *buf, size_t n)
+{
+	standby_state_t state;
+	char *p;
+	int len;
+
+	p = memchr(buf, '\n', n);
+	len = p ? p - buf : n;
+
+	for (state = PM_STANDBY_MIN; state < PM_STANDBY_MAX; state++) {
+		const char *label = standby_states[state];
+
+		if (label && len == strlen(label) && !strncmp(buf, label, len))
+			return state;
+	}
+
+	return PM_STANDBY_MAX;
+}
+
+static ssize_t standby_store(struct kobject *kobj, struct kobj_attribute *attr,
+			   const char *buf, size_t n)
+{
+	int error;
+	standby_state_t state;
+
+	state = decode_standby_state(buf, n);
+
+	if (state >= PM_STANDBY_MAX)
+		return -EINVAL;
+
+	error = pm_standby_transition(state);
+	return error ? error : n;
+}
+
+power_attr(standby);
+#endif
+
 #ifdef CONFIG_PM_SLEEP
 /*
  * The 'wakeup_count' attribute, along with the functions defined in
@@ -974,6 +1048,7 @@ static struct attribute * g[] = {
 #ifdef CONFIG_SUSPEND
 	&mem_sleep_attr.attr,
 	&sync_on_suspend_attr.attr,
+	&standby_attr.attr,
 #endif
 #ifdef CONFIG_PM_AUTOSLEEP
 	&autosleep_attr.attr,
-- 
2.47.0


  parent reply	other threads:[~2024-11-21 17:23 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-21 17:22 [RFC 00/13] acpi/x86: s2idle: implement Modern Standby transition states and expose to userspace Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 01/13] Documentation: PM: Add documentation for S0ix Standby States Antheas Kapenekakis
2024-11-21 18:58   ` Mario Limonciello
2024-11-21 19:11     ` Antheas Kapenekakis
2024-11-21 19:40       ` Mario Limonciello
2024-11-21 20:33         ` Antheas Kapenekakis
2024-11-21 21:08           ` Mario Limonciello
2024-11-21 21:23             ` Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 02/13] acpi/x86: s2idle: add support for Display Off and Display On callbacks Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 03/13] acpi/x86: s2idle: add support for Sleep Entry and Sleep Exit callbacks Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 04/13] acpi/x86: s2idle: add support for Turn On Display callback Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 05/13] acpi/x86: s2idle: add modern standby transition function Antheas Kapenekakis
2024-11-21 18:15   ` Mario Limonciello
2024-11-21 18:29     ` Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 06/13] acpi/x86: s2idle: rename Screen On/Off to Display On/Off Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 07/13] acpi/x86: s2idle: call Display On/Off as part of callbacks Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 08/13] acpi/x86: s2idle: rename MS Exit/Entry to Sleep Exit/Entry Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 09/13] acpi/x86: s2idle: call Sleep Entry/Exit as part of callbacks Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 10/13] acpi/x86: s2idle: add Turn On Display and call as part of callback Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 11/13] acpi/x86: s2idle: add quirk table for modern standby delays Antheas Kapenekakis
2024-11-21 18:04   ` Mario Limonciello
2024-11-21 18:19     ` Antheas Kapenekakis
2024-11-21 17:22 ` [RFC 12/13] platform/x86: asus-wmi: remove Ally (1st gen) and Ally X suspend quirk Antheas Kapenekakis
2024-11-21 17:22 ` Antheas Kapenekakis [this message]
2024-11-28 11:45   ` [RFC 13/13] PM: standby: Add sysfs attribute for modern standby transitions Ilpo Järvinen
2024-11-21 17:41 ` [RFC 00/13] acpi/x86: s2idle: implement Modern Standby transition states and expose to userspace Rafael J. Wysocki
2024-12-06 21:37   ` Antheas Kapenekakis
2024-11-22 19:25 ` Xaver Hugl
2024-11-22 23:55   ` Antheas Kapenekakis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241121172239.119590-14-lkml@antheas.dev \
    --to=lkml@antheas.dev \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=hdegoede@redhat.com \
    --cc=linux-pm@vger.kernel.org \
    --cc=mario.limonciello@amd.com \
    --cc=me@kylegospodneti.ch \
    --cc=platform-driver-x86@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox