| 1 |
#!/bin/sh |
| 2 |
# |
| 3 |
# Modify the power profile based on AC line state. This script is |
| 4 |
# usually called from devd(8). |
| 5 |
# |
| 6 |
# Arguments: 0x00 (AC offline, economy) or 0x01 (AC online, performance) |
| 7 |
# |
| 8 |
# $FreeBSD$ |
| 9 |
# |
| 10 |
|
| 11 |
# PROVIDE: power_profile |
| 12 |
# REQUIRE: FILESYSTEMS syslogd |
| 13 |
# KEYWORD: nojail nostart |
| 14 |
|
| 15 |
. /etc/rc.subr |
| 16 |
|
| 17 |
name="power_profile" |
| 18 |
stop_cmd=':' |
| 19 |
LOGGER="logger -t power_profile -p daemon.notice" |
| 20 |
|
| 21 |
# Set a given sysctl node to a value. |
| 22 |
# |
| 23 |
# Variables: |
| 24 |
# $node: sysctl node to set with the new value |
| 25 |
# $value: HIGH for the highest performance value, LOW for the best |
| 26 |
# economy value, or the value itself. |
| 27 |
# $highest_value: maximum value for this sysctl, when $value is "HIGH" |
| 28 |
# $lowest_value: minimum value for this sysctl, when $value is "LOW" |
| 29 |
# |
| 30 |
sysctl_set() |
| 31 |
{ |
| 32 |
# Check if the node exists |
| 33 |
if [ -z "$(sysctl -n ${node} 2> /dev/null)" ]; then |
| 34 |
return |
| 35 |
fi |
| 36 |
|
| 37 |
# Get the new value, checking for special types HIGH or LOW |
| 38 |
case ${value} in |
| 39 |
[Hh][Ii][Gg][Hh]) |
| 40 |
value=${highest_value} |
| 41 |
;; |
| 42 |
[Ll][Oo][Ww]) |
| 43 |
value=${lowest_value} |
| 44 |
;; |
| 45 |
[Nn][Oo][Nn][Ee]) |
| 46 |
return |
| 47 |
;; |
| 48 |
*) |
| 49 |
;; |
| 50 |
esac |
| 51 |
|
| 52 |
# Set the desired value |
| 53 |
if [ -n "${value}" ]; then |
| 54 |
if ! sysctl ${node}=${value} > /dev/null 2>&1; then |
| 55 |
warn "unable to set ${node}=${value}" |
| 56 |
fi |
| 57 |
fi |
| 58 |
} |
| 59 |
|
| 60 |
if [ $# -ne 1 ]; then |
| 61 |
err 1 "Usage: $0 [0x00|0x01]" |
| 62 |
fi |
| 63 |
load_rc_config $name |
| 64 |
|
| 65 |
# Find the next state (performance or economy). |
| 66 |
state=$1 |
| 67 |
case ${state} in |
| 68 |
0x01 | '') |
| 69 |
${LOGGER} "changed to 'performance'" |
| 70 |
profile="performance" |
| 71 |
;; |
| 72 |
0x00) |
| 73 |
${LOGGER} "changed to 'economy'" |
| 74 |
profile="economy" |
| 75 |
;; |
| 76 |
*) |
| 77 |
echo "Usage: $0 [0x00|0x01]" |
| 78 |
exit 1 |
| 79 |
esac |
| 80 |
|
| 81 |
# Set the various sysctls based on the profile's values. |
| 82 |
node="hw.acpi.cpu.cx_lowest" |
| 83 |
highest_value="C1" |
| 84 |
lowest_value="Cmax" |
| 85 |
eval value=\$${profile}_cx_lowest |
| 86 |
sysctl_set |
| 87 |
|
| 88 |
node="dev.cpu.0.freq" |
| 89 |
highest_value="`(sysctl -n dev.cpu.0.freq_levels | \ |
| 90 |
awk '{ split($0, a, "[/ ]"); print a[1] }' -) 2> /dev/null`" |
| 91 |
lowest_value="`(sysctl -n dev.cpu.0.freq_levels | \ |
| 92 |
awk '{ split($0, a, "[/ ]"); print a[length(a) - 1] }' -) 2> /dev/null`" |
| 93 |
eval value=\$${profile}_cpu_freq |
| 94 |
sysctl_set |
| 95 |
|
| 96 |
exit 0 |