diff options
author | Viresh Kumar <viresh.kumar@linaro.org> | 2017-01-13 01:36:45 -0500 |
---|---|---|
committer | Shuah Khan <shuahkh@osg.samsung.com> | 2017-01-19 12:32:05 -0500 |
commit | e66d5b673741cf6b7da250da9f84a165b1e4342d (patch) | |
tree | 8f9208141d6680a61dfe931544cf0e19b8a7b242 /tools | |
parent | 6320303fb27ae46919c13b2f9ebf3f3a3ad63859 (diff) |
selftest: cpufreq: Add support for cpufreq tests
This patch adds supports for basic cpufreq tests, which can be performed
independent of any platform.
It does basic tests for now, like
- reading all cpufreq files
- trying to update them
- switching frequencies
- switching governors
This can be extended to have more specific tests later on.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/testing/selftests/Makefile | 1 | ||||
-rw-r--r-- | tools/testing/selftests/cpufreq/Makefile | 8 | ||||
-rwxr-xr-x | tools/testing/selftests/cpufreq/cpu.sh | 84 | ||||
-rwxr-xr-x | tools/testing/selftests/cpufreq/cpufreq.sh | 201 | ||||
-rwxr-xr-x | tools/testing/selftests/cpufreq/governor.sh | 146 | ||||
-rwxr-xr-x | tools/testing/selftests/cpufreq/main.sh | 128 |
6 files changed, 568 insertions, 0 deletions
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index c6ccf57f2cb5..e23bed2e2e94 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile | |||
@@ -1,6 +1,7 @@ | |||
1 | TARGETS = bpf | 1 | TARGETS = bpf |
2 | TARGETS += breakpoints | 2 | TARGETS += breakpoints |
3 | TARGETS += capabilities | 3 | TARGETS += capabilities |
4 | TARGETS += cpufreq | ||
4 | TARGETS += cpu-hotplug | 5 | TARGETS += cpu-hotplug |
5 | TARGETS += efivarfs | 6 | TARGETS += efivarfs |
6 | TARGETS += exec | 7 | TARGETS += exec |
diff --git a/tools/testing/selftests/cpufreq/Makefile b/tools/testing/selftests/cpufreq/Makefile new file mode 100644 index 000000000000..f5c6bb1965a1 --- /dev/null +++ b/tools/testing/selftests/cpufreq/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | all: | ||
2 | |||
3 | TEST_PROGS := main.sh | ||
4 | TEST_FILES := cpu.sh cpufreq.sh governor.sh | ||
5 | |||
6 | include ../lib.mk | ||
7 | |||
8 | clean: | ||
diff --git a/tools/testing/selftests/cpufreq/cpu.sh b/tools/testing/selftests/cpufreq/cpu.sh new file mode 100755 index 000000000000..8e08a83d65f2 --- /dev/null +++ b/tools/testing/selftests/cpufreq/cpu.sh | |||
@@ -0,0 +1,84 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # CPU helpers | ||
4 | |||
5 | # protect against multiple inclusion | ||
6 | if [ $FILE_CPU ]; then | ||
7 | return 0 | ||
8 | else | ||
9 | FILE_CPU=DONE | ||
10 | fi | ||
11 | |||
12 | source cpufreq.sh | ||
13 | |||
14 | for_each_cpu() | ||
15 | { | ||
16 | cpus=$(ls $CPUROOT | grep "cpu[0-9].*") | ||
17 | for cpu in $cpus; do | ||
18 | $@ $cpu | ||
19 | done | ||
20 | } | ||
21 | |||
22 | for_each_non_boot_cpu() | ||
23 | { | ||
24 | cpus=$(ls $CPUROOT | grep "cpu[1-9].*") | ||
25 | for cpu in $cpus; do | ||
26 | $@ $cpu | ||
27 | done | ||
28 | } | ||
29 | |||
30 | #$1: cpu | ||
31 | offline_cpu() | ||
32 | { | ||
33 | printf "Offline $1\n" | ||
34 | echo 0 > $CPUROOT/$1/online | ||
35 | } | ||
36 | |||
37 | #$1: cpu | ||
38 | online_cpu() | ||
39 | { | ||
40 | printf "Online $1\n" | ||
41 | echo 1 > $CPUROOT/$1/online | ||
42 | } | ||
43 | |||
44 | #$1: cpu | ||
45 | reboot_cpu() | ||
46 | { | ||
47 | offline_cpu $1 | ||
48 | online_cpu $1 | ||
49 | } | ||
50 | |||
51 | # Reboot CPUs | ||
52 | # param: number of times we want to run the loop | ||
53 | reboot_cpus() | ||
54 | { | ||
55 | printf "** Test: Running ${FUNCNAME[0]} for $1 loops **\n\n" | ||
56 | |||
57 | for i in `seq 1 $1`; do | ||
58 | for_each_non_boot_cpu offline_cpu | ||
59 | for_each_non_boot_cpu online_cpu | ||
60 | printf "\n" | ||
61 | done | ||
62 | |||
63 | printf "\n%s\n\n" "------------------------------------------------" | ||
64 | } | ||
65 | |||
66 | # Prints warning for all CPUs with missing cpufreq directory | ||
67 | print_unmanaged_cpus() | ||
68 | { | ||
69 | for_each_cpu cpu_should_have_cpufreq_directory | ||
70 | } | ||
71 | |||
72 | # Counts CPUs with cpufreq directories | ||
73 | count_cpufreq_managed_cpus() | ||
74 | { | ||
75 | count=0; | ||
76 | |||
77 | for cpu in `ls $CPUROOT | grep "cpu[0-9].*"`; do | ||
78 | if [ -d $CPUROOT/$cpu/cpufreq ]; then | ||
79 | let count=count+1; | ||
80 | fi | ||
81 | done | ||
82 | |||
83 | echo $count; | ||
84 | } | ||
diff --git a/tools/testing/selftests/cpufreq/cpufreq.sh b/tools/testing/selftests/cpufreq/cpufreq.sh new file mode 100755 index 000000000000..2b8b05aaa874 --- /dev/null +++ b/tools/testing/selftests/cpufreq/cpufreq.sh | |||
@@ -0,0 +1,201 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | # protect against multiple inclusion | ||
4 | if [ $FILE_CPUFREQ ]; then | ||
5 | return 0 | ||
6 | else | ||
7 | FILE_CPUFREQ=DONE | ||
8 | fi | ||
9 | |||
10 | source cpu.sh | ||
11 | |||
12 | |||
13 | # $1: cpu | ||
14 | cpu_should_have_cpufreq_directory() | ||
15 | { | ||
16 | if [ ! -d $CPUROOT/$1/cpufreq ]; then | ||
17 | printf "Warning: No cpufreq directory present for $1\n" | ||
18 | fi | ||
19 | } | ||
20 | |||
21 | cpu_should_not_have_cpufreq_directory() | ||
22 | { | ||
23 | if [ -d $CPUROOT/$1/cpufreq ]; then | ||
24 | printf "Warning: cpufreq directory present for $1\n" | ||
25 | fi | ||
26 | } | ||
27 | |||
28 | for_each_policy() | ||
29 | { | ||
30 | policies=$(ls $CPUFREQROOT| grep "policy[0-9].*") | ||
31 | for policy in $policies; do | ||
32 | $@ $policy | ||
33 | done | ||
34 | } | ||
35 | |||
36 | for_each_policy_concurrent() | ||
37 | { | ||
38 | policies=$(ls $CPUFREQROOT| grep "policy[0-9].*") | ||
39 | for policy in $policies; do | ||
40 | $@ $policy & | ||
41 | done | ||
42 | } | ||
43 | |||
44 | # $1: Path | ||
45 | read_cpufreq_files_in_dir() | ||
46 | { | ||
47 | local files=`ls $1` | ||
48 | |||
49 | printf "Printing directory: $1\n\n" | ||
50 | |||
51 | for file in $files; do | ||
52 | if [ -f $1/$file ]; then | ||
53 | printf "$file:" | ||
54 | cat $1/$file | ||
55 | else | ||
56 | printf "\n" | ||
57 | read_cpufreq_files_in_dir "$1/$file" | ||
58 | fi | ||
59 | done | ||
60 | printf "\n" | ||
61 | } | ||
62 | |||
63 | |||
64 | read_all_cpufreq_files() | ||
65 | { | ||
66 | printf "** Test: Running ${FUNCNAME[0]} **\n\n" | ||
67 | |||
68 | read_cpufreq_files_in_dir $CPUFREQROOT | ||
69 | |||
70 | printf "%s\n\n" "------------------------------------------------" | ||
71 | } | ||
72 | |||
73 | |||
74 | # UPDATE CPUFREQ FILES | ||
75 | |||
76 | # $1: directory path | ||
77 | update_cpufreq_files_in_dir() | ||
78 | { | ||
79 | local files=`ls $1` | ||
80 | |||
81 | printf "Updating directory: $1\n\n" | ||
82 | |||
83 | for file in $files; do | ||
84 | if [ -f $1/$file ]; then | ||
85 | # file is writable ? | ||
86 | local wfile=$(ls -l $1/$file | awk '$1 ~ /^.*w.*/ { print $NF; }') | ||
87 | |||
88 | if [ ! -z $wfile ]; then | ||
89 | # scaling_setspeed is a special file and we | ||
90 | # should skip updating it | ||
91 | if [ $file != "scaling_setspeed" ]; then | ||
92 | local val=$(cat $1/$file) | ||
93 | printf "Writing $val to: $file\n" | ||
94 | echo $val > $1/$file | ||
95 | fi | ||
96 | fi | ||
97 | else | ||
98 | printf "\n" | ||
99 | update_cpufreq_files_in_dir "$1/$file" | ||
100 | fi | ||
101 | done | ||
102 | |||
103 | printf "\n" | ||
104 | } | ||
105 | |||
106 | # Update all writable files with their existing values | ||
107 | update_all_cpufreq_files() | ||
108 | { | ||
109 | printf "** Test: Running ${FUNCNAME[0]} **\n\n" | ||
110 | |||
111 | update_cpufreq_files_in_dir $CPUFREQROOT | ||
112 | |||
113 | printf "%s\n\n" "------------------------------------------------" | ||
114 | } | ||
115 | |||
116 | |||
117 | # CHANGE CPU FREQUENCIES | ||
118 | |||
119 | # $1: policy | ||
120 | find_current_freq() | ||
121 | { | ||
122 | cat $CPUFREQROOT/$1/scaling_cur_freq | ||
123 | } | ||
124 | |||
125 | # $1: policy | ||
126 | # $2: frequency | ||
127 | set_cpu_frequency() | ||
128 | { | ||
129 | printf "Change frequency for $1 to $2\n" | ||
130 | echo $2 > $CPUFREQROOT/$1/scaling_setspeed | ||
131 | } | ||
132 | |||
133 | # $1: policy | ||
134 | test_all_frequencies() | ||
135 | { | ||
136 | local filepath="$CPUFREQROOT/$1" | ||
137 | |||
138 | backup_governor $1 | ||
139 | |||
140 | local found=$(switch_governor $1 "userspace") | ||
141 | if [ $found = 1 ]; then | ||
142 | printf "${FUNCNAME[0]}: userspace governor not available for: $1\n" | ||
143 | return; | ||
144 | fi | ||
145 | |||
146 | printf "Switched governor for $1 to userspace\n\n" | ||
147 | |||
148 | local freqs=$(cat $filepath/scaling_available_frequencies) | ||
149 | printf "Available frequencies for $1: $freqs\n\n" | ||
150 | |||
151 | # Set all frequencies one-by-one | ||
152 | for freq in $freqs; do | ||
153 | set_cpu_frequency $1 $freq | ||
154 | done | ||
155 | |||
156 | printf "\n" | ||
157 | |||
158 | restore_governor $1 | ||
159 | } | ||
160 | |||
161 | # $1: loop count | ||
162 | shuffle_frequency_for_all_cpus() | ||
163 | { | ||
164 | printf "** Test: Running ${FUNCNAME[0]} for $1 loops **\n\n" | ||
165 | |||
166 | for i in `seq 1 $1`; do | ||
167 | for_each_policy test_all_frequencies | ||
168 | done | ||
169 | printf "\n%s\n\n" "------------------------------------------------" | ||
170 | } | ||
171 | |||
172 | # Basic cpufreq tests | ||
173 | cpufreq_basic_tests() | ||
174 | { | ||
175 | printf "*** RUNNING CPUFREQ SANITY TESTS ***\n" | ||
176 | printf "====================================\n\n" | ||
177 | |||
178 | count=$(count_cpufreq_managed_cpus) | ||
179 | if [ $count = 0 ]; then | ||
180 | printf "No cpu is managed by cpufreq core, exiting\n" | ||
181 | exit; | ||
182 | else | ||
183 | printf "CPUFreq manages: $count CPUs\n\n" | ||
184 | fi | ||
185 | |||
186 | # Detect & print which CPUs are not managed by cpufreq | ||
187 | print_unmanaged_cpus | ||
188 | |||
189 | # read/update all cpufreq files | ||
190 | read_all_cpufreq_files | ||
191 | update_all_cpufreq_files | ||
192 | |||
193 | # hotplug cpus | ||
194 | reboot_cpus 5 | ||
195 | |||
196 | # Test all frequencies | ||
197 | shuffle_frequency_for_all_cpus 2 | ||
198 | |||
199 | # Test all governors | ||
200 | shuffle_governors_for_all_cpus 1 | ||
201 | } | ||
diff --git a/tools/testing/selftests/cpufreq/governor.sh b/tools/testing/selftests/cpufreq/governor.sh new file mode 100755 index 000000000000..2e42432892ab --- /dev/null +++ b/tools/testing/selftests/cpufreq/governor.sh | |||
@@ -0,0 +1,146 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Test governors | ||
4 | |||
5 | # protect against multiple inclusion | ||
6 | if [ $FILE_GOVERNOR ]; then | ||
7 | return 0 | ||
8 | else | ||
9 | FILE_GOVERNOR=DONE | ||
10 | fi | ||
11 | |||
12 | source cpu.sh | ||
13 | source cpufreq.sh | ||
14 | |||
15 | CUR_GOV= | ||
16 | CUR_FREQ= | ||
17 | |||
18 | # Find governor's directory path | ||
19 | # $1: policy, $2: governor | ||
20 | find_gov_directory() | ||
21 | { | ||
22 | if [ -d $CPUFREQROOT/$2 ]; then | ||
23 | printf "$CPUFREQROOT/$2\n" | ||
24 | elif [ -d $CPUFREQROOT/$1/$2 ]; then | ||
25 | printf "$CPUFREQROOT/$1/$2\n" | ||
26 | else | ||
27 | printf "INVALID\n" | ||
28 | fi | ||
29 | } | ||
30 | |||
31 | # $1: policy | ||
32 | find_current_governor() | ||
33 | { | ||
34 | cat $CPUFREQROOT/$1/scaling_governor | ||
35 | } | ||
36 | |||
37 | # $1: policy | ||
38 | backup_governor() | ||
39 | { | ||
40 | CUR_GOV=$(find_current_governor $1) | ||
41 | |||
42 | printf "Governor backup done for $1: $CUR_GOV\n" | ||
43 | |||
44 | if [ $CUR_GOV == "userspace" ]; then | ||
45 | CUR_FREQ=$(find_current_freq $1) | ||
46 | printf "Governor frequency backup done for $1: $CUR_FREQ\n" | ||
47 | fi | ||
48 | |||
49 | printf "\n" | ||
50 | } | ||
51 | |||
52 | # $1: policy | ||
53 | restore_governor() | ||
54 | { | ||
55 | __switch_governor $1 $CUR_GOV | ||
56 | |||
57 | printf "Governor restored for $1 to $CUR_GOV\n" | ||
58 | |||
59 | if [ $CUR_GOV == "userspace" ]; then | ||
60 | set_cpu_frequency $1 $CUR_FREQ | ||
61 | printf "Governor frequency restored for $1: $CUR_FREQ\n" | ||
62 | fi | ||
63 | |||
64 | printf "\n" | ||
65 | } | ||
66 | |||
67 | # param: | ||
68 | # $1: policy, $2: governor | ||
69 | __switch_governor() | ||
70 | { | ||
71 | echo $2 > $CPUFREQROOT/$1/scaling_governor | ||
72 | } | ||
73 | |||
74 | # SWITCH GOVERNORS | ||
75 | |||
76 | # $1: cpu, $2: governor | ||
77 | switch_governor() | ||
78 | { | ||
79 | local filepath=$CPUFREQROOT/$1/scaling_available_governors | ||
80 | |||
81 | # check if governor is available | ||
82 | local found=$(cat $filepath | grep $2 | wc -l) | ||
83 | if [ $found = 0 ]; then | ||
84 | echo 1; | ||
85 | return | ||
86 | fi | ||
87 | |||
88 | __switch_governor $1 $2 | ||
89 | echo 0; | ||
90 | } | ||
91 | |||
92 | # $1: policy, $2: governor | ||
93 | switch_show_governor() | ||
94 | { | ||
95 | cur_gov=find_current_governor | ||
96 | if [ $cur_gov == "userspace" ]; then | ||
97 | cur_freq=find_current_freq | ||
98 | fi | ||
99 | |||
100 | # switch governor | ||
101 | __switch_governor $1 $2 | ||
102 | |||
103 | printf "\nSwitched governor for $1 to $2\n\n" | ||
104 | |||
105 | if [ $2 == "userspace" -o $2 == "powersave" -o $2 == "performance" ]; then | ||
106 | printf "No files to read for $2 governor\n\n" | ||
107 | return | ||
108 | fi | ||
109 | |||
110 | # show governor files | ||
111 | local govpath=$(find_gov_directory $1 $2) | ||
112 | read_cpufreq_files_in_dir $govpath | ||
113 | } | ||
114 | |||
115 | # $1: function to be called, $2: policy | ||
116 | call_for_each_governor() | ||
117 | { | ||
118 | local filepath=$CPUFREQROOT/$2/scaling_available_governors | ||
119 | |||
120 | # Exit if cpu isn't managed by cpufreq core | ||
121 | if [ ! -f $filepath ]; then | ||
122 | return; | ||
123 | fi | ||
124 | |||
125 | backup_governor $2 | ||
126 | |||
127 | local governors=$(cat $filepath) | ||
128 | printf "Available governors for $2: $governors\n" | ||
129 | |||
130 | for governor in $governors; do | ||
131 | $1 $2 $governor | ||
132 | done | ||
133 | |||
134 | restore_governor $2 | ||
135 | } | ||
136 | |||
137 | # $1: loop count | ||
138 | shuffle_governors_for_all_cpus() | ||
139 | { | ||
140 | printf "** Test: Running ${FUNCNAME[0]} for $1 loops **\n\n" | ||
141 | |||
142 | for i in `seq 1 $1`; do | ||
143 | for_each_policy call_for_each_governor switch_show_governor | ||
144 | done | ||
145 | printf "%s\n\n" "------------------------------------------------" | ||
146 | } | ||
diff --git a/tools/testing/selftests/cpufreq/main.sh b/tools/testing/selftests/cpufreq/main.sh new file mode 100755 index 000000000000..3224652ccbd4 --- /dev/null +++ b/tools/testing/selftests/cpufreq/main.sh | |||
@@ -0,0 +1,128 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | source cpu.sh | ||
4 | source cpufreq.sh | ||
5 | source governor.sh | ||
6 | |||
7 | FUNC=basic # do basic tests by default | ||
8 | OUTFILE=cpufreq_selftest | ||
9 | SYSFS= | ||
10 | CPUROOT= | ||
11 | CPUFREQROOT= | ||
12 | |||
13 | helpme() | ||
14 | { | ||
15 | printf "Usage: $0 [-h] [-to args] | ||
16 | [-h <help>] | ||
17 | [-o <output-file-for-dump>] | ||
18 | [-t <basic: Basic cpufreq testing>] | ||
19 | \n" | ||
20 | exit 2 | ||
21 | } | ||
22 | |||
23 | prerequisite() | ||
24 | { | ||
25 | msg="skip all tests:" | ||
26 | |||
27 | if [ $UID != 0 ]; then | ||
28 | echo $msg must be run as root >&2 | ||
29 | exit 2 | ||
30 | fi | ||
31 | |||
32 | taskset -p 01 $$ | ||
33 | |||
34 | SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'` | ||
35 | |||
36 | if [ ! -d "$SYSFS" ]; then | ||
37 | echo $msg sysfs is not mounted >&2 | ||
38 | exit 2 | ||
39 | fi | ||
40 | |||
41 | CPUROOT=$SYSFS/devices/system/cpu | ||
42 | CPUFREQROOT="$CPUROOT/cpufreq" | ||
43 | |||
44 | if ! ls $CPUROOT/cpu* > /dev/null 2>&1; then | ||
45 | echo $msg cpus not available in sysfs >&2 | ||
46 | exit 2 | ||
47 | fi | ||
48 | |||
49 | if ! ls $CPUROOT/cpufreq > /dev/null 2>&1; then | ||
50 | echo $msg cpufreq directory not available in sysfs >&2 | ||
51 | exit 2 | ||
52 | fi | ||
53 | } | ||
54 | |||
55 | parse_arguments() | ||
56 | { | ||
57 | while getopts ht:o: arg | ||
58 | do | ||
59 | case $arg in | ||
60 | h) # --help | ||
61 | helpme | ||
62 | ;; | ||
63 | |||
64 | t) # --func_type (Function to perform: basic (default: basic)) | ||
65 | FUNC=$OPTARG | ||
66 | ;; | ||
67 | |||
68 | o) # --output-file (Output file to store dumps) | ||
69 | OUTFILE=$OPTARG | ||
70 | ;; | ||
71 | |||
72 | \?) | ||
73 | helpme | ||
74 | ;; | ||
75 | esac | ||
76 | done | ||
77 | } | ||
78 | |||
79 | do_test() | ||
80 | { | ||
81 | # Check if CPUs are managed by cpufreq or not | ||
82 | count=$(count_cpufreq_managed_cpus) | ||
83 | |||
84 | if [ $count = 0 ]; then | ||
85 | echo "No cpu is managed by cpufreq core, exiting" | ||
86 | exit 2; | ||
87 | fi | ||
88 | |||
89 | case "$FUNC" in | ||
90 | "basic") | ||
91 | cpufreq_basic_tests | ||
92 | ;; | ||
93 | |||
94 | *) | ||
95 | echo "Invalid [-f] function type" | ||
96 | helpme | ||
97 | ;; | ||
98 | esac | ||
99 | } | ||
100 | |||
101 | # clear dumps | ||
102 | # $1: file name | ||
103 | clear_dumps() | ||
104 | { | ||
105 | echo "" > $1.txt | ||
106 | echo "" > $1.dmesg_cpufreq.txt | ||
107 | echo "" > $1.dmesg_full.txt | ||
108 | } | ||
109 | |||
110 | # $1: output file name | ||
111 | dmesg_dumps() | ||
112 | { | ||
113 | dmesg | grep cpufreq >> $1.dmesg_cpufreq.txt | ||
114 | |||
115 | # We may need the full logs as well | ||
116 | dmesg >> $1.dmesg_full.txt | ||
117 | } | ||
118 | |||
119 | # Parse arguments | ||
120 | parse_arguments $@ | ||
121 | |||
122 | # Make sure all requirements are met | ||
123 | prerequisite | ||
124 | |||
125 | # Run requested functions | ||
126 | clear_dumps $OUTFILE | ||
127 | do_test >> $OUTFILE.txt | ||
128 | dmesg_dumps $OUTFILE | ||