Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 26 Sep 2025 16:03:51 GMT
From:      Aymeric Wibo <obiwac@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 5632b0d4628d - main - sys/power: Sleep type reporting by PM backends
Message-ID:  <202509261603.58QG3pq4069287@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by obiwac:

URL: https://cgit.FreeBSD.org/src/commit/?id=5632b0d4628d768c125594a3edee21fb23940067

commit 5632b0d4628d768c125594a3edee21fb23940067
Author:     Aymeric Wibo <obiwac@FreeBSD.org>
AuthorDate: 2025-09-26 15:50:16 +0000
Commit:     Aymeric Wibo <obiwac@FreeBSD.org>
CommitDate: 2025-09-26 16:03:13 +0000

    sys/power: Sleep type reporting by PM backends
    
    Allow PM backends to report supported sleep types when registering
    through `power_pm_register`. Expose this information through
    `kern.power.supported_stype` sysctl, and set defaults for
    `power_standby/suspend/hibernate_stype` based on this.
    
    Implement this in ACPI PM backend.
    
    Reviewed by:    cy
    Approved by:    cy
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D52727
    Event:          EuroBSDcon 2025 Devsummit
---
 sys/dev/acpica/acpi.c |  6 ++++--
 sys/kern/subr_power.c | 46 +++++++++++++++++++++++++++++++++++++++++-----
 sys/sys/power.h       |  3 ++-
 3 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 6994f46eba10..7f9ca6e39df8 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -746,7 +746,8 @@ acpi_attach(device_t dev)
 	goto out;
 
     /* Register ACPI again to pass the correct argument of pm_func. */
-    power_pm_register(POWER_PM_TYPE_ACPI, acpi_pm_func, sc);
+    power_pm_register(POWER_PM_TYPE_ACPI, acpi_pm_func, sc,
+	acpi_supported_stypes);
 
     acpi_platform_osc(dev);
 
@@ -4819,7 +4820,8 @@ acpi_pm_register(void *arg)
     if (!cold || resource_disabled("acpi", 0))
 	return;
 
-    power_pm_register(POWER_PM_TYPE_ACPI, acpi_pm_func, NULL);
+    power_pm_register(POWER_PM_TYPE_ACPI, acpi_pm_func, NULL,
+	acpi_supported_stypes);
 }
 
 SYSINIT(power, SI_SUB_KLD, SI_ORDER_ANY, acpi_pm_register, NULL);
diff --git a/sys/kern/subr_power.c b/sys/kern/subr_power.c
index eb5bd03f5018..f5a581e42bf3 100644
--- a/sys/kern/subr_power.c
+++ b/sys/kern/subr_power.c
@@ -39,13 +39,14 @@
 #include <sys/systm.h>
 #include <sys/taskqueue.h>
 
-enum power_stype	 power_standby_stype	= POWER_STYPE_STANDBY;
-enum power_stype	 power_suspend_stype	= POWER_STYPE_SUSPEND_TO_IDLE;
-enum power_stype	 power_hibernate_stype	= POWER_STYPE_HIBERNATE;
+enum power_stype	 power_standby_stype	= POWER_STYPE_UNKNOWN;
+enum power_stype	 power_suspend_stype	= POWER_STYPE_UNKNOWN;
+enum power_stype	 power_hibernate_stype	= POWER_STYPE_UNKNOWN;
 
 static u_int		 power_pm_type	= POWER_PM_TYPE_NONE;
 static power_pm_fn_t	 power_pm_fn	= NULL;
 static void		*power_pm_arg	= NULL;
+static bool		 power_pm_supported[POWER_STYPE_COUNT] = {0};
 static struct task	 power_pm_task;
 
 enum power_stype
@@ -70,6 +71,26 @@ power_stype_to_name(enum power_stype stype)
 	return (power_stype_names[stype]);
 }
 
+static int
+sysctl_supported_stypes(SYSCTL_HANDLER_ARGS)
+{
+	int error;
+	struct sbuf sb;
+	enum power_stype stype;
+
+	sbuf_new(&sb, NULL, 32, SBUF_AUTOEXTEND);
+	for (stype = 0; stype < POWER_STYPE_COUNT; stype++) {
+		if (power_pm_supported[stype])
+			sbuf_printf(&sb, "%s ", power_stype_to_name(stype));
+	}
+	sbuf_trim(&sb);
+	sbuf_finish(&sb);
+	error = sysctl_handle_string(oidp, sbuf_data(&sb), sbuf_len(&sb), req);
+	sbuf_delete(&sb);
+
+	return (error);
+}
+
 static int
 power_sysctl_stype(SYSCTL_HANDLER_ARGS)
 {
@@ -86,7 +107,8 @@ power_sysctl_stype(SYSCTL_HANDLER_ARGS)
 	new_stype = power_name_to_stype(name);
 	if (new_stype == POWER_STYPE_UNKNOWN)
 		return (EINVAL);
-	/* TODO Check to see if the new stype is supported. */
+	if (!power_pm_supported[new_stype])
+		return (EOPNOTSUPP);
 	if (new_stype != old_stype)
 		*(enum power_stype *)oidp->oid_arg1 = new_stype;
 	return (0);
@@ -95,6 +117,9 @@ power_sysctl_stype(SYSCTL_HANDLER_ARGS)
 static SYSCTL_NODE(_kern, OID_AUTO, power, CTLFLAG_RW, 0,
     "Generic power management related sysctls");
 
+SYSCTL_PROC(_kern_power, OID_AUTO, supported_stype,
+    CTLTYPE_STRING | CTLFLAG_RD, 0, 0, sysctl_supported_stypes, "A",
+    "List supported sleep types");
 SYSCTL_PROC(_kern_power, OID_AUTO, standby, CTLTYPE_STRING | CTLFLAG_RW,
     &power_standby_stype, 0, power_sysctl_stype, "A",
     "Sleep type to enter on standby");
@@ -114,7 +139,8 @@ power_pm_deferred_fn(void *arg, int pending)
 }
 
 int
-power_pm_register(u_int pm_type, power_pm_fn_t pm_fn, void *pm_arg)
+power_pm_register(u_int pm_type, power_pm_fn_t pm_fn, void *pm_arg,
+    bool pm_supported[static POWER_STYPE_COUNT])
 {
 	int	error;
 
@@ -123,6 +149,16 @@ power_pm_register(u_int pm_type, power_pm_fn_t pm_fn, void *pm_arg)
 		power_pm_type	= pm_type;
 		power_pm_fn	= pm_fn;
 		power_pm_arg	= pm_arg;
+		memcpy(power_pm_supported, pm_supported,
+		    sizeof(power_pm_supported));
+		if (power_pm_supported[POWER_STYPE_STANDBY])
+			power_standby_stype = POWER_STYPE_STANDBY;
+		if (power_pm_supported[POWER_STYPE_SUSPEND_TO_MEM])
+			power_suspend_stype = POWER_STYPE_SUSPEND_TO_MEM;
+		else if (power_pm_supported[POWER_STYPE_SUSPEND_TO_IDLE])
+			power_suspend_stype = POWER_STYPE_SUSPEND_TO_IDLE;
+		if (power_pm_supported[POWER_STYPE_HIBERNATE])
+			power_hibernate_stype = POWER_STYPE_HIBERNATE;
 		error = 0;
 		TASK_INIT(&power_pm_task, 0, power_pm_deferred_fn, NULL);
 	} else {
diff --git a/sys/sys/power.h b/sys/sys/power.h
index 44d7fc354423..33ace400bfd2 100644
--- a/sys/sys/power.h
+++ b/sys/sys/power.h
@@ -91,7 +91,8 @@ extern const char	*power_stype_to_name(enum power_stype _stype);
 
 typedef int (*power_pm_fn_t)(u_long _cmd, void* _arg, enum power_stype _stype);
 extern int	 power_pm_register(u_int _pm_type, power_pm_fn_t _pm_fn,
-			void *_pm_arg);
+			void *_pm_arg,
+			bool _pm_supported[static POWER_STYPE_COUNT]);
 extern u_int	 power_pm_get_type(void);
 extern void	 power_pm_suspend(int);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202509261603.58QG3pq4069287>