Path: blob/master/tools/testing/selftests/gpio/gpio-mockup.sh
26285 views
#!/bin/bash -efu1# SPDX-License-Identifier: GPL-2.023#exit status4#0: success5#1: fail6#4: skip test - including run as non-root user78BASE=${0%/*}9DEBUGFS=10GPIO_DEBUGFS=11dev_type="cdev"12module="gpio-mockup"13verbose=14full_test=15random=16uapi_opt=17active_opt=18bias_opt=19line_set_pid=2021# Kselftest return codes22ksft_fail=123ksft_skip=42425usage()26{27echo "Usage:"28echo "$0 [-frv] [-t type]"29echo "-f: full test (minimal set run by default)"30echo "-r: test random lines as well as fence posts"31echo "-t: interface type:"32echo " cdev (character device ABI) - default"33echo " cdev_v1 (deprecated character device ABI)"34echo " sysfs (deprecated SYSFS ABI)"35echo "-v: verbose progress reporting"36exit $ksft_fail37}3839skip()40{41echo "$*" >&242echo "GPIO $module test SKIP"43exit $ksft_skip44}4546prerequisite()47{48[ $(id -u) -eq 0 ] || skip "must be run as root"4950DEBUGFS=$(grep -w debugfs /proc/mounts | cut -f2 -d' ')51[ -d "$DEBUGFS" ] || skip "debugfs is not mounted"5253GPIO_DEBUGFS=$DEBUGFS/$module54}5556remove_module()57{58modprobe -r -q $module59}6061cleanup()62{63set +e64release_line65remove_module66jobs -p | xargs -r kill > /dev/null 2>&167}6869fail()70{71echo "test failed: $*" >&272echo "GPIO $module test FAIL"73exit $ksft_fail74}7576try_insert_module()77{78modprobe -q $module "$1" || fail "insert $module failed with error $?"79}8081log()82{83[ -z "$verbose" ] || echo "$*"84}8586# The following line helpers, release_Line, get_line and set_line, all87# make use of the global $chip and $offset variables.88#89# This implementation drives the GPIO character device (cdev) uAPI.90# Other implementations may override these to test different uAPIs.9192# Release any resources related to the line93release_line()94{95[ "$line_set_pid" ] && kill $line_set_pid && wait $line_set_pid || true96line_set_pid=97}9899# Read the current value of the line100get_line()101{102release_line103104local cdev_opts=${uapi_opt}${active_opt}105$BASE/gpio-mockup-cdev $cdev_opts /dev/$chip $offset106echo $?107}108109# Set the state of the line110#111# Changes to line configuration are provided as parameters.112# The line is assumed to be an output if the line value 0 or 1 is113# specified, else an input.114set_line()115{116local val=117118release_line119120# parse config options...121for option in $*; do122case $option in123active-low)124active_opt="-l "125;;126active-high)127active_opt=128;;129bias-none)130bias_opt=131;;132pull-down)133bias_opt="-bpull-down "134;;135pull-up)136bias_opt="-bpull-up "137;;1380)139val=0140;;1411)142val=1143;;144esac145done146147local cdev_opts=${uapi_opt}${active_opt}148if [ "$val" ]; then149$BASE/gpio-mockup-cdev $cdev_opts -s$val /dev/$chip $offset &150# failure to set is detected by reading mockup and toggling values151line_set_pid=$!152# allow for gpio-mockup-cdev to launch and request line153# (there is limited value in checking if line has been requested)154sleep 0.01155elif [ "$bias_opt" ]; then156cdev_opts=${cdev_opts}${bias_opt}157$BASE/gpio-mockup-cdev $cdev_opts /dev/$chip $offset || true158fi159}160161assert_line()162{163local val164# don't need any retry here as set_mock allows for propagation165val=$(get_line)166[ "$val" = "$1" ] || fail "line value is ${val:-empty} when $1 was expected"167}168169# The following mockup helpers all make use of the $mock_line170assert_mock()171{172local backoff_wait=10173local retry=0174local val175# retry allows for set propagation from uAPI to mockup176while true; do177val=$(< $mock_line)178[ "$val" = "$1" ] && break179retry=$((retry + 1))180[ $retry -lt 5 ] || fail "mockup $mock_line value ${val:-empty} when $1 expected"181sleep $(printf "%0.2f" $((backoff_wait))e-3)182backoff_wait=$((backoff_wait * 2))183done184}185186set_mock()187{188echo "$1" > $mock_line189# allow for set propagation - so we won't be in a race with set_line190assert_mock "$1"191}192193# test the functionality of a line194#195# The line is set from the mockup side and is read from the userspace side196# (input), and is set from the userspace side and is read from the mockup side197# (output).198#199# Setting the mockup pull using the userspace interface bias settings is200# tested where supported by the userspace interface (cdev).201test_line()202{203chip=$1204offset=$2205log "test_line $chip $offset"206mock_line=$GPIO_DEBUGFS/$chip/$offset207[ -e "$mock_line" ] || fail "missing line $chip:$offset"208209# test input active-high210set_mock 1211set_line input active-high212assert_line 1213set_mock 0214assert_line 0215set_mock 1216assert_line 1217218if [ "$full_test" ]; then219if [ "$dev_type" != "sysfs" ]; then220# test pulls221set_mock 0222set_line input pull-up223assert_line 1224set_mock 0225assert_line 0226227set_mock 1228set_line input pull-down229assert_line 0230set_mock 1231assert_line 1232233set_line bias-none234fi235236# test input active-low237set_mock 0238set_line active-low239assert_line 1240set_mock 1241assert_line 0242set_mock 0243assert_line 1244245# test output active-high246set_mock 1247set_line active-high 0248assert_mock 0249set_line 1250assert_mock 1251set_line 0252assert_mock 0253fi254255# test output active-low256set_mock 0257set_line active-low 0258assert_mock 1259set_line 1260assert_mock 0261set_line 0262assert_mock 1263264release_line265}266267test_no_line()268{269log test_no_line "$*"270[ ! -e "$GPIO_DEBUGFS/$1/$2" ] || fail "unexpected line $1:$2"271}272273# Load the module and check that the expected number of gpiochips, with the274# expected number of lines, are created and are functional.275#276# $1 is the gpio_mockup_ranges parameter for the module277# The remaining parameters are the number of lines, n, expected for each of278# the gpiochips expected to be created.279#280# For each gpiochip the fence post lines, 0 and n-1, are tested, and the281# line on the far side of the fence post, n, is tested to not exist.282#283# If the $random flag is set then a random line in the middle of the284# gpiochip is tested as well.285insmod_test()286{287local ranges=288local gc=289local width=290291[ "${1:-}" ] || fail "missing ranges"292ranges=$1 ; shift293try_insert_module "gpio_mockup_ranges=$ranges"294log "GPIO $module test with ranges: <$ranges>:"295# e.g. /sys/kernel/debug/gpio-mockup/gpiochip1296gpiochip=$(find "$DEBUGFS/$module/" -name gpiochip* -type d | sort)297for chip in $gpiochip; do298gc=${chip##*/}299[ "${1:-}" ] || fail "unexpected chip - $gc"300width=$1 ; shift301test_line $gc 0302if [ "$random" -a $width -gt 2 ]; then303test_line $gc $((RANDOM % ($width - 2) + 1))304fi305test_line $gc $(($width - 1))306test_no_line $gc $width307done308[ "${1:-}" ] && fail "missing expected chip of width $1"309remove_module || fail "failed to remove module with error $?"310}311312while getopts ":frvt:" opt; do313case $opt in314f)315full_test=true316;;317r)318random=true319;;320t)321dev_type=$OPTARG322;;323v)324verbose=true325;;326*)327usage328;;329esac330done331shift $((OPTIND - 1))332333[ "${1:-}" ] && fail "unknown argument '$1'"334335prerequisite336337trap 'exit $ksft_fail' SIGTERM SIGINT338trap cleanup EXIT339340case "$dev_type" in341sysfs)342source $BASE/gpio-mockup-sysfs.sh343echo "WARNING: gpio sysfs ABI is deprecated."344;;345cdev_v1)346echo "WARNING: gpio cdev ABI v1 is deprecated."347uapi_opt="-u1 "348;;349cdev)350;;351*)352fail "unknown interface type: $dev_type"353;;354esac355356remove_module || fail "can't remove existing $module module"357358# manual gpio allocation tests fail if a physical chip already exists359[ "$full_test" -a -e "/dev/gpiochip0" ] && skip "full tests conflict with gpiochip0"360361echo "1. Module load tests"362echo "1.1. dynamic allocation of gpio"363insmod_test "-1,32" 32364insmod_test "-1,23,-1,32" 23 32365insmod_test "-1,23,-1,26,-1,32" 23 26 32366if [ "$full_test" ]; then367echo "1.2. manual allocation of gpio"368insmod_test "0,32" 32369insmod_test "0,32,32,60" 32 28370insmod_test "0,32,40,64,64,96" 32 24 32371echo "1.3. dynamic and manual allocation of gpio"372insmod_test "-1,32,32,62" 32 30373insmod_test "-1,22,-1,23,0,24,32,64" 22 23 24 32374insmod_test "-1,32,32,60,-1,29" 32 28 29375insmod_test "-1,32,40,64,-1,5" 32 24 5376insmod_test "0,32,32,44,-1,22,-1,31" 32 12 22 31377fi378echo "2. Module load error tests"379echo "2.1 no lines defined"380insmod_test "0,0"381if [ "$full_test" ]; then382echo "2.2 ignore range overlap"383insmod_test "0,32,0,1" 32384insmod_test "0,32,1,5" 32385insmod_test "0,32,30,35" 32386insmod_test "0,32,31,32" 32387insmod_test "10,32,30,35" 22388insmod_test "10,32,9,14" 22389insmod_test "0,32,20,21,40,56" 32 16390insmod_test "0,32,32,64,32,40" 32 32391insmod_test "0,32,32,64,36,37" 32 32392insmod_test "0,32,35,64,34,36" 32 29393insmod_test "0,30,35,64,35,45" 30 29394insmod_test "0,32,40,56,30,33" 32 16395insmod_test "0,32,40,56,30,41" 32 16396insmod_test "0,32,40,56,39,45" 32 16397fi398399echo "GPIO $module test PASS"400401402