Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145491838
D52036.id160637.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D52036.id160637.diff
View Options
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -4,6 +4,10 @@
* Copyright (c) 2000, 2001 Michael Smith
* Copyright (c) 2000 BSDi
* All rights reserved.
+ * Copyright (c) 2025 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Aymeric Wibo
+ * <obiwac@freebsd.org> under sponsorship from the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -181,7 +185,8 @@
static int acpi_supported_sleep_state_sysctl(SYSCTL_HANDLER_ARGS);
static int acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS);
static int acpi_debug_objects_sysctl(SYSCTL_HANDLER_ARGS);
-static int acpi_pm_func(u_long cmd, void *arg, ...);
+static int acpi_stype_to_sstate(struct acpi_softc *sc, enum power_stype stype);
+static int acpi_pm_func(u_long cmd, void *arg, enum power_stype stype);
static void acpi_enable_pcie(void);
static void acpi_reset_interfaces(device_t dev);
@@ -741,6 +746,28 @@
return_VALUE (error);
}
+static int
+acpi_stype_to_sstate(struct acpi_softc *sc, enum power_stype stype)
+{
+ switch (stype) {
+ case POWER_STYPE_AWAKE:
+ return (ACPI_STATE_S0);
+ case POWER_STYPE_STANDBY:
+ return (sc->acpi_standby_sx);
+ case POWER_STYPE_SUSPEND_TO_MEM:
+ return (ACPI_STATE_S3);
+ case POWER_STYPE_HIBERNATE:
+ return (ACPI_STATE_S4);
+ case POWER_STYPE_POWEROFF:
+ return (ACPI_STATE_S5);
+ case POWER_STYPE_SUSPEND_TO_IDLE:
+ case POWER_STYPE_COUNT:
+ case POWER_STYPE_UNKNOWN:
+ return (ACPI_STATE_UNKNOWN);
+ }
+ return (ACPI_STATE_UNKNOWN);
+}
+
static void
acpi_set_power_children(device_t dev, int state)
{
@@ -4621,12 +4648,10 @@
}
static int
-acpi_pm_func(u_long cmd, void *arg, ...)
+acpi_pm_func(u_long cmd, void *arg, enum power_stype stype)
{
- int state, acpi_state;
- int error;
+ int error, sstate;
struct acpi_softc *sc;
- va_list ap;
error = 0;
switch (cmd) {
@@ -4636,27 +4661,8 @@
error = EINVAL;
goto out;
}
-
- va_start(ap, arg);
- state = va_arg(ap, int);
- va_end(ap);
-
- switch (state) {
- case POWER_SLEEP_STATE_STANDBY:
- acpi_state = sc->acpi_standby_sx;
- break;
- case POWER_SLEEP_STATE_SUSPEND:
- acpi_state = sc->acpi_suspend_sx;
- break;
- case POWER_SLEEP_STATE_HIBERNATE:
- acpi_state = ACPI_STATE_S4;
- break;
- default:
- error = EINVAL;
- goto out;
- }
-
- if (ACPI_FAILURE(acpi_EnterSleepState(sc, acpi_state)))
+ sstate = acpi_stype_to_sstate(sc, stype);
+ if (ACPI_FAILURE(acpi_EnterSleepState(sc, sstate)))
error = ENXIO;
break;
default:
diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h
--- a/sys/dev/acpica/acpivar.h
+++ b/sys/dev/acpica/acpivar.h
@@ -40,6 +40,7 @@
#include <sys/ktr.h>
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/power.h>
#include <sys/selinfo.h>
#include <sys/sx.h>
#include <sys/sysctl.h>
diff --git a/sys/kern/subr_power.c b/sys/kern/subr_power.c
--- a/sys/kern/subr_power.c
+++ b/sys/kern/subr_power.c
@@ -3,6 +3,10 @@
*
* Copyright (c) 2001 Mitsuru IWASAKI
* All rights reserved.
+ * Copyright (c) 2025 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Aymeric Wibo
+ * <obiwac@freebsd.org> under sponsorship from the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,20 +34,85 @@
#include <sys/eventhandler.h>
#include <sys/power.h>
#include <sys/proc.h>
+#include <sys/sbuf.h>
+#include <sys/sysctl.h>
#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;
+
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 struct task power_pm_task;
+enum power_stype
+power_name_to_stype(const char *name)
+{
+ enum power_stype stype;
+
+ for (stype = 0; stype < POWER_STYPE_COUNT; stype++) {
+ if (strcasecmp(name, power_stype_names[stype]) == 0)
+ return (stype);
+ }
+ return (POWER_STYPE_UNKNOWN);
+}
+
+const char *
+power_stype_to_name(enum power_stype stype)
+{
+ if (stype == POWER_STYPE_UNKNOWN)
+ return ("NONE");
+ if (stype < POWER_STYPE_AWAKE || stype >= POWER_STYPE_COUNT)
+ return (NULL);
+ return (power_stype_names[stype]);
+}
+
+int
+power_sysctl_stype(SYSCTL_HANDLER_ARGS)
+{
+ char sleep_type[10];
+ int error;
+ enum power_stype new_stype, old_stype;
+
+ old_stype = *(enum power_stype *)oidp->oid_arg1;
+ strlcpy(sleep_type, power_stype_to_name(old_stype), sizeof(sleep_type));
+ error = sysctl_handle_string(oidp, sleep_type, sizeof(sleep_type), req);
+
+ if (error == 0 && req->newptr != NULL) {
+ new_stype = power_name_to_stype(sleep_type);
+
+ if (new_stype == POWER_STYPE_UNKNOWN)
+ return (EINVAL);
+ /* TODO Check to see if the new stype is supported. */
+ if (new_stype != old_stype)
+ *(enum power_stype *)oidp->oid_arg1 = new_stype;
+ }
+
+ return (error);
+}
+
+static SYSCTL_NODE(_kern, OID_AUTO, power, CTLFLAG_RW, 0,
+ "Generic power management related sysctls.");
+
+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");
+SYSCTL_PROC(_kern_power, OID_AUTO, suspend, CTLTYPE_STRING | CTLFLAG_RW,
+ &power_suspend_stype, 0, power_sysctl_stype, "A",
+ "Sleep type to enter on suspend");
+SYSCTL_PROC(_kern_power, OID_AUTO, hibernate, CTLTYPE_STRING | CTLFLAG_RW,
+ &power_hibernate_stype, 0, power_sysctl_stype, "A",
+ "Sleep type to enter on hibernate");
+
static void
power_pm_deferred_fn(void *arg, int pending)
{
- int state = (intptr_t)arg;
+ enum power_stype stype = (intptr_t)arg;
- power_pm_fn(POWER_CMD_SUSPEND, power_pm_arg, state);
+ power_pm_fn(POWER_CMD_SUSPEND, power_pm_arg, stype);
}
int
@@ -75,14 +144,27 @@
void
power_pm_suspend(int state)
{
+ enum power_stype stype;
+
if (power_pm_fn == NULL)
return;
- if (state != POWER_SLEEP_STATE_STANDBY &&
- state != POWER_SLEEP_STATE_SUSPEND &&
- state != POWER_SLEEP_STATE_HIBERNATE)
+ switch (state) {
+ case POWER_SLEEP_STATE_STANDBY:
+ stype = power_standby_stype;
+ break;
+ case POWER_SLEEP_STATE_SUSPEND:
+ stype = power_suspend_stype;
+ break;
+ case POWER_SLEEP_STATE_HIBERNATE:
+ stype = power_hibernate_stype;
+ break;
+ default:
+ printf("%s: unknown sleep state %d\n", __func__, state);
return;
- power_pm_task.ta_context = (void *)(intptr_t)state;
+ }
+
+ power_pm_task.ta_context = (void *)(intptr_t)stype;
taskqueue_enqueue(taskqueue_thread, &power_pm_task);
}
diff --git a/sys/sys/power.h b/sys/sys/power.h
--- a/sys/sys/power.h
+++ b/sys/sys/power.h
@@ -3,6 +3,10 @@
*
* Copyright (c) 2001 Mitsuru IWASAKI
* All rights reserved.
+ * Copyright (c) 2025 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Aymeric Wibo
+ * <obiwac@freebsd.org> under sponsorship from the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,6 +34,8 @@
#define _SYS_POWER_H_
#include <sys/_eventhandler.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
/* Power management system type */
#define POWER_PM_TYPE_ACPI 0x01
@@ -38,13 +44,57 @@
/* Commands for Power management function */
#define POWER_CMD_SUSPEND 0x00
-/* Sleep state */
+/*
+ * Sleep state.
+ *
+ * These are high-level sleep states that the system can enter. They map to
+ * a specific generic sleep type (enum power_stype).
+ *
+ * TODO Can this just be an enum?
+ */
#define POWER_SLEEP_STATE_STANDBY 0x00
#define POWER_SLEEP_STATE_SUSPEND 0x01
#define POWER_SLEEP_STATE_HIBERNATE 0x02
-typedef int (*power_pm_fn_t)(u_long, void*, ...);
-extern int power_pm_register(u_int, power_pm_fn_t, void *);
+/*
+ * Sleep type.
+ *
+ * These are the specific generic methods of entering a sleep state. E.g.
+ * POWER_SLEEP_STATE_SUSPEND could be set to enter either suspend-to-RAM (which
+ * is S3 on ACPI systems), or suspend-to-idle (S0ix on ACPI systems). This
+ * would be done through the kern.power.suspend sysctl.
+ */
+enum power_stype {
+ POWER_STYPE_AWAKE,
+ POWER_STYPE_STANDBY,
+ POWER_STYPE_SUSPEND_TO_MEM,
+ POWER_STYPE_SUSPEND_TO_IDLE,
+ POWER_STYPE_HIBERNATE,
+ POWER_STYPE_POWEROFF,
+ POWER_STYPE_COUNT,
+ POWER_STYPE_UNKNOWN,
+};
+
+static const char *power_stype_names[POWER_STYPE_COUNT] = {
+ [POWER_STYPE_AWAKE] = "awake",
+ [POWER_STYPE_STANDBY] = "standby",
+ [POWER_STYPE_SUSPEND_TO_MEM] = "s2mem",
+ [POWER_STYPE_SUSPEND_TO_IDLE] = "s2idle",
+ [POWER_STYPE_HIBERNATE] = "hibernate",
+ [POWER_STYPE_POWEROFF] = "poweroff",
+};
+
+extern enum power_stype power_standby_stype;
+extern enum power_stype power_suspend_stype;
+extern enum power_stype power_hibernate_stype;
+
+extern enum power_stype power_name_to_stype(const char *_name);
+extern const char *power_stype_to_name(enum power_stype _stype);
+extern int power_sysctl_stype(SYSCTL_HANDLER_ARGS);
+
+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);
extern u_int power_pm_get_type(void);
extern void power_pm_suspend(int);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Feb 21, 12:26 PM (13 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28922742
Default Alt Text
D52036.id160637.diff (9 KB)
Attached To
Mode
D52036: sys/power: Generic sleep types
Attached
Detach File
Event Timeline
Log In to Comment