#!/bin/bash
#
# trigger script to enable a profile. Part of the pm-profiler
#
# Copyright (C) 2008 Holger Macht <hmacht@suse.de>
#
# This file is released under the GPLv2.
#

# where are the profiles?
PROFILE_PATH="/etc/pm-profiler"

STATEFILE="/var/run/pm-profiler.profile"

ERROR_GENERAL_ERROR=1
ERROR_INVALID_ARGUMENTS=2
ERROR_INVALID_PROFILE=3
ERROR_CONFIG_OPTION=4

LOGGER="logger -s -t pm-profiler"

if [ -z "$1" ]; then
    $LOGGER "missing profile name"
    exit $ERROR_INVALID_ARGUMENTS
else
    PROFILE="$1"
fi

. $PROFILE_PATH/$PROFILE/config >/dev/null 2>&1
if [ "$?" != "0" ]; then
    $LOGGER "the requested profile $PROFILE does not exist"
    exit $ERROR_INVALID_PROFILE
fi

function get_cpufreq_governor {
    Option="CPUFREQ_GOVERNOR"
    Governor=`cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor`
    echo $Option"="$Governor
}

function cpufreq_governor {
    for I in /sys/devices/system/cpu/cpu[[:digit:]]*/cpufreq; do
        Driver=`cat $I/scaling_driver`
        # intel_pstate has no ondemand governor, powersave handles this just fine
        if [ "$Driver" = "intel_pstate" -a "$CPUFREQ_GOVERNOR" != "performance" ]; then
            echo powersave > $I/scaling_governor
        else
            echo $CPUFREQ_GOVERNOR > $I/scaling_governor
        fi
    done
}

function cpufreq_reset_scaling_max_freq {
    for I in /sys/devices/system/cpu/cpu[[:digit:]]*/cpufreq; do
        if [ -r "$I/cpuinfo_max_freq" -a -w "$I/scaling_max_freq" ]; then
            Maxvalue=`cat $I/cpuinfo_max_freq`
            Maxscalingvalue=`cat $I/scaling_max_freq`
            if [ "$Maxvalue" != "$Maxscalingvalue" ]; then
                echo "$Maxvalue" > $I/scaling_max_freq
            fi
        fi
    done
}

function cpufreq_minimize_scaling_max_freq {
    for I in /sys/devices/system/cpu/cpu[[:digit:]]*/cpufreq; do
        if [ -r "$I/cpuinfo_max_freq" -a -r "$I/cpuinfo_min_freq" -a -w "$I/scaling_max_freq" ]; then
            Minvalue=`cat $I/cpuinfo_min_freq`
            echo "$Minvalue" > $I/scaling_max_freq
        fi
    done
}

function cpufreq_up_threshold {
    # kernel 3.1 onwards has some cpufreq params at a new toplevel location
    if [ -f /sys/devices/system/cpu/cpu0/cpufreq/$Governor/up_threshold ]; then
	echo $CPUFREQ_UP_THRESHOLD > /sys/devices/system/cpu/cpu0/cpufreq/$Governor/up_threshold
    elif [ -f /sys/devices/system/cpu/cpufreq/$Governor/up_threshold ]; then
	echo $CPUFREQ_UP_THRESHOLD > /sys/devices/system/cpu/cpufreq/$Governor/up_threshold
    fi
}

function cpufreq_sampling_rate {
    # kernel 3.1 onwards has some cpufreq params at a new toplevel location
    if [ -f /sys/devices/system/cpu/cpu0/cpufreq/$Governor/sampling_rate ]; then
	echo $CPUFREQ_SAMPLING_RATE >/sys/devices/system/cpu/cpu0/cpufreq/$Governor/sampling_rate;
    elif [ -f /sys/devices/system/cpu/cpufreq/$Governor/sampling_rate ]; then
	echo $CPUFREQ_SAMPLING_RATE >/sys/devices/system/cpu/cpufreq/$Governor/sampling_rate;
    fi
}

function cpufreq_sampling_down_factor {
    # kernel 3.1 onwards has some cpufreq params at a new toplevel location
    if [ -f /sys/devices/system/cpu/cpu0/cpufreq/$Governor/sampling_down_factor ]; then
        echo $CPUFREQ_SAMPLING_DOWN_FACTOR >/sys/devices/system/cpu/cpu0/cpufreq/$Governor/sampling_down_factor;
    elif [ -f /sys/devices/system/cpu/cpufreq/$Governor/sampling_down_factor ]; then
        echo $CPUFREQ_SAMPLING_DOWN_FACTOR >/sys/devices/system/cpu/cpufreq/$Governor/sampling_down_factor;
    fi
}

function cpufreq_ondemand_powersave_bias {
    # kernel 3.1 onwards has some cpufreq params at a new toplevel location
    if [ -f /sys/devices/system/cpu/cpu0/cpufreq/ondemand/powersave_bias ]; then
	echo $CPUFREQ_ONDEMAND_POWERSAVE_BIAS >/sys/devices/system/cpu/cpu0/cpufreq/ondemand/powersave_bias;
    elif [ -f /sys/devices/system/cpu/cpufreq/ondemand/powersave_bias ]; then
	echo $CPUFREQ_ONDEMAND_POWERSAVE_BIAS >/sys/devices/system/cpu/cpufreq/ondemand/powersave_bias;
    fi
}

function cpufreq_schedutil_rate_limit_us {
    echo $CPUFREQ_SCHEDUTIL_RATE_LIMIT_US >/sys/devices/system/cpu/cpufreq/schedutil/rate_limit_us;
}

function sata_alpm {
    for I in /sys/class/scsi_host/host*/link_power_management_policy; do
	[ -e $I ] && echo $SATA_ALPM > $I
    done
}

function external_hook {
    $EXTERNAL_HOOK 2>&1 | $LOGGER &
}

function dirty_writeback_centisecs {
    echo $DIRTY_WRITEBACK_CENTISECS > /proc/sys/vm/dirty_writeback_centisecs
}

function read_ahead_kb {
    for I in /sys/block/sd*/queue/read_ahead_kb; do
	echo $READ_AHEAD_KB > $I
    done
}


# in case scaling_max_freq has been reduced, reset value to avoid surprises
cpufreq_reset_scaling_max_freq

if [ -n "$CPUFREQ_GOVERNOR" ]; then
    cpufreq_governor
else
    get_cpufreq_governor
fi

case "$Governor" in
  ondemand)
    [ -n "$CPUFREQ_ONDEMAND_UP_THRESHOLD" ] && CPUFREQ_UP_THRESHOLD="$CPUFREQ_ONDEMAND_UP_THRESHOLD"
    [ -n "$CPUFREQ_ONDEMAND_SAMPLING_RATE" ] && CPUFREQ_SAMPLING_RATE="$CPUFREQ_ONDEMAND_SAMPLING_RATE"
    [ -n "$CPUFREQ_ONDEMAND_SAMPLING_DOWN_FACTOR" ] && CPUFREQ_SAMPLING_DOWN_FACTOR="$CPUFREQ_ONDEMAND_SAMPLING_DOWN_FACTOR"
    ;;
  conservative)
    [ -n "$CPUFREQ_CONSERVATIVE_UP_THRESHOLD" ] && CPUFREQ_UP_THRESHOLD="$CPUFREQ_CONSERVATIVE_UP_THRESHOLD"
    [ -n "$CPUFREQ_CONSERVATIVE_SAMPLING_RATE" ] && CPUFREQ_SAMPLING_RATE="$CPUFREQ_CONSERVATIVE_SAMPLING_RATE"
    [ -n "$CPUFREQ_CONSERVATIVE_SAMPLING_DOWN_FACTOR" ] && CPUFREQ_SAMPLING_DOWN_FACTOR="$CPUFREQ_CONSERVATIVE_SAMPLING_DOWN_FACTOR"
    ;;
esac
[ -n "$CPUFREQ_MINIMIZE_SCALING_MAX_FREQ" ] && cpufreq_minimize_scaling_max_freq
[ -n "$CPUFREQ_UP_THRESHOLD" ] && cpufreq_up_threshold
[ -n "$CPUFREQ_SAMPLING_RATE" ] && cpufreq_sampling_rate
[ -n "$CPUFREQ_SAMPLING_DOWN_FACTOR" ] && cpufreq_sampling_down_factor
[ -n "$CPUFREQ_ONDEMAND_POWERSAVE_BIAS" ] && cpufreq_ondemand_powersave_bias
[ -n "$CPUFREQ_SCHEDUTIL_RATE_LIMIT_US" ] && cpufreq_schedutil_rate_limit_us
[ -n "$SATA_ALPM" ] && sata_alpm
[ -n "$EXTERNAL_HOOK" ] && external_hook
[ -n "$DIRTY_WRITEBACK_CENTISECS" ] && dirty_writeback_centisecs
[ -n "$READ_AHEAD_KB" ] && read_ahead_kb

echo $PROFILE > $STATEFILE


exit 0
