401 lines · bash
1#!/bin/bash -efu2# SPDX-License-Identifier: GPL-2.03 4#exit status5#0: success6#1: fail7#4: skip test - including run as non-root user8 9BASE=${0%/*}10DEBUGFS=11GPIO_DEBUGFS=12dev_type="cdev"13module="gpio-mockup"14verbose=15full_test=16random=17uapi_opt=18active_opt=19bias_opt=20line_set_pid=21 22# Kselftest return codes23ksft_fail=124ksft_skip=425 26usage()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_fail38}39 40skip()41{42 echo "$*" >&243 echo "GPIO $module test SKIP"44 exit $ksft_skip45}46 47prerequisite()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/$module55}56 57remove_module()58{59 modprobe -r -q $module60}61 62cleanup()63{64 set +e65 release_line66 remove_module67 jobs -p | xargs -r kill > /dev/null 2>&168}69 70fail()71{72 echo "test failed: $*" >&273 echo "GPIO $module test FAIL"74 exit $ksft_fail75}76 77try_insert_module()78{79 modprobe -q $module "$1" || fail "insert $module failed with error $?"80}81 82log()83{84 [ -z "$verbose" ] || echo "$*"85}86 87# The following line helpers, release_Line, get_line and set_line, all88# 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 line94release_line()95{96 [ "$line_set_pid" ] && kill $line_set_pid && wait $line_set_pid || true97 line_set_pid=98}99 100# Read the current value of the line101get_line()102{103 release_line104 105 local cdev_opts=${uapi_opt}${active_opt}106 $BASE/gpio-mockup-cdev $cdev_opts /dev/$chip $offset107 echo $?108}109 110# Set the state of the line111#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 is114# specified, else an input.115set_line()116{117 local val=118 119 release_line120 121 # parse config options...122 for option in $*; do123 case $option in124 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=0141 ;;142 1)143 val=1144 ;;145 esac146 done147 148 local cdev_opts=${uapi_opt}${active_opt}149 if [ "$val" ]; then150 $BASE/gpio-mockup-cdev $cdev_opts -s$val /dev/$chip $offset &151 # failure to set is detected by reading mockup and toggling values152 line_set_pid=$!153 # allow for gpio-mockup-cdev to launch and request line154 # (there is limited value in checking if line has been requested)155 sleep 0.01156 elif [ "$bias_opt" ]; then157 cdev_opts=${cdev_opts}${bias_opt}158 $BASE/gpio-mockup-cdev $cdev_opts /dev/$chip $offset || true159 fi160}161 162assert_line()163{164 local val165 # don't need any retry here as set_mock allows for propagation166 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_line171assert_mock()172{173 local backoff_wait=10174 local retry=0175 local val176 # retry allows for set propagation from uAPI to mockup177 while true; do178 val=$(< $mock_line)179 [ "$val" = "$1" ] && break180 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 done185}186 187set_mock()188{189 echo "$1" > $mock_line190 # allow for set propagation - so we won't be in a race with set_line191 assert_mock "$1"192}193 194# test the functionality of a line195#196# The line is set from the mockup side and is read from the userspace side197# (input), and is set from the userspace side and is read from the mockup side198# (output).199#200# Setting the mockup pull using the userspace interface bias settings is201# tested where supported by the userspace interface (cdev).202test_line()203{204 chip=$1205 offset=$2206 log "test_line $chip $offset"207 mock_line=$GPIO_DEBUGFS/$chip/$offset208 [ -e "$mock_line" ] || fail "missing line $chip:$offset"209 210 # test input active-high211 set_mock 1212 set_line input active-high213 assert_line 1214 set_mock 0215 assert_line 0216 set_mock 1217 assert_line 1218 219 if [ "$full_test" ]; then220 if [ "$dev_type" != "sysfs" ]; then221 # test pulls222 set_mock 0223 set_line input pull-up224 assert_line 1225 set_mock 0226 assert_line 0227 228 set_mock 1229 set_line input pull-down230 assert_line 0231 set_mock 1232 assert_line 1233 234 set_line bias-none235 fi236 237 # test input active-low238 set_mock 0239 set_line active-low240 assert_line 1241 set_mock 1242 assert_line 0243 set_mock 0244 assert_line 1245 246 # test output active-high247 set_mock 1248 set_line active-high 0249 assert_mock 0250 set_line 1251 assert_mock 1252 set_line 0253 assert_mock 0254 fi255 256 # test output active-low257 set_mock 0258 set_line active-low 0259 assert_mock 1260 set_line 1261 assert_mock 0262 set_line 0263 assert_mock 1264 265 release_line266}267 268test_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 the275# expected number of lines, are created and are functional.276#277# $1 is the gpio_mockup_ranges parameter for the module278# The remaining parameters are the number of lines, n, expected for each of279# the gpiochips expected to be created.280#281# For each gpiochip the fence post lines, 0 and n-1, are tested, and the282# 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 the285# gpiochip is tested as well.286insmod_test()287{288 local ranges=289 local gc=290 local width=291 292 [ "${1:-}" ] || fail "missing ranges"293 ranges=$1 ; shift294 try_insert_module "gpio_mockup_ranges=$ranges"295 log "GPIO $module test with ranges: <$ranges>:"296 # e.g. /sys/kernel/debug/gpio-mockup/gpiochip1297 gpiochip=$(find "$DEBUGFS/$module/" -name gpiochip* -type d | sort)298 for chip in $gpiochip; do299 gc=${chip##*/}300 [ "${1:-}" ] || fail "unexpected chip - $gc"301 width=$1 ; shift302 test_line $gc 0303 if [ "$random" -a $width -gt 2 ]; then304 test_line $gc $((RANDOM % ($width - 2) + 1))305 fi306 test_line $gc $(($width - 1))307 test_no_line $gc $width308 done309 [ "${1:-}" ] && fail "missing expected chip of width $1"310 remove_module || fail "failed to remove module with error $?"311}312 313while getopts ":frvt:" opt; do314 case $opt in315 f)316 full_test=true317 ;;318 r)319 random=true320 ;;321 t)322 dev_type=$OPTARG323 ;;324 v)325 verbose=true326 ;;327 *)328 usage329 ;;330 esac331done332shift $((OPTIND - 1))333 334[ "${1:-}" ] && fail "unknown argument '$1'"335 336prerequisite337 338trap 'exit $ksft_fail' SIGTERM SIGINT339trap cleanup EXIT340 341case "$dev_type" in342sysfs)343 source $BASE/gpio-mockup-sysfs.sh344 echo "WARNING: gpio sysfs ABI is deprecated."345 ;;346cdev_v1)347 echo "WARNING: gpio cdev ABI v1 is deprecated."348 uapi_opt="-u1 "349 ;;350cdev)351 ;;352*)353 fail "unknown interface type: $dev_type"354 ;;355esac356 357remove_module || fail "can't remove existing $module module"358 359# manual gpio allocation tests fail if a physical chip already exists360[ "$full_test" -a -e "/dev/gpiochip0" ] && skip "full tests conflict with gpiochip0"361 362echo "1. Module load tests"363echo "1.1. dynamic allocation of gpio"364insmod_test "-1,32" 32365insmod_test "-1,23,-1,32" 23 32366insmod_test "-1,23,-1,26,-1,32" 23 26 32367if [ "$full_test" ]; then368 echo "1.2. manual allocation of gpio"369 insmod_test "0,32" 32370 insmod_test "0,32,32,60" 32 28371 insmod_test "0,32,40,64,64,96" 32 24 32372 echo "1.3. dynamic and manual allocation of gpio"373 insmod_test "-1,32,32,62" 32 30374 insmod_test "-1,22,-1,23,0,24,32,64" 22 23 24 32375 insmod_test "-1,32,32,60,-1,29" 32 28 29376 insmod_test "-1,32,40,64,-1,5" 32 24 5377 insmod_test "0,32,32,44,-1,22,-1,31" 32 12 22 31378fi379echo "2. Module load error tests"380echo "2.1 no lines defined"381insmod_test "0,0"382if [ "$full_test" ]; then383 echo "2.2 ignore range overlap"384 insmod_test "0,32,0,1" 32385 insmod_test "0,32,1,5" 32386 insmod_test "0,32,30,35" 32387 insmod_test "0,32,31,32" 32388 insmod_test "10,32,30,35" 22389 insmod_test "10,32,9,14" 22390 insmod_test "0,32,20,21,40,56" 32 16391 insmod_test "0,32,32,64,32,40" 32 32392 insmod_test "0,32,32,64,36,37" 32 32393 insmod_test "0,32,35,64,34,36" 32 29394 insmod_test "0,30,35,64,35,45" 30 29395 insmod_test "0,32,40,56,30,33" 32 16396 insmod_test "0,32,40,56,30,41" 32 16397 insmod_test "0,32,40,56,39,45" 32 16398fi399 400echo "GPIO $module test PASS"401