Commit 23a68d14 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'linux-kselftest-next-6.2-rc1' of...

Merge tag 'linux-kselftest-next-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull Kselftest updates from Shuah Khan:
 "Several fixes and enhancements to existing tests and a few new tests:

   - add new amd-pstate tests and fix and enhance existing ones

   - add new watchdog tests and enhance existing ones to improve
     coverage

   - fixes to ftrace, splice_read, rtc, and efivars tests

   - fixes to handle egrep obsolescence in the latest grep release

   - miscellaneous spelling and SPDX fixes"

* tag 'linux-kselftest-next-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: (24 commits)
  selftests/ftrace: Use long for synthetic event probe test
  selftests/tpm2: Split async tests call to separate shell script runner
  selftests: splice_read: Fix sysfs read cases
  selftests: ftrace: Use "grep -E" instead of "egrep"
  selftests: gpio: Use "grep -E" instead of "egrep"
  selftests: kselftest_deps: Use "grep -E" instead of "egrep"
  selftests/efivarfs: Add checking of the test return value
  cpufreq: amd-pstate: fix spdxcheck warnings for amd-pstate-ut.c
  selftests: rtc: skip when RTC is not present
  selftests/ftrace: event_triggers: wait longer for test_event_enable
  selftests/vDSO: Add riscv getcpu & gettimeofday test
  Documentation: amd-pstate: Add tbench and gitsource test introduction
  selftests: amd-pstate: Trigger gitsource benchmark and test cpus
  selftests: amd-pstate: Trigger tbench benchmark and test cpus
  selftests: amd-pstate: Split basic.sh into run.sh and basic.sh.
  selftests: amd-pstate: Rename amd-pstate-ut.sh to basic.sh.
  selftests/ftrace: Convert tracer tests to use 'requires' to specify program dependency
  selftests/ftrace: Add check for ping command for trigger tests
  selftests/watchdog: Fix spelling mistake "Temeprature" -> "Temperature"
  selftests/watchdog: add test for WDIOC_GETTEMP
  ...
parents 268325bd d5ba85d6
...@@ -405,37 +405,55 @@ Unit Tests for amd-pstate ...@@ -405,37 +405,55 @@ Unit Tests for amd-pstate
1. Test case decriptions 1. Test case decriptions
1). Basic tests
Test prerequisite and basic functions for the ``amd-pstate`` driver.
+---------+--------------------------------+------------------------------------------------------------------------------------+ +---------+--------------------------------+------------------------------------------------------------------------------------+
| Index | Functions | Description | | Index | Functions | Description |
+=========+================================+====================================================================================+ +=========+================================+====================================================================================+
| 0 | amd_pstate_ut_acpi_cpc_valid || Check whether the _CPC object is present in SBIOS. | | 1 | amd_pstate_ut_acpi_cpc_valid || Check whether the _CPC object is present in SBIOS. |
| | || | | | || |
| | || The detail refer to `Processor Support <processor_support_>`_. | | | || The detail refer to `Processor Support <processor_support_>`_. |
+---------+--------------------------------+------------------------------------------------------------------------------------+ +---------+--------------------------------+------------------------------------------------------------------------------------+
| 1 | amd_pstate_ut_check_enabled || Check whether AMD P-State is enabled. | | 2 | amd_pstate_ut_check_enabled || Check whether AMD P-State is enabled. |
| | || | | | || |
| | || AMD P-States and ACPI hardware P-States always can be supported in one processor. | | | || AMD P-States and ACPI hardware P-States always can be supported in one processor. |
| | | But AMD P-States has the higher priority and if it is enabled with | | | | But AMD P-States has the higher priority and if it is enabled with |
| | | :c:macro:`MSR_AMD_CPPC_ENABLE` or ``cppc_set_enable``, it will respond to the | | | | :c:macro:`MSR_AMD_CPPC_ENABLE` or ``cppc_set_enable``, it will respond to the |
| | | request from AMD P-States. | | | | request from AMD P-States. |
+---------+--------------------------------+------------------------------------------------------------------------------------+ +---------+--------------------------------+------------------------------------------------------------------------------------+
| 2 | amd_pstate_ut_check_perf || Check if the each performance values are reasonable. | | 3 | amd_pstate_ut_check_perf || Check if the each performance values are reasonable. |
| | || highest_perf >= nominal_perf > lowest_nonlinear_perf > lowest_perf > 0. | | | || highest_perf >= nominal_perf > lowest_nonlinear_perf > lowest_perf > 0. |
+---------+--------------------------------+------------------------------------------------------------------------------------+ +---------+--------------------------------+------------------------------------------------------------------------------------+
| 3 | amd_pstate_ut_check_freq || Check if the each frequency values and max freq when set support boost mode | | 4 | amd_pstate_ut_check_freq || Check if the each frequency values and max freq when set support boost mode |
| | | are reasonable. | | | | are reasonable. |
| | || max_freq >= nominal_freq > lowest_nonlinear_freq > min_freq > 0 | | | || max_freq >= nominal_freq > lowest_nonlinear_freq > min_freq > 0 |
| | || If boost is not active but supported, this maximum frequency will be larger than | | | || If boost is not active but supported, this maximum frequency will be larger than |
| | | the one in ``cpuinfo``. | | | | the one in ``cpuinfo``. |
+---------+--------------------------------+------------------------------------------------------------------------------------+ +---------+--------------------------------+------------------------------------------------------------------------------------+
2). Tbench test
Test and monitor the cpu changes when running tbench benchmark under the specified governor.
These changes include desire performance, frequency, load, performance, energy etc.
The specified governor is ondemand or schedutil.
Tbench can also be tested on the ``acpi-cpufreq`` kernel driver for comparison.
3). Gitsource test
Test and monitor the cpu changes when running gitsource benchmark under the specified governor.
These changes include desire performance, frequency, load, time, energy etc.
The specified governor is ondemand or schedutil.
Gitsource can also be tested on the ``acpi-cpufreq`` kernel driver for comparison.
#. How to execute the tests #. How to execute the tests
We use test module in the kselftest frameworks to implement it. We use test module in the kselftest frameworks to implement it.
We create amd-pstate-ut module and tie it into kselftest.(for We create ``amd-pstate-ut`` module and tie it into kselftest.(for
details refer to Linux Kernel Selftests [4]_). details refer to Linux Kernel Selftests [4]_).
1. Build 1). Build
+ open the :c:macro:`CONFIG_X86_AMD_PSTATE` configuration option. + open the :c:macro:`CONFIG_X86_AMD_PSTATE` configuration option.
+ set the :c:macro:`CONFIG_X86_AMD_PSTATE_UT` configuration option to M. + set the :c:macro:`CONFIG_X86_AMD_PSTATE_UT` configuration option to M.
...@@ -445,17 +463,47 @@ Unit Tests for amd-pstate ...@@ -445,17 +463,47 @@ Unit Tests for amd-pstate
$ cd linux $ cd linux
$ make -C tools/testing/selftests $ make -C tools/testing/selftests
#. Installation & Steps :: + make perf ::
$ cd tools/perf/
$ make
2). Installation & Steps ::
$ make -C tools/testing/selftests install INSTALL_PATH=~/kselftest $ make -C tools/testing/selftests install INSTALL_PATH=~/kselftest
$ cp tools/perf/perf /usr/bin/perf
$ sudo ./kselftest/run_kselftest.sh -c amd-pstate $ sudo ./kselftest/run_kselftest.sh -c amd-pstate
TAP version 13
1..1
# selftests: amd-pstate: amd-pstate-ut.sh
# amd-pstate-ut: ok
ok 1 selftests: amd-pstate: amd-pstate-ut.sh
#. Results :: 3). Specified test case ::
$ cd ~/kselftest/amd-pstate
$ sudo ./run.sh -t basic
$ sudo ./run.sh -t tbench
$ sudo ./run.sh -t tbench -m acpi-cpufreq
$ sudo ./run.sh -t gitsource
$ sudo ./run.sh -t gitsource -m acpi-cpufreq
$ ./run.sh --help
./run.sh: illegal option -- -
Usage: ./run.sh [OPTION...]
[-h <help>]
[-o <output-file-for-dump>]
[-c <all: All testing,
basic: Basic testing,
tbench: Tbench testing,
gitsource: Gitsource testing.>]
[-t <tbench time limit>]
[-p <tbench process number>]
[-l <loop times for tbench>]
[-i <amd tracer interval>]
[-m <comparative test: acpi-cpufreq>]
4). Results
+ basic
When you finish test, you will get the following log info ::
$ dmesg | grep "amd_pstate_ut" | tee log.txt $ dmesg | grep "amd_pstate_ut" | tee log.txt
[12977.570663] amd_pstate_ut: 1 amd_pstate_ut_acpi_cpc_valid success! [12977.570663] amd_pstate_ut: 1 amd_pstate_ut_acpi_cpc_valid success!
...@@ -463,6 +511,112 @@ Unit Tests for amd-pstate ...@@ -463,6 +511,112 @@ Unit Tests for amd-pstate
[12977.571207] amd_pstate_ut: 3 amd_pstate_ut_check_perf success! [12977.571207] amd_pstate_ut: 3 amd_pstate_ut_check_perf success!
[12977.571212] amd_pstate_ut: 4 amd_pstate_ut_check_freq success! [12977.571212] amd_pstate_ut: 4 amd_pstate_ut_check_freq success!
+ tbench
When you finish test, you will get selftest.tbench.csv and png images.
The selftest.tbench.csv file contains the raw data and the drop of the comparative test.
The png images shows the performance, energy and performan per watt of each test.
Open selftest.tbench.csv :
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ Governor | Round | Des-perf | Freq | Load | Performance | Energy | Performance Per Watt |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ Unit | | | GHz | | MB/s | J | MB/J |
+=================================================+==============+==========+=========+==========+=============+=========+======================+
+ amd-pstate-ondemand | 1 | | | | 2504.05 | 1563.67 | 158.5378 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ amd-pstate-ondemand | 2 | | | | 2243.64 | 1430.32 | 155.2941 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ amd-pstate-ondemand | 3 | | | | 2183.88 | 1401.32 | 154.2860 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ amd-pstate-ondemand | Average | | | | 2310.52 | 1465.1 | 156.1268 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ amd-pstate-schedutil | 1 | 165.329 | 1.62257 | 99.798 | 2136.54 | 1395.26 | 151.5971 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ amd-pstate-schedutil | 2 | 166 | 1.49761 | 99.9993 | 2100.56 | 1380.5 | 150.6377 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ amd-pstate-schedutil | 3 | 166 | 1.47806 | 99.9993 | 2084.12 | 1375.76 | 149.9737 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ amd-pstate-schedutil | Average | 165.776 | 1.53275 | 99.9322 | 2107.07 | 1383.84 | 150.7399 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-ondemand | 1 | | | | 2529.9 | 1564.4 | 160.0997 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-ondemand | 2 | | | | 2249.76 | 1432.97 | 155.4297 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-ondemand | 3 | | | | 2181.46 | 1406.88 | 153.5060 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-ondemand | Average | | | | 2320.37 | 1468.08 | 156.4741 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-schedutil | 1 | | | | 2137.64 | 1385.24 | 152.7723 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-schedutil | 2 | | | | 2107.05 | 1372.23 | 152.0138 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-schedutil | 3 | | | | 2085.86 | 1365.35 | 151.2433 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-schedutil | Average | | | | 2110.18 | 1374.27 | 152.0136 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-ondemand VS acpi-cpufreq-schedutil | Comprison(%) | | | | -9.0584 | -6.3899 | -2.8506 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ amd-pstate-ondemand VS amd-pstate-schedutil | Comprison(%) | | | | 8.8053 | -5.5463 | -3.4503 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-ondemand VS amd-pstate-ondemand | Comprison(%) | | | | -0.4245 | -0.2029 | -0.2219 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-schedutil VS amd-pstate-schedutil | Comprison(%) | | | | -0.1473 | 0.6963 | -0.8378 |
+-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ gitsource
When you finish test, you will get selftest.gitsource.csv and png images.
The selftest.gitsource.csv file contains the raw data and the drop of the comparative test.
The png images shows the performance, energy and performan per watt of each test.
Open selftest.gitsource.csv :
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ Governor | Round | Des-perf | Freq | Load | Time | Energy | Performance Per Watt |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ Unit | | | GHz | | s | J | 1/J |
+=================================================+==============+==========+==========+==========+=============+=========+======================+
+ amd-pstate-ondemand | 1 | 50.119 | 2.10509 | 23.3076 | 475.69 | 865.78 | 0.001155027 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ amd-pstate-ondemand | 2 | 94.8006 | 1.98771 | 56.6533 | 467.1 | 839.67 | 0.001190944 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ amd-pstate-ondemand | 3 | 76.6091 | 2.53251 | 43.7791 | 467.69 | 855.85 | 0.001168429 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ amd-pstate-ondemand | Average | 73.8429 | 2.20844 | 41.2467 | 470.16 | 853.767 | 0.001171279 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ amd-pstate-schedutil | 1 | 165.919 | 1.62319 | 98.3868 | 464.17 | 866.8 | 0.001153668 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ amd-pstate-schedutil | 2 | 165.97 | 1.31309 | 99.5712 | 480.15 | 880.4 | 0.001135847 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ amd-pstate-schedutil | 3 | 165.973 | 1.28448 | 99.9252 | 481.79 | 867.02 | 0.001153375 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ amd-pstate-schedutil | Average | 165.954 | 1.40692 | 99.2944 | 475.37 | 871.407 | 0.001147569 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-ondemand | 1 | | | | 2379.62 | 742.96 | 0.001345967 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-ondemand | 2 | | | | 441.74 | 817.49 | 0.001223256 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-ondemand | 3 | | | | 455.48 | 820.01 | 0.001219497 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-ondemand | Average | | | | 425.613 | 793.487 | 0.001260260 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-schedutil | 1 | | | | 459.69 | 838.54 | 0.001192548 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-schedutil | 2 | | | | 466.55 | 830.89 | 0.001203528 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-schedutil | 3 | | | | 470.38 | 837.32 | 0.001194286 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-schedutil | Average | | | | 465.54 | 835.583 | 0.001196769 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-ondemand VS acpi-cpufreq-schedutil | Comprison(%) | | | | 9.3810 | 5.3051 | -5.0379 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ amd-pstate-ondemand VS amd-pstate-schedutil | Comprison(%) | 124.7392 | -36.2934 | 140.7329 | 1.1081 | 2.0661 | -2.0242 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-ondemand VS amd-pstate-ondemand | Comprison(%) | | | | 10.4665 | 7.5968 | -7.0605 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ acpi-cpufreq-schedutil VS amd-pstate-schedutil | Comprison(%) | | | | 2.1115 | 4.2873 | -4.1110 |
+-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
Reference Reference
=========== ===========
......
// SPDX-License-Identifier: GPL-1.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
/* /*
* AMD Processor P-state Frequency Driver Unit Test * AMD Processor P-state Frequency Driver Unit Test
* *
......
...@@ -4,6 +4,15 @@ ...@@ -4,6 +4,15 @@
# No binaries, but make sure arg-less "make" doesn't trigger "run_tests" # No binaries, but make sure arg-less "make" doesn't trigger "run_tests"
all: all:
TEST_PROGS := amd-pstate-ut.sh uname_M := $(shell uname -m 2>/dev/null || echo not)
ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
ifeq (x86,$(ARCH))
TEST_GEN_FILES += ../../../power/x86/amd_pstate_tracer/amd_pstate_trace.py
TEST_GEN_FILES += ../../../power/x86/intel_pstate_tracer/intel_pstate_tracer.py
endif
TEST_PROGS := run.sh
TEST_FILES := basic.sh tbench.sh gitsource.sh
include ../lib.mk include ../lib.mk
...@@ -11,46 +11,28 @@ ...@@ -11,46 +11,28 @@
# (3) We can introduce more functional or performance tests to align # (3) We can introduce more functional or performance tests to align
# the result together, it will benefit power and performance scale optimization. # the result together, it will benefit power and performance scale optimization.
# Kselftest framework requirement - SKIP code is 4. # protect against multiple inclusion
ksft_skip=4 if [ $FILE_BASIC ]; then
return 0
# amd-pstate-ut only run on x86/x86_64 AMD systems. else
ARCH=$(uname -m 2>/dev/null | sed -e 's/i.86/x86/' -e 's/x86_64/x86/') FILE_BASIC=DONE
VENDOR=$(cat /proc/cpuinfo | grep -m 1 'vendor_id' | awk '{print $NF}')
if ! echo "$ARCH" | grep -q x86; then
echo "$0 # Skipped: Test can only run on x86 architectures."
exit $ksft_skip
fi
if ! echo "$VENDOR" | grep -iq amd; then
echo "$0 # Skipped: Test can only run on AMD CPU."
echo "$0 # Current cpu vendor is $VENDOR."
exit $ksft_skip
fi
scaling_driver=$(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_driver)
if [ "$scaling_driver" != "amd-pstate" ]; then
echo "$0 # Skipped: Test can only run on amd-pstate driver."
echo "$0 # Please set X86_AMD_PSTATE enabled."
echo "$0 # Current cpufreq scaling drvier is $scaling_driver."
exit $ksft_skip
fi fi
msg="Skip all tests:" amd_pstate_basic()
if [ ! -w /dev ]; then {
echo $msg please run this as root >&2 printf "\n---------------------------------------------\n"
exit $ksft_skip printf "*** Running AMD P-state ut ***"
fi printf "\n---------------------------------------------\n"
if ! /sbin/modprobe -q -n amd-pstate-ut; then if ! /sbin/modprobe -q -n amd-pstate-ut; then
echo "amd-pstate-ut: module amd-pstate-ut is not found [SKIP]" echo "amd-pstate-ut: module amd-pstate-ut is not found [SKIP]"
exit $ksft_skip exit $ksft_skip
fi fi
if /sbin/modprobe -q amd-pstate-ut; then if /sbin/modprobe -q amd-pstate-ut; then
/sbin/modprobe -q -r amd-pstate-ut /sbin/modprobe -q -r amd-pstate-ut
echo "amd-pstate-ut: ok" echo "amd-pstate-basic: ok"
else else
echo "amd-pstate-ut: [FAIL]" echo "amd-pstate-basic: [FAIL]"
exit 1 exit 1
fi fi
}
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Testing and monitor the cpu desire performance, frequency, load,
# power consumption and throughput etc. when this script trigger
# gitsource test.
# 1) Download and tar gitsource codes.
# 2) Run gitsource benchmark on specific governors, ondemand or schedutil.
# 3) Run tbench benchmark comparative test on acpi-cpufreq kernel driver.
# 4) Get desire performance, frequency, load by perf.
# 5) Get power consumption and throughput by amd_pstate_trace.py.
# 6) Get run time by /usr/bin/time.
# 7) Analyse test results and save it in file selftest.gitsource.csv.
#8) Plot png images about time, energy and performance per watt for each test.
# protect against multiple inclusion
if [ $FILE_GITSOURCE ]; then
return 0
else
FILE_GITSOURCE=DONE
fi
git_name="git-2.15.1"
git_tar="$git_name.tar.gz"
gitsource_url="https://github.com/git/git/archive/refs/tags/v2.15.1.tar.gz"
gitsource_governors=("ondemand" "schedutil")
# $1: governor, $2: round, $3: des-perf, $4: freq, $5: load, $6: time $7: energy, $8: PPW
store_csv_gitsource()
{
echo "$1, $2, $3, $4, $5, $6, $7, $8" | tee -a $OUTFILE_GIT.csv > /dev/null 2>&1
}
# clear some special lines
clear_csv_gitsource()
{
if [ -f $OUTFILE_GIT.csv ]; then
sed -i '/Comprison(%)/d' $OUTFILE_GIT.csv
sed -i "/$(scaling_name)/d" $OUTFILE_GIT.csv
fi
}
# find string $1 in file csv and get the number of lines
get_lines_csv_gitsource()
{
if [ -f $OUTFILE_GIT.csv ]; then
return `grep -c "$1" $OUTFILE_GIT.csv`
else
return 0
fi
}
pre_clear_gitsource()
{
post_clear_gitsource
rm -rf gitsource_*.png
clear_csv_gitsource
}
post_clear_gitsource()
{
rm -rf results/tracer-gitsource*
rm -rf $OUTFILE_GIT*.log
rm -rf $OUTFILE_GIT*.result
}
install_gitsource()
{
if [ ! -d $git_name ]; then
printf "Download gitsource, please wait a moment ...\n\n"
wget -O $git_tar $gitsource_url > /dev/null 2>&1
printf "Tar gitsource ...\n\n"
tar -xzf $git_tar
fi
}
# $1: governor, $2: loop
run_gitsource()
{
echo "Launching amd pstate tracer for $1 #$2 tracer_interval: $TRACER_INTERVAL"
./amd_pstate_trace.py -n tracer-gitsource-$1-$2 -i $TRACER_INTERVAL > /dev/null 2>&1 &
printf "Make and test gitsource for $1 #$2 make_cpus: $MAKE_CPUS\n"
cd $git_name
perf stat -a --per-socket -I 1000 -e power/energy-pkg/ /usr/bin/time -o ../$OUTFILE_GIT.time-gitsource-$1-$2.log make test -j$MAKE_CPUS > ../$OUTFILE_GIT-perf-$1-$2.log 2>&1
cd ..
for job in `jobs -p`
do
echo "Waiting for job id $job"
wait $job
done
}
# $1: governor, $2: loop
parse_gitsource()
{
awk '{print $5}' results/tracer-gitsource-$1-$2/cpu.csv | sed -e '1d' | sed s/,// > $OUTFILE_GIT-des-perf-$1-$2.log
avg_des_perf=$(awk 'BEGIN {i=0; sum=0};{i++; sum += $1};END {print sum/i}' $OUTFILE_GIT-des-perf-$1-$2.log)
printf "Gitsource-$1-#$2 avg des perf: $avg_des_perf\n" | tee -a $OUTFILE_GIT.result
awk '{print $7}' results/tracer-gitsource-$1-$2/cpu.csv | sed -e '1d' | sed s/,// > $OUTFILE_GIT-freq-$1-$2.log
avg_freq=$(awk 'BEGIN {i=0; sum=0};{i++; sum += $1};END {print sum/i}' $OUTFILE_GIT-freq-$1-$2.log)
printf "Gitsource-$1-#$2 avg freq: $avg_freq\n" | tee -a $OUTFILE_GIT.result
awk '{print $11}' results/tracer-gitsource-$1-$2/cpu.csv | sed -e '1d' | sed s/,// > $OUTFILE_GIT-load-$1-$2.log
avg_load=$(awk 'BEGIN {i=0; sum=0};{i++; sum += $1};END {print sum/i}' $OUTFILE_GIT-load-$1-$2.log)
printf "Gitsource-$1-#$2 avg load: $avg_load\n" | tee -a $OUTFILE_GIT.result
grep user $OUTFILE_GIT.time-gitsource-$1-$2.log | awk '{print $1}' | sed -e 's/user//' > $OUTFILE_GIT-time-$1-$2.log
time_sum=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum}' $OUTFILE_GIT-time-$1-$2.log)
printf "Gitsource-$1-#$2 user time(s): $time_sum\n" | tee -a $OUTFILE_GIT.result
grep Joules $OUTFILE_GIT-perf-$1-$2.log | awk '{print $4}' > $OUTFILE_GIT-energy-$1-$2.log
en_sum=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum}' $OUTFILE_GIT-energy-$1-$2.log)
printf "Gitsource-$1-#$2 power consumption(J): $en_sum\n" | tee -a $OUTFILE_GIT.result
# Permance is the number of run gitsource per second, denoted 1/t, where 1 is the number of run gitsource in t
# senconds. It is well known that P=E/t, where P is power measured in watts(W), E is energy measured in joules(J),
# and t is time measured in seconds(s). This means that performance per watt becomes
# 1/t 1/t 1
# ----- = ----- = ---
# P E/t E
# with unit given by 1 per joule.
ppw=`echo "scale=9;1/$en_sum" | bc | awk '{printf "%.9f", $0}'`
printf "Gitsource-$1-#$2 performance per watt(1/J): $ppw\n" | tee -a $OUTFILE_GIT.result
printf "\n" | tee -a $OUTFILE_GIT.result
driver_name=`echo $(scaling_name)`
store_csv_gitsource "$driver_name-$1" $2 $avg_des_perf $avg_freq $avg_load $time_sum $en_sum $ppw
}
# $1: governor
loop_gitsource()
{
printf "\nGitsource total test times is $LOOP_TIMES for $1\n\n"
for i in `seq 1 $LOOP_TIMES`
do
run_gitsource $1 $i
parse_gitsource $1 $i
done
}
# $1: governor
gather_gitsource()
{
printf "Gitsource test result for $1 (loops:$LOOP_TIMES)" | tee -a $OUTFILE_GIT.result
printf "\n--------------------------------------------------\n" | tee -a $OUTFILE_GIT.result
grep "Gitsource-$1-#" $OUTFILE_GIT.result | grep "avg des perf:" | awk '{print $NF}' > $OUTFILE_GIT-des-perf-$1.log
avg_des_perf=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_GIT-des-perf-$1.log)
printf "Gitsource-$1 avg des perf: $avg_des_perf\n" | tee -a $OUTFILE_GIT.result
grep "Gitsource-$1-#" $OUTFILE_GIT.result | grep "avg freq:" | awk '{print $NF}' > $OUTFILE_GIT-freq-$1.log
avg_freq=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_GIT-freq-$1.log)
printf "Gitsource-$1 avg freq: $avg_freq\n" | tee -a $OUTFILE_GIT.result
grep "Gitsource-$1-#" $OUTFILE_GIT.result | grep "avg load:" | awk '{print $NF}' > $OUTFILE_GIT-load-$1.log
avg_load=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_GIT-load-$1.log)
printf "Gitsource-$1 avg load: $avg_load\n" | tee -a $OUTFILE_GIT.result
grep "Gitsource-$1-#" $OUTFILE_GIT.result | grep "user time(s):" | awk '{print $NF}' > $OUTFILE_GIT-time-$1.log
time_sum=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum}' $OUTFILE_GIT-time-$1.log)
printf "Gitsource-$1 total user time(s): $time_sum\n" | tee -a $OUTFILE_GIT.result
avg_time=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_GIT-time-$1.log)
printf "Gitsource-$1 avg user times(s): $avg_time\n" | tee -a $OUTFILE_GIT.result
grep "Gitsource-$1-#" $OUTFILE_GIT.result | grep "power consumption(J):" | awk '{print $NF}' > $OUTFILE_GIT-energy-$1.log
en_sum=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum}' $OUTFILE_GIT-energy-$1.log)
printf "Gitsource-$1 total power consumption(J): $en_sum\n" | tee -a $OUTFILE_GIT.result
avg_en=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_GIT-energy-$1.log)
printf "Gitsource-$1 avg power consumption(J): $avg_en\n" | tee -a $OUTFILE_GIT.result
# Permance is the number of run gitsource per second, denoted 1/t, where 1 is the number of run gitsource in t
# senconds. It is well known that P=E/t, where P is power measured in watts(W), E is energy measured in joules(J),
# and t is time measured in seconds(s). This means that performance per watt becomes
# 1/t 1/t 1
# ----- = ----- = ---
# P E/t E
# with unit given by 1 per joule.
ppw=`echo "scale=9;1/$avg_en" | bc | awk '{printf "%.9f", $0}'`
printf "Gitsource-$1 performance per watt(1/J): $ppw\n" | tee -a $OUTFILE_GIT.result
printf "\n" | tee -a $OUTFILE_GIT.result
driver_name=`echo $(scaling_name)`
store_csv_gitsource "$driver_name-$1" "Average" $avg_des_perf $avg_freq $avg_load $avg_time $avg_en $ppw
}
# $1: base scaling_driver $2: base governor $3: comparison scaling_driver $4: comparison governor
__calc_comp_gitsource()
{
base=`grep "$1-$2" $OUTFILE_GIT.csv | grep "Average"`
comp=`grep "$3-$4" $OUTFILE_GIT.csv | grep "Average"`
if [ -n "$base" -a -n "$comp" ]; then
printf "\n==================================================\n" | tee -a $OUTFILE_GIT.result
printf "Gitsource comparison $1-$2 VS $3-$4" | tee -a $OUTFILE_GIT.result
printf "\n==================================================\n" | tee -a $OUTFILE_GIT.result
# get the base values
des_perf_base=`echo "$base" | awk '{print $3}' | sed s/,//`
freq_base=`echo "$base" | awk '{print $4}' | sed s/,//`
load_base=`echo "$base" | awk '{print $5}' | sed s/,//`
time_base=`echo "$base" | awk '{print $6}' | sed s/,//`
energy_base=`echo "$base" | awk '{print $7}' | sed s/,//`
ppw_base=`echo "$base" | awk '{print $8}' | sed s/,//`
# get the comparison values
des_perf_comp=`echo "$comp" | awk '{print $3}' | sed s/,//`
freq_comp=`echo "$comp" | awk '{print $4}' | sed s/,//`
load_comp=`echo "$comp" | awk '{print $5}' | sed s/,//`
time_comp=`echo "$comp" | awk '{print $6}' | sed s/,//`
energy_comp=`echo "$comp" | awk '{print $7}' | sed s/,//`
ppw_comp=`echo "$comp" | awk '{print $8}' | sed s/,//`
# compare the base and comp values
des_perf_drop=`echo "scale=4;($des_perf_comp-$des_perf_base)*100/$des_perf_base" | bc | awk '{printf "%.4f", $0}'`
printf "Gitsource-$1 des perf base: $des_perf_base comprison: $des_perf_comp percent: $des_perf_drop\n" | tee -a $OUTFILE_GIT.result
freq_drop=`echo "scale=4;($freq_comp-$freq_base)*100/$freq_base" | bc | awk '{printf "%.4f", $0}'`
printf "Gitsource-$1 freq base: $freq_base comprison: $freq_comp percent: $freq_drop\n" | tee -a $OUTFILE_GIT.result
load_drop=`echo "scale=4;($load_comp-$load_base)*100/$load_base" | bc | awk '{printf "%.4f", $0}'`
printf "Gitsource-$1 load base: $load_base comprison: $load_comp percent: $load_drop\n" | tee -a $OUTFILE_GIT.result
time_drop=`echo "scale=4;($time_comp-$time_base)*100/$time_base" | bc | awk '{printf "%.4f", $0}'`
printf "Gitsource-$1 time base: $time_base comprison: $time_comp percent: $time_drop\n" | tee -a $OUTFILE_GIT.result
energy_drop=`echo "scale=4;($energy_comp-$energy_base)*100/$energy_base" | bc | awk '{printf "%.4f", $0}'`
printf "Gitsource-$1 energy base: $energy_base comprison: $energy_comp percent: $energy_drop\n" | tee -a $OUTFILE_GIT.result
ppw_drop=`echo "scale=4;($ppw_comp-$ppw_base)*100/$ppw_base" | bc | awk '{printf "%.4f", $0}'`
printf "Gitsource-$1 performance per watt base: $ppw_base comprison: $ppw_comp percent: $ppw_drop\n" | tee -a $OUTFILE_GIT.result
printf "\n" | tee -a $OUTFILE_GIT.result
store_csv_gitsource "$1-$2 VS $3-$4" "Comprison(%)" "$des_perf_drop" "$freq_drop" "$load_drop" "$time_drop" "$energy_drop" "$ppw_drop"
fi
}
# calculate the comparison(%)
calc_comp_gitsource()
{
# acpi-cpufreq-ondemand VS acpi-cpufreq-schedutil
__calc_comp_gitsource ${all_scaling_names[0]} ${gitsource_governors[0]} ${all_scaling_names[0]} ${gitsource_governors[1]}
# amd-pstate-ondemand VS amd-pstate-schedutil
__calc_comp_gitsource ${all_scaling_names[1]} ${gitsource_governors[0]} ${all_scaling_names[1]} ${gitsource_governors[1]}
# acpi-cpufreq-ondemand VS amd-pstate-ondemand
__calc_comp_gitsource ${all_scaling_names[0]} ${gitsource_governors[0]} ${all_scaling_names[1]} ${gitsource_governors[0]}
# acpi-cpufreq-schedutil VS amd-pstate-schedutil
__calc_comp_gitsource ${all_scaling_names[0]} ${gitsource_governors[1]} ${all_scaling_names[1]} ${gitsource_governors[1]}
}
# $1: file_name, $2: title, $3: ylable, $4: column
plot_png_gitsource()
{
# all_scaling_names[1] all_scaling_names[0] flag
# amd-pstate acpi-cpufreq
# N N 0
# N Y 1
# Y N 2
# Y Y 3
ret=`grep -c "${all_scaling_names[1]}" $OUTFILE_GIT.csv`
if [ $ret -eq 0 ]; then
ret=`grep -c "${all_scaling_names[0]}" $OUTFILE_GIT.csv`
if [ $ret -eq 0 ]; then
flag=0
else
flag=1
fi
else
ret=`grep -c "${all_scaling_names[0]}" $OUTFILE_GIT.csv`
if [ $ret -eq 0 ]; then
flag=2
else
flag=3
fi
fi
gnuplot << EOF
set term png
set output "$1"
set title "$2"
set xlabel "Test Cycles (round)"
set ylabel "$3"
set grid
set style data histogram
set style fill solid 0.5 border
set boxwidth 0.8
if ($flag == 1) {
plot \
"<(sed -n -e 's/,//g' -e '/${all_scaling_names[0]}-${gitsource_governors[0]}/p' $OUTFILE_GIT.csv)" using $4:xtic(2) title "${all_scaling_names[0]}-${gitsource_governors[0]}", \
"<(sed -n -e 's/,//g' -e '/${all_scaling_names[0]}-${gitsource_governors[1]}/p' $OUTFILE_GIT.csv)" using $4:xtic(2) title "${all_scaling_names[0]}-${gitsource_governors[1]}"
} else {
if ($flag == 2) {
plot \
"<(sed -n -e 's/,//g' -e '/${all_scaling_names[1]}-${gitsource_governors[0]}/p' $OUTFILE_GIT.csv)" using $4:xtic(2) title "${all_scaling_names[1]}-${gitsource_governors[0]}", \
"<(sed -n -e 's/,//g' -e '/${all_scaling_names[1]}-${gitsource_governors[1]}/p' $OUTFILE_GIT.csv)" using $4:xtic(2) title "${all_scaling_names[1]}-${gitsource_governors[1]}"
} else {
if ($flag == 3 ) {
plot \
"<(sed -n -e 's/,//g' -e '/${all_scaling_names[0]}-${gitsource_governors[0]}/p' $OUTFILE_GIT.csv)" using $4:xtic(2) title "${all_scaling_names[0]}-${gitsource_governors[0]}", \
"<(sed -n -e 's/,//g' -e '/${all_scaling_names[0]}-${gitsource_governors[1]}/p' $OUTFILE_GIT.csv)" using $4:xtic(2) title "${all_scaling_names[0]}-${gitsource_governors[1]}", \
"<(sed -n -e 's/,//g' -e '/${all_scaling_names[1]}-${gitsource_governors[0]}/p' $OUTFILE_GIT.csv)" using $4:xtic(2) title "${all_scaling_names[1]}-${gitsource_governors[0]}", \
"<(sed -n -e 's/,//g' -e '/${all_scaling_names[1]}-${gitsource_governors[1]}/p' $OUTFILE_GIT.csv)" using $4:xtic(2) title "${all_scaling_names[1]}-${gitsource_governors[1]}"
}
}
}
quit
EOF
}
amd_pstate_gitsource()
{
printf "\n---------------------------------------------\n"
printf "*** Running gitsource ***"
printf "\n---------------------------------------------\n"
pre_clear_gitsource
install_gitsource
get_lines_csv_gitsource "Governor"
if [ $? -eq 0 ]; then
# add titles and unit for csv file
store_csv_gitsource "Governor" "Round" "Des-perf" "Freq" "Load" "Time" "Energy" "Performance Per Watt"
store_csv_gitsource "Unit" "" "" "GHz" "" "s" "J" "1/J"
fi
backup_governor
for governor in ${gitsource_governors[*]} ; do
printf "\nSpecified governor is $governor\n\n"
switch_governor $governor
loop_gitsource $governor
gather_gitsource $governor
done
restore_governor
plot_png_gitsource "gitsource_time.png" "Gitsource Benchmark Time" "Time (s)" 6
plot_png_gitsource "gitsource_energy.png" "Gitsource Benchmark Energy" "Energy (J)" 7
plot_png_gitsource "gitsource_ppw.png" "Gitsource Benchmark Performance Per Watt" "Performance Per Watt (1/J)" 8
calc_comp_gitsource
post_clear_gitsource
}
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# protect against multiple inclusion
if [ $FILE_MAIN ]; then
return 0
else
FILE_MAIN=DONE
fi
source basic.sh
source tbench.sh
source gitsource.sh
# amd-pstate-ut only run on x86/x86_64 AMD systems.
ARCH=$(uname -m 2>/dev/null | sed -e 's/i.86/x86/' -e 's/x86_64/x86/')
VENDOR=$(cat /proc/cpuinfo | grep -m 1 'vendor_id' | awk '{print $NF}')
msg="Skip all tests:"
FUNC=all
OUTFILE=selftest
OUTFILE_TBENCH="$OUTFILE.tbench"
OUTFILE_GIT="$OUTFILE.gitsource"
SYSFS=
CPUROOT=
CPUFREQROOT=
MAKE_CPUS=
TIME_LIMIT=100
PROCESS_NUM=128
LOOP_TIMES=3
TRACER_INTERVAL=10
CURRENT_TEST=amd-pstate
COMPARATIVE_TEST=
# Kselftest framework requirement - SKIP code is 4.
ksft_skip=4
all_scaling_names=("acpi-cpufreq" "amd-pstate")
# Get current cpufreq scaling driver name
scaling_name()
{
if [ "$COMPARATIVE_TEST" = "" ]; then
echo "$CURRENT_TEST"
else
echo "$COMPARATIVE_TEST"
fi
}
# Counts CPUs with cpufreq directories
count_cpus()
{
count=0;
for cpu in `ls $CPUROOT | grep "cpu[0-9].*"`; do
if [ -d $CPUROOT/$cpu/cpufreq ]; then
let count=count+1;
fi
done
echo $count;
}
# $1: policy
find_current_governor()
{
cat $CPUFREQROOT/$1/scaling_governor
}
backup_governor()
{
policies=$(ls $CPUFREQROOT| grep "policy[0-9].*")
for policy in $policies; do
cur_gov=$(find_current_governor $policy)
echo "$policy $cur_gov" >> $OUTFILE.backup_governor.log
done
printf "Governor $cur_gov backup done.\n"
}
restore_governor()
{
i=0;
policies=$(awk '{print $1}' $OUTFILE.backup_governor.log)
for policy in $policies; do
let i++;
governor=$(sed -n ''$i'p' $OUTFILE.backup_governor.log | awk '{print $2}')
# switch governor
echo $governor > $CPUFREQROOT/$policy/scaling_governor
done
printf "Governor restored to $governor.\n"
}
# $1: governor
switch_governor()
{
policies=$(ls $CPUFREQROOT| grep "policy[0-9].*")
for policy in $policies; do
filepath=$CPUFREQROOT/$policy/scaling_available_governors
# Exit if cpu isn't managed by cpufreq core
if [ ! -f $filepath ]; then
return;
fi
echo $1 > $CPUFREQROOT/$policy/scaling_governor
done
printf "Switched governor to $1.\n"
}
# All amd-pstate tests
amd_pstate_all()
{
printf "\n=============================================\n"
printf "***** Running AMD P-state Sanity Tests *****\n"
printf "=============================================\n\n"
count=$(count_cpus)
if [ $count = 0 ]; then
printf "No cpu is managed by cpufreq core, exiting\n"
exit;
else
printf "AMD P-state manages: $count CPUs\n"
fi
# unit test for amd-pstate kernel driver
amd_pstate_basic
# tbench
amd_pstate_tbench
# gitsource
amd_pstate_gitsource
}
help()
{
printf "Usage: $0 [OPTION...]
[-h <help>]
[-o <output-file-for-dump>]
[-c <all: All testing,
basic: Basic testing,
tbench: Tbench testing,
gitsource: Gitsource testing.>]
[-t <tbench time limit>]
[-p <tbench process number>]
[-l <loop times for tbench>]
[-i <amd tracer interval>]
[-m <comparative test: acpi-cpufreq>]
\n"
exit 2
}
parse_arguments()
{
while getopts ho:c:t:p:l:i:m: arg
do
case $arg in
h) # --help
help
;;
c) # --func_type (Function to perform: basic, tbench, gitsource (default: all))
FUNC=$OPTARG
;;
o) # --output-file (Output file to store dumps)
OUTFILE=$OPTARG
;;
t) # --tbench-time-limit
TIME_LIMIT=$OPTARG
;;
p) # --tbench-process-number
PROCESS_NUM=$OPTARG
;;
l) # --tbench/gitsource-loop-times
LOOP_TIMES=$OPTARG
;;
i) # --amd-tracer-interval
TRACER_INTERVAL=$OPTARG
;;
m) # --comparative-test
COMPARATIVE_TEST=$OPTARG
;;
*)
help
;;
esac
done
}
command_perf()
{
if ! command -v perf > /dev/null; then
echo $msg please install perf. >&2
exit $ksft_skip
fi
}
command_tbench()
{
if ! command -v tbench > /dev/null; then
if apt policy dbench > /dev/null 2>&1; then
echo $msg apt install dbench >&2
exit $ksft_skip
elif yum list available | grep dbench > /dev/null 2>&1; then
echo $msg yum install dbench >&2
exit $ksft_skip
fi
fi
if ! command -v tbench > /dev/null; then
echo $msg please install tbench. >&2
exit $ksft_skip
fi
}
prerequisite()
{
if ! echo "$ARCH" | grep -q x86; then
echo "$0 # Skipped: Test can only run on x86 architectures."
exit $ksft_skip
fi
if ! echo "$VENDOR" | grep -iq amd; then
echo "$0 # Skipped: Test can only run on AMD CPU."
echo "$0 # Current cpu vendor is $VENDOR."
exit $ksft_skip
fi
scaling_driver=$(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_driver)
if [ "$COMPARATIVE_TEST" = "" ]; then
if [ "$scaling_driver" != "$CURRENT_TEST" ]; then
echo "$0 # Skipped: Test can only run on $CURRENT_TEST driver or run comparative test."
echo "$0 # Please set X86_AMD_PSTATE enabled or run comparative test."
echo "$0 # Current cpufreq scaling drvier is $scaling_driver."
exit $ksft_skip
fi
else
case "$FUNC" in
"tbench" | "gitsource")
if [ "$scaling_driver" != "$COMPARATIVE_TEST" ]; then
echo "$0 # Skipped: Comparison test can only run on $COMPARISON_TEST driver."
echo "$0 # Current cpufreq scaling drvier is $scaling_driver."
exit $ksft_skip
fi
;;
*)
echo "$0 # Skipped: Comparison test are only for tbench or gitsource."
echo "$0 # Current comparative test is for $FUNC."
exit $ksft_skip
;;
esac
fi
if [ ! -w /dev ]; then
echo $msg please run this as root >&2
exit $ksft_skip
fi
case "$FUNC" in
"all")
command_perf
command_tbench
;;
"tbench")
command_perf
command_tbench
;;
"gitsource")
command_perf
;;
esac
SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'`
if [ ! -d "$SYSFS" ]; then
echo $msg sysfs is not mounted >&2
exit 2
fi
CPUROOT=$SYSFS/devices/system/cpu
CPUFREQROOT="$CPUROOT/cpufreq"
if ! ls $CPUROOT/cpu* > /dev/null 2>&1; then
echo $msg cpus not available in sysfs >&2
exit 2
fi
if ! ls $CPUROOT/cpufreq > /dev/null 2>&1; then
echo $msg cpufreq directory not available in sysfs >&2
exit 2
fi
}
do_test()
{
# Check if CPUs are managed by cpufreq or not
count=$(count_cpus)
MAKE_CPUS=$((count*2))
if [ $count = 0 ]; then
echo "No cpu is managed by cpufreq core, exiting"
exit 2;
fi
case "$FUNC" in
"all")
amd_pstate_all
;;
"basic")
amd_pstate_basic
;;
"tbench")
amd_pstate_tbench
;;
"gitsource")
amd_pstate_gitsource
;;
*)
echo "Invalid [-f] function type"
help
;;
esac
}
# clear dumps
pre_clear_dumps()
{
case "$FUNC" in
"all")
rm -rf $OUTFILE.log
rm -rf $OUTFILE.backup_governor.log
rm -rf *.png
;;
"tbench")
rm -rf $OUTFILE.log
rm -rf $OUTFILE.backup_governor.log
rm -rf tbench_*.png
;;
"gitsource")
rm -rf $OUTFILE.log
rm -rf $OUTFILE.backup_governor.log
rm -rf gitsource_*.png
;;
*)
;;
esac
}
post_clear_dumps()
{
rm -rf $OUTFILE.log
rm -rf $OUTFILE.backup_governor.log
}
# Parse arguments
parse_arguments $@
# Make sure all requirements are met
prerequisite
# Run requested functions
pre_clear_dumps
do_test | tee -a $OUTFILE.log
post_clear_dumps
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Testing and monitor the cpu desire performance, frequency, load,
# power consumption and throughput etc.when this script trigger tbench
# test cases.
# 1) Run tbench benchmark on specific governors, ondemand or schedutil.
# 2) Run tbench benchmark comparative test on acpi-cpufreq kernel driver.
# 3) Get desire performance, frequency, load by perf.
# 4) Get power consumption and throughput by amd_pstate_trace.py.
# 5) Analyse test results and save it in file selftest.tbench.csv.
# 6) Plot png images about performance, energy and performance per watt for each test.
# protect against multiple inclusion
if [ $FILE_TBENCH ]; then
return 0
else
FILE_TBENCH=DONE
fi
tbench_governors=("ondemand" "schedutil")
# $1: governor, $2: round, $3: des-perf, $4: freq, $5: load, $6: performance, $7: energy, $8: performance per watt
store_csv_tbench()
{
echo "$1, $2, $3, $4, $5, $6, $7, $8" | tee -a $OUTFILE_TBENCH.csv > /dev/null 2>&1
}
# clear some special lines
clear_csv_tbench()
{
if [ -f $OUTFILE_TBENCH.csv ]; then
sed -i '/Comprison(%)/d' $OUTFILE_TBENCH.csv
sed -i "/$(scaling_name)/d" $OUTFILE_TBENCH.csv
fi
}
# find string $1 in file csv and get the number of lines
get_lines_csv_tbench()
{
if [ -f $OUTFILE_TBENCH.csv ]; then
return `grep -c "$1" $OUTFILE_TBENCH.csv`
else
return 0
fi
}
pre_clear_tbench()
{
post_clear_tbench
rm -rf tbench_*.png
clear_csv_tbench
}
post_clear_tbench()
{
rm -rf results/tracer-tbench*
rm -rf $OUTFILE_TBENCH*.log
rm -rf $OUTFILE_TBENCH*.result
}
# $1: governor, $2: loop
run_tbench()
{
echo "Launching amd pstate tracer for $1 #$2 tracer_interval: $TRACER_INTERVAL"
./amd_pstate_trace.py -n tracer-tbench-$1-$2 -i $TRACER_INTERVAL > /dev/null 2>&1 &
printf "Test tbench for $1 #$2 time_limit: $TIME_LIMIT procs_num: $PROCESS_NUM\n"
tbench_srv > /dev/null 2>&1 &
perf stat -a --per-socket -I 1000 -e power/energy-pkg/ tbench -t $TIME_LIMIT $PROCESS_NUM > $OUTFILE_TBENCH-perf-$1-$2.log 2>&1
pid=`pidof tbench_srv`
kill $pid
for job in `jobs -p`
do
echo "Waiting for job id $job"
wait $job
done
}
# $1: governor, $2: loop
parse_tbench()
{
awk '{print $5}' results/tracer-tbench-$1-$2/cpu.csv | sed -e '1d' | sed s/,// > $OUTFILE_TBENCH-des-perf-$1-$2.log
avg_des_perf=$(awk 'BEGIN {i=0; sum=0};{i++; sum += $1};END {print sum/i}' $OUTFILE_TBENCH-des-perf-$1-$2.log)
printf "Tbench-$1-#$2 avg des perf: $avg_des_perf\n" | tee -a $OUTFILE_TBENCH.result
awk '{print $7}' results/tracer-tbench-$1-$2/cpu.csv | sed -e '1d' | sed s/,// > $OUTFILE_TBENCH-freq-$1-$2.log
avg_freq=$(awk 'BEGIN {i=0; sum=0};{i++; sum += $1};END {print sum/i}' $OUTFILE_TBENCH-freq-$1-$2.log)
printf "Tbench-$1-#$2 avg freq: $avg_freq\n" | tee -a $OUTFILE_TBENCH.result
awk '{print $11}' results/tracer-tbench-$1-$2/cpu.csv | sed -e '1d' | sed s/,// > $OUTFILE_TBENCH-load-$1-$2.log
avg_load=$(awk 'BEGIN {i=0; sum=0};{i++; sum += $1};END {print sum/i}' $OUTFILE_TBENCH-load-$1-$2.log)
printf "Tbench-$1-#$2 avg load: $avg_load\n" | tee -a $OUTFILE_TBENCH.result
grep Throughput $OUTFILE_TBENCH-perf-$1-$2.log | awk '{print $2}' > $OUTFILE_TBENCH-throughput-$1-$2.log
tp_sum=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum}' $OUTFILE_TBENCH-throughput-$1-$2.log)
printf "Tbench-$1-#$2 throughput(MB/s): $tp_sum\n" | tee -a $OUTFILE_TBENCH.result
grep Joules $OUTFILE_TBENCH-perf-$1-$2.log | awk '{print $4}' > $OUTFILE_TBENCH-energy-$1-$2.log
en_sum=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum}' $OUTFILE_TBENCH-energy-$1-$2.log)
printf "Tbench-$1-#$2 power consumption(J): $en_sum\n" | tee -a $OUTFILE_TBENCH.result
# Permance is throughput per second, denoted T/t, where T is throught rendered in t seconds.
# It is well known that P=E/t, where P is power measured in watts(W), E is energy measured in joules(J),
# and t is time measured in seconds(s). This means that performance per watt becomes
# T/t T/t T
# --- = --- = ---
# P E/t E
# with unit given by MB per joule.
ppw=`echo "scale=4;($TIME_LIMIT-1)*$tp_sum/$en_sum" | bc | awk '{printf "%.4f", $0}'`
printf "Tbench-$1-#$2 performance per watt(MB/J): $ppw\n" | tee -a $OUTFILE_TBENCH.result
printf "\n" | tee -a $OUTFILE_TBENCH.result
driver_name=`echo $(scaling_name)`
store_csv_tbench "$driver_name-$1" $2 $avg_des_perf $avg_freq $avg_load $tp_sum $en_sum $ppw
}
# $1: governor
loop_tbench()
{
printf "\nTbench total test times is $LOOP_TIMES for $1\n\n"
for i in `seq 1 $LOOP_TIMES`
do
run_tbench $1 $i
parse_tbench $1 $i
done
}
# $1: governor
gather_tbench()
{
printf "Tbench test result for $1 (loops:$LOOP_TIMES)" | tee -a $OUTFILE_TBENCH.result
printf "\n--------------------------------------------------\n" | tee -a $OUTFILE_TBENCH.result
grep "Tbench-$1-#" $OUTFILE_TBENCH.result | grep "avg des perf:" | awk '{print $NF}' > $OUTFILE_TBENCH-des-perf-$1.log
avg_des_perf=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_TBENCH-des-perf-$1.log)
printf "Tbench-$1 avg des perf: $avg_des_perf\n" | tee -a $OUTFILE_TBENCH.result
grep "Tbench-$1-#" $OUTFILE_TBENCH.result | grep "avg freq:" | awk '{print $NF}' > $OUTFILE_TBENCH-freq-$1.log
avg_freq=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_TBENCH-freq-$1.log)
printf "Tbench-$1 avg freq: $avg_freq\n" | tee -a $OUTFILE_TBENCH.result
grep "Tbench-$1-#" $OUTFILE_TBENCH.result | grep "avg load:" | awk '{print $NF}' > $OUTFILE_TBENCH-load-$1.log
avg_load=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_TBENCH-load-$1.log)
printf "Tbench-$1 avg load: $avg_load\n" | tee -a $OUTFILE_TBENCH.result
grep "Tbench-$1-#" $OUTFILE_TBENCH.result | grep "throughput(MB/s):" | awk '{print $NF}' > $OUTFILE_TBENCH-throughput-$1.log
tp_sum=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum}' $OUTFILE_TBENCH-throughput-$1.log)
printf "Tbench-$1 total throughput(MB/s): $tp_sum\n" | tee -a $OUTFILE_TBENCH.result
avg_tp=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_TBENCH-throughput-$1.log)
printf "Tbench-$1 avg throughput(MB/s): $avg_tp\n" | tee -a $OUTFILE_TBENCH.result
grep "Tbench-$1-#" $OUTFILE_TBENCH.result | grep "power consumption(J):" | awk '{print $NF}' > $OUTFILE_TBENCH-energy-$1.log
en_sum=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum}' $OUTFILE_TBENCH-energy-$1.log)
printf "Tbench-$1 total power consumption(J): $en_sum\n" | tee -a $OUTFILE_TBENCH.result
avg_en=$(awk 'BEGIN {sum=0};{sum += $1};END {print sum/'$LOOP_TIMES'}' $OUTFILE_TBENCH-energy-$1.log)
printf "Tbench-$1 avg power consumption(J): $avg_en\n" | tee -a $OUTFILE_TBENCH.result
# Permance is throughput per second, denoted T/t, where T is throught rendered in t seconds.
# It is well known that P=E/t, where P is power measured in watts(W), E is energy measured in joules(J),
# and t is time measured in seconds(s). This means that performance per watt becomes
# T/t T/t T
# --- = --- = ---
# P E/t E
# with unit given by MB per joule.
ppw=`echo "scale=4;($TIME_LIMIT-1)*$avg_tp/$avg_en" | bc | awk '{printf "%.4f", $0}'`
printf "Tbench-$1 performance per watt(MB/J): $ppw\n" | tee -a $OUTFILE_TBENCH.result
printf "\n" | tee -a $OUTFILE_TBENCH.result
driver_name=`echo $(scaling_name)`
store_csv_tbench "$driver_name-$1" "Average" $avg_des_perf $avg_freq $avg_load $avg_tp $avg_en $ppw
}
# $1: base scaling_driver $2: base governor $3: comparative scaling_driver $4: comparative governor
__calc_comp_tbench()
{
base=`grep "$1-$2" $OUTFILE_TBENCH.csv | grep "Average"`
comp=`grep "$3-$4" $OUTFILE_TBENCH.csv | grep "Average"`
if [ -n "$base" -a -n "$comp" ]; then
printf "\n==================================================\n" | tee -a $OUTFILE_TBENCH.result
printf "Tbench comparison $1-$2 VS $3-$4" | tee -a $OUTFILE_TBENCH.result
printf "\n==================================================\n" | tee -a $OUTFILE_TBENCH.result
# get the base values
des_perf_base=`echo "$base" | awk '{print $3}' | sed s/,//`
freq_base=`echo "$base" | awk '{print $4}' | sed s/,//`
load_base=`echo "$base" | awk '{print $5}' | sed s/,//`
perf_base=`echo "$base" | awk '{print $6}' | sed s/,//`
energy_base=`echo "$base" | awk '{print $7}' | sed s/,//`
ppw_base=`echo "$base" | awk '{print $8}' | sed s/,//`
# get the comparative values
des_perf_comp=`echo "$comp" | awk '{print $3}' | sed s/,//`
freq_comp=`echo "$comp" | awk '{print $4}' | sed s/,//`
load_comp=`echo "$comp" | awk '{print $5}' | sed s/,//`
perf_comp=`echo "$comp" | awk '{print $6}' | sed s/,//`
energy_comp=`echo "$comp" | awk '{print $7}' | sed s/,//`
ppw_comp=`echo "$comp" | awk '{print $8}' | sed s/,//`
# compare the base and comp values
des_perf_drop=`echo "scale=4;($des_perf_comp-$des_perf_base)*100/$des_perf_base" | bc | awk '{printf "%.4f", $0}'`
printf "Tbench-$1 des perf base: $des_perf_base comprison: $des_perf_comp percent: $des_perf_drop\n" | tee -a $OUTFILE_TBENCH.result
freq_drop=`echo "scale=4;($freq_comp-$freq_base)*100/$freq_base" | bc | awk '{printf "%.4f", $0}'`
printf "Tbench-$1 freq base: $freq_base comprison: $freq_comp percent: $freq_drop\n" | tee -a $OUTFILE_TBENCH.result
load_drop=`echo "scale=4;($load_comp-$load_base)*100/$load_base" | bc | awk '{printf "%.4f", $0}'`
printf "Tbench-$1 load base: $load_base comprison: $load_comp percent: $load_drop\n" | tee -a $OUTFILE_TBENCH.result
perf_drop=`echo "scale=4;($perf_comp-$perf_base)*100/$perf_base" | bc | awk '{printf "%.4f", $0}'`
printf "Tbench-$1 perf base: $perf_base comprison: $perf_comp percent: $perf_drop\n" | tee -a $OUTFILE_TBENCH.result
energy_drop=`echo "scale=4;($energy_comp-$energy_base)*100/$energy_base" | bc | awk '{printf "%.4f", $0}'`
printf "Tbench-$1 energy base: $energy_base comprison: $energy_comp percent: $energy_drop\n" | tee -a $OUTFILE_TBENCH.result
ppw_drop=`echo "scale=4;($ppw_comp-$ppw_base)*100/$ppw_base" | bc | awk '{printf "%.4f", $0}'`
printf "Tbench-$1 performance per watt base: $ppw_base comprison: $ppw_comp percent: $ppw_drop\n" | tee -a $OUTFILE_TBENCH.result
printf "\n" | tee -a $OUTFILE_TBENCH.result
store_csv_tbench "$1-$2 VS $3-$4" "Comprison(%)" "$des_perf_drop" "$freq_drop" "$load_drop" "$perf_drop" "$energy_drop" "$ppw_drop"
fi
}
# calculate the comparison(%)
calc_comp_tbench()
{
# acpi-cpufreq-ondemand VS acpi-cpufreq-schedutil
__calc_comp_tbench ${all_scaling_names[0]} ${tbench_governors[0]} ${all_scaling_names[0]} ${tbench_governors[1]}
# amd-pstate-ondemand VS amd-pstate-schedutil
__calc_comp_tbench ${all_scaling_names[1]} ${tbench_governors[0]} ${all_scaling_names[1]} ${tbench_governors[1]}
# acpi-cpufreq-ondemand VS amd-pstate-ondemand
__calc_comp_tbench ${all_scaling_names[0]} ${tbench_governors[0]} ${all_scaling_names[1]} ${tbench_governors[0]}
# acpi-cpufreq-schedutil VS amd-pstate-schedutil
__calc_comp_tbench ${all_scaling_names[0]} ${tbench_governors[1]} ${all_scaling_names[1]} ${tbench_governors[1]}
}
# $1: file_name, $2: title, $3: ylable, $4: column
plot_png_tbench()
{
# all_scaling_names[1] all_scaling_names[0] flag
# amd-pstate acpi-cpufreq
# N N 0
# N Y 1
# Y N 2
# Y Y 3
ret=`grep -c "${all_scaling_names[1]}" $OUTFILE_TBENCH.csv`
if [ $ret -eq 0 ]; then
ret=`grep -c "${all_scaling_names[0]}" $OUTFILE_TBENCH.csv`
if [ $ret -eq 0 ]; then
flag=0
else
flag=1
fi
else
ret=`grep -c "${all_scaling_names[0]}" $OUTFILE_TBENCH.csv`
if [ $ret -eq 0 ]; then
flag=2
else
flag=3
fi
fi
gnuplot << EOF
set term png
set output "$1"
set title "$2"
set xlabel "Test Cycles (round)"
set ylabel "$3"
set grid
set style data histogram
set style fill solid 0.5 border
set boxwidth 0.8
if ($flag == 1) {
plot \
"<(sed -n -e 's/,//g' -e '/${all_scaling_names[0]}-${tbench_governors[0]}/p' $OUTFILE_TBENCH.csv)" using $4:xtic(2) title "${all_scaling_names[0]}-${tbench_governors[0]}", \
"<(sed -n -e 's/,//g' -e '/${all_scaling_names[0]}-${tbench_governors[1]}/p' $OUTFILE_TBENCH.csv)" using $4:xtic(2) title "${all_scaling_names[0]}-${tbench_governors[1]}"
} else {
if ($flag == 2) {
plot \
"<(sed -n -e 's/,//g' -e '/${all_scaling_names[1]}-${tbench_governors[0]}/p' $OUTFILE_TBENCH.csv)" using $4:xtic(2) title "${all_scaling_names[1]}-${tbench_governors[0]}", \
"<(sed -n -e 's/,//g' -e '/${all_scaling_names[1]}-${tbench_governors[1]}/p' $OUTFILE_TBENCH.csv)" using $4:xtic(2) title "${all_scaling_names[1]}-${tbench_governors[1]}"
} else {
if ($flag == 3 ) {
plot \
"<(sed -n -e 's/,//g' -e '/${all_scaling_names[0]}-${tbench_governors[0]}/p' $OUTFILE_TBENCH.csv)" using $4:xtic(2) title "${all_scaling_names[0]}-${tbench_governors[0]}", \
"<(sed -n -e 's/,//g' -e '/${all_scaling_names[0]}-${tbench_governors[1]}/p' $OUTFILE_TBENCH.csv)" using $4:xtic(2) title "${all_scaling_names[0]}-${tbench_governors[1]}", \
"<(sed -n -e 's/,//g' -e '/${all_scaling_names[1]}-${tbench_governors[0]}/p' $OUTFILE_TBENCH.csv)" using $4:xtic(2) title "${all_scaling_names[1]}-${tbench_governors[0]}", \
"<(sed -n -e 's/,//g' -e '/${all_scaling_names[1]}-${tbench_governors[1]}/p' $OUTFILE_TBENCH.csv)" using $4:xtic(2) title "${all_scaling_names[1]}-${tbench_governors[1]}"
}
}
}
quit
EOF
}
amd_pstate_tbench()
{
printf "\n---------------------------------------------\n"
printf "*** Running tbench ***"
printf "\n---------------------------------------------\n"
pre_clear_tbench
get_lines_csv_tbench "Governor"
if [ $? -eq 0 ]; then
# add titles and unit for csv file
store_csv_tbench "Governor" "Round" "Des-perf" "Freq" "Load" "Performance" "Energy" "Performance Per Watt"
store_csv_tbench "Unit" "" "" "GHz" "" "MB/s" "J" "MB/J"
fi
backup_governor
for governor in ${tbench_governors[*]} ; do
printf "\nSpecified governor is $governor\n\n"
switch_governor $governor
loop_tbench $governor
gather_tbench $governor
done
restore_governor
plot_png_tbench "tbench_perfromance.png" "Tbench Benchmark Performance" "Performance" 6
plot_png_tbench "tbench_energy.png" "Tbench Benchmark Energy" "Energy (J)" 7
plot_png_tbench "tbench_ppw.png" "Tbench Benchmark Performance Per Watt" "Performance Per Watt (MB/J)" 8
calc_comp_tbench
post_clear_tbench
}
...@@ -87,6 +87,11 @@ test_create_read() ...@@ -87,6 +87,11 @@ test_create_read()
{ {
local file=$efivarfs_mount/$FUNCNAME-$test_guid local file=$efivarfs_mount/$FUNCNAME-$test_guid
./create-read $file ./create-read $file
if [ $? -ne 0 ]; then
echo "create and read $file failed"
file_cleanup $file
exit 1
fi
file_cleanup $file file_cleanup $file
} }
......
...@@ -38,11 +38,18 @@ cnt_trace() { ...@@ -38,11 +38,18 @@ cnt_trace() {
test_event_enabled() { test_event_enabled() {
val=$1 val=$1
check_times=10 # wait for 10 * SLEEP_TIME at most
while [ $check_times -ne 0 ]; do
e=`cat $EVENT_ENABLE` e=`cat $EVENT_ENABLE`
if [ "$e" != $val ]; then if [ "$e" == $val ]; then
fail "Expected $val but found $e" return 0
fi fi
sleep $SLEEP_TIME
check_times=$((check_times - 1))
done
fail "Expected $val but found $e"
} }
run_enable_disable() { run_enable_disable() {
......
...@@ -142,9 +142,15 @@ finish_ftrace() { ...@@ -142,9 +142,15 @@ finish_ftrace() {
check_requires() { # Check required files and tracers check_requires() { # Check required files and tracers
for i in "$@" ; do for i in "$@" ; do
p=${i%:program}
r=${i%:README} r=${i%:README}
t=${i%:tracer} t=${i%:tracer}
if [ $t != $i ]; then if [ $p != $i ]; then
if ! which $p ; then
echo "Required program $p is not found."
exit_unresolved
fi
elif [ $t != $i ]; then
if ! grep -wq $t available_tracers ; then if ! grep -wq $t available_tracers ; then
echo "Required tracer $t is not configured." echo "Required tracer $t is not configured."
exit_unsupported exit_unsupported
......
...@@ -46,10 +46,10 @@ cat trace ...@@ -46,10 +46,10 @@ cat trace
grep -q "tracer: preemptoff" trace || fail grep -q "tracer: preemptoff" trace || fail
# Check the end of the section # Check the end of the section
egrep -q "5.....us : <stack trace>" trace || fail grep -E -q "5.....us : <stack trace>" trace || fail
# Check for 500ms of latency # Check for 500ms of latency
egrep -q "latency: 5..... us" trace || fail grep -E -q "latency: 5..... us" trace || fail
reset_tracer reset_tracer
...@@ -69,10 +69,10 @@ cat trace ...@@ -69,10 +69,10 @@ cat trace
grep -q "tracer: irqsoff" trace || fail grep -q "tracer: irqsoff" trace || fail
# Check the end of the section # Check the end of the section
egrep -q "5.....us : <stack trace>" trace || fail grep -E -q "5.....us : <stack trace>" trace || fail
# Check for 500ms of latency # Check for 500ms of latency
egrep -q "latency: 5..... us" trace || fail grep -E -q "latency: 5..... us" trace || fail
reset_tracer reset_tracer
exit 0 exit 0
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# description: Test wakeup tracer # description: Test wakeup tracer
# requires: wakeup:tracer # requires: wakeup:tracer chrt:program
if ! which chrt ; then
echo "chrt is not found. This test requires nice command."
exit_unresolved
fi
echo wakeup > current_tracer echo wakeup > current_tracer
echo 1 > tracing_on echo 1 > tracing_on
......
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# description: Test wakeup RT tracer # description: Test wakeup RT tracer
# requires: wakeup_rt:tracer # requires: wakeup_rt:tracer chrt:program
if ! which chrt ; then
echo "chrt is not found. This test requires chrt command."
exit_unresolved
fi
echo wakeup_rt > current_tracer echo wakeup_rt > current_tracer
echo 1 > tracing_on echo 1 > tracing_on
......
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# description: event trigger - test field variable support # description: event trigger - test field variable support
# requires: set_event synthetic_events events/sched/sched_process_fork/hist # requires: set_event synthetic_events events/sched/sched_process_fork/hist ping:program
fail() { #msg fail() { #msg
echo $1 echo $1
......
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# description: event trigger - test inter-event combined histogram trigger # description: event trigger - test inter-event combined histogram trigger
# requires: set_event synthetic_events events/sched/sched_process_fork/hist # requires: set_event synthetic_events events/sched/sched_process_fork/hist ping:program
fail() { #msg fail() { #msg
echo $1 echo $1
......
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# description: event trigger - test inter-event histogram trigger onchange action # description: event trigger - test inter-event histogram trigger onchange action
# requires: set_event "onchange(var)":README # requires: set_event "onchange(var)":README ping:program
fail() { #msg fail() { #msg
echo $1 echo $1
......
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# description: event trigger - test inter-event histogram trigger onmatch action # description: event trigger - test inter-event histogram trigger onmatch action
# requires: set_event synthetic_events events/sched/sched_process_fork/hist # requires: set_event synthetic_events events/sched/sched_process_fork/hist ping:program
fail() { #msg fail() { #msg
echo $1 echo $1
......
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# description: event trigger - test inter-event histogram trigger onmatch-onmax action # description: event trigger - test inter-event histogram trigger onmatch-onmax action
# requires: set_event synthetic_events events/sched/sched_process_fork/hist # requires: set_event synthetic_events events/sched/sched_process_fork/hist ping:program
fail() { #msg fail() { #msg
echo $1 echo $1
......
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# description: event trigger - test inter-event histogram trigger onmax action # description: event trigger - test inter-event histogram trigger onmax action
# requires: set_event synthetic_events events/sched/sched_process_fork/hist # requires: set_event synthetic_events events/sched/sched_process_fork/hist ping:program
fail() { #msg fail() { #msg
echo $1 echo $1
......
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# description: event trigger - test inter-event histogram trigger snapshot action # description: event trigger - test inter-event histogram trigger snapshot action
# requires: set_event snapshot events/sched/sched_process_fork/hist "onchange(var)":README "snapshot()":README # requires: set_event snapshot events/sched/sched_process_fork/hist "onchange(var)":README "snapshot()":README ping:program
fail() { #msg fail() { #msg
echo $1 echo $1
......
...@@ -14,7 +14,7 @@ FIELD="filename" ...@@ -14,7 +14,7 @@ FIELD="filename"
SYNTH="synth_open" SYNTH="synth_open"
EPROBE="eprobe_open" EPROBE="eprobe_open"
echo "$SYNTH u64 filename; s64 ret;" > synthetic_events echo "$SYNTH unsigned long filename; long ret;" > synthetic_events
echo "hist:keys=common_pid:__arg__1=$FIELD" > events/$SYSTEM/$START/trigger echo "hist:keys=common_pid:__arg__1=$FIELD" > events/$SYSTEM/$START/trigger
echo "hist:keys=common_pid:filename=\$__arg__1,ret=ret:onmatch($SYSTEM.$START).trace($SYNTH,\$filename,\$ret)" > events/$SYSTEM/$END/trigger echo "hist:keys=common_pid:filename=\$__arg__1,ret=ret:onmatch($SYSTEM.$START).trace($SYNTH,\$filename,\$ret)" > events/$SYSTEM/$END/trigger
......
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# description: event trigger - test inter-event histogram trigger trace action with dynamic string param # description: event trigger - test inter-event histogram trigger trace action with dynamic string param
# requires: set_event synthetic_events events/sched/sched_process_exec/hist "char name[]' >> synthetic_events":README # requires: set_event synthetic_events events/sched/sched_process_exec/hist "char name[]' >> synthetic_events":README ping:program
fail() { #msg fail() { #msg
echo $1 echo $1
......
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# description: event trigger - test inter-event histogram trigger trace action # description: event trigger - test inter-event histogram trigger trace action
# requires: set_event synthetic_events events/sched/sched_process_fork/hist "trace(<synthetic_event>":README # requires: set_event synthetic_events events/sched/sched_process_fork/hist "trace(<synthetic_event>":README ping:program
fail() { #msg fail() { #msg
echo $1 echo $1
......
...@@ -27,7 +27,7 @@ remove_chip() { ...@@ -27,7 +27,7 @@ remove_chip() {
continue continue
fi fi
LINES=`ls $CONFIGFS_DIR/$CHIP/$BANK/ | egrep ^line` LINES=`ls $CONFIGFS_DIR/$CHIP/$BANK/ | grep -E ^line`
if [ "$?" = 0 ]; then if [ "$?" = 0 ]; then
for LINE in $LINES; do for LINE in $LINES; do
if [ -e $CONFIGFS_DIR/$CHIP/$BANK/$LINE/hog ]; then if [ -e $CONFIGFS_DIR/$CHIP/$BANK/$LINE/hog ]; then
......
...@@ -90,7 +90,7 @@ pass_libs=() ...@@ -90,7 +90,7 @@ pass_libs=()
pass_cnt=0 pass_cnt=0
# Get all TARGETS from selftests Makefile # Get all TARGETS from selftests Makefile
targets=$(egrep "^TARGETS +|^TARGETS =" Makefile | cut -d "=" -f2) targets=$(grep -E "^TARGETS +|^TARGETS =" Makefile | cut -d "=" -f2)
# Single test case # Single test case
if [ $# -eq 2 ] if [ $# -eq 2 ]
......
...@@ -123,6 +123,11 @@ endef ...@@ -123,6 +123,11 @@ endef
clean: clean:
$(CLEAN) $(CLEAN)
# Enables to extend CFLAGS and LDFLAGS from command line, e.g.
# make USERCFLAGS=-Werror USERLDFLAGS=-static
CFLAGS += $(USERCFLAGS)
LDFLAGS += $(USERLDFLAGS)
# When make O= with kselftest target from main level # When make O= with kselftest target from main level
# the following aren't defined. # the following aren't defined.
# #
......
...@@ -31,7 +31,6 @@ FIXTURE(rtc) { ...@@ -31,7 +31,6 @@ FIXTURE(rtc) {
FIXTURE_SETUP(rtc) { FIXTURE_SETUP(rtc) {
self->fd = open(rtc_file, O_RDONLY); self->fd = open(rtc_file, O_RDONLY);
ASSERT_NE(-1, self->fd);
} }
FIXTURE_TEARDOWN(rtc) { FIXTURE_TEARDOWN(rtc) {
...@@ -42,6 +41,10 @@ TEST_F(rtc, date_read) { ...@@ -42,6 +41,10 @@ TEST_F(rtc, date_read) {
int rc; int rc;
struct rtc_time rtc_tm; struct rtc_time rtc_tm;
if (self->fd == -1 && errno == ENOENT)
SKIP(return, "Skipping test since %s does not exist", rtc_file);
ASSERT_NE(-1, self->fd);
/* Read the RTC time/date */ /* Read the RTC time/date */
rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm); rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm);
ASSERT_NE(-1, rc); ASSERT_NE(-1, rc);
...@@ -85,6 +88,10 @@ TEST_F_TIMEOUT(rtc, date_read_loop, READ_LOOP_DURATION_SEC + 2) { ...@@ -85,6 +88,10 @@ TEST_F_TIMEOUT(rtc, date_read_loop, READ_LOOP_DURATION_SEC + 2) {
struct rtc_time rtc_tm; struct rtc_time rtc_tm;
time_t start_rtc_read, prev_rtc_read; time_t start_rtc_read, prev_rtc_read;
if (self->fd == -1 && errno == ENOENT)
SKIP(return, "Skipping test since %s does not exist", rtc_file);
ASSERT_NE(-1, self->fd);
TH_LOG("Continuously reading RTC time for %ds (with %dms breaks after every read).", TH_LOG("Continuously reading RTC time for %ds (with %dms breaks after every read).",
READ_LOOP_DURATION_SEC, READ_LOOP_SLEEP_MS); READ_LOOP_DURATION_SEC, READ_LOOP_SLEEP_MS);
...@@ -119,6 +126,10 @@ TEST_F_TIMEOUT(rtc, uie_read, NUM_UIE + 2) { ...@@ -119,6 +126,10 @@ TEST_F_TIMEOUT(rtc, uie_read, NUM_UIE + 2) {
int i, rc, irq = 0; int i, rc, irq = 0;
unsigned long data; unsigned long data;
if (self->fd == -1 && errno == ENOENT)
SKIP(return, "Skipping test since %s does not exist", rtc_file);
ASSERT_NE(-1, self->fd);
/* Turn on update interrupts */ /* Turn on update interrupts */
rc = ioctl(self->fd, RTC_UIE_ON, 0); rc = ioctl(self->fd, RTC_UIE_ON, 0);
if (rc == -1) { if (rc == -1) {
...@@ -144,6 +155,10 @@ TEST_F(rtc, uie_select) { ...@@ -144,6 +155,10 @@ TEST_F(rtc, uie_select) {
int i, rc, irq = 0; int i, rc, irq = 0;
unsigned long data; unsigned long data;
if (self->fd == -1 && errno == ENOENT)
SKIP(return, "Skipping test since %s does not exist", rtc_file);
ASSERT_NE(-1, self->fd);
/* Turn on update interrupts */ /* Turn on update interrupts */
rc = ioctl(self->fd, RTC_UIE_ON, 0); rc = ioctl(self->fd, RTC_UIE_ON, 0);
if (rc == -1) { if (rc == -1) {
...@@ -183,6 +198,10 @@ TEST_F(rtc, alarm_alm_set) { ...@@ -183,6 +198,10 @@ TEST_F(rtc, alarm_alm_set) {
time_t secs, new; time_t secs, new;
int rc; int rc;
if (self->fd == -1 && errno == ENOENT)
SKIP(return, "Skipping test since %s does not exist", rtc_file);
ASSERT_NE(-1, self->fd);
rc = ioctl(self->fd, RTC_RD_TIME, &tm); rc = ioctl(self->fd, RTC_RD_TIME, &tm);
ASSERT_NE(-1, rc); ASSERT_NE(-1, rc);
...@@ -237,6 +256,10 @@ TEST_F(rtc, alarm_wkalm_set) { ...@@ -237,6 +256,10 @@ TEST_F(rtc, alarm_wkalm_set) {
time_t secs, new; time_t secs, new;
int rc; int rc;
if (self->fd == -1 && errno == ENOENT)
SKIP(return, "Skipping test since %s does not exist", rtc_file);
ASSERT_NE(-1, self->fd);
rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time); rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time);
ASSERT_NE(-1, rc); ASSERT_NE(-1, rc);
...@@ -285,6 +308,10 @@ TEST_F_TIMEOUT(rtc, alarm_alm_set_minute, 65) { ...@@ -285,6 +308,10 @@ TEST_F_TIMEOUT(rtc, alarm_alm_set_minute, 65) {
time_t secs, new; time_t secs, new;
int rc; int rc;
if (self->fd == -1 && errno == ENOENT)
SKIP(return, "Skipping test since %s does not exist", rtc_file);
ASSERT_NE(-1, self->fd);
rc = ioctl(self->fd, RTC_RD_TIME, &tm); rc = ioctl(self->fd, RTC_RD_TIME, &tm);
ASSERT_NE(-1, rc); ASSERT_NE(-1, rc);
...@@ -339,6 +366,10 @@ TEST_F_TIMEOUT(rtc, alarm_wkalm_set_minute, 65) { ...@@ -339,6 +366,10 @@ TEST_F_TIMEOUT(rtc, alarm_wkalm_set_minute, 65) {
time_t secs, new; time_t secs, new;
int rc; int rc;
if (self->fd == -1 && errno == ENOENT)
SKIP(return, "Skipping test since %s does not exist", rtc_file);
ASSERT_NE(-1, self->fd);
rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time); rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time);
ASSERT_NE(-1, rc); ASSERT_NE(-1, rc);
......
...@@ -127,7 +127,7 @@ expect_success "proc_handler: special read splice" test_splice /proc/sys/kernel/ ...@@ -127,7 +127,7 @@ expect_success "proc_handler: special read splice" test_splice /proc/sys/kernel/
if ! [ -d /sys/module/test_module/sections ] ; then if ! [ -d /sys/module/test_module/sections ] ; then
expect_success "test_module kernel module load" modprobe test_module expect_success "test_module kernel module load" modprobe test_module
fi fi
expect_failure "kernfs attr splice" test_splice /sys/module/test_module/coresize expect_success "kernfs attr splice" test_splice /sys/module/test_module/coresize
expect_failure "kernfs binattr splice" test_splice /sys/module/test_module/sections/.init.text expect_success "kernfs binattr splice" test_splice /sys/module/test_module/sections/.init.text
exit $ret exit $ret
# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
include ../lib.mk include ../lib.mk
TEST_PROGS := test_smoke.sh test_space.sh TEST_PROGS := test_smoke.sh test_space.sh test_async.sh
TEST_PROGS_EXTENDED := tpm2.py tpm2_tests.py TEST_PROGS_EXTENDED := tpm2.py tpm2_tests.py
#!/bin/sh
# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
# Kselftest framework requirement - SKIP code is 4.
ksft_skip=4
[ -e /dev/tpm0 ] || exit $ksft_skip
[ -e /dev/tpmrm0 ] || exit $ksft_skip
python3 -m unittest -v tpm2_tests.AsyncTest
...@@ -7,4 +7,3 @@ ksft_skip=4 ...@@ -7,4 +7,3 @@ ksft_skip=4
[ -e /dev/tpm0 ] || exit $ksft_skip [ -e /dev/tpm0 ] || exit $ksft_skip
python3 -m unittest -v tpm2_tests.SmokeTest python3 -m unittest -v tpm2_tests.SmokeTest
python3 -m unittest -v tpm2_tests.AsyncTest
...@@ -14,7 +14,11 @@ ...@@ -14,7 +14,11 @@
#include "../kselftest.h" #include "../kselftest.h"
#include "parse_vdso.h" #include "parse_vdso.h"
#if defined(__riscv)
const char *version = "LINUX_4.15";
#else
const char *version = "LINUX_2.6"; const char *version = "LINUX_2.6";
#endif
const char *name = "__vdso_getcpu"; const char *name = "__vdso_getcpu";
struct getcpu_cache; struct getcpu_cache;
......
...@@ -27,6 +27,9 @@ ...@@ -27,6 +27,9 @@
#if defined(__aarch64__) #if defined(__aarch64__)
const char *version = "LINUX_2.6.39"; const char *version = "LINUX_2.6.39";
const char *name = "__kernel_gettimeofday"; const char *name = "__kernel_gettimeofday";
#elif defined(__riscv)
const char *version = "LINUX_4.15";
const char *name = "__vdso_gettimeofday";
#else #else
const char *version = "LINUX_2.6"; const char *version = "LINUX_2.6";
const char *name = "__vdso_gettimeofday"; const char *name = "__vdso_gettimeofday";
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
/* /*
* Watchdog Driver Test Program * Watchdog Driver Test Program
* - Tests all ioctls
* - Tests Magic Close - CONFIG_WATCHDOG_NOWAYOUT
* - Could be tested against softdog driver on systems that
* don't have watchdog hardware.
* - TODO:
* - Enhance test to add coverage for WDIOC_GETTEMP.
*
* Reference: Documentation/watchdog/watchdog-api.rst
*/ */
#include <errno.h> #include <errno.h>
...@@ -19,13 +27,14 @@ ...@@ -19,13 +27,14 @@
int fd; int fd;
const char v = 'V'; const char v = 'V';
static const char sopts[] = "bdehp:t:Tn:NLf:i"; static const char sopts[] = "bdehp:st:Tn:NLf:i";
static const struct option lopts[] = { static const struct option lopts[] = {
{"bootstatus", no_argument, NULL, 'b'}, {"bootstatus", no_argument, NULL, 'b'},
{"disable", no_argument, NULL, 'd'}, {"disable", no_argument, NULL, 'd'},
{"enable", no_argument, NULL, 'e'}, {"enable", no_argument, NULL, 'e'},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{"pingrate", required_argument, NULL, 'p'}, {"pingrate", required_argument, NULL, 'p'},
{"status", no_argument, NULL, 's'},
{"timeout", required_argument, NULL, 't'}, {"timeout", required_argument, NULL, 't'},
{"gettimeout", no_argument, NULL, 'T'}, {"gettimeout", no_argument, NULL, 'T'},
{"pretimeout", required_argument, NULL, 'n'}, {"pretimeout", required_argument, NULL, 'n'},
...@@ -74,6 +83,7 @@ static void usage(char *progname) ...@@ -74,6 +83,7 @@ static void usage(char *progname)
printf(" -f, --file\t\tOpen watchdog device file\n"); printf(" -f, --file\t\tOpen watchdog device file\n");
printf("\t\t\tDefault is /dev/watchdog\n"); printf("\t\t\tDefault is /dev/watchdog\n");
printf(" -i, --info\t\tShow watchdog_info\n"); printf(" -i, --info\t\tShow watchdog_info\n");
printf(" -s, --status\t\tGet status & supported features\n");
printf(" -b, --bootstatus\tGet last boot status (Watchdog/POR)\n"); printf(" -b, --bootstatus\tGet last boot status (Watchdog/POR)\n");
printf(" -d, --disable\t\tTurn off the watchdog timer\n"); printf(" -d, --disable\t\tTurn off the watchdog timer\n");
printf(" -e, --enable\t\tTurn on the watchdog timer\n"); printf(" -e, --enable\t\tTurn on the watchdog timer\n");
...@@ -91,6 +101,73 @@ static void usage(char *progname) ...@@ -91,6 +101,73 @@ static void usage(char *progname)
printf("Example: %s -t 12 -T -n 7 -N\n", progname); printf("Example: %s -t 12 -T -n 7 -N\n", progname);
} }
struct wdiof_status {
int flag;
const char *status_str;
};
#define WDIOF_NUM_STATUS 8
static const struct wdiof_status wdiof_status[WDIOF_NUM_STATUS] = {
{WDIOF_SETTIMEOUT, "Set timeout (in seconds)"},
{WDIOF_MAGICCLOSE, "Supports magic close char"},
{WDIOF_PRETIMEOUT, "Pretimeout (in seconds), get/set"},
{WDIOF_ALARMONLY, "Watchdog triggers a management or other external alarm not a reboot"},
{WDIOF_KEEPALIVEPING, "Keep alive ping reply"},
{WDIOS_DISABLECARD, "Turn off the watchdog timer"},
{WDIOS_ENABLECARD, "Turn on the watchdog timer"},
{WDIOS_TEMPPANIC, "Kernel panic on temperature trip"},
};
static void print_status(int flags)
{
int wdiof = 0;
if (flags == WDIOS_UNKNOWN) {
printf("Unknown status error from WDIOC_GETSTATUS\n");
return;
}
for (wdiof = 0; wdiof < WDIOF_NUM_STATUS; wdiof++) {
if (flags & wdiof_status[wdiof].flag)
printf("Support/Status: %s\n",
wdiof_status[wdiof].status_str);
}
}
#define WDIOF_NUM_BOOTSTATUS 7
static const struct wdiof_status wdiof_bootstatus[WDIOF_NUM_BOOTSTATUS] = {
{WDIOF_OVERHEAT, "Reset due to CPU overheat"},
{WDIOF_FANFAULT, "Fan failed"},
{WDIOF_EXTERN1, "External relay 1"},
{WDIOF_EXTERN2, "External relay 2"},
{WDIOF_POWERUNDER, "Power bad/power fault"},
{WDIOF_CARDRESET, "Card previously reset the CPU"},
{WDIOF_POWEROVER, "Power over voltage"},
};
static void print_boot_status(int flags)
{
int wdiof = 0;
if (flags == WDIOF_UNKNOWN) {
printf("Unknown flag error from WDIOC_GETBOOTSTATUS\n");
return;
}
if (flags == 0) {
printf("Last boot is caused by: Power-On-Reset\n");
return;
}
for (wdiof = 0; wdiof < WDIOF_NUM_BOOTSTATUS; wdiof++) {
if (flags & wdiof_bootstatus[wdiof].flag)
printf("Last boot is caused by: %s\n",
wdiof_bootstatus[wdiof].status_str);
}
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int flags; int flags;
...@@ -100,6 +177,7 @@ int main(int argc, char *argv[]) ...@@ -100,6 +177,7 @@ int main(int argc, char *argv[])
int oneshot = 0; int oneshot = 0;
char *file = "/dev/watchdog"; char *file = "/dev/watchdog";
struct watchdog_info info; struct watchdog_info info;
int temperature;
setbuf(stdout, NULL); setbuf(stdout, NULL);
...@@ -140,8 +218,7 @@ int main(int argc, char *argv[]) ...@@ -140,8 +218,7 @@ int main(int argc, char *argv[])
oneshot = 1; oneshot = 1;
ret = ioctl(fd, WDIOC_GETBOOTSTATUS, &flags); ret = ioctl(fd, WDIOC_GETBOOTSTATUS, &flags);
if (!ret) if (!ret)
printf("Last boot is caused by: %s.\n", (flags != 0) ? print_boot_status(flags);
"Watchdog" : "Power-On-Reset");
else else
printf("WDIOC_GETBOOTSTATUS error '%s'\n", strerror(errno)); printf("WDIOC_GETBOOTSTATUS error '%s'\n", strerror(errno));
break; break;
...@@ -170,6 +247,21 @@ int main(int argc, char *argv[]) ...@@ -170,6 +247,21 @@ int main(int argc, char *argv[])
if (!ping_rate) if (!ping_rate)
ping_rate = DEFAULT_PING_RATE; ping_rate = DEFAULT_PING_RATE;
printf("Watchdog ping rate set to %u seconds.\n", ping_rate); printf("Watchdog ping rate set to %u seconds.\n", ping_rate);
break;
case 's':
flags = 0;
oneshot = 1;
ret = ioctl(fd, WDIOC_GETSTATUS, &flags);
if (!ret)
print_status(flags);
else
printf("WDIOC_GETSTATUS error '%s'\n", strerror(errno));
ret = ioctl(fd, WDIOC_GETTEMP, &temperature);
if (ret)
printf("WDIOC_GETTEMP: '%s'\n", strerror(errno));
else
printf("Temperature %d\n", temperature);
break; break;
case 't': case 't':
flags = strtoul(optarg, NULL, 0); flags = strtoul(optarg, NULL, 0);
...@@ -228,7 +320,7 @@ int main(int argc, char *argv[]) ...@@ -228,7 +320,7 @@ int main(int argc, char *argv[])
printf(" identity:\t\t%s\n", info.identity); printf(" identity:\t\t%s\n", info.identity);
printf(" firmware_version:\t%u\n", printf(" firmware_version:\t%u\n",
info.firmware_version); info.firmware_version);
printf(" options:\t\t%08x\n", info.options); print_status(info.options);
break; break;
default: default:
...@@ -249,6 +341,10 @@ int main(int argc, char *argv[]) ...@@ -249,6 +341,10 @@ int main(int argc, char *argv[])
sleep(ping_rate); sleep(ping_rate);
} }
end: end:
/*
* Send specific magic character 'V' just in case Magic Close is
* enabled to ensure watchdog gets disabled on close.
*/
ret = write(fd, &v, 1); ret = write(fd, &v, 1);
if (ret < 0) if (ret < 0)
printf("Stopping watchdog ticks failed (%d)...\n", errno); printf("Stopping watchdog ticks failed (%d)...\n", errno);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment