Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[cris-mirror.git] / tools / testing / selftests / firmware / fw_fallback.sh
blob722cad91df741bcb16ae736c528b64f7a410a9f6
1 #!/bin/sh
2 # SPDX-License-Identifier: GPL-2.0
3 # This validates that the kernel will fall back to using the fallback mechanism
4 # to load firmware it can't find on disk itself. We must request a firmware
5 # that the kernel won't find, and any installed helper (e.g. udev) also
6 # won't find so that we can do the load ourself manually.
7 set -e
9 modprobe test_firmware
11 DIR=/sys/devices/virtual/misc/test_firmware
13 # CONFIG_FW_LOADER_USER_HELPER has a sysfs class under /sys/class/firmware/
14 # These days no one enables CONFIG_FW_LOADER_USER_HELPER so check for that
15 # as an indicator for CONFIG_FW_LOADER_USER_HELPER.
16 HAS_FW_LOADER_USER_HELPER=$(if [ -d /sys/class/firmware/ ]; then echo yes; else echo no; fi)
18 if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
19 OLD_TIMEOUT=$(cat /sys/class/firmware/timeout)
20 else
21 echo "usermode helper disabled so ignoring test"
22 exit 0
25 FWPATH=$(mktemp -d)
26 FW="$FWPATH/test-firmware.bin"
28 test_finish()
30 echo "$OLD_TIMEOUT" >/sys/class/firmware/timeout
31 rm -f "$FW"
32 rmdir "$FWPATH"
35 load_fw()
37 local name="$1"
38 local file="$2"
40 # This will block until our load (below) has finished.
41 echo -n "$name" >"$DIR"/trigger_request &
43 # Give kernel a chance to react.
44 local timeout=10
45 while [ ! -e "$DIR"/"$name"/loading ]; do
46 sleep 0.1
47 timeout=$(( $timeout - 1 ))
48 if [ "$timeout" -eq 0 ]; then
49 echo "$0: firmware interface never appeared" >&2
50 exit 1
52 done
54 echo 1 >"$DIR"/"$name"/loading
55 cat "$file" >"$DIR"/"$name"/data
56 echo 0 >"$DIR"/"$name"/loading
58 # Wait for request to finish.
59 wait
62 load_fw_cancel()
64 local name="$1"
65 local file="$2"
67 # This will block until our load (below) has finished.
68 echo -n "$name" >"$DIR"/trigger_request 2>/dev/null &
70 # Give kernel a chance to react.
71 local timeout=10
72 while [ ! -e "$DIR"/"$name"/loading ]; do
73 sleep 0.1
74 timeout=$(( $timeout - 1 ))
75 if [ "$timeout" -eq 0 ]; then
76 echo "$0: firmware interface never appeared" >&2
77 exit 1
79 done
81 echo -1 >"$DIR"/"$name"/loading
83 # Wait for request to finish.
84 wait
87 load_fw_custom()
89 if [ ! -e "$DIR"/trigger_custom_fallback ]; then
90 echo "$0: custom fallback trigger not present, ignoring test" >&2
91 return 1
94 local name="$1"
95 local file="$2"
97 echo -n "$name" >"$DIR"/trigger_custom_fallback 2>/dev/null &
99 # Give kernel a chance to react.
100 local timeout=10
101 while [ ! -e "$DIR"/"$name"/loading ]; do
102 sleep 0.1
103 timeout=$(( $timeout - 1 ))
104 if [ "$timeout" -eq 0 ]; then
105 echo "$0: firmware interface never appeared" >&2
106 exit 1
108 done
110 echo 1 >"$DIR"/"$name"/loading
111 cat "$file" >"$DIR"/"$name"/data
112 echo 0 >"$DIR"/"$name"/loading
114 # Wait for request to finish.
115 wait
116 return 0
120 load_fw_custom_cancel()
122 if [ ! -e "$DIR"/trigger_custom_fallback ]; then
123 echo "$0: canceling custom fallback trigger not present, ignoring test" >&2
124 return 1
127 local name="$1"
128 local file="$2"
130 echo -n "$name" >"$DIR"/trigger_custom_fallback 2>/dev/null &
132 # Give kernel a chance to react.
133 local timeout=10
134 while [ ! -e "$DIR"/"$name"/loading ]; do
135 sleep 0.1
136 timeout=$(( $timeout - 1 ))
137 if [ "$timeout" -eq 0 ]; then
138 echo "$0: firmware interface never appeared" >&2
139 exit 1
141 done
143 echo -1 >"$DIR"/"$name"/loading
145 # Wait for request to finish.
146 wait
147 return 0
150 load_fw_fallback_with_child()
152 local name="$1"
153 local file="$2"
155 # This is the value already set but we want to be explicit
156 echo 4 >/sys/class/firmware/timeout
158 sleep 1 &
159 SECONDS_BEFORE=$(date +%s)
160 echo -n "$name" >"$DIR"/trigger_request 2>/dev/null
161 SECONDS_AFTER=$(date +%s)
162 SECONDS_DELTA=$(($SECONDS_AFTER - $SECONDS_BEFORE))
163 if [ "$SECONDS_DELTA" -lt 4 ]; then
164 RET=1
165 else
166 RET=0
168 wait
169 return $RET
172 trap "test_finish" EXIT
174 # This is an unlikely real-world firmware content. :)
175 echo "ABCD0123" >"$FW"
176 NAME=$(basename "$FW")
178 test_syfs_timeout()
180 DEVPATH="$DIR"/"nope-$NAME"/loading
182 # Test failure when doing nothing (timeout works).
183 echo -n 2 >/sys/class/firmware/timeout
184 echo -n "nope-$NAME" >"$DIR"/trigger_request 2>/dev/null &
186 # Give the kernel some time to load the loading file, must be less
187 # than the timeout above.
188 sleep 1
189 if [ ! -f $DEVPATH ]; then
190 echo "$0: fallback mechanism immediately cancelled"
191 echo ""
192 echo "The file never appeared: $DEVPATH"
193 echo ""
194 echo "This might be a distribution udev rule setup by your distribution"
195 echo "to immediately cancel all fallback requests, this must be"
196 echo "removed before running these tests. To confirm look for"
197 echo "a firmware rule like /lib/udev/rules.d/50-firmware.rules"
198 echo "and see if you have something like this:"
199 echo ""
200 echo "SUBSYSTEM==\"firmware\", ACTION==\"add\", ATTR{loading}=\"-1\""
201 echo ""
202 echo "If you do remove this file or comment out this line before"
203 echo "proceeding with these tests."
204 exit 1
207 if diff -q "$FW" /dev/test_firmware >/dev/null ; then
208 echo "$0: firmware was not expected to match" >&2
209 exit 1
210 else
211 echo "$0: timeout works"
215 run_sysfs_main_tests()
217 test_syfs_timeout
218 # Put timeout high enough for us to do work but not so long that failures
219 # slow down this test too much.
220 echo 4 >/sys/class/firmware/timeout
222 # Load this script instead of the desired firmware.
223 load_fw "$NAME" "$0"
224 if diff -q "$FW" /dev/test_firmware >/dev/null ; then
225 echo "$0: firmware was not expected to match" >&2
226 exit 1
227 else
228 echo "$0: firmware comparison works"
231 # Do a proper load, which should work correctly.
232 load_fw "$NAME" "$FW"
233 if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
234 echo "$0: firmware was not loaded" >&2
235 exit 1
236 else
237 echo "$0: fallback mechanism works"
240 load_fw_cancel "nope-$NAME" "$FW"
241 if diff -q "$FW" /dev/test_firmware >/dev/null ; then
242 echo "$0: firmware was expected to be cancelled" >&2
243 exit 1
244 else
245 echo "$0: cancelling fallback mechanism works"
248 set +e
249 load_fw_fallback_with_child "nope-signal-$NAME" "$FW"
250 if [ "$?" -eq 0 ]; then
251 echo "$0: SIGCHLD on sync ignored as expected" >&2
252 else
253 echo "$0: error - sync firmware request cancelled due to SIGCHLD" >&2
254 exit 1
256 set -e
259 run_sysfs_custom_load_tests()
261 if load_fw_custom "$NAME" "$FW" ; then
262 if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
263 echo "$0: firmware was not loaded" >&2
264 exit 1
265 else
266 echo "$0: custom fallback loading mechanism works"
270 if load_fw_custom "$NAME" "$FW" ; then
271 if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
272 echo "$0: firmware was not loaded" >&2
273 exit 1
274 else
275 echo "$0: custom fallback loading mechanism works"
279 if load_fw_custom_cancel "nope-$NAME" "$FW" ; then
280 if diff -q "$FW" /dev/test_firmware >/dev/null ; then
281 echo "$0: firmware was expected to be cancelled" >&2
282 exit 1
283 else
284 echo "$0: cancelling custom fallback mechanism works"
289 run_sysfs_main_tests
290 run_sysfs_custom_load_tests
292 exit 0