~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/gpio/gpio-mockup.sh

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #!/bin/bash -efu
  2 # SPDX-License-Identifier: GPL-2.0
  3 
  4 #exit status
  5 #0: success
  6 #1: fail
  7 #4: skip test - including run as non-root user
  8 
  9 BASE=${0%/*}
 10 DEBUGFS=
 11 GPIO_DEBUGFS=
 12 dev_type="cdev"
 13 module="gpio-mockup"
 14 verbose=
 15 full_test=
 16 random=
 17 uapi_opt=
 18 active_opt=
 19 bias_opt=
 20 line_set_pid=
 21 
 22 # Kselftest return codes
 23 ksft_fail=1
 24 ksft_skip=4
 25 
 26 usage()
 27 {
 28         echo "Usage:"
 29         echo "$0 [-frv] [-t type]"
 30         echo "-f:  full test (minimal set run by default)"
 31         echo "-r:  test random lines as well as fence posts"
 32         echo "-t:  interface type:"
 33         echo "      cdev (character device ABI) - default"
 34         echo "      cdev_v1 (deprecated character device ABI)"
 35         echo "      sysfs (deprecated SYSFS ABI)"
 36         echo "-v:  verbose progress reporting"
 37         exit $ksft_fail
 38 }
 39 
 40 skip()
 41 {
 42         echo "$*" >&2
 43         echo "GPIO $module test SKIP"
 44         exit $ksft_skip
 45 }
 46 
 47 prerequisite()
 48 {
 49         [ $(id -u) -eq 0 ] || skip "must be run as root"
 50 
 51         DEBUGFS=$(grep -w debugfs /proc/mounts | cut -f2 -d' ')
 52         [ -d "$DEBUGFS" ] || skip "debugfs is not mounted"
 53 
 54         GPIO_DEBUGFS=$DEBUGFS/$module
 55 }
 56 
 57 remove_module()
 58 {
 59         modprobe -r -q $module
 60 }
 61 
 62 cleanup()
 63 {
 64         set +e
 65         release_line
 66         remove_module
 67         jobs -p | xargs -r kill > /dev/null 2>&1
 68 }
 69 
 70 fail()
 71 {
 72         echo "test failed: $*" >&2
 73         echo "GPIO $module test FAIL"
 74         exit $ksft_fail
 75 }
 76 
 77 try_insert_module()
 78 {
 79         modprobe -q $module "$1" || fail "insert $module failed with error $?"
 80 }
 81 
 82 log()
 83 {
 84         [ -z "$verbose" ] || echo "$*"
 85 }
 86 
 87 # The following line helpers, release_Line, get_line and set_line, all
 88 # make use of the global $chip and $offset variables.
 89 #
 90 # This implementation drives the GPIO character device (cdev) uAPI.
 91 # Other implementations may override these to test different uAPIs.
 92 
 93 # Release any resources related to the line
 94 release_line()
 95 {
 96         [ "$line_set_pid" ] && kill $line_set_pid && wait $line_set_pid || true
 97         line_set_pid=
 98 }
 99 
100 # Read the current value of the line
101 get_line()
102 {
103         release_line
104 
105         local cdev_opts=${uapi_opt}${active_opt}
106         $BASE/gpio-mockup-cdev $cdev_opts /dev/$chip $offset
107         echo $?
108 }
109 
110 # Set the state of the line
111 #
112 # Changes to line configuration are provided as parameters.
113 # The line is assumed to be an output if the line value 0 or 1 is
114 # specified, else an input.
115 set_line()
116 {
117         local val=
118 
119         release_line
120 
121         # parse config options...
122         for option in $*; do
123                 case $option in
124                 active-low)
125                         active_opt="-l "
126                         ;;
127                 active-high)
128                         active_opt=
129                         ;;
130                 bias-none)
131                         bias_opt=
132                         ;;
133                 pull-down)
134                         bias_opt="-bpull-down "
135                         ;;
136                 pull-up)
137                         bias_opt="-bpull-up "
138                         ;;
139                 0)
140                         val=0
141                         ;;
142                 1)
143                         val=1
144                         ;;
145                 esac
146         done
147 
148         local cdev_opts=${uapi_opt}${active_opt}
149         if [ "$val" ]; then
150                 $BASE/gpio-mockup-cdev $cdev_opts -s$val /dev/$chip $offset &
151                 # failure to set is detected by reading mockup and toggling values
152                 line_set_pid=$!
153                 # allow for gpio-mockup-cdev to launch and request line
154                 # (there is limited value in checking if line has been requested)
155                 sleep 0.01
156         elif [ "$bias_opt" ]; then
157                 cdev_opts=${cdev_opts}${bias_opt}
158                 $BASE/gpio-mockup-cdev $cdev_opts /dev/$chip $offset || true
159         fi
160 }
161 
162 assert_line()
163 {
164         local val
165         # don't need any retry here as set_mock allows for propagation
166         val=$(get_line)
167         [ "$val" = "$1" ] || fail "line value is ${val:-empty} when $1 was expected"
168 }
169 
170 # The following mockup helpers all make use of the $mock_line
171 assert_mock()
172 {
173         local backoff_wait=10
174         local retry=0
175         local val
176         # retry allows for set propagation from uAPI to mockup
177         while true; do
178                 val=$(< $mock_line)
179                 [ "$val" = "$1" ] && break
180                 retry=$((retry + 1))
181                 [ $retry -lt 5 ] || fail "mockup $mock_line value ${val:-empty} when $1 expected"
182                 sleep $(printf "%0.2f" $((backoff_wait))e-3)
183                 backoff_wait=$((backoff_wait * 2))
184         done
185 }
186 
187 set_mock()
188 {
189         echo "$1" > $mock_line
190         # allow for set propagation - so we won't be in a race with set_line
191         assert_mock "$1"
192 }
193 
194 # test the functionality of a line
195 #
196 # The line is set from the mockup side and is read from the userspace side
197 # (input), and is set from the userspace side and is read from the mockup side
198 # (output).
199 #
200 # Setting the mockup pull using the userspace interface bias settings is
201 # tested where supported by the userspace interface (cdev).
202 test_line()
203 {
204         chip=$1
205         offset=$2
206         log "test_line $chip $offset"
207         mock_line=$GPIO_DEBUGFS/$chip/$offset
208         [ -e "$mock_line" ] || fail "missing line $chip:$offset"
209 
210         # test input active-high
211         set_mock 1
212         set_line input active-high
213         assert_line 1
214         set_mock 0
215         assert_line 0
216         set_mock 1
217         assert_line 1
218 
219         if [ "$full_test" ]; then
220                 if [ "$dev_type" != "sysfs" ]; then
221                         # test pulls
222                         set_mock 0
223                         set_line input pull-up
224                         assert_line 1
225                         set_mock 0
226                         assert_line 0
227 
228                         set_mock 1
229                         set_line input pull-down
230                         assert_line 0
231                         set_mock 1
232                         assert_line 1
233 
234                         set_line bias-none
235                 fi
236 
237                 # test input active-low
238                 set_mock 0
239                 set_line active-low
240                 assert_line 1
241                 set_mock 1
242                 assert_line 0
243                 set_mock 0
244                 assert_line 1
245 
246                 # test output active-high
247                 set_mock 1
248                 set_line active-high 0
249                 assert_mock 0
250                 set_line 1
251                 assert_mock 1
252                 set_line 0
253                 assert_mock 0
254         fi
255 
256         # test output active-low
257         set_mock 0
258         set_line active-low 0
259         assert_mock 1
260         set_line 1
261         assert_mock 0
262         set_line 0
263         assert_mock 1
264 
265         release_line
266 }
267 
268 test_no_line()
269 {
270         log test_no_line "$*"
271         [ ! -e "$GPIO_DEBUGFS/$1/$2" ] || fail "unexpected line $1:$2"
272 }
273 
274 # Load the module and check that the expected number of gpiochips, with the
275 # expected number of lines, are created and are functional.
276 #
277 # $1 is the gpio_mockup_ranges parameter for the module
278 # The remaining parameters are the number of lines, n, expected for each of
279 # the gpiochips expected to be created.
280 #
281 # For each gpiochip the fence post lines, 0 and n-1, are tested, and the
282 # line on the far side of the fence post, n, is tested to not exist.
283 #
284 # If the $random flag is set then a random line in the middle of the
285 # gpiochip is tested as well.
286 insmod_test()
287 {
288         local ranges=
289         local gc=
290         local width=
291 
292         [ "${1:-}" ] || fail "missing ranges"
293         ranges=$1 ; shift
294         try_insert_module "gpio_mockup_ranges=$ranges"
295         log "GPIO $module test with ranges: <$ranges>:"
296         # e.g. /sys/kernel/debug/gpio-mockup/gpiochip1
297         gpiochip=$(find "$DEBUGFS/$module/" -name gpiochip* -type d | sort)
298         for chip in $gpiochip; do
299                 gc=${chip##*/}
300                 [ "${1:-}" ] || fail "unexpected chip - $gc"
301                 width=$1 ; shift
302                 test_line $gc 0
303                 if [ "$random" -a $width -gt 2 ]; then
304                         test_line $gc $((RANDOM % ($width - 2) + 1))
305                 fi
306                 test_line $gc $(($width - 1))
307                 test_no_line $gc $width
308         done
309         [ "${1:-}" ] && fail "missing expected chip of width $1"
310         remove_module || fail "failed to remove module with error $?"
311 }
312 
313 while getopts ":frvt:" opt; do
314         case $opt in
315         f)
316                 full_test=true
317                 ;;
318         r)
319                 random=true
320                 ;;
321         t)
322                 dev_type=$OPTARG
323                 ;;
324         v)
325                 verbose=true
326                 ;;
327         *)
328                 usage
329                 ;;
330         esac
331 done
332 shift $((OPTIND - 1))
333 
334 [ "${1:-}" ] && fail "unknown argument '$1'"
335 
336 prerequisite
337 
338 trap 'exit $ksft_fail' SIGTERM SIGINT
339 trap cleanup EXIT
340 
341 case "$dev_type" in
342 sysfs)
343         source $BASE/gpio-mockup-sysfs.sh
344         echo "WARNING: gpio sysfs ABI is deprecated."
345         ;;
346 cdev_v1)
347         echo "WARNING: gpio cdev ABI v1 is deprecated."
348         uapi_opt="-u1 "
349         ;;
350 cdev)
351         ;;
352 *)
353         fail "unknown interface type: $dev_type"
354         ;;
355 esac
356 
357 remove_module || fail "can't remove existing $module module"
358 
359 # manual gpio allocation tests fail if a physical chip already exists
360 [ "$full_test" -a -e "/dev/gpiochip0" ] && skip "full tests conflict with gpiochip0"
361 
362 echo "1.  Module load tests"
363 echo "1.1.  dynamic allocation of gpio"
364 insmod_test "-1,32" 32
365 insmod_test "-1,23,-1,32" 23 32
366 insmod_test "-1,23,-1,26,-1,32" 23 26 32
367 if [ "$full_test" ]; then
368         echo "1.2.  manual allocation of gpio"
369         insmod_test "0,32" 32
370         insmod_test "0,32,32,60" 32 28
371         insmod_test "0,32,40,64,64,96" 32 24 32
372         echo "1.3.  dynamic and manual allocation of gpio"
373         insmod_test "-1,32,32,62" 32 30
374         insmod_test "-1,22,-1,23,0,24,32,64" 22 23 24 32
375         insmod_test "-1,32,32,60,-1,29" 32 28 29
376         insmod_test "-1,32,40,64,-1,5" 32 24 5
377         insmod_test "0,32,32,44,-1,22,-1,31" 32 12 22 31
378 fi
379 echo "2.  Module load error tests"
380 echo "2.1 no lines defined"
381 insmod_test "0,0"
382 if [ "$full_test" ]; then
383         echo "2.2 ignore range overlap"
384         insmod_test "0,32,0,1" 32
385         insmod_test "0,32,1,5" 32
386         insmod_test "0,32,30,35" 32
387         insmod_test "0,32,31,32" 32
388         insmod_test "10,32,30,35" 22
389         insmod_test "10,32,9,14" 22
390         insmod_test "0,32,20,21,40,56" 32 16
391         insmod_test "0,32,32,64,32,40" 32 32
392         insmod_test "0,32,32,64,36,37" 32 32
393         insmod_test "0,32,35,64,34,36" 32 29
394         insmod_test "0,30,35,64,35,45" 30 29
395         insmod_test "0,32,40,56,30,33" 32 16
396         insmod_test "0,32,40,56,30,41" 32 16
397         insmod_test "0,32,40,56,39,45" 32 16
398 fi
399 
400 echo "GPIO $module test PASS"

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php