#!/bin/sh # # CPU Frequency Scaling manipulation tool # # Author: Adam Drzewiecki # e-mail: A.Drzewiecki@ztpnet.pl # WWW: http://drzewiecki.zgora.pl # # Last modified: 12 Oct 2008 # # path to information about CPUs, located at SYSFS CPUINFO="/sys/devices/system/cpu" # some useful variables CPUFREQ="cpufreq" SCALING_GOVERNORS="$CPUFREQ/scaling_available_governors" SCALING_FREQUENCIES="$CPUFREQ/scaling_available_frequencies" SCALING_MIN="$CPUFREQ/scaling_min_freq" SCALING_MAX="$CPUFREQ/scaling_max_freq" SCALING_CUR="$CPUFREQ/scaling_cur_freq" SCALING_GOV="$CPUFREQ/scaling_governor" SCALING_SSP="$CPUFREQ/scaling_setspeed" SCALING_DRV="$CPUFREQ/scaling_driver" CPUINFO_MIN="$CPUFREQ/cpuinfo_min_freq" CPUINFO_MAX="$CPUFREQ/cpuinfo_max_freq" # # Most of the operations are available only for user root # is_root() { if [ "$(id -u)" -ne "0" ]; then echo "you must be root to do that" exit -1 fi } # # Create a CPFreq'ed CPU's list # cpu_list() { CPUS="" for CPU in $CPUINFO/cpu* ; do # build a path to CPUFreq interface CFSPATH="$CPUINFO/$(basename $CPU)/$CPUFREQ" # if CPU have an interface CPUFreq, add it to list if [ -d "$CFSPATH" ]; then if [ -z "$CPUS" ]; then CPUS="$(basename $CPU)" else CPUS="$CPUS $(basename $CPU)" fi fi done } # # Create list of governors, compiled as a modules # modules_list() { MODULES="" # extract modules path from modules.dep, filter paths with "cpufreq_" for MODULE in $(cat /lib/modules/$(uname -r)/modules.dep | cut -f 1 -d ":" | grep "cpufreq_" ) ; do # take module filename without extension and take part after first occurence of "_" sign GOVNAME="$(basename $MODULE .ko | cut -f 2 -d _)" # "cpufreq_stats" is the only module name beginnning with "cpufreq_" which isn't a governor... if [ "$GOVNAME" != "stats" ]; then if [ -z "$MODULES" ]; then MODULES="$GOVNAME" else MODULES="$MODULES $GOVNAME" fi fi done } # # Create governors list available for particular processor # # $1 - cpuN # governors_list() { if [ -f "$CPUINFO/$1/$SCALING_GOVERNORS" ]; then # create list of known governors GOVERNORS="" for GOVERNOR in $(cat $CPUINFO/$1/$SCALING_GOVERNORS) ; do if [ -z "$GOVERNORS" ]; then GOVERNORS="$GOVERNOR" else GOVERNORS="$GOVERNORS $GOVERNOR" fi done # add governors available as a not loaded modules modules_list for MODULE in $MODULES ; do # add governor name from MODULES only if it isn't on the governors list if ! echo "$GOVERNORS" | grep -qs "$MODULE" ; then if [ -z "$GOVERNORS" ] ; then GOVERNORS="$MODULE" else GOVERNORS="$GOVERNORS $MODULE" fi fi done fi } # # Create list of available frequencies for particular processor # # $1 - cpuN # frequencies_list() { FREQUENCIES="" for FREQ in $(cat $CPUINFO/$1/$SCALING_FREQUENCIES) ; do if [ -z "$FREQUENCIES" ]; then FREQUENCIES="$FREQ" else FREQUENCIES="$FREQUENCIES $FREQ" fi done } # # Show infromation about particular processor # # $1 - cpuN # show_processor() { CFSPATH="$CPUINFO/$1" if [ -d "$CFSPATH/$CPUFREQ" ]; then echo -e "Processor \"$1\":\n" echo -e "Current frequency:\t$(cat $CFSPATH/$SCALING_CUR) kHz " echo -e "Frequency range:\t$(cat $CFSPATH/$SCALING_MIN)-$(cat $CFSPATH/$SCALING_MAX) kHz" echo -e "Current governor:\t$(cat $CFSPATH/$SCALING_GOV)" governors_list $1 echo -e "Available governors:\t$GOVERNORS" echo -e "Scaling driver:\t\t$(cat $CFSPATH/$SCALING_DRV)" echo -e "Available frequencies:\t$(cat $CFSPATH/$CPUINFO_MIN)-$(cat $CFSPATH/$CPUINFO_MAX) kHz " frequencies_list $1 echo -e "Frequencies list:\t$FREQUENCIES" fi } # # Show real processor signature from given alias # # $1 - cpufreq file # show_real() { echo -n "\"$(readlink $1 | tr '/' '\n' | grep 'cpu[0-9]\+$')\"" } # # Show short information about aliased processor # # $1 - cpuN # show_alias() { CFSPATH="$CPUINFO/$1" if [ -d "$CFSPATH/$CPUFREQ" ]; then echo -n "Processor \"$1\": " echo -n "alias to processor " show_real $CFSPATH/$CPUFREQ fi } # # Shows information about CPUFreq-capable processor[s] # # $1 - cpuN # show_info() { if [ -z "$1" ]; then cpu_list CPULIST="$CPUS" else CPULIST="$1" fi if [ -z "$CPULIST" ]; then echo "No CPUFreq capable CPUs found" else for CPU in $CPULIST ; do CFSPATH="$CPUINFO/$CPU" if [ -d "$CFSPATH" ]; then if [ -d "$CFSPATH/$CPUFREQ" ]; then if [ ! -h "$CFSPATH/$CPUFREQ" ]; then show_processor $CPU else show_alias $CPU if [ "$(echo $CPULIST | wc -w)" -lt "2" ]; then echo show_processor $(readlink $CFSPATH/$CPUFREQ | tr '/' '\n' | grep 'cpu[0-9]\+$') fi fi else echo "Processor \"$CPU\" haven't CPUFreq interface" fi else echo "Processor \"$CPU\" doesn't exist" fi echo done fi } # # Activating particular governor for a given processor[s] # # $1 - governor's name # $2 - cpuN # setup_governor() { if [ -z "$2" ]; then cpu_list CPUGOV="$CPUS" else CPUGOV="$2" fi for CPU in $CPUGOV; do CFSPATH="$CPUINFO/$CPU" if [ -d "$CFSPATH" ]; then if [ -d "$CFSPATH/$CPUFREQ" ]; then echo -n "Set up governor \"$1\" for CPU \"$CPU\": " if [ ! -h "$CFSPATH/$CPUFREQ" -o "$(echo $CPUGOV | wc -w)" -lt "2" ]; then if echo "$1" >$CFSPATH/$SCALING_GOV 2>/dev/null ; then echo "success" else echo "failed" fi else echo -n "skipped, \"$CPU\" is alias to processor " show_real $CFSPATH/$CPUFREQ echo fi else echo "Processor \"$CPU\" haven't CPUFreq interface" fi else echo "Processor \"$CPU\" doesn't exist" fi done } # # Set up particular frequency for a given processor # # $1 - frequency # $2 - cpuN # setup_frequency() { if [ -z "$2" ]; then cpu_list CPUFRQ="$CPUS" else CPUFRQ="$2" fi for CPU in $CPUFRQ; do CFSPATH="$CPUINFO/$CPU" if [ -d "$CFSPATH" ]; then if [ -d "$CFSPATH/$CPUGREQ" ]; then # only "userspace" governor can change current frequency [ "$(cat $CFSPATH/$SCALING_GOV)" != "userspace" ] && setup_governor "userspace" $CPU if [ -f "$CFSPATH/$SCALING_SSP" ] ; then echo -n "Set up frequency for CPU \"$CPU\": " if [ ! -h "$CFSPATH/$CPUFREQ" -o "$(echo $CPUGOV | wc -w)" -lt "2" ]; then if echo "$1" >$CFSPATH/$SCALING_SSP 2>/dev/null ; then echo "success, frequency set to $(cat $CFSPATH/$SCALING_CUR)" else echo "failed" fi else echo -n "skipped, \"$CPU\" is alias to processor " show_real $CFSPATH/$CPUFREQ fi else echo "Can't set \"$CPU\" frequency to \"$1\". Enable \"userspace\" governor in kernel" fi else echo "Processor \"$CPU\" haven't CPUFreq interface" fi else echo "Processor \"$CPU\" doesn't exist" fi done } # # Set up frequency range for a given processor[s] # # $1 - min freq # $2 - max freq # $3 - cpuN # setup_range() { if [ -z "$3" ]; then cpu_list CPUGOV="$CPUS" else CPUGOV="$3" fi for CPU in $CPUGOV; do CFSPATH="$CPUINFO/$CPU" if [ -d "$CFSPATH" ]; then if [ -d "$CFSPATH/$CPUFREQ" ]; then echo -n "Set up frequency range \"$1-$2\" for CPU \"$CPU\": " if [ ! -h "$CFSPATH/$CPUFREQ" -o "$(echo $CPUGOV | wc -w)" -lt "2" ]; then # higher frequency must be set as a first, then lower if echo "$2" >$CFSPATH/$SCALING_MAX 2>/dev/null && \ echo "$1" >$CFSPATH/$SCALING_MIN 2>/dev/null ; then echo -n "success" else echo -n "failed" fi echo -e " ($(cat $CFSPATH/$SCALING_MIN)-$(cat $CFSPATH/$SCALING_MAX) kHz)" else echo -n "skipped, \"$CPU\" is alias to processor " show_real $CFSPATH/$CPUFREQ fi else echo "Processor \"$CPU\" haven't CPUFreq interface" fi else echo "Processor \"$CPU\" doesn't exist" fi done } # # main() # case "$1" in i|info) show_info $2 ;; g|governor) is_root setup_governor $2 $3 ;; f|frequency) is_root setup_frequency $2 $3 ;; r|range) is_root setup_range $2 $3 $4 ;; h|help|*) echo echo "CPU Frequency Scaling tool" echo "(c) by Adam Drzewiecki" echo echo -e "usage:" echo -e "\t$(basename $0) i[nfo] [cpuN] - shows information about cpuN (or all)" echo -e "\t$(basename $0) g[overnor] name [cpuN] - set up governor \"name\" for cpuN (or all)" echo -e "\t$(basename $0) f[requency] frequency [cpuN] - set up current frequency for cpuN (or all)" echo -e "\t$(basename $0) r[ange] fmin fmax [cpuN] - set up frequency range for cpuN (or all)" echo -e "\t$(basename $0) h[elp] - shows this information" echo ;; esac