Users of the custom firmware fallback interface is are not supposed to use the firmware cache interface, this can happen if for instance the one of the APIs which use the firmware cache is used first with one firmware file and then the request_firmware_nowait(uevent=false) API is used with the same file. We'll soon become strict about this on the firmware interface to reject such calls later, so correct the test scripts to avoid such uses as well. We address this on the tests scripts by simply using unique names when testing the custom fallback interface. Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
331 lines
7.1 KiB
Bash
Executable File
331 lines
7.1 KiB
Bash
Executable File
#!/bin/bash
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
# This validates that the kernel will load firmware out of its list of
|
|
# firmware locations on disk. Since the user helper does similar work,
|
|
# we reset the custom load directory to a location the user helper doesn't
|
|
# know so we can be sure we're not accidentally testing the user helper.
|
|
set -e
|
|
|
|
TEST_REQS_FW_SYSFS_FALLBACK="no"
|
|
TEST_REQS_FW_SET_CUSTOM_PATH="yes"
|
|
TEST_DIR=$(dirname $0)
|
|
source $TEST_DIR/fw_lib.sh
|
|
|
|
check_mods
|
|
check_setup
|
|
verify_reqs
|
|
setup_tmp_file
|
|
|
|
trap "test_finish" EXIT
|
|
|
|
if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
|
|
# Turn down the timeout so failures don't take so long.
|
|
echo 1 >/sys/class/firmware/timeout
|
|
fi
|
|
|
|
if printf '\000' >"$DIR"/trigger_request 2> /dev/null; then
|
|
echo "$0: empty filename should not succeed" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -e "$DIR"/trigger_async_request ]; then
|
|
echo "$0: empty filename: async trigger not present, ignoring test" >&2
|
|
else
|
|
if printf '\000' >"$DIR"/trigger_async_request 2> /dev/null; then
|
|
echo "$0: empty filename should not succeed (async)" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Request a firmware that doesn't exist, it should fail.
|
|
if echo -n "nope-$NAME" >"$DIR"/trigger_request 2> /dev/null; then
|
|
echo "$0: firmware shouldn't have loaded" >&2
|
|
exit 1
|
|
fi
|
|
if diff -q "$FW" /dev/test_firmware >/dev/null ; then
|
|
echo "$0: firmware was not expected to match" >&2
|
|
exit 1
|
|
else
|
|
if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
|
|
echo "$0: timeout works"
|
|
fi
|
|
fi
|
|
|
|
# This should succeed via kernel load or will fail after 1 second after
|
|
# being handed over to the user helper, which won't find the fw either.
|
|
if ! echo -n "$NAME" >"$DIR"/trigger_request ; then
|
|
echo "$0: could not trigger request" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Verify the contents are what we expect.
|
|
if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
|
|
echo "$0: firmware was not loaded" >&2
|
|
exit 1
|
|
else
|
|
echo "$0: filesystem loading works"
|
|
fi
|
|
|
|
# Try the asynchronous version too
|
|
if [ ! -e "$DIR"/trigger_async_request ]; then
|
|
echo "$0: firmware loading: async trigger not present, ignoring test" >&2
|
|
else
|
|
if ! echo -n "$NAME" >"$DIR"/trigger_async_request ; then
|
|
echo "$0: could not trigger async request" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Verify the contents are what we expect.
|
|
if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
|
|
echo "$0: firmware was not loaded (async)" >&2
|
|
exit 1
|
|
else
|
|
echo "$0: async filesystem loading works"
|
|
fi
|
|
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_reset
|
|
config_unset_uevent
|
|
RANDOM_FILE_PATH=$(setup_random_file_fake)
|
|
RANDOM_FILE="$(basename $RANDOM_FILE_PATH)"
|
|
config_set_name $RANDOM_FILE
|
|
config_trigger_async &
|
|
test_wait_and_cancel_custom_load $RANDOM_FILE
|
|
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_reset
|
|
config_unset_uevent
|
|
RANDOM_FILE_PATH=$(setup_random_file)
|
|
RANDOM_FILE="$(basename $RANDOM_FILE_PATH)"
|
|
config_set_name $RANDOM_FILE
|
|
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
|