| #!/bin/sh |
| # |
| # PM-QA validation test suite for the power management on Linux |
| # |
| # Copyright (C) 2008-2009 Canonical Ltd. |
| # Copyright (C) 2011-2016, Linaro Limited. |
| # |
| # This program is free software; you can redistribute it and/or |
| # modify it under the terms of the GNU General Public License |
| # as published by the Free Software Foundation; either version 2 |
| # of the License, or (at your option) any later version. |
| # |
| # This program is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| # |
| # You should have received a copy of the GNU General Public License |
| # along with this program; if not, write to the Free Software |
| # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| # |
| # Contributors: |
| # Daniel Lezcano <daniel.lezcano@linaro.org> (IBM Corporation) |
| # - initial API and implementation |
| # Michael Frey <michael.frey@canonical.com> |
| # - initial suspend/resume functions |
| # Andy Whitcroft <apw@canonical.com> |
| # - initial suspend/resume functions |
| # Hongbo Zhang <hongbo.zhang@linaro.org> |
| # - updated suspend/resume functions |
| # |
| |
| . ../Switches/Switches.sh |
| |
| LOGDIR='/var/lib/pm-utils' |
| LOGFILE="$LOGDIR/stress.log" |
| CPU_PATH="/sys/devices/system/cpu" |
| TEST_NAME=$(basename ${0%.sh}) |
| PREFIX=$TEST_NAME |
| INC=0 |
| cpus=$(ls $CPU_PATH | grep "cpu[0-9].*") |
| pass_count=0 |
| fail_count=0 |
| skip_count=0 |
| test_script_status="pass" |
| NANOSLEEP="../utils/nanosleep" |
| gov_array="governors_backup" |
| freq_array="frequencies_backup" |
| THERMAL_PATH="/sys/devices/virtual/thermal" |
| MAX_ZONE=0-12 |
| MAX_CDEV=0-50 |
| scaling_freq_array="scaling_freq" |
| mode_array="mode_list" |
| thermal_gov_array="thermal_governor_backup" |
| |
| # config options for suspend/resume |
| dry=0 |
| auto=1 |
| pm_trace=1 |
| timer_sleep=20 |
| |
| test_status_show() { |
| if [ $fail_count -ne 0 ]; then |
| test_script_status="fail" |
| else |
| if [ $skip_count -ne 0 ]; then |
| if [ $pass_count -ne 0 ]; then |
| test_script_status="pass" |
| else |
| test_script_status="skip" |
| fi |
| fi |
| fi |
| |
| echo " " |
| if [ "$test_script_status" = "fail" ]; then |
| echo "$TEST_NAME: fail" |
| elif [ "$test_script_status" = "skip" ]; then |
| echo "$TEST_NAME: skip" |
| else |
| echo "$TEST_NAME: pass" |
| fi |
| echo " " |
| } |
| |
| skip_tests() { |
| dir=$1 |
| |
| test_script_list=$(ls ../$1/*.sh | grep -v 'sanity.sh$' | grep -v '00.sh$') |
| |
| for test_script in $test_script_list; do |
| test_case=$(basename $test_script .sh) |
| echo "$test_case: skip" |
| done |
| } |
| |
| log_begin() { |
| printf "%-76s" "$TEST_NAME.$INC$CPU: $@... " |
| INC=$(($INC+1)) |
| } |
| |
| log_end() { |
| printf "$*\n" |
| |
| if [ "$*" = "Err" ]; then |
| fail_count=$((fail_count + 1)) |
| elif [ "$*" = "skip" ]; then |
| skip_count=$((skip_count + 1)) |
| else |
| pass_count=$((pass_count + 1)) |
| fi |
| } |
| |
| log_skip() { |
| log_begin "$@" |
| log_end "skip" |
| } |
| |
| for_each_cpu() { |
| |
| cpu_func=$1 |
| shift 1 |
| |
| for cpu in $cpus; do |
| INC=0 |
| CPU=/$cpu |
| $cpu_func $cpu $@ |
| done |
| |
| return 0 |
| } |
| |
| for_each_governor() { |
| |
| gov_cpu=$1 |
| gov_func=$2 |
| cpufreq_dirpath=$CPU_PATH/$gov_cpu/cpufreq |
| governors=$(cat $cpufreq_dirpath/scaling_available_governors) |
| shift 2 |
| |
| for governor in $governors; do |
| $gov_func $gov_cpu $governor $@ |
| done |
| |
| return 0 |
| } |
| |
| for_each_frequency() { |
| |
| freq_cpu=$1 |
| freq_func=$2 |
| cpufreq_dirpath=$CPU_PATH/$freq_cpu/cpufreq |
| frequencies=$(cat $cpufreq_dirpath/scaling_available_frequencies) |
| shift 2 |
| |
| for frequency in $frequencies; do |
| $freq_func $freq_cpu $frequency $@ |
| done |
| |
| return 0 |
| } |
| |
| set_governor() { |
| |
| gov_cpu=$1 |
| scaling_gov_dirpath=$CPU_PATH/$gov_cpu/cpufreq/scaling_governor |
| newgov=$2 |
| |
| echo $newgov > $scaling_gov_dirpath |
| } |
| |
| get_governor() { |
| |
| gov_cpu=$1 |
| scaling_gov_dirpath=$CPU_PATH/$gov_cpu/cpufreq/scaling_governor |
| |
| cat $scaling_gov_dirpath |
| } |
| |
| wait_latency() { |
| wait_latency_cpu=$1 |
| cpufreq_dirpath=$CPU_PATH/$wait_latency_cpu/cpufreq |
| gov=$(cat $cpufreq_dirpath/scaling_governor) |
| |
| # consider per-policy governor case |
| if [ -e $CPU_PATH/$wait_latency_cpu/cpufreq/$gov ]; then |
| #try one path to see if the sampling_rate can be found |
| if [ -e $CPU_PATH/$wait_latency_cpu/cpufreq/$gov/sampling_rate ]; then |
| sampling_rate=$(cat $CPU_PATH/$wait_latency_cpu/cpufreq/$gov/sampling_rate) |
| else |
| # try another path to get the sampling_rate |
| if [ -e $CPU_PATH/cpufreq/$gov/sampling_rate ]; then |
| sampling_rate=$(cat $CPU_PATH/cpufreq/$gov/sampling_rate) |
| else |
| return 1 |
| fi |
| fi |
| else |
| return 1 |
| fi |
| sampling_rate=$((sampling_rate * 1000)) # unit nsec |
| |
| latency=$(cat $cpufreq_dirpath/cpuinfo_transition_latency) |
| if [ $? -ne 0 ]; then |
| return 1 |
| fi |
| |
| nrfreq=$(cat $cpufreq_dirpath/scaling_available_frequencies | wc -w) |
| if [ $? -ne 0 ]; then |
| return 1 |
| fi |
| |
| nrfreq=$((nrfreq + 1)) |
| |
| sleep_time=$(($latency + $sampling_rate)) |
| |
| $NANOSLEEP $(($nrfreq * $sleep_time)) |
| } |
| |
| frequnit() { |
| freq=$1 |
| ghz=$(echo $freq | awk '{printf "%.1f", ($1 / 1000000)}') |
| mhz=$(echo $freq | awk '{printf "%.1f", ($1 / 1000)}') |
| |
| ghz_value=$(echo $ghz | awk '{printf "%f", ($1 > 1.0)}') |
| if [ "$ghz_value" = "1" ]; then |
| echo $ghz GHz |
| return 0 |
| fi |
| |
| mhz_value=$(echo $mhz | awk '{printf "%f", ($1 > 1.0)}') |
| if [ "$mhz_value" = "1" ];then |
| echo $mhz MHz |
| return 0 |
| fi |
| |
| echo $freq KHz |
| } |
| |
| set_frequency() { |
| |
| freq_cpu=$1 |
| cpufreq_dirpath=$CPU_PATH/$freq_cpu/cpufreq |
| newfreq=$2 |
| setfreqpath=$cpufreq_dirpath/scaling_setspeed |
| |
| echo $newfreq > $setfreqpath |
| wait_latency $freq_cpu |
| } |
| |
| get_frequency() { |
| freq_cpu=$1 |
| scaling_cur_freq=$CPU_PATH/$freq_cpu/cpufreq/scaling_cur_freq |
| cat $scaling_cur_freq |
| } |
| |
| get_max_frequency() { |
| freq_cpu=$1 |
| scaling_max_freq=$CPU_PATH/$freq_cpu/cpufreq/scaling_max_freq |
| cat $scaling_max_freq |
| } |
| |
| get_min_frequency() { |
| freq_cpu=$1 |
| scaling_min_freq=$CPU_PATH/$freq_cpu/cpufreq/scaling_min_freq |
| cat $scaling_min_freq |
| } |
| |
| set_online() { |
| current_cpu=$1 |
| current_cpu_path=$CPU_PATH/$current_cpu |
| |
| if [ "$current_cpu" = "cpu0" ]; then |
| return 0 |
| fi |
| |
| echo 1 > $current_cpu_path/online |
| } |
| |
| set_offline() { |
| current_cpu=$1 |
| current_cpu_path=$CPU_PATH/$current_cpu |
| |
| if [ "$current_cpu" = "cpu0" ]; then |
| return 0 |
| fi |
| |
| echo 0 > $current_cpu_path/online |
| } |
| |
| get_online() { |
| current_cpu=$1 |
| current_cpu_path=$CPU_PATH/$current_cpu |
| |
| cat $current_cpu_path/online |
| } |
| |
| check() { |
| |
| check_descr=$1 |
| check_func=$2 |
| shift 2; |
| |
| log_begin "checking $check_descr" |
| |
| $check_func $@ |
| if [ $? -ne 0 ]; then |
| log_end "Err" |
| return 1 |
| fi |
| |
| log_end "Ok" |
| |
| return 0 |
| } |
| |
| check_file() { |
| file=$1 |
| dir=$2 |
| |
| check "'$file' exists in '$dir'" "test -f" $dir/$file |
| } |
| |
| check_cpufreq_files() { |
| cpu_id=$1 |
| cpufreq_files_dir=$CPU_PATH/$cpu_id/cpufreq |
| shift 1 |
| |
| for i in $@; do |
| check_file $i $cpufreq_files_dir || return 1 |
| done |
| |
| return 0 |
| } |
| |
| check_sched_mc_files() { |
| |
| for i in $@; do |
| check_file $i $CPU_PATH || return 1 |
| done |
| |
| return 0 |
| } |
| |
| check_topology_files() { |
| cpu=$1 |
| topology_files_dir=$CPU_PATH/$cpu/topology |
| shift 1 |
| |
| for i in $@; do |
| check_file $i $topology_files_dir || return 1 |
| done |
| |
| return 0 |
| } |
| |
| check_cpuhotplug_files() { |
| |
| cpuhotplug_files_dir=$CPU_PATH/$1 |
| shift 1 |
| |
| for i in $@; do |
| if [ `echo $cpuhotplug_files_dir | grep -c "cpu0"` -eq 1 ]; then |
| if [ $hotplug_allow_cpu0 -eq 0 ]; then |
| continue |
| fi |
| fi |
| |
| check_file $i $cpuhotplug_files_dir || return 1 |
| done |
| |
| return 0 |
| } |
| |
| save_governors() { |
| |
| index=0 |
| |
| for cpu in $cpus; do |
| scaling_gov_value=$(cat $CPU_PATH/$cpu/cpufreq/scaling_governor) |
| eval $gov_array$index=$scaling_gov_value |
| eval export $gov_array$index |
| index=$((index + 1)) |
| done |
| } |
| |
| restore_governors() { |
| |
| index=0 |
| |
| for cpu in $cpus; do |
| oldgov=$(eval echo \$$gov_array$index) |
| echo $oldgov > $CPU_PATH/$cpu/cpufreq/scaling_governor |
| index=$((index + 1)) |
| done |
| } |
| |
| save_frequencies() { |
| |
| index=0 |
| |
| for cpu in $cpus; do |
| freq_value=$(cat $CPU_PATH/$cpu/cpufreq/scaling_cur_freq) |
| eval $freq_array$index=$freq_value |
| eval export $freq_array$index |
| done |
| } |
| |
| restore_frequencies() { |
| |
| index=0 |
| |
| for cpu in $cpus; do |
| oldfreq=$(eval echo \$$freq_array$index) |
| echo $oldfreq > $CPU_PATH/$cpu/cpufreq/scaling_setspeed |
| index=$((index + 1)) |
| done |
| } |
| |
| sigtrap() { |
| exit 255 |
| } |
| |
| # currently we support ubuntu and android |
| get_os() { |
| build_prop_file="\system\build.prop" |
| |
| if [ ! -e "$build_prop_file" ]; then |
| # for ubuntu |
| return 1 |
| else |
| # for android |
| return 2 |
| fi |
| } |
| |
| is_root() { |
| get_os |
| if [ $? -eq 1 ]; then |
| # for ubuntu |
| ret=$(id -u) |
| else |
| # for android |
| ret=$(id | awk '{if ($1) print $1}' | sed 's/[^0-9]*//g') |
| fi |
| return $ret |
| } |
| |
| is_cpu0_hotplug_allowed() { |
| status=$1 |
| |
| if [ $status -eq 1 ]; then |
| return 0 |
| else |
| return 1 |
| fi |
| } |
| |
| check_valid_temp() { |
| file=$1 |
| zone_name=$2 |
| dir=$THERMAL_PATH/$zone_name |
| |
| temp_file=$dir/$file |
| shift 2; |
| |
| temp_val=$(cat $temp_file) |
| descr="'$zone_name'/'$file' ='$temp_val'" |
| log_begin "checking $descr" |
| |
| if [ $temp_val -gt 0 ]; then |
| log_end "Ok" |
| return 0 |
| fi |
| |
| log_end "Err" |
| |
| return 1 |
| } |
| |
| for_each_thermal_zone() { |
| thermal_zones=$(ls $THERMAL_PATH | grep "thermal_zone['$MAX_ZONE']") |
| thermal_func=$1 |
| shift 1 |
| |
| for thermal_zone in $thermal_zones; do |
| INC=0 |
| $thermal_func $thermal_zone $@ |
| done |
| |
| return 0 |
| } |
| |
| get_total_trip_point_of_zone() { |
| zone=$1 |
| zone_path=$THERMAL_PATH/$zone |
| count=0 |
| shift 1 |
| trips=$(ls $zone_path | grep "trip_point_['$MAX_ZONE']_temp") |
| for trip in $trips; do |
| count=$((count + 1)) |
| done |
| return $count |
| } |
| |
| for_each_trip_point_of_zone() { |
| |
| zone_path=$THERMAL_PATH/$1 |
| count=0 |
| func=$2 |
| zone_name=$1 |
| shift 2 |
| trips=$(ls $zone_path | grep "trip_point_['$MAX_ZONE']_temp") |
| for trip in $trips; do |
| $func $zone_name $count |
| count=$((count + 1)) |
| done |
| return 0 |
| } |
| |
| for_each_binding_of_zone() { |
| |
| zone_path=$THERMAL_PATH/$1 |
| count=0 |
| func=$2 |
| zone_name=$1 |
| shift 2 |
| trips=$(ls $zone_path | grep "cdev['$MAX_CDEV']_trip_point") |
| for trip in $trips; do |
| $func $zone_name $count |
| count=$((count + 1)) |
| done |
| |
| return 0 |
| |
| } |
| |
| check_valid_binding() { |
| trip_point=$1 |
| zone_name=$2 |
| dirpath=$THERMAL_PATH/$zone_name |
| temp_file=$zone_name/$trip_point |
| trip_point_val=$(cat $dirpath/$trip_point) |
| get_total_trip_point_of_zone $zone_name |
| trip_point_max=$? |
| descr="'$temp_file' valid binding" |
| shift 2 |
| |
| log_begin "checking $descr" |
| if [ $trip_point_val -ge $trip_point_max ]; then |
| log_end "Err" |
| return 1 |
| fi |
| |
| log_end "Ok" |
| return 0 |
| } |
| |
| validate_trip_bindings() { |
| zone_name=$1 |
| bind_no=$2 |
| dirpath=$THERMAL_PATH/$zone_name |
| trip_point=cdev"$bind_no"_trip_point |
| shift 2 |
| |
| check_file $trip_point $dirpath || return 1 |
| check_valid_binding $trip_point $zone_name || return 1 |
| } |
| |
| validate_trip_level() { |
| zone_name=$1 |
| trip_no=$2 |
| dirpath=$THERMAL_PATH/$zone_name |
| trip_temp=trip_point_"$trip_no"_temp |
| trip_type=trip_point_"$trip_no"_type |
| shift 2 |
| |
| check_file $trip_temp $dirpath || return 1 |
| check_file $trip_type $dirpath || return 1 |
| check_valid_temp $trip_temp $zone_name || return 1 |
| } |
| |
| for_each_cooling_device() { |
| |
| cdev_func=$1 |
| shift 1 |
| |
| cooling_devices=$(ls $THERMAL_PATH | grep "cooling_device['$MAX_CDEV']") |
| if [ "$cooling_devices" = "" ]; then |
| log_skip "no cooling devices" |
| return 0 |
| fi |
| |
| for cooling_device in $cooling_devices; do |
| INC=0 |
| $cdev_func $cooling_device $@ |
| done |
| |
| return 0 |
| } |
| check_scaling_freq() { |
| |
| before_freq_list=$1 |
| after_freq_list=$2 |
| shift 2 |
| index=0 |
| |
| flag=0 |
| for cpu in $cpus; do |
| after_freq=$(eval echo \$$after_freq_list$index) |
| before_freq=$(eval echo \$$before_freq_list$index) |
| |
| if [ $after_freq -ne $before_freq ]; then |
| flag=1 |
| fi |
| |
| index=$((index + 1)) |
| done |
| |
| return $flag |
| } |
| |
| store_scaling_maxfreq() { |
| index=0 |
| |
| for cpu in $cpus; do |
| scaling_freq_max_value=$(cat $CPU_PATH/$cpu/cpufreq/scaling_max_freq) |
| eval $scaling_freq_array$index=$scaling_freq_max_value |
| eval export $scaling_freq_array$index |
| |
| index=$((index + 1)) |
| done |
| |
| return 0 |
| } |
| |
| get_trip_id() { |
| |
| trip_name=$1 |
| shift 1 |
| |
| id1=$(echo $trip_name|cut -c12) |
| id2=$(echo $trip_name|cut -c13) |
| if [ $id2 != "_" ]; then |
| id1=$(($id2 + 10*$id1)) |
| fi |
| return $id1 |
| } |
| |
| disable_all_thermal_zones() { |
| thermal_zones=$(ls $THERMAL_PATH | grep "thermal_zone['$MAX_ZONE']") |
| index=0 |
| |
| for thermal_zone in $thermal_zones; do |
| mode=$(cat $THERMAL_PATH/$thermal_zone/mode) |
| eval $mode_array$index=$mode |
| eval export $mode_array$index |
| index=$((index + 1)) |
| echo -n "disabled" > $THERMAL_PATH/$thermal_zone/mode |
| done |
| |
| return 0 |
| } |
| |
| enable_all_thermal_zones() { |
| thermal_zones=$(ls $THERMAL_PATH | grep "thermal_zone['$MAX_ZONE']") |
| index=0 |
| |
| for thermal_zone in $thermal_zones; do |
| mode=$(eval echo \$$mode_array$index) |
| echo $mode > $THERMAL_PATH/$thermal_zone/mode |
| index=$((index + 1)) |
| done |
| |
| return 0 |
| } |
| |
| GPU_HEAT_BIN=/usr/bin/glmark2 |
| gpu_pid=0 |
| |
| check_for_glmark2() { |
| glmark2_found=$(which glmark2) |
| |
| if [ $? -ne 0 ]; then |
| return 1 |
| else |
| return 0 |
| fi |
| } |
| |
| start_glmark2() { |
| if [ -n "$ANDROID" ]; then |
| am start org.linaro.glmark2/.Glmark2Activity |
| return |
| fi |
| |
| if [ -x $GPU_HEAT_BIN ]; then |
| $GPU_HEAT_BIN & |
| gpu_pid=$(pidof $GPU_HEAT_BIN) |
| # Starting X application from serial console needs this |
| if [ -z "$gpu_pid" ]; then |
| cp /etc/lightdm/lightdm.conf /etc/lightdm/lightdm.conf.bk |
| echo "autologin-user=root" >> /etc/lightdm/lightdm.conf |
| export DISPLAY=localhost:0.0 |
| restart lightdm |
| sleep 5 |
| mv /etc/lightdm/lightdm.conf.bk /etc/lightdm/lightdm.conf |
| $GPU_HEAT_BIN & |
| gpu_pid=$(pidof $GPU_HEAT_BIN) |
| fi |
| test -z "$gpu_pid" && cpu_pid=0 |
| echo "start gpu heat binary $gpu_pid" |
| else |
| echo "glmark2 not found." 1>&2 |
| fi |
| } |
| |
| kill_glmark2() { |
| if [ -n "$ANDROID" ]; then |
| am kill org.linaro.glmark2 |
| return |
| fi |
| |
| if [ "$gpu_pid" -ne 0 ]; then |
| kill -9 $gpu_pid |
| fi |
| } |
| |
| set_thermal_governors() { |
| thermal_zones=$(ls $THERMAL_PATH | grep "thermal_zone['$MAX_ZONE']") |
| gov=$1 |
| index=0 |
| |
| for thermal_zone in $thermal_zones; do |
| policy=$(cat $THERMAL_PATH/$thermal_zone/policy) |
| eval $thermal_gov_array$index=$policy |
| eval export $thermal_gov_array$index |
| index=$((index + 1)) |
| echo $gov > $THERMAL_PATH/$thermal_zone/policy |
| done |
| |
| return 0 |
| } |
| |
| restore_thermal_governors() { |
| thermal_zones=$(ls $THERMAL_PATH | grep "thermal_zone['$MAX_ZONE']") |
| index=0 |
| |
| for thermal_zone in $thermal_zones; do |
| old_policy=$(eval echo \$$thermal_gov_array$index) |
| echo $old_policy > $THERMAL_PATH/$thermal_zone/policy |
| index=$((index + 1)) |
| done |
| |
| return 0 |
| } |
| |
| check_for_thermal_zones() |
| { |
| thermal_zones=$(ls $THERMAL_PATH | grep "thermal_zone['$MAX_ZONE']" 2>/dev/null) |
| if [ ! -z "$thermal_zones" ]; then |
| return 0 |
| else |
| return 1 |
| fi |
| } |
| |
| check_logdir() |
| { |
| if [ ! -f $LOGDIR ]; then |
| mkdir -p $LOGDIR |
| fi |
| } |
| |
| setup_wakeup_timer () |
| { |
| timeout="$1" |
| |
| # Request wakeup from the RTC or ACPI alarm timers. Set the timeout |
| # at 'now' + $timeout seconds. |
| ctl='/sys/class/rtc/rtc0/wakealarm' |
| if [ -f "$ctl" ]; then |
| # Cancel any outstanding timers. |
| echo "0" >"$ctl" |
| # rtcN/wakealarm can use relative time in seconds |
| echo "+$timeout" >"$ctl" |
| return 0 |
| fi |
| ctl='/proc/acpi/alarm' |
| if [ -f "$ctl" ]; then |
| echo `date '+%F %H:%M:%S' -d '+ '$timeout' seconds'` >"$ctl" |
| return 0 |
| fi |
| |
| echo "no method to awaken machine automatically" 1>&2 |
| exit 1 |
| } |
| |
| suspend_system () |
| { |
| if [ "$dry" -eq 1 ]; then |
| echo "DRY-RUN: suspend machine for $timer_sleep" |
| sleep 1 |
| return |
| fi |
| |
| setup_wakeup_timer "$timer_sleep" |
| |
| dmesg >"$LOGFILE.dmesg.A" |
| |
| # Initiate suspend in different ways. |
| case "$1" in |
| dbus) |
| dbus-send --session --type=method_call \ |
| --dest=org.freedesktop.PowerManagement \ |
| /org/freedesktop/PowerManagement \ |
| org.freedesktop.PowerManagement.Suspend \ |
| >> "$LOGFILE" || { |
| ECHO "FAILED: dbus suspend failed" 1>&2 |
| return 1 |
| } |
| ;; |
| pmsuspend) |
| pm-suspend >> "$LOGFILE" |
| ;; |
| mem) |
| `echo "mem" > /sys/power/state` >> "$LOGFILE" |
| ;; |
| esac |
| |
| # Wait on the machine coming back up -- pulling the dmesg over. |
| echo "v---" >>"$LOGFILE" |
| retry=30 |
| while [ "$retry" -gt 0 ]; do |
| retry=$((retry - 1)) |
| |
| # Accumulate the dmesg delta. |
| dmesg >"$LOGFILE.dmesg.B" |
| diff "$LOGFILE.dmesg.A" "$LOGFILE.dmesg.B" | \ |
| grep '^>' >"$LOGFILE.dmesg" |
| mv "$LOGFILE.dmesg.B" "$LOGFILE.dmesg.A" |
| |
| echo "Waiting for suspend to complete $retry to go ..." \ |
| >> "$LOGFILE" |
| cat "$LOGFILE.dmesg" >> "$LOGFILE" |
| |
| if [ "`grep -c 'Back to C!' $LOGFILE.dmesg`" -ne 0 ]; then |
| break; |
| fi |
| sleep 1 |
| done |
| echo "^---" >>"$LOGFILE" |
| rm -f "$LOGFILE.dmesg"* |
| if [ "$retry" -eq 0 ]; then |
| ECHO "SUSPEND FAILED, did not go to sleep" 1>&2 |
| return 1 |
| fi |
| } |
| |
| ECHO () |
| { |
| echo "$@" | tee -a "$LOGFILE" |
| } |
| |
| enable_trace() |
| { |
| if [ -w /sys/power/pm_trace ]; then |
| echo 1 > '/sys/power/pm_trace' |
| fi |
| } |
| |
| disable_trace() |
| { |
| if [ -w /sys/power/pm_trace ]; then |
| echo 0 > '/sys/power/pm_trace' |
| fi |
| } |
| |
| trace_state=-1 |
| |
| save_trace() |
| { |
| if [ -r /sys/power/pm_trace ]; then |
| trace_state=`cat /sys/power/pm_trace` |
| fi |
| } |
| |
| restore_trace() |
| { |
| if [ "$trace_state" -ne -1 -a -w /sys/power/pm_trace ]; then |
| echo "$trace_state" > '/sys/power/pm_trace' |
| fi |
| } |
| |
| battery_count() |
| { |
| cat /proc/acpi/battery/*/state 2>/dev/null | \ |
| awk ' |
| BEGIN { total = 0 } |
| /present:.*yes/ { total += 1 } |
| END { print total } |
| ' |
| } |
| |
| battery_capacity() |
| { |
| cat /proc/acpi/battery/*/state 2>/dev/null | \ |
| awk ' |
| BEGIN { total = 0 } |
| /remaining capacity:/ { total += $3 } |
| END { print total } |
| ' |
| } |
| |
| ac_needed=-1 |
| ac_is=-1 |
| ac_becomes=-1 |
| |
| ac_required() |
| { |
| ac_check |
| |
| ac_needed="$1" |
| ac_becomes="$1" |
| } |
| |
| ac_transitions() |
| { |
| ac_check |
| |
| ac_needed="$1" |
| ac_becomes="$2" |
| } |
| |
| ac_online() |
| { |
| cat /proc/acpi/ac_adapter/*/state 2>/dev/null | \ |
| awk ' |
| BEGIN { online = 0; offline = 0 } |
| /on-line/ { online = 1 } |
| /off-line/ { offline = 1 } |
| END { |
| if (online) { |
| print "1" |
| } else if (offline) { |
| print "0" |
| } else { |
| print "-1" |
| } |
| } |
| ' |
| } |
| |
| ac_check() |
| { |
| ac_current=`ac_online` |
| |
| if [ "$ac_becomes" -ne -1 -a "$ac_current" -ne -1 -a \ |
| "$ac_current" -ne "$ac_becomes" ]; then |
| ECHO "*** WARNING: AC power not in expected state" \ |
| "($ac_becomes) after test" |
| fi |
| ac_is="$ac_becomes" |
| } |
| |
| phase=0 |
| phase_first=1 |
| phase_interactive=1 |
| |
| phase() |
| { |
| phase=$((phase + 1)) |
| |
| if [ "$ac_needed" -ne "$ac_is" ]; then |
| case "$ac_needed" in |
| 0) echo "*** please ensure your AC cord is detached" ;; |
| 1) echo "*** please ensure your AC cord is attached" ;; |
| esac |
| ac_is="$ac_needed" |
| fi |
| |
| if [ "$timer_sleep" -gt 60 ]; then |
| sleep="$timer_sleep / 60" |
| sleep="$sleep minutes" |
| else |
| sleep="$timer_sleep seconds" |
| fi |
| echo "*** machine will suspend for $sleep" |
| |
| if [ "$auto" -eq 1 ]; then |
| : |
| elif [ "$phase_interactive" -eq 1 ]; then |
| echo "*** press return when ready" |
| read x |
| |
| elif [ "$phase_first" -eq 1 ]; then |
| echo "*** NOTE: there will be no further user interaction from this point" |
| echo "*** press return when ready" |
| phase_first=0 |
| read x |
| fi |
| } |
| |
| save_trace |
| |
| if [ "$pm_trace" -eq 1 ]; then |
| enable_trace |
| else |
| disable_trace |
| fi |