aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2015-01-09 10:29:07 +0530
committerViresh Kumar <viresh.kumar@linaro.org>2015-01-09 14:30:25 +0530
commit0ffa7e0aade150bb9911b13f7fccda172da24498 (patch)
tree353d54cd01a25dd89ec319ecd27916428ad901db
cpufreq-tets: Initial git repo
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r--.gitignore5
-rw-r--r--README16
-rwxr-xr-xcpu.sh84
-rwxr-xr-xcpufreq.sh194
-rwxr-xr-xgovernor.sh86
-rwxr-xr-xrunme.sh51
-rwxr-xr-xspecial-tests.sh60
7 files changed, 496 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e2f3646
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+*.swp
+.tmp_versions
+cscope.*
+ncscope.*
+*.patch
diff --git a/README b/README
new file mode 100644
index 0000000..789eb7e
--- /dev/null
+++ b/README
@@ -0,0 +1,16 @@
+CPUFREQ SANITY TESTS
+====================
+
+This does a variety of tests to test cpufreq frameworks again bugs.
+
+Examples:
+- hoplugging CPUs in and out.
+- switching governors.
+- switching frequencies after setting to userspace governor (if available).
+- Showing content of all cpufreq files.
+- And finally dumping all debug messages in: ${1-debug}.txt and ${1-debug}.full.txt.
+
+How to run:
+==========
+
+./runme.sh <output-file-name>
diff --git a/cpu.sh b/cpu.sh
new file mode 100755
index 0000000..b5b0620
--- /dev/null
+++ b/cpu.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+#
+# CPU helpers
+
+source cpufreq.sh
+
+offline_cpu()
+{
+ echo 0 > /sys/devices/system/cpu/$1/online
+}
+
+online_cpu()
+{
+ echo 1 > /sys/devices/system/cpu/$1/online
+}
+
+offline_online_cpu()
+{
+ offline_cpu $1
+ online_cpu $1
+}
+
+# Offline + online CPUs
+# param: number of times we want to run the loop
+hotplug_1_by_1()
+{
+ echo "** Test: Running ${FUNCNAME[0]} for $1 loops **"
+ echo ""
+
+ for i in `seq 1 $1`; do
+ for_each_non_boot_cpu offline_online_cpu
+ done
+ echo "------------------------------------------------"
+ echo ""
+}
+
+# Offline all CPUs, followed by online all CPUs
+# param: number of times we want to run the loop
+hotplug_together()
+{
+ echo "** Test: Running ${FUNCNAME[0]} for $1 loops **"
+ echo ""
+
+ for i in `seq 1 $1`; do
+ for_each_non_boot_cpu offline_cpu
+ for_each_non_boot_cpu online_cpu
+ done
+ echo "------------------------------------------------"
+ echo ""
+}
+
+for_each_cpu() {
+ cpus=$(ls $CPU_PATH | grep "cpu[0-9].*")
+ for cpu in $cpus; do
+ $@ $cpu
+ done
+}
+
+for_each_non_boot_cpu() {
+ cpus=$(ls $CPU_PATH | grep "cpu[1-9].*")
+ for cpu in $cpus; do
+ $@ $cpu
+ done
+}
+
+# Prints warning for all CPUs with missing cpufreq directory
+print_unmanaged_cpus()
+{
+ for_each_cpu cpu_has_cpufreq_directory
+}
+
+# Counts CPUs with cpufreq directories
+count_cpufreq_managed_cpus()
+{
+ count=0;
+
+ for cpu in `ls $CPU_PATH | grep "cpu[0-9].*"`; do
+ if [ -d /sys/devices/system/cpu/$cpu/cpufreq ]; then
+ let count=count+1;
+ fi
+ done
+
+ echo $count;
+}
diff --git a/cpufreq.sh b/cpufreq.sh
new file mode 100755
index 0000000..2bb3f4e
--- /dev/null
+++ b/cpufreq.sh
@@ -0,0 +1,194 @@
+#!/bin/bash
+
+source cpu.sh
+
+# GLOBALS
+CPU_PATH="/sys/devices/system/cpu"
+GLOBAL_CPUFREQ="/sys/devices/system/cpu/cpufreq"
+
+
+# GENERIC HELPERS
+# $1: cpu
+cpu_has_cpufreq_directory()
+{
+ if [ ! -d /sys/devices/system/cpu/$1/cpufreq ]; then
+ echo "Warning: No cpufreq directory present for $1"
+ fi
+}
+
+
+# READ CPUFREQ FILES
+
+# $1: directory path
+__read_cpufreq_files()
+{
+ local filepath=$1
+
+ # Exit if cpu isn't mananged by cpufreq core
+ if [ ! -d $filepath ]; then
+ return;
+ fi
+
+ local files=`ls $filepath`
+
+ echo "Printing directory: $filepath"
+ echo ""
+
+ for file in $files; do
+ if [ -f $filepath/$file ]; then
+ echo "$file:"
+ cat $filepath/$file
+ else
+ echo ""
+ __read_cpufreq_files "$filepath/$file"
+ fi
+ done
+
+ echo ""
+}
+
+# $1: directory path
+# $2: cpu
+read_cpufreq_files_for_cpu()
+{
+ local filepath=$CPU_PATH/$2/$1
+
+ __read_cpufreq_files $filepath
+}
+
+read_all_cpufreq_files()
+{
+ echo "** Test: Running ${FUNCNAME[0]} **"
+ echo ""
+
+ __read_cpufreq_files $GLOBAL_CPUFREQ
+ echo ""
+
+ for_each_cpu read_cpufreq_files_for_cpu "cpufreq"
+ echo "------------------------------------------------"
+ echo ""
+}
+
+
+# UPDATE CPUFREQ FILES
+
+# $1: directory path
+__update_cpufreq_files()
+{
+ local filepath=$1
+
+ # Exit if cpu isn't mananged by cpufreq core
+ if [ ! -d $filepath ]; then
+ return;
+ fi
+
+ local files=`ls $filepath`
+
+ echo "Updating directory: $filepath"
+ echo ""
+
+ for file in $files; do
+ if [ -f $filepath/$file ]; then
+ # file is writable ?
+ local wfile=$(ls -l $filepath/$file | awk '$1 ~ /^.*w.*/ { print $NF; }')
+ if [ ! -z $wfile ]; then
+ local val=$(cat $filepath/$file)
+ echo "Writing $val to: $file"
+ echo $val > $filepath/$file
+ fi
+ else
+ echo ""
+ __update_cpufreq_files "$filepath/$file"
+ fi
+ done
+
+ echo ""
+}
+
+# $1: directory path
+# $2: cpu
+update_cpufreq_files_for_cpu()
+{
+ local filepath=$CPU_PATH/$2/$1
+
+ __update_cpufreq_files $filepath
+}
+
+# Update all writable files with their existing values
+update_all_cpufreq_files()
+{
+ echo "** Test: Running ${FUNCNAME[0]} **"
+ echo ""
+
+ __update_cpufreq_files $GLOBAL_CPUFREQ
+ echo ""
+
+ for_each_cpu update_cpufreq_files_for_cpu "cpufreq"
+ echo "------------------------------------------------"
+ echo ""
+}
+
+
+# CHANGE CPU FREQUENCIES
+
+# $1: cpu
+# $2: frequency
+set_cpu_frequency()
+{
+ echo $2 > $CPU_PATH/$1/cpufreq/scaling_setspeed
+}
+
+# $1: cpu
+test_all_cpu_frequencies()
+{
+ local filepath="$CPU_PATH/$1/cpufreq"
+
+ # Exit if cpu isn't mananged by cpufreq core
+ if [ ! -d $filepath ]; then
+ return;
+ fi
+
+ local found=$(switch_governor $1 "userspace")
+ if [ $found = 1 ]; then
+ echo "${FUNCNAME[0]}: userspace governor not available for: $1"
+ return;
+ else
+ echo "Switching governor for $1 to userspace"
+ fi
+
+ local freqs=$(cat $filepath/scaling_available_frequencies)
+ echo "Available frequencies for $1: $freqs"
+
+ # Set all frequencies one-by-one
+ for freq in $freqs; do
+ set_cpu_frequency $1 $freq
+ done
+}
+
+# $1: loop count
+shuffle_frequency_for_all_cpus()
+{
+ echo "** Test: Running ${FUNCNAME[0]} for $1 loops **"
+ echo ""
+
+ for i in `seq 1 $1`; do
+ for_each_cpu test_all_cpu_frequencies
+ done
+ echo "------------------------------------------------"
+ echo ""
+}
+
+# Calls the routine $1 passed to it and dumps all messages in:
+# - script output: $2.txt
+# - cpufreq messages: $2.cpufreq.txt
+# - complete dmesg: $2.full.txt
+call_routine()
+{
+ # call routine
+ $1 > $2.txt
+
+ dmesg | grep cpufreq > $2.cpufreq.txt
+
+ # We may need the full logs as well
+ dmesg --read-clear > $2.full.txt
+}
diff --git a/governor.sh b/governor.sh
new file mode 100755
index 0000000..1c56426
--- /dev/null
+++ b/governor.sh
@@ -0,0 +1,86 @@
+#!/bin/bash
+#
+# Test governors
+
+source cpu.sh
+source cpufreq.sh
+
+# Find governor's directory path
+# $1: cpu, $2: governor
+find_gov_directory()
+{
+ if [ -d $GLOBAL_CPUFREQ -a -d $GLOBAL_CPUFREQ/$2 ]; then
+ echo "$GLOBAL_CPUFREQ/$2"
+ elif [ -d $CPU_PATH/$1/cpufreq -a -d $CPU_PATH/$1/cpufreq/$2 ]; then
+ echo "$CPU_PATH/$1/cpufreq/$2"
+ fi
+}
+
+# SWITCH GOVERNORS
+
+# param:
+# $1: cpu, $2: governor
+__switch_governor()
+{
+ echo $2 > $CPU_PATH/$1/cpufreq/scaling_governor
+}
+
+# $1: cpu, $2: governor
+switch_governor()
+{
+ local filepath=$CPU_PATH/$1/cpufreq/scaling_available_governors
+
+ # check if governor is available
+ local found=$(cat $filepath | grep $2 | wc -l)
+ if [ $found = 0 ]; then
+ echo 1;
+ return
+ fi
+
+ __switch_governor $1 $2
+ echo 0;
+}
+
+# $1: cpu, $2: governor
+switch_show_governor()
+{
+ # switch governor
+ __switch_governor $1 $2
+
+ # show governor files
+ local govpath=$(find_gov_directory $1 $2)
+
+ if [ ! -z $govpath ]; then
+ __read_cpufreq_files $govpath
+ fi
+}
+
+# $1: function to be called, $2: cpu
+call_for_each_governor() {
+ local filepath=$CPU_PATH/$2/cpufreq/scaling_available_governors
+
+ # Exit if cpu isn't mananged by cpufreq core
+ if [ ! -f $filepath ]; then
+ return;
+ fi
+
+ local governors=$(cat $filepath)
+ echo "Available governors for $2: $governors"
+
+ for governor in $governors; do
+ $1 $2 $governor
+ done
+}
+
+# $1: loop count
+shuffle_governors_for_all_cpus()
+{
+ echo "** Test: Running ${FUNCNAME[0]} for $1 loops **"
+ echo ""
+
+ for i in `seq 1 $1`; do
+ for_each_cpu call_for_each_governor switch_show_governor
+ done
+ echo "------------------------------------------------"
+ echo ""
+}
diff --git a/runme.sh b/runme.sh
new file mode 100755
index 0000000..b4889a6
--- /dev/null
+++ b/runme.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+# parameters:
+# - $1: Name of the output file with all the logs, dump.txt by default.
+
+source cpu.sh
+source governor.sh
+source special-tests.sh
+
+OUTFILE=${1-dump}
+
+cpufreq_test()
+{
+ echo "*** RUNNING CPUFREQ SANITY TESTS ***"
+ echo "===================================="
+ echo ""
+
+ count=$(count_cpufreq_managed_cpus)
+ if [ $count = 0 ]; then
+ echo "No cpu is managed by cpufreq core, exiting"
+ exit;
+ else
+ echo "CPUFreq manages: $count CPUs"
+ echo ""
+ fi
+
+ # Detect & print which CPUs aren't managed by cpufreq
+ print_unmanaged_cpus
+
+ # read/update all cpufreq files
+ read_all_cpufreq_files
+ update_all_cpufreq_files
+
+ # hotplug cpus
+ hotplug_1_by_1 5
+ hotplug_together 5
+
+ # Test all governors
+ shuffle_governors_for_all_cpus 1
+
+ # Test all frequencies
+ shuffle_frequency_for_all_cpus 2
+}
+
+# Check validity of arguments
+if [ "$1" = "-h" -o "$1" = "--help" ]; then
+ echo "Usage: $0 <output-file-for-kernel-dumps>"
+ exit
+fi
+
+call_routine cpufreq_test $OUTFILE
diff --git a/special-tests.sh b/special-tests.sh
new file mode 100755
index 0000000..b29f644
--- /dev/null
+++ b/special-tests.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+#
+# Special test cases reported by people
+
+# Testcase 1: Reported here: http://marc.info/?l=linux-pm&m=140618592709858&w=2
+
+source cpu.sh
+source cpufreq.sh
+source governor.sh
+
+quick_shuffle_test1()
+{
+ # this is called concurrently from governor_race_test
+ for I in `seq 1000`
+ do
+ echo ondemand | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor &
+ echo userspace | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor &
+ done
+}
+
+governor_race_test()
+{
+ echo "** Test: Running ${FUNCNAME[0]} **"
+ echo ""
+
+ # run 8 concurrent instances
+ for I in `seq 8`
+ do
+ quick_shuffle_test1 &
+ done
+}
+
+# $1: cpu
+__simple_lockdep()
+{
+ # switch to ondemand
+ __switch_governor $1 "ondemand"
+
+ # cat ondemand files
+ local ondir=$(find_gov_directory $1 "ondemand")
+ if [ -z $ondir ]; then
+ echo "${FUNCNAME[0]}Ondemand directory not created, quit"
+ return
+ fi
+
+ cat $ondir/*
+
+ # switch to conservative
+ __switch_governor $1 "conservative"
+}
+
+simple_lockdep()
+{
+ echo "** Test: Running ${FUNCNAME[0]} **"
+ echo ""
+
+ for_each_cpu __simple_lockdep
+}
+simple_lockdep
+governor_race_test