aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/tools/testing/selftests/firmware
diff options
context:
space:
mode:
authorLuis R. Rodriguez <mcgrof@kernel.org>2017-07-20 13:13:42 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-08-10 13:58:41 -0700
commitc92316bf8e94830a0225f2e904cbdbd173768419 (patch)
treee371d9fa54a84901d9ea0640327742eedfc49b86 /tools/testing/selftests/firmware
parentfirmware: enable a debug print for batched requests (diff)
downloadwireguard-linux-c92316bf8e94830a0225f2e904cbdbd173768419.tar.xz
wireguard-linux-c92316bf8e94830a0225f2e904cbdbd173768419.zip
test_firmware: add batched firmware tests
The firmware API has a feature to enable batching requests for the same fil e under one worker, so only one lookup is done. This only triggers if we so happen to schedule two lookups for same file around the same time, or if release_firmware() has not been called for a successful firmware call. This can happen for instance if you happen to have multiple devices and one device driver for certain drivers where the stars line up scheduling wise. This adds a new sync and async test trigger. Instead of adding a new trigger for each new test type we make the tests a bit configurable so that we could configure the tests in userspace and just kick a test through a few basic triggers. With this, for instance the two types of sync requests: o request_firmware() and o request_firmware_direct() can be modified with a knob. Likewise the two type of async requests: o request_firmware_nowait(uevent=true) and o request_firmware_nowait(uevent=false) can be configured with another knob. The call request_firmware_into_buf() has no users... yet. The old tests are left in place as-is given they serve a few other purposes which we are currently not interested in also testing yet. This will change later as we will be able to just consolidate all tests under a few basic triggers with just one general configuration setup. We perform two types of tests, one for where the file is present and one for where the file is not present. All test tests go tested and they now pass for the following 3 kernel builds possible for the firmware API: 0. Most distro setup: CONFIG_FW_LOADER_USER_HELPER_FALLBACK=n CONFIG_FW_LOADER_USER_HELPER=y 1. Android: CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y CONFIG_FW_LOADER_USER_HELPER=y 2. Rare build: CONFIG_FW_LOADER_USER_HELPER_FALLBACK=n CONFIG_FW_LOADER_USER_HELPER=n Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'tools/testing/selftests/firmware')
-rwxr-xr-xtools/testing/selftests/firmware/fw_filesystem.sh241
1 files changed, 239 insertions, 2 deletions
diff --git a/tools/testing/selftests/firmware/fw_filesystem.sh b/tools/testing/selftests/firmware/fw_filesystem.sh
index e35691239350..7d8fd2e3695a 100755
--- a/tools/testing/selftests/firmware/fw_filesystem.sh
+++ b/tools/testing/selftests/firmware/fw_filesystem.sh
@@ -25,8 +25,9 @@ if [ ! -d $DIR ]; then
fi
# CONFIG_FW_LOADER_USER_HELPER has a sysfs class under /sys/class/firmware/
-# These days no one enables CONFIG_FW_LOADER_USER_HELPER so check for that
-# as an indicator for CONFIG_FW_LOADER_USER_HELPER.
+# These days most distros enable CONFIG_FW_LOADER_USER_HELPER but disable
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK. We use /sys/class/firmware/ as an
+# indicator for CONFIG_FW_LOADER_USER_HELPER.
HAS_FW_LOADER_USER_HELPER=$(if [ -d /sys/class/firmware/ ]; then echo yes; else echo no; fi)
if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
@@ -116,4 +117,240 @@ else
echo "$0: async filesystem loading works"
fi
+### Batched requests tests
+test_config_present()
+{
+ if [ ! -f $DIR/reset ]; then
+ echo "Configuration triggers not present, ignoring test"
+ exit 0
+ fi
+}
+
+# Defaults :
+#
+# send_uevent: 1
+# sync_direct: 0
+# name: test-firmware.bin
+# num_requests: 4
+config_reset()
+{
+ echo 1 > $DIR/reset
+}
+
+release_all_firmware()
+{
+ echo 1 > $DIR/release_all_firmware
+}
+
+config_set_name()
+{
+ echo -n $1 > $DIR/config_name
+}
+
+config_set_sync_direct()
+{
+ echo 1 > $DIR/config_sync_direct
+}
+
+config_unset_sync_direct()
+{
+ echo 0 > $DIR/config_sync_direct
+}
+
+config_set_uevent()
+{
+ echo 1 > $DIR/config_send_uevent
+}
+
+config_unset_uevent()
+{
+ echo 0 > $DIR/config_send_uevent
+}
+
+config_trigger_sync()
+{
+ echo -n 1 > $DIR/trigger_batched_requests 2>/dev/null
+}
+
+config_trigger_async()
+{
+ echo -n 1 > $DIR/trigger_batched_requests_async 2> /dev/null
+}
+
+config_set_read_fw_idx()
+{
+ echo -n $1 > $DIR/config_read_fw_idx 2> /dev/null
+}
+
+read_firmwares()
+{
+ for i in $(seq 0 3); do
+ config_set_read_fw_idx $i
+ # Verify the contents are what we expect.
+ # -Z required for now -- check for yourself, md5sum
+ # on $FW and DIR/read_firmware will yield the same. Even
+ # cmp agrees, so something is off.
+ if ! diff -q -Z "$FW" $DIR/read_firmware 2>/dev/null ; then
+ echo "request #$i: firmware was not loaded" >&2
+ exit 1
+ fi
+ done
+}
+
+read_firmwares_expect_nofile()
+{
+ for i in $(seq 0 3); do
+ config_set_read_fw_idx $i
+ # Ensures contents differ
+ if diff -q -Z "$FW" $DIR/read_firmware 2>/dev/null ; then
+ echo "request $i: file was not expected to match" >&2
+ exit 1
+ fi
+ done
+}
+
+test_batched_request_firmware_nofile()
+{
+ echo -n "Batched request_firmware() nofile try #$1: "
+ config_reset
+ config_set_name nope-test-firmware.bin
+ config_trigger_sync
+ read_firmwares_expect_nofile
+ release_all_firmware
+ echo "OK"
+}
+
+test_batched_request_firmware_direct_nofile()
+{
+ echo -n "Batched request_firmware_direct() nofile try #$1: "
+ config_reset
+ config_set_name nope-test-firmware.bin
+ config_set_sync_direct
+ config_trigger_sync
+ release_all_firmware
+ echo "OK"
+}
+
+test_request_firmware_nowait_uevent_nofile()
+{
+ echo -n "Batched request_firmware_nowait(uevent=true) nofile try #$1: "
+ config_reset
+ config_set_name nope-test-firmware.bin
+ config_trigger_async
+ release_all_firmware
+ echo "OK"
+}
+
+test_wait_and_cancel_custom_load()
+{
+ if [ "$HAS_FW_LOADER_USER_HELPER" != "yes" ]; then
+ return
+ fi
+ local timeout=10
+ name=$1
+ while [ ! -e "$DIR"/"$name"/loading ]; do
+ sleep 0.1
+ timeout=$(( $timeout - 1 ))
+ if [ "$timeout" -eq 0 ]; then
+ echo "firmware interface never appeared:" >&2
+ echo "$DIR/$name/loading" >&2
+ exit 1
+ fi
+ done
+ echo -1 >"$DIR"/"$name"/loading
+}
+
+test_request_firmware_nowait_custom_nofile()
+{
+ echo -n "Batched request_firmware_nowait(uevent=false) nofile try #$1: "
+ config_unset_uevent
+ config_set_name nope-test-firmware.bin
+ config_trigger_async &
+ test_wait_and_cancel_custom_load nope-test-firmware.bin
+ wait
+ release_all_firmware
+ echo "OK"
+}
+
+test_batched_request_firmware()
+{
+ echo -n "Batched request_firmware() try #$1: "
+ config_reset
+ config_trigger_sync
+ read_firmwares
+ release_all_firmware
+ echo "OK"
+}
+
+test_batched_request_firmware_direct()
+{
+ echo -n "Batched request_firmware_direct() try #$1: "
+ config_reset
+ config_set_sync_direct
+ config_trigger_sync
+ release_all_firmware
+ echo "OK"
+}
+
+test_request_firmware_nowait_uevent()
+{
+ echo -n "Batched request_firmware_nowait(uevent=true) try #$1: "
+ config_reset
+ config_trigger_async
+ release_all_firmware
+ echo "OK"
+}
+
+test_request_firmware_nowait_custom()
+{
+ echo -n "Batched request_firmware_nowait(uevent=false) try #$1: "
+ config_unset_uevent
+ config_trigger_async
+ release_all_firmware
+ echo "OK"
+}
+
+# Only continue if batched request triggers are present on the
+# test-firmware driver
+test_config_present
+
+# test with the file present
+echo
+echo "Testing with the file present..."
+for i in $(seq 1 5); do
+ test_batched_request_firmware $i
+done
+
+for i in $(seq 1 5); do
+ test_batched_request_firmware_direct $i
+done
+
+for i in $(seq 1 5); do
+ test_request_firmware_nowait_uevent $i
+done
+
+for i in $(seq 1 5); do
+ test_request_firmware_nowait_custom $i
+done
+
+# Test for file not found, errors are expected, the failure would be
+# a hung task, which would require a hard reset.
+echo
+echo "Testing with the file missing..."
+for i in $(seq 1 5); do
+ test_batched_request_firmware_nofile $i
+done
+
+for i in $(seq 1 5); do
+ test_batched_request_firmware_direct_nofile $i
+done
+
+for i in $(seq 1 5); do
+ test_request_firmware_nowait_uevent_nofile $i
+done
+
+for i in $(seq 1 5); do
+ test_request_firmware_nowait_custom_nofile $i
+done
+
exit 0