Page MenuHomeFreeBSD

D52036.id160637.diff
No OneTemporary

D52036.id160637.diff

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

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)

Event Timeline