Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests: gpio: add test cases for gpio-aggregator

Add a set of tests for gpio-aggregator module. This test covers both
pre-existing new_device/delete_device interface and new configfs-based
interface.

Signed-off-by: Koichiro Den <koichiro.den@canonical.com>
Link: https://lore.kernel.org/r/20250407043019.4105613-10-koichiro.den@canonical.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

authored by

Koichiro Den and committed by
Bartosz Golaszewski
6d7f0c11 10f94d09

+725 -1
+1 -1
tools/testing/selftests/gpio/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 3 - TEST_PROGS := gpio-mockup.sh gpio-sim.sh 3 + TEST_PROGS := gpio-mockup.sh gpio-sim.sh gpio-aggregator.sh 4 4 TEST_FILES := gpio-mockup-sysfs.sh 5 5 TEST_GEN_PROGS_EXTENDED := gpio-mockup-cdev gpio-chip-info gpio-line-name 6 6 CFLAGS += -O2 -g -Wall $(KHDR_INCLUDES)
+1
tools/testing/selftests/gpio/config
··· 2 2 CONFIG_GPIO_CDEV=y 3 3 CONFIG_GPIO_MOCKUP=m 4 4 CONFIG_GPIO_SIM=m 5 + CONFIG_GPIO_AGGREGATOR=m
+723
tools/testing/selftests/gpio/gpio-aggregator.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Copyright (C) 2025 Bartosz Golaszewski <brgl@bgdev.pl> 4 + # Copyright (C) 2025 Koichiro Den <koichiro.den@canonical.com> 5 + 6 + BASE_DIR=$(dirname "$0") 7 + CONFIGFS_SIM_DIR="/sys/kernel/config/gpio-sim" 8 + CONFIGFS_AGG_DIR="/sys/kernel/config/gpio-aggregator" 9 + SYSFS_AGG_DIR="/sys/bus/platform/drivers/gpio-aggregator" 10 + MODULE="gpio-aggregator" 11 + 12 + fail() { 13 + echo "$*" >&2 14 + echo "GPIO $MODULE test FAIL" 15 + exit 1 16 + } 17 + 18 + skip() { 19 + echo "$*" >&2 20 + echo "GPIO $MODULE test SKIP" 21 + exit 4 22 + } 23 + 24 + # gpio-sim 25 + sim_enable_chip() { 26 + local CHIP=$1 27 + 28 + echo 1 > "$CONFIGFS_SIM_DIR/$CHIP/live" || fail "Unable to enable the chip" 29 + } 30 + 31 + sim_disable_chip() { 32 + local CHIP=$1 33 + 34 + echo 0 > "$CONFIGFS_SIM_DIR/$CHIP/live" || fail "Unable to disable the chip" 35 + } 36 + 37 + sim_configfs_cleanup() { 38 + local NOCHECK=${1:-0} 39 + 40 + for CHIP_DIR in "$CONFIGFS_SIM_DIR"/*; do 41 + [ -d "$CHIP_DIR" ] || continue 42 + echo 0 > "$CHIP_DIR/live" 43 + find "$CHIP_DIR" -depth -type d -exec rmdir {} \; 44 + done 45 + [ "$NOCHECK" -eq 1 ] && return; 46 + remaining=$(find "$CONFIGFS_SIM_DIR" -mindepth 1 -type d 2> /dev/null) 47 + if [ -n "$remaining" ]; then 48 + fail "Directories remain in $CONFIGFS_SIM_DIR: $remaining" 49 + fi 50 + } 51 + 52 + sim_get_chip_label() { 53 + local CHIP=$1 54 + local BANK=$2 55 + local CHIP_NAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/$BANK/chip_name" 2> /dev/null) || \ 56 + fail "Unable to read the chip name from configfs" 57 + 58 + $BASE_DIR/gpio-chip-info "/dev/$CHIP_NAME" label || \ 59 + fail "Unable to read the chip label from the character device" 60 + } 61 + 62 + # gpio-aggregator 63 + agg_create_chip() { 64 + local CHIP=$1 65 + 66 + mkdir "$CONFIGFS_AGG_DIR/$CHIP" 67 + } 68 + 69 + agg_remove_chip() { 70 + local CHIP=$1 71 + 72 + find "$CONFIGFS_AGG_DIR/$CHIP/" -depth -type d -exec rmdir {} \; || \ 73 + fail "Unable to remove $CONFIGFS_AGG_DIR/$CHIP" 74 + } 75 + 76 + agg_create_line() { 77 + local CHIP=$1 78 + local LINE=$2 79 + 80 + mkdir "$CONFIGFS_AGG_DIR/$CHIP/$LINE" 81 + } 82 + 83 + agg_remove_line() { 84 + local CHIP=$1 85 + local LINE=$2 86 + 87 + rmdir "$CONFIGFS_AGG_DIR/$CHIP/$LINE" 88 + } 89 + 90 + agg_set_key() { 91 + local CHIP=$1 92 + local LINE=$2 93 + local KEY=$3 94 + 95 + echo "$KEY" > "$CONFIGFS_AGG_DIR/$CHIP/$LINE/key" || fail "Unable to set the lookup key" 96 + } 97 + 98 + agg_set_offset() { 99 + local CHIP=$1 100 + local LINE=$2 101 + local OFFSET=$3 102 + 103 + echo "$OFFSET" > "$CONFIGFS_AGG_DIR/$CHIP/$LINE/offset" || \ 104 + fail "Unable to set the lookup offset" 105 + } 106 + 107 + agg_set_line_name() { 108 + local CHIP=$1 109 + local LINE=$2 110 + local NAME=$3 111 + 112 + echo "$NAME" > "$CONFIGFS_AGG_DIR/$CHIP/$LINE/name" || fail "Unable to set the line name" 113 + } 114 + 115 + agg_enable_chip() { 116 + local CHIP=$1 117 + 118 + echo 1 > "$CONFIGFS_AGG_DIR/$CHIP/live" || fail "Unable to enable the chip" 119 + } 120 + 121 + agg_disable_chip() { 122 + local CHIP=$1 123 + 124 + echo 0 > "$CONFIGFS_AGG_DIR/$CHIP/live" || fail "Unable to disable the chip" 125 + } 126 + 127 + agg_configfs_cleanup() { 128 + local NOCHECK=${1:-0} 129 + 130 + for CHIP_DIR in "$CONFIGFS_AGG_DIR"/*; do 131 + [ -d "$CHIP_DIR" ] || continue 132 + echo 0 > "$CHIP_DIR/live" 2> /dev/null 133 + find "$CHIP_DIR" -depth -type d -exec rmdir {} \; 134 + done 135 + [ "$NOCHECK" -eq 1 ] && return; 136 + remaining=$(find "$CONFIGFS_AGG_DIR" -mindepth 1 -type d 2> /dev/null) 137 + if [ -n "$remaining" ]; then 138 + fail "Directories remain in $CONFIGFS_AGG_DIR: $remaining" 139 + fi 140 + } 141 + 142 + agg_configfs_dev_name() { 143 + local CHIP=$1 144 + 145 + cat "$CONFIGFS_AGG_DIR/$CHIP/dev_name" 2> /dev/null || \ 146 + fail "Unable to read the device name from configfs" 147 + } 148 + 149 + agg_configfs_chip_name() { 150 + local CHIP=$1 151 + local DEV_NAME=$(agg_configfs_dev_name "$CHIP") 152 + local CHIP_LIST=$(find "/sys/devices/platform/$DEV_NAME" \ 153 + -maxdepth 1 -type d -name "gpiochip[0-9]*" 2> /dev/null) 154 + local CHIP_COUNT=$(echo "$CHIP_LIST" | wc -l) 155 + 156 + if [ -z "$CHIP_LIST" ]; then 157 + fail "No gpiochip in /sys/devices/platform/$DEV_NAME/" 158 + elif [ "$CHIP_COUNT" -ne 1 ]; then 159 + fail "Multiple gpiochips unexpectedly found: $CHIP_LIST" 160 + fi 161 + basename "$CHIP_LIST" 162 + } 163 + 164 + agg_get_chip_num_lines() { 165 + local CHIP=$1 166 + local N_DIR=$(ls -d $CONFIGFS_AGG_DIR/$CHIP/line[0-9]* 2> /dev/null | wc -l) 167 + local N_LINES 168 + 169 + if [ "$(cat $CONFIGFS_AGG_DIR/$CHIP/live)" = 0 ]; then 170 + echo "$N_DIR" 171 + else 172 + N_LINES=$( 173 + $BASE_DIR/gpio-chip-info \ 174 + "/dev/$(agg_configfs_chip_name "$CHIP")" num-lines 175 + ) || fail "Unable to read the number of lines from the character device" 176 + if [ $N_DIR != $N_LINES ]; then 177 + fail "Discrepancy between two sources for the number of lines" 178 + fi 179 + echo "$N_LINES" 180 + fi 181 + } 182 + 183 + agg_get_chip_label() { 184 + local CHIP=$1 185 + 186 + $BASE_DIR/gpio-chip-info "/dev/$(agg_configfs_chip_name "$CHIP")" label || \ 187 + fail "Unable to read the chip label from the character device" 188 + } 189 + 190 + agg_get_line_name() { 191 + local CHIP=$1 192 + local OFFSET=$2 193 + local NAME_CONFIGFS=$(cat "$CONFIGFS_AGG_DIR/$CHIP/line${OFFSET}/name") 194 + local NAME_CDEV 195 + 196 + if [ "$(cat "$CONFIGFS_AGG_DIR/$CHIP/live")" = 0 ]; then 197 + echo "$NAME_CONFIGFS" 198 + else 199 + NAME_CDEV=$( 200 + $BASE_DIR/gpio-line-name \ 201 + "/dev/$(agg_configfs_chip_name "$CHIP")" "$OFFSET" 202 + ) || fail "Unable to read the line name from the character device" 203 + if [ "$NAME_CONFIGFS" != "$NAME_CDEV" ]; then 204 + fail "Discrepancy between two sources for the name of line" 205 + fi 206 + echo "$NAME_CDEV" 207 + fi 208 + } 209 + 210 + 211 + # Load the modules. This will pull in configfs if needed too. 212 + modprobe gpio-sim || skip "unable to load the gpio-sim module" 213 + modprobe gpio-aggregator || skip "unable to load the gpio-aggregator module" 214 + 215 + # Make sure configfs is mounted at /sys/kernel/config. Wait a bit if needed. 216 + for IDX in $(seq 5); do 217 + if [ "$IDX" -eq "5" ]; then 218 + skip "configfs not mounted at /sys/kernel/config" 219 + fi 220 + 221 + mountpoint -q /sys/kernel/config && break 222 + sleep 0.1 223 + done 224 + 225 + # If the module was already loaded: remove all previous chips 226 + agg_configfs_cleanup 227 + sim_configfs_cleanup 228 + 229 + trap "exit 1" SIGTERM SIGINT 230 + trap "agg_configfs_cleanup 1; sim_configfs_cleanup 1" EXIT 231 + 232 + # Use gpio-sim chips as the test backend 233 + for CHIP in $(seq -f "chip%g" 0 1); do 234 + mkdir $CONFIGFS_SIM_DIR/$CHIP 235 + for BANK in $(seq -f "bank%g" 0 1); do 236 + mkdir -p "$CONFIGFS_SIM_DIR/$CHIP/$BANK" 237 + echo "${CHIP}_${BANK}" > "$CONFIGFS_SIM_DIR/$CHIP/$BANK/label" || \ 238 + fail "unable to set the chip label" 239 + echo 16 > "$CONFIGFS_SIM_DIR/$CHIP/$BANK/num_lines" || \ 240 + fail "unable to set the number of lines" 241 + for IDX in $(seq 0 15); do 242 + LINE_NAME="${CHIP}${BANK}_${IDX}" 243 + LINE_DIR="$CONFIGFS_SIM_DIR/$CHIP/$BANK/line$IDX" 244 + mkdir -p $LINE_DIR 245 + echo "$LINE_NAME" > "$LINE_DIR/name" || fail "unable to set the line name" 246 + done 247 + done 248 + sim_enable_chip "$CHIP" 249 + done 250 + 251 + echo "1. GPIO aggregator creation/deletion" 252 + 253 + echo "1.1. Creation/deletion via configfs" 254 + 255 + echo "1.1.1. Minimum creation/deletion" 256 + agg_create_chip agg0 257 + agg_create_line agg0 line0 258 + agg_set_key agg0 line0 "$(sim_get_chip_label chip0 bank0)" 259 + agg_set_offset agg0 line0 5 260 + agg_set_line_name agg0 line0 test0 261 + agg_enable_chip agg0 262 + test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 1 || fail "chip unexpectedly dead" 263 + test "$(agg_get_chip_label agg0)" = "$(agg_configfs_dev_name agg0)" || \ 264 + fail "label is inconsistent" 265 + test "$(agg_get_chip_num_lines agg0)" = "1" || fail "number of lines is not 1" 266 + test "$(agg_get_line_name agg0 0)" = "test0" || fail "line name is unset" 267 + agg_disable_chip agg0 268 + agg_remove_line agg0 line0 269 + agg_remove_chip agg0 270 + 271 + echo "1.1.2. Complex creation/deletion" 272 + agg_create_chip agg0 273 + agg_create_line agg0 line0 274 + agg_create_line agg0 line1 275 + agg_create_line agg0 line2 276 + agg_create_line agg0 line3 277 + agg_set_key agg0 line0 "$(sim_get_chip_label chip0 bank0)" 278 + agg_set_key agg0 line1 "$(sim_get_chip_label chip0 bank1)" 279 + agg_set_key agg0 line2 "$(sim_get_chip_label chip1 bank0)" 280 + agg_set_key agg0 line3 "$(sim_get_chip_label chip1 bank1)" 281 + agg_set_offset agg0 line0 1 282 + agg_set_offset agg0 line1 3 283 + agg_set_offset agg0 line2 5 284 + agg_set_offset agg0 line3 7 285 + agg_set_line_name agg0 line0 test0 286 + agg_set_line_name agg0 line1 test1 287 + agg_set_line_name agg0 line2 test2 288 + agg_set_line_name agg0 line3 test3 289 + agg_enable_chip agg0 290 + test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 1 || fail "chip unexpectedly dead" 291 + test "$(agg_get_chip_label agg0)" = "$(agg_configfs_dev_name agg0)" || \ 292 + fail "label is inconsistent" 293 + test "$(agg_get_chip_num_lines agg0)" = "4" || fail "number of lines is not 1" 294 + test "$(agg_get_line_name agg0 0)" = "test0" || fail "line name is unset" 295 + test "$(agg_get_line_name agg0 1)" = "test1" || fail "line name is unset" 296 + test "$(agg_get_line_name agg0 2)" = "test2" || fail "line name is unset" 297 + test "$(agg_get_line_name agg0 3)" = "test3" || fail "line name is unset" 298 + agg_disable_chip agg0 299 + agg_remove_line agg0 line0 300 + agg_remove_line agg0 line1 301 + agg_remove_line agg0 line2 302 + agg_remove_line agg0 line3 303 + agg_remove_chip agg0 304 + 305 + echo "1.1.3. Can't instantiate a chip without any line" 306 + agg_create_chip agg0 307 + echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled" 308 + test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 0 || fail "chip unexpectedly alive" 309 + agg_remove_chip agg0 310 + 311 + echo "1.1.4. Can't instantiate a chip with invalid configuration" 312 + agg_create_chip agg0 313 + agg_create_line agg0 line0 314 + agg_set_key agg0 line0 "chipX_bankX" 315 + agg_set_offset agg0 line0 99 316 + agg_set_line_name agg0 line0 test0 317 + echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled" 318 + test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 0 || fail "chip unexpectedly alive" 319 + agg_remove_line agg0 line0 320 + agg_remove_chip agg0 321 + 322 + echo "1.1.5. Can't instantiate a chip asynchronously via deferred probe" 323 + agg_create_chip agg0 324 + agg_create_line agg0 line0 325 + agg_set_key agg0 line0 "chip0_bank0" 326 + agg_set_offset agg0 line0 5 327 + agg_set_line_name agg0 line0 test0 328 + sim_disable_chip chip0 329 + echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled" 330 + test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 0 || fail "chip unexpectedly alive" 331 + sim_enable_chip chip0 332 + sleep 1 333 + test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 0 || \ 334 + fail "chip unexpectedly transitioned to 'live' state" 335 + agg_remove_line agg0 line0 336 + agg_remove_chip agg0 337 + 338 + echo "1.2. Creation/deletion via sysfs" 339 + 340 + echo "1.2.1. Minimum creation/deletion" 341 + echo "chip0_bank0 0" > "$SYSFS_AGG_DIR/new_device" 342 + CHIPNAME=$(agg_configfs_chip_name _sysfs.0) 343 + test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 1 || fail "chip unexpectedly dead" 344 + test "$(agg_get_chip_label _sysfs.0)" = "$(agg_configfs_dev_name _sysfs.0)" || \ 345 + fail "label is inconsistent" 346 + test "$(agg_get_chip_num_lines _sysfs.0)" = "1" || fail "number of lines is not 1" 347 + test "$(agg_get_line_name _sysfs.0 0)" = "" || fail "line name is unset" 348 + echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device" 349 + test -d $CONFIGFS_AGG_DIR/_sysfs.0 && fail "_sysfs.0 unexpectedly remains" 350 + test -d /dev/${CHIPNAME} && fail "/dev/${CHIPNAME} unexpectedly remains" 351 + 352 + echo "1.2.2. Complex creation/deletion" 353 + echo "chip0bank0_0 chip1_bank1 10-11" > "$SYSFS_AGG_DIR/new_device" 354 + CHIPNAME=$(agg_configfs_chip_name _sysfs.0) 355 + test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 1 || fail "chip unexpectedly dead" 356 + test "$(agg_get_chip_label _sysfs.0)" = "$(agg_configfs_dev_name _sysfs.0)" || \ 357 + fail "label is inconsistent" 358 + test "$(agg_get_chip_num_lines _sysfs.0)" = "3" || fail "number of lines is not 3" 359 + test "$(agg_get_line_name _sysfs.0 0)" = "" || fail "line name is unset" 360 + test "$(agg_get_line_name _sysfs.0 1)" = "" || fail "line name is unset" 361 + test "$(agg_get_line_name _sysfs.0 2)" = "" || fail "line name is unset" 362 + echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device" 363 + test -d $CONFIGFS_AGG_DIR/_sysfs.0 && fail "_sysfs.0 unexpectedly remains" 364 + test -d /dev/${CHIPNAME} && fail "/dev/${CHIPNAME} unexpectedly remains" 365 + 366 + echo "1.2.3. Asynchronous creation with deferred probe" 367 + sim_disable_chip chip0 368 + echo 'chip0_bank0 0' > $SYSFS_AGG_DIR/new_device 369 + sleep 1 370 + test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 0 || fail "chip unexpectedly alive" 371 + sim_enable_chip chip0 372 + sleep 1 373 + CHIPNAME=$(agg_configfs_chip_name _sysfs.0) 374 + test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 1 || fail "chip unexpectedly remains dead" 375 + test "$(agg_get_chip_label _sysfs.0)" = "$(agg_configfs_dev_name _sysfs.0)" || \ 376 + fail "label is inconsistent" 377 + test "$(agg_get_chip_num_lines _sysfs.0)" = "1" || fail "number of lines is not 1" 378 + test "$(agg_get_line_name _sysfs.0 0)" = "" || fail "line name unexpectedly set" 379 + echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device" 380 + test -d $CONFIGFS_AGG_DIR/_sysfs.0 && fail "_sysfs.0 unexpectedly remains" 381 + test -d /dev/${CHIPNAME} && fail "/dev/${CHIPNAME} unexpectedly remains" 382 + 383 + echo "1.2.4. Can't instantiate a chip with invalid configuration" 384 + echo "xyz 0" > "$SYSFS_AGG_DIR/new_device" 385 + test "$(cat $CONFIGFS_AGG_DIR/_sysfs.0/live)" = 0 || fail "chip unexpectedly alive" 386 + echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device" 387 + 388 + echo "2. GPIO aggregator configuration" 389 + 390 + echo "2.1. Configuring aggregators instantiated via configfs" 391 + setup_2_1() { 392 + agg_create_chip agg0 393 + agg_create_line agg0 line0 394 + agg_create_line agg0 line1 395 + agg_set_key agg0 line0 "$(sim_get_chip_label chip0 bank0)" 396 + agg_set_key agg0 line1 "$(sim_get_chip_label chip1 bank0)" 397 + agg_set_offset agg0 line0 1 398 + agg_set_offset agg0 line1 3 399 + agg_set_line_name agg0 line0 test0 400 + agg_set_line_name agg0 line1 test1 401 + agg_enable_chip agg0 402 + } 403 + teardown_2_1() { 404 + agg_configfs_cleanup 405 + } 406 + 407 + echo "2.1.1. While offline" 408 + 409 + echo "2.1.1.1. Line can be added/removed" 410 + setup_2_1 411 + agg_disable_chip agg0 412 + agg_create_line agg0 line2 413 + agg_set_key agg0 line2 "$(sim_get_chip_label chip0 bank1)" 414 + agg_set_offset agg0 line2 5 415 + agg_enable_chip agg0 416 + test "$(agg_get_chip_num_lines agg0)" = "3" || fail "number of lines is not 1" 417 + teardown_2_1 418 + 419 + echo "2.1.1.2. Line key can be modified" 420 + setup_2_1 421 + agg_disable_chip agg0 422 + agg_set_key agg0 line0 "$(sim_get_chip_label chip0 bank1)" 423 + agg_set_key agg0 line1 "$(sim_get_chip_label chip1 bank1)" 424 + agg_enable_chip agg0 425 + teardown_2_1 426 + 427 + echo "2.1.1.3. Line name can be modified" 428 + setup_2_1 429 + agg_disable_chip agg0 430 + agg_set_line_name agg0 line0 new0 431 + agg_set_line_name agg0 line1 new1 432 + agg_enable_chip agg0 433 + test "$(agg_get_line_name agg0 0)" = "new0" || fail "line name is unset" 434 + test "$(agg_get_line_name agg0 1)" = "new1" || fail "line name is unset" 435 + teardown_2_1 436 + 437 + echo "2.1.1.4. Line offset can be modified" 438 + setup_2_1 439 + agg_disable_chip agg0 440 + agg_set_offset agg0 line0 5 441 + agg_set_offset agg0 line1 7 442 + agg_enable_chip agg0 443 + teardown_2_1 444 + 445 + echo "2.1.1.5. Can re-enable a chip after valid reconfiguration" 446 + setup_2_1 447 + agg_disable_chip agg0 448 + agg_set_key agg0 line0 "$(sim_get_chip_label chip1 bank1)" 449 + agg_set_offset agg0 line0 15 450 + agg_set_key agg0 line1 "$(sim_get_chip_label chip0 bank1)" 451 + agg_set_offset agg0 line0 14 452 + agg_create_line agg0 line2 453 + agg_set_key agg0 line2 "$(sim_get_chip_label chip0 bank1)" 454 + agg_set_offset agg0 line2 13 455 + agg_enable_chip agg0 456 + test "$(agg_get_chip_num_lines agg0)" = "3" || fail "number of lines is not 1" 457 + teardown_2_1 458 + 459 + echo "2.1.1.7. Can't re-enable a chip with invalid reconfiguration" 460 + setup_2_1 461 + agg_disable_chip agg0 462 + agg_set_key agg0 line0 invalidkey 463 + echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled" 464 + teardown_2_1 465 + setup_2_1 466 + agg_disable_chip agg0 467 + agg_set_offset agg0 line0 99 468 + echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled" 469 + teardown_2_1 470 + 471 + echo "2.1.2. While online" 472 + 473 + echo "2.1.2.1. Can't add/remove line" 474 + setup_2_1 475 + mkdir "$CONFIGFS_AGG_DIR/agg0/line2" 2> /dev/null && fail "line unexpectedly added" 476 + rmdir "$CONFIGFS_AGG_DIR/agg0/line1" 2> /dev/null && fail "line unexpectedly removed" 477 + teardown_2_1 478 + 479 + echo "2.1.2.2. Can't modify line key" 480 + setup_2_1 481 + echo "chip1_bank1" > "$CONFIGFS_AGG_DIR/agg0/line0/key" 2> /dev/null && \ 482 + fail "lookup key unexpectedly updated" 483 + teardown_2_1 484 + 485 + echo "2.1.2.3. Can't modify line name" 486 + setup_2_1 487 + echo "new0" > "$CONFIGFS_AGG_DIR/agg0/line0/name" 2> /dev/null && \ 488 + fail "name unexpectedly updated" 489 + teardown_2_1 490 + 491 + echo "2.1.2.4. Can't modify line offset" 492 + setup_2_1 493 + echo "5" > "$CONFIGFS_AGG_DIR/agg0/line0/offset" 2> /dev/null && \ 494 + fail "offset unexpectedly updated" 495 + teardown_2_1 496 + 497 + echo "2.2. Configuring aggregators instantiated via sysfs" 498 + setup_2_2() { 499 + echo "chip0_bank0 1 chip1_bank0 3" > "$SYSFS_AGG_DIR/new_device" 500 + } 501 + teardown_2_2() { 502 + echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device" 503 + } 504 + 505 + echo "2.2.1. While online" 506 + 507 + echo "2.2.1.1. Can toggle live" 508 + setup_2_2 509 + agg_disable_chip _sysfs.0 510 + agg_enable_chip _sysfs.0 511 + teardown_2_2 512 + 513 + echo "2.2.1.2. Can't add/remove line" 514 + setup_2_2 515 + mkdir "$CONFIGFS_AGG_DIR/_sysfs.0/line2" 2> /dev/null && fail "line unexpectedly added" 516 + rmdir "$CONFIGFS_AGG_DIR/_sysfs.0/line1" 2> /dev/null && fail "line unexpectedly removed" 517 + teardown_2_2 518 + 519 + echo "2.2.1.3. Can't modify line key" 520 + setup_2_2 521 + echo "chip1_bank1" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/key" 2> /dev/null && \ 522 + fail "lookup key unexpectedly updated" 523 + teardown_2_2 524 + 525 + echo "2.2.1.4. Can't modify line name" 526 + setup_2_2 527 + echo "new0" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/name" 2> /dev/null && \ 528 + fail "name unexpectedly updated" 529 + teardown_2_2 530 + 531 + echo "2.2.1.5. Can't modify line offset" 532 + setup_2_2 533 + echo "5" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/offset" 2> /dev/null && \ 534 + fail "offset unexpectedly updated" 535 + teardown_2_2 536 + 537 + echo "2.2.2. While waiting for deferred probe" 538 + 539 + echo "2.2.2.1. Can't add/remove line despite live = 0" 540 + sim_disable_chip chip0 541 + setup_2_2 542 + mkdir "$CONFIGFS_AGG_DIR/_sysfs.0/line2" 2> /dev/null && fail "line unexpectedly added" 543 + rmdir "$CONFIGFS_AGG_DIR/_sysfs.0/line1" 2> /dev/null && fail "line unexpectedly removed" 544 + teardown_2_2 545 + sim_enable_chip chip0 546 + 547 + echo "2.2.2.2. Can't modify line key" 548 + sim_disable_chip chip0 549 + setup_2_2 550 + echo "chip1_bank1" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/key" 2> /dev/null && \ 551 + fail "lookup key unexpectedly updated" 552 + teardown_2_2 553 + sim_enable_chip chip0 554 + 555 + echo "2.2.2.3. Can't modify line name" 556 + sim_disable_chip chip0 557 + setup_2_2 558 + echo "new0" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/name" 2> /dev/null && \ 559 + fail "name unexpectedly updated" 560 + teardown_2_2 561 + sim_enable_chip chip0 562 + 563 + echo "2.2.2.4. Can't modify line offset" 564 + sim_disable_chip chip0 565 + setup_2_2 566 + echo 5 > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/offset" 2> /dev/null && \ 567 + fail "offset unexpectedly updated" 568 + teardown_2_2 569 + sim_enable_chip chip0 570 + 571 + echo "2.2.2.5. Can't toggle live" 572 + sim_disable_chip chip0 573 + setup_2_2 574 + test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 0 || fail "chip unexpectedly alive" 575 + echo 1 > "$CONFIGFS_AGG_DIR/_sysfs.0/live" 2> /dev/null && fail "chip unexpectedly enabled" 576 + teardown_2_2 577 + sim_enable_chip chip0 578 + 579 + echo "2.2.3. While offline" 580 + 581 + echo "2.2.3.1. Can't add/remove line despite live = 0" 582 + setup_2_2 583 + agg_disable_chip _sysfs.0 584 + mkdir "$CONFIGFS_AGG_DIR/_sysfs.0/line2" 2> /dev/null && fail "line unexpectedly added" 585 + rmdir "$CONFIGFS_AGG_DIR/_sysfs.0/line1" 2> /dev/null && fail "line unexpectedly removed" 586 + teardown_2_2 587 + 588 + echo "2.2.3.2. Line key can be modified" 589 + setup_2_2 590 + agg_disable_chip _sysfs.0 591 + agg_set_key _sysfs.0 line0 "$(sim_get_chip_label chip0 bank1)" 592 + agg_set_key _sysfs.0 line1 "$(sim_get_chip_label chip1 bank1)" 593 + agg_enable_chip _sysfs.0 594 + teardown_2_2 595 + 596 + echo "2.2.3.3. Line name can be modified" 597 + setup_2_2 598 + agg_disable_chip _sysfs.0 599 + agg_set_line_name _sysfs.0 line0 new0 600 + agg_set_line_name _sysfs.0 line1 new1 601 + agg_enable_chip _sysfs.0 602 + test "$(agg_get_line_name _sysfs.0 0)" = "new0" || fail "line name is unset" 603 + test "$(agg_get_line_name _sysfs.0 1)" = "new1" || fail "line name is unset" 604 + teardown_2_2 605 + 606 + echo "2.2.3.4. Line offset can be modified" 607 + setup_2_2 608 + agg_disable_chip _sysfs.0 609 + agg_set_offset _sysfs.0 line0 5 610 + agg_set_offset _sysfs.0 line1 7 611 + agg_enable_chip _sysfs.0 612 + teardown_2_2 613 + 614 + echo "2.2.3.5. Can re-enable a chip with valid reconfiguration" 615 + setup_2_2 616 + agg_disable_chip _sysfs.0 617 + agg_set_key _sysfs.0 line0 "$(sim_get_chip_label chip1 bank1)" 618 + agg_set_offset _sysfs.0 line0 15 619 + agg_set_key _sysfs.0 line1 "$(sim_get_chip_label chip0 bank1)" 620 + agg_set_offset _sysfs.0 line0 14 621 + agg_enable_chip _sysfs.0 622 + teardown_2_2 623 + 624 + echo "2.2.3.6. Can't re-enable a chip with invalid reconfiguration" 625 + setup_2_2 626 + agg_disable_chip _sysfs.0 627 + agg_set_key _sysfs.0 line0 invalidkey 628 + echo 1 > "$CONFIGFS_AGG_DIR/_sysfs.0/live" 2> /dev/null && fail "chip unexpectedly enabled" 629 + teardown_2_2 630 + setup_2_2 631 + agg_disable_chip _sysfs.0 632 + agg_set_offset _sysfs.0 line0 99 633 + echo 1 > "$CONFIGFS_AGG_DIR/_sysfs.0/live" 2> /dev/null && fail "chip unexpectedly enabled" 634 + teardown_2_2 635 + 636 + echo "3. Module unload" 637 + 638 + echo "3.1. Can't unload module if there is at least one device created via configfs" 639 + agg_create_chip agg0 640 + modprobe -r gpio-aggregator 2> /dev/null 641 + test -d /sys/module/gpio_aggregator || fail "module unexpectedly unloaded" 642 + agg_remove_chip agg0 643 + 644 + echo "3.2. Can unload module if there is no device created via configfs" 645 + echo "chip0_bank0 1 chip1_bank0 3" > "$SYSFS_AGG_DIR/new_device" 646 + modprobe -r gpio-aggregator 2> /dev/null 647 + test -d /sys/module/gpio_aggregator && fail "module unexpectedly remains to be loaded" 648 + modprobe gpio-aggregator 2> /dev/null 649 + 650 + echo "4. GPIO forwarder functional" 651 + SETTINGS="chip0:bank0:2 chip0:bank1:4 chip1:bank0:6 chip1:bank1:8" 652 + setup_4() { 653 + local OFFSET=0 654 + agg_create_chip agg0 655 + for SETTING in $SETTINGS; do 656 + CHIP=$(echo "$SETTING" | cut -d: -f1) 657 + BANK=$(echo "$SETTING" | cut -d: -f2) 658 + LINE=$(echo "$SETTING" | cut -d: -f3) 659 + agg_create_line agg0 "line${OFFSET}" 660 + agg_set_key agg0 "line${OFFSET}" "$(sim_get_chip_label "$CHIP" "$BANK")" 661 + agg_set_offset agg0 "line${OFFSET}" "$LINE" 662 + OFFSET=$(expr $OFFSET + 1) 663 + done 664 + agg_enable_chip agg0 665 + } 666 + teardown_4() { 667 + agg_configfs_cleanup 668 + } 669 + 670 + echo "4.1. Forwarding set values" 671 + setup_4 672 + OFFSET=0 673 + for SETTING in $SETTINGS; do 674 + CHIP=$(echo "$SETTING" | cut -d: -f1) 675 + BANK=$(echo "$SETTING" | cut -d: -f2) 676 + LINE=$(echo "$SETTING" | cut -d: -f3) 677 + DEVNAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/dev_name") 678 + CHIPNAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/$BANK/chip_name") 679 + VAL_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio${LINE}/value" 680 + test $(cat $VAL_PATH) = "0" || fail "incorrect value read from sysfs" 681 + $BASE_DIR/gpio-mockup-cdev -s 1 "/dev/$(agg_configfs_chip_name agg0)" "$OFFSET" & 682 + mock_pid=$! 683 + sleep 0.1 # FIXME Any better way? 684 + test "$(cat $VAL_PATH)" = "1" || fail "incorrect value read from sysfs" 685 + kill "$mock_pid" 686 + OFFSET=$(expr $OFFSET + 1) 687 + done 688 + teardown_4 689 + 690 + echo "4.2. Forwarding set config" 691 + setup_4 692 + OFFSET=0 693 + for SETTING in $SETTINGS; do 694 + CHIP=$(echo "$SETTING" | cut -d: -f1) 695 + BANK=$(echo "$SETTING" | cut -d: -f2) 696 + LINE=$(echo "$SETTING" | cut -d: -f3) 697 + DEVNAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/dev_name") 698 + CHIPNAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/$BANK/chip_name") 699 + VAL_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio${LINE}/value" 700 + $BASE_DIR/gpio-mockup-cdev -b pull-up "/dev/$(agg_configfs_chip_name agg0)" "$OFFSET" 701 + test $(cat "$VAL_PATH") = "1" || fail "incorrect value read from sysfs" 702 + OFFSET=$(expr $OFFSET + 1) 703 + done 704 + teardown_4 705 + 706 + echo "5. Race condition verification" 707 + 708 + echo "5.1. Stress test of new_device/delete_device and module load/unload" 709 + for _ in $(seq 1000); do 710 + { 711 + echo "dummy 0" > "$SYSFS_AGG_DIR/new_device" 712 + cat "$CONFIGFS_AGG_DIR/_sysfs.0/dev_name" > "$SYSFS_AGG_DIR/delete_device" 713 + } 2> /dev/null 714 + done & 715 + writer_pid=$! 716 + while kill -0 "$writer_pid" 2> /dev/null; do 717 + { 718 + modprobe gpio-aggregator 719 + modprobe -r gpio-aggregator 720 + } 2> /dev/null 721 + done 722 + 723 + echo "GPIO $MODULE test PASS"