blob: e8c2d3c69d76b3ac663e3fd672fcfa7af08d2475 [file] [log] [blame]
#!/bin/sh
# Copyright 2017 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Configures cpufreq if /etc/cpufreq.conf exists and contains valid
# configuration data.
# Convenience variables with sysfs paths.
CPU_BASE_DIR=/sys/devices/system/cpu
CPUFREQ_DIR="${CPU_BASE_DIR}/cpufreq"
##############################################
# Sets the cpufreq governor for all CPUs.
# Globals:
# CPU_BASE_DIR
# Arguments:
# Name of the cpufreq governor
# Returns:
# nothing
##############################################
cpufreq_set_governor() {
local governor="$1"
local cpu
for cpu in "${CPU_BASE_DIR}"/cpu[0-9]*; do
if [ -e "${cpu}/cpufreq" ]; then
echo "${governor}" > "${cpu}/cpufreq/scaling_governor"
fi
done
}
###########################################################################
# Gets the value of a configuration setting for the cpufreq governor.
# The settings are specified in the configuration file.
# Arguments:
# Name of the sysfs attribute of the setting
# Number of the cpufreq policy, empty for systems with a single policy
# for all CPUs
# Returns:
# Value of the requested setting, or an empty string if the setting is
# not specified in the configuration file.
###########################################################################
governor_get_config_value() {
local setting="$1"
local policy="$2"
local conf_var
conf_var="CPUFREQ_$(echo "${setting}" | tr "[:lower:]" "[:upper:]")"
if [ -n "${policy}" ]; then
conf_var="${conf_var}_POLICY_${policy}"
fi
echo "$(eval "echo \$$conf_var")"
}
#############################################################################
# Configures a setting of the cpufreq governor on systems with a single
# cpufreq policy. Does nothing if the setting is not specified in the
# configuration file.
# Globals:
# GOVERNOR_DIR
# Arguments:
# Name of the sysfs attribute of the setting
# Returns:
# nothing
###########################################################################
governor_set_optional() {
local setting="$1"
local sysfs_attr
sysfs_attr="${GOVERNOR_DIR}/${setting}"
if [ ! -f "${sysfs_attr}" ]; then
return
fi
local value="$(governor_get_config_value "${setting}")"
if [ -z "${value}" ]; then
return
fi
echo "${value}" > "${sysfs_attr}"
}
######################################################################
#
# Interactive governor
#
#############################################################################
# Configures a setting of the interactive cpufreq governor on systems with
# multiple cpufreq policies. Does nothing if the setting is not specified
# in the configuration file.
# Globals:
# CPUFREQ_DIR
# Arguments:
# Number of the cpufreq policy
# Name of the sysfs attribute of the setting
# Returns:
# nothing
###########################################################################
interactive_policy_set_optional() {
local policy="$1"
local setting="$2"
local sysfs_attr="${CPUFREQ_DIR}/policy${policy}/interactive/${setting}"
if [ ! -f "${sysfs_attr}" ]; then
return
fi
local value="$(governor_get_config_value "${setting}" "${policy}")"
if [ -z "${value}" ]; then
return
fi
echo "${value}" > "${sysfs_attr}"
}
#########################################################################
# Configures the interactive cpufreq governor according to the values
# from the configuration file.
# Globals:
# GOVERNOR_DIR
# CPUFREQ_DIR
# Arguments:
# None
# Returns:
# nothing
#########################################################################
cpufreq_config_interactive() {
local setting
GOVERNOR_DIR="${CPUFREQ_DIR}/interactive"
if [ -d "${GOVERNOR_DIR}" ]; then
for setting in input_boost above_hispeed_delay go_hispeed_load \
hispeed_freq min_sample_time target_loads timer_rate; do
governor_set_optional "${setting}"
done
else
local p
for p in "${CPUFREQ_DIR}"/policy[0-9]*; do
local policy="${p##*/policy}"
for setting in input_boost above_hispeed_delay go_hispeed_load \
hispeed_freq min_sample_time target_loads timer_rate; do
interactive_policy_set_optional "${policy}" "${setting}"
done
done
fi
}
######################################################################
#
# Ondemand governor
#
#########################################################################
# Configures the ondemand cpufreq governor according to the values
# from the configuration file.
# Globals:
# GOVERNOR_DIR
# Arguments:
# None
# Returns:
# nothing
#########################################################################
cpufreq_config_ondemand() {
local setting
GOVERNOR_DIR="${CPUFREQ_DIR}/ondemand"
for setting in sampling_rate up_threshold ignore_nice_load \
io_is_busy sampling_down_factor powersave_bias; do
governor_set_optional "${setting}"
done
}
######################################################################
if [ ! -f /etc/cpufreq.conf ]; then
exit 0
fi
. /etc/cpufreq.conf
if [ -z "${CPUFREQ_GOVERNOR}" ]; then
if dump_power_status | grep -q 'battery_status Discharging'; then
CPUFREQ_GOVERNOR="${CPUFREQ_GOVERNOR_BATTERY_DISCHARGE}"
else
CPUFREQ_GOVERNOR="${CPUFREQ_GOVERNOR_BATTERY_CHARGE}"
fi
fi
if [ -z "${CPUFREQ_GOVERNOR}" ]; then
exit 0
fi
cpufreq_set_governor "${CPUFREQ_GOVERNOR}"
if [ "${CPUFREQ_GOVERNOR}" = "interactive" ]; then
cpufreq_config_interactive
elif [ "${CPUFREQ_GOVERNOR}" = "ondemand" ]; then
cpufreq_config_ondemand
fi
# Set SELinux contexts for the newly created files (if any)
if [ -f /sys/fs/selinux/enforce ]; then
/sbin/restorecon -R "${CPUFREQ_DIR}"
fi