diff options
-rw-r--r-- | etc/rc.d/power_profile | 4 | ||||
-rw-r--r-- | share/man/man4/acpi.4 | 10 | ||||
-rw-r--r-- | sys/dev/acpica/acpi_cpu.c | 21 |
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); |