summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--etc/rc.d/power_profile4
-rw-r--r--share/man/man4/acpi.410
-rw-r--r--sys/dev/acpica/acpi_cpu.c21
3 files changed, 20 insertions, 15 deletions
diff --git a/etc/rc.d/power_profile b/etc/rc.d/power_profile
index a5113d5..7e23cf5 100644
--- a/etc/rc.d/power_profile
+++ b/etc/rc.d/power_profile
@@ -71,9 +71,9 @@ esac
# Set the various sysctls based on the profile's values.
node="hw.acpi.cpu.cx_lowest"
-highest_value=0
+highest_value="C1"
lowest_value="$(sysctl -n hw.acpi.cpu.cx_supported | \
- awk '{ print split($0, a) - 1 }' - 2> /dev/null)"
+ awk '{ print "C" split($0, a) }' - 2> /dev/null)"
eval value=\$${profile}_cx_lowest
sysctl_set
diff --git a/share/man/man4/acpi.4 b/share/man/man4/acpi.4
index 0a16d70..8f47880 100644
--- a/share/man/man4/acpi.4
+++ b/share/man/man4/acpi.4
@@ -366,19 +366,21 @@ The counters are reset when
.Va hw.acpi.cpu.cx_lowest
is modified.
.It Va hw.acpi.cpu.cx_lowest
-Zero-based index of the lowest CPU idle state to use.
-A scheduling algorithm will select between 0...index for the state
-to use during the next sleep.
+Lowest Cx state to use for idling the CPU.
+A scheduling algorithm will select states between C1 and this setting
+as system load dictates.
To enable ACPI CPU idling control,
.Va machdep.cpu_idle_hlt
must be set to 1.
.It Va hw.acpi.cpu.cx_supported
List of supported CPU idle states and their transition latency
in microseconds.
-Each state has a type, C1-3.
+Each state has a type (e.g., C2.)
C1 is equivalent to the ia32 HLT instruction, C2 provides a deeper
sleep with the same semantics, and C3 provides the deepest sleep
but additionally requires bus mastering to be disabled.
+States greater than C3 provide even more power savings with the same
+semantics as the C3 state.
Deeper sleeps provide more power savings but increased transition
latency when an interrupt occurs.
.El
diff --git a/sys/dev/acpica/acpi_cpu.c b/sys/dev/acpica/acpi_cpu.c
index 3a9279c..f92c4b1f 100644
--- a/sys/dev/acpica/acpi_cpu.c
+++ b/sys/dev/acpica/acpi_cpu.c
@@ -739,10 +739,8 @@ acpi_cpu_startup_cx()
sc = device_get_softc(cpu_devices[0]);
sbuf_new(&sb, cpu_cx_supported, sizeof(cpu_cx_supported), SBUF_FIXEDLEN);
- for (i = 0; i < cpu_cx_count; i++) {
- sbuf_printf(&sb, "C%d/%d ", sc->cpu_cx_states[i].type,
- sc->cpu_cx_states[i].trans_lat);
- }
+ for (i = 0; i < cpu_cx_count; i++)
+ sbuf_printf(&sb, "C%d/%d ", i + 1, sc->cpu_cx_states[i].trans_lat);
sbuf_trim(&sb);
sbuf_finish(&sb);
SYSCTL_ADD_STRING(&acpi_cpu_sysctl_ctx,
@@ -751,8 +749,8 @@ acpi_cpu_startup_cx()
0, "Cx/microsecond values for supported Cx states");
SYSCTL_ADD_PROC(&acpi_cpu_sysctl_ctx,
SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
- OID_AUTO, "cx_lowest", CTLTYPE_INT | CTLFLAG_RW,
- NULL, 0, acpi_cpu_cx_lowest_sysctl, "I",
+ OID_AUTO, "cx_lowest", CTLTYPE_STRING | CTLFLAG_RW,
+ NULL, 0, acpi_cpu_cx_lowest_sysctl, "A",
"lowest Cx sleep state to use");
SYSCTL_ADD_PROC(&acpi_cpu_sysctl_ctx,
SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
@@ -1085,7 +1083,8 @@ acpi_cpu_history_sysctl(SYSCTL_HANDLER_ARGS)
}
sbuf_trim(&sb);
sbuf_finish(&sb);
- sysctl_handle_string(oidp, sbuf_data(&sb), 0, req);
+ sysctl_handle_string(oidp, sbuf_data(&sb), sbuf_len(&sb), req);
+ sbuf_delete(&sb);
return (0);
}
@@ -1094,13 +1093,17 @@ static int
acpi_cpu_cx_lowest_sysctl(SYSCTL_HANDLER_ARGS)
{
struct acpi_cpu_softc *sc;
+ char state[8];
int val, error, i;
sc = device_get_softc(cpu_devices[0]);
- val = cpu_cx_lowest;
- error = sysctl_handle_int(oidp, &val, 0, req);
+ snprintf(state, sizeof(state), "C%d", cpu_cx_lowest + 1);
+ error = sysctl_handle_string(oidp, state, sizeof(state), req);
if (error != 0 || req->newptr == NULL)
return (error);
+ if (strlen(state) < 2 || toupper(state[0]) != 'C')
+ return (EINVAL);
+ val = (int) strtol(state + 1, NULL, 10) - 1;
if (val < 0 || val > cpu_cx_count - 1)
return (EINVAL);
OpenPOWER on IntegriCloud