Path: blob/master/tools/testing/selftests/gpio/gpio-aggregator.sh
26285 views
#!/bin/sh1# SPDX-License-Identifier: GPL-2.02# Copyright (C) 2025 Bartosz Golaszewski <[email protected]>3# Copyright (C) 2025 Koichiro Den <[email protected]>45BASE_DIR=$(dirname "$0")6CONFIGFS_SIM_DIR="/sys/kernel/config/gpio-sim"7CONFIGFS_AGG_DIR="/sys/kernel/config/gpio-aggregator"8SYSFS_AGG_DIR="/sys/bus/platform/drivers/gpio-aggregator"9MODULE="gpio-aggregator"1011fail() {12echo "$*" >&213echo "GPIO $MODULE test FAIL"14exit 115}1617skip() {18echo "$*" >&219echo "GPIO $MODULE test SKIP"20exit 421}2223# gpio-sim24sim_enable_chip() {25local CHIP=$12627echo 1 > "$CONFIGFS_SIM_DIR/$CHIP/live" || fail "Unable to enable the chip"28}2930sim_disable_chip() {31local CHIP=$13233echo 0 > "$CONFIGFS_SIM_DIR/$CHIP/live" || fail "Unable to disable the chip"34}3536sim_configfs_cleanup() {37local NOCHECK=${1:-0}3839for CHIP_DIR in "$CONFIGFS_SIM_DIR"/*; do40[ -d "$CHIP_DIR" ] || continue41echo 0 > "$CHIP_DIR/live"42find "$CHIP_DIR" -depth -type d -exec rmdir {} \;43done44[ "$NOCHECK" -eq 1 ] && return;45remaining=$(find "$CONFIGFS_SIM_DIR" -mindepth 1 -type d 2> /dev/null)46if [ -n "$remaining" ]; then47fail "Directories remain in $CONFIGFS_SIM_DIR: $remaining"48fi49}5051sim_get_chip_label() {52local CHIP=$153local BANK=$254local CHIP_NAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/$BANK/chip_name" 2> /dev/null) || \55fail "Unable to read the chip name from configfs"5657$BASE_DIR/gpio-chip-info "/dev/$CHIP_NAME" label || \58fail "Unable to read the chip label from the character device"59}6061# gpio-aggregator62agg_create_chip() {63local CHIP=$16465mkdir "$CONFIGFS_AGG_DIR/$CHIP"66}6768agg_remove_chip() {69local CHIP=$17071find "$CONFIGFS_AGG_DIR/$CHIP/" -depth -type d -exec rmdir {} \; || \72fail "Unable to remove $CONFIGFS_AGG_DIR/$CHIP"73}7475agg_create_line() {76local CHIP=$177local LINE=$27879mkdir "$CONFIGFS_AGG_DIR/$CHIP/$LINE"80}8182agg_remove_line() {83local CHIP=$184local LINE=$28586rmdir "$CONFIGFS_AGG_DIR/$CHIP/$LINE"87}8889agg_set_key() {90local CHIP=$191local LINE=$292local KEY=$39394echo "$KEY" > "$CONFIGFS_AGG_DIR/$CHIP/$LINE/key" || fail "Unable to set the lookup key"95}9697agg_set_offset() {98local CHIP=$199local LINE=$2100local OFFSET=$3101102echo "$OFFSET" > "$CONFIGFS_AGG_DIR/$CHIP/$LINE/offset" || \103fail "Unable to set the lookup offset"104}105106agg_set_line_name() {107local CHIP=$1108local LINE=$2109local NAME=$3110111echo "$NAME" > "$CONFIGFS_AGG_DIR/$CHIP/$LINE/name" || fail "Unable to set the line name"112}113114agg_enable_chip() {115local CHIP=$1116117echo 1 > "$CONFIGFS_AGG_DIR/$CHIP/live" || fail "Unable to enable the chip"118}119120agg_disable_chip() {121local CHIP=$1122123echo 0 > "$CONFIGFS_AGG_DIR/$CHIP/live" || fail "Unable to disable the chip"124}125126agg_configfs_cleanup() {127local NOCHECK=${1:-0}128129for CHIP_DIR in "$CONFIGFS_AGG_DIR"/*; do130[ -d "$CHIP_DIR" ] || continue131echo 0 > "$CHIP_DIR/live" 2> /dev/null132find "$CHIP_DIR" -depth -type d -exec rmdir {} \;133done134[ "$NOCHECK" -eq 1 ] && return;135remaining=$(find "$CONFIGFS_AGG_DIR" -mindepth 1 -type d 2> /dev/null)136if [ -n "$remaining" ]; then137fail "Directories remain in $CONFIGFS_AGG_DIR: $remaining"138fi139}140141agg_configfs_dev_name() {142local CHIP=$1143144cat "$CONFIGFS_AGG_DIR/$CHIP/dev_name" 2> /dev/null || \145fail "Unable to read the device name from configfs"146}147148agg_configfs_chip_name() {149local CHIP=$1150local DEV_NAME=$(agg_configfs_dev_name "$CHIP")151local CHIP_LIST=$(find "/sys/devices/platform/$DEV_NAME" \152-maxdepth 1 -type d -name "gpiochip[0-9]*" 2> /dev/null)153local CHIP_COUNT=$(echo "$CHIP_LIST" | wc -l)154155if [ -z "$CHIP_LIST" ]; then156fail "No gpiochip in /sys/devices/platform/$DEV_NAME/"157elif [ "$CHIP_COUNT" -ne 1 ]; then158fail "Multiple gpiochips unexpectedly found: $CHIP_LIST"159fi160basename "$CHIP_LIST"161}162163agg_get_chip_num_lines() {164local CHIP=$1165local N_DIR=$(ls -d $CONFIGFS_AGG_DIR/$CHIP/line[0-9]* 2> /dev/null | wc -l)166local N_LINES167168if [ "$(cat $CONFIGFS_AGG_DIR/$CHIP/live)" = 0 ]; then169echo "$N_DIR"170else171N_LINES=$(172$BASE_DIR/gpio-chip-info \173"/dev/$(agg_configfs_chip_name "$CHIP")" num-lines174) || fail "Unable to read the number of lines from the character device"175if [ $N_DIR != $N_LINES ]; then176fail "Discrepancy between two sources for the number of lines"177fi178echo "$N_LINES"179fi180}181182agg_get_chip_label() {183local CHIP=$1184185$BASE_DIR/gpio-chip-info "/dev/$(agg_configfs_chip_name "$CHIP")" label || \186fail "Unable to read the chip label from the character device"187}188189agg_get_line_name() {190local CHIP=$1191local OFFSET=$2192local NAME_CONFIGFS=$(cat "$CONFIGFS_AGG_DIR/$CHIP/line${OFFSET}/name")193local NAME_CDEV194195if [ "$(cat "$CONFIGFS_AGG_DIR/$CHIP/live")" = 0 ]; then196echo "$NAME_CONFIGFS"197else198NAME_CDEV=$(199$BASE_DIR/gpio-line-name \200"/dev/$(agg_configfs_chip_name "$CHIP")" "$OFFSET"201) || fail "Unable to read the line name from the character device"202if [ "$NAME_CONFIGFS" != "$NAME_CDEV" ]; then203fail "Discrepancy between two sources for the name of line"204fi205echo "$NAME_CDEV"206fi207}208209210# Load the modules. This will pull in configfs if needed too.211modprobe gpio-sim || skip "unable to load the gpio-sim module"212modprobe gpio-aggregator || skip "unable to load the gpio-aggregator module"213214# Make sure configfs is mounted at /sys/kernel/config. Wait a bit if needed.215for IDX in $(seq 5); do216if [ "$IDX" -eq "5" ]; then217skip "configfs not mounted at /sys/kernel/config"218fi219220mountpoint -q /sys/kernel/config && break221sleep 0.1222done223224# If the module was already loaded: remove all previous chips225agg_configfs_cleanup226sim_configfs_cleanup227228trap "exit 1" SIGTERM SIGINT229trap "agg_configfs_cleanup 1; sim_configfs_cleanup 1" EXIT230231# Use gpio-sim chips as the test backend232for CHIP in $(seq -f "chip%g" 0 1); do233mkdir $CONFIGFS_SIM_DIR/$CHIP234for BANK in $(seq -f "bank%g" 0 1); do235mkdir -p "$CONFIGFS_SIM_DIR/$CHIP/$BANK"236echo "${CHIP}_${BANK}" > "$CONFIGFS_SIM_DIR/$CHIP/$BANK/label" || \237fail "unable to set the chip label"238echo 16 > "$CONFIGFS_SIM_DIR/$CHIP/$BANK/num_lines" || \239fail "unable to set the number of lines"240for IDX in $(seq 0 15); do241LINE_NAME="${CHIP}${BANK}_${IDX}"242LINE_DIR="$CONFIGFS_SIM_DIR/$CHIP/$BANK/line$IDX"243mkdir -p $LINE_DIR244echo "$LINE_NAME" > "$LINE_DIR/name" || fail "unable to set the line name"245done246done247sim_enable_chip "$CHIP"248done249250echo "1. GPIO aggregator creation/deletion"251252echo "1.1. Creation/deletion via configfs"253254echo "1.1.1. Minimum creation/deletion"255agg_create_chip agg0256agg_create_line agg0 line0257agg_set_key agg0 line0 "$(sim_get_chip_label chip0 bank0)"258agg_set_offset agg0 line0 5259agg_set_line_name agg0 line0 test0260agg_enable_chip agg0261test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 1 || fail "chip unexpectedly dead"262test "$(agg_get_chip_label agg0)" = "$(agg_configfs_dev_name agg0)" || \263fail "label is inconsistent"264test "$(agg_get_chip_num_lines agg0)" = "1" || fail "number of lines is not 1"265test "$(agg_get_line_name agg0 0)" = "test0" || fail "line name is unset"266agg_disable_chip agg0267agg_remove_line agg0 line0268agg_remove_chip agg0269270echo "1.1.2. Complex creation/deletion"271agg_create_chip agg0272agg_create_line agg0 line0273agg_create_line agg0 line1274agg_create_line agg0 line2275agg_create_line agg0 line3276agg_set_key agg0 line0 "$(sim_get_chip_label chip0 bank0)"277agg_set_key agg0 line1 "$(sim_get_chip_label chip0 bank1)"278agg_set_key agg0 line2 "$(sim_get_chip_label chip1 bank0)"279agg_set_key agg0 line3 "$(sim_get_chip_label chip1 bank1)"280agg_set_offset agg0 line0 1281agg_set_offset agg0 line1 3282agg_set_offset agg0 line2 5283agg_set_offset agg0 line3 7284agg_set_line_name agg0 line0 test0285agg_set_line_name agg0 line1 test1286agg_set_line_name agg0 line2 test2287agg_set_line_name agg0 line3 test3288agg_enable_chip agg0289test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 1 || fail "chip unexpectedly dead"290test "$(agg_get_chip_label agg0)" = "$(agg_configfs_dev_name agg0)" || \291fail "label is inconsistent"292test "$(agg_get_chip_num_lines agg0)" = "4" || fail "number of lines is not 1"293test "$(agg_get_line_name agg0 0)" = "test0" || fail "line name is unset"294test "$(agg_get_line_name agg0 1)" = "test1" || fail "line name is unset"295test "$(agg_get_line_name agg0 2)" = "test2" || fail "line name is unset"296test "$(agg_get_line_name agg0 3)" = "test3" || fail "line name is unset"297agg_disable_chip agg0298agg_remove_line agg0 line0299agg_remove_line agg0 line1300agg_remove_line agg0 line2301agg_remove_line agg0 line3302agg_remove_chip agg0303304echo "1.1.3. Can't instantiate a chip without any line"305agg_create_chip agg0306echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled"307test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 0 || fail "chip unexpectedly alive"308agg_remove_chip agg0309310echo "1.1.4. Can't instantiate a chip with invalid configuration"311agg_create_chip agg0312agg_create_line agg0 line0313agg_set_key agg0 line0 "chipX_bankX"314agg_set_offset agg0 line0 99315agg_set_line_name agg0 line0 test0316echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled"317test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 0 || fail "chip unexpectedly alive"318agg_remove_line agg0 line0319agg_remove_chip agg0320321echo "1.1.5. Can't instantiate a chip asynchronously via deferred probe"322agg_create_chip agg0323agg_create_line agg0 line0324agg_set_key agg0 line0 "chip0_bank0"325agg_set_offset agg0 line0 5326agg_set_line_name agg0 line0 test0327sim_disable_chip chip0328echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled"329test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 0 || fail "chip unexpectedly alive"330sim_enable_chip chip0331sleep 1332test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 0 || \333fail "chip unexpectedly transitioned to 'live' state"334agg_remove_line agg0 line0335agg_remove_chip agg0336337echo "1.1.6. Can't instantiate a chip with _sysfs prefix"338mkdir "$CONFIGFS_AGG_DIR/_sysfs" 2> /dev/null && fail "chip _sysfs unexpectedly created"339mkdir "$CONFIGFS_AGG_DIR/_sysfs.foo" 2> /dev/null && fail "chip _sysfs.foo unexpectedly created"340341echo "1.2. Creation/deletion via sysfs"342343echo "1.2.1. Minimum creation/deletion"344echo "chip0_bank0 0" > "$SYSFS_AGG_DIR/new_device"345CHIPNAME=$(agg_configfs_chip_name _sysfs.0)346test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 1 || fail "chip unexpectedly dead"347test "$(agg_get_chip_label _sysfs.0)" = "$(agg_configfs_dev_name _sysfs.0)" || \348fail "label is inconsistent"349test "$(agg_get_chip_num_lines _sysfs.0)" = "1" || fail "number of lines is not 1"350test "$(agg_get_line_name _sysfs.0 0)" = "" || fail "line name is unset"351echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device"352test -d $CONFIGFS_AGG_DIR/_sysfs.0 && fail "_sysfs.0 unexpectedly remains"353test -d /dev/${CHIPNAME} && fail "/dev/${CHIPNAME} unexpectedly remains"354355echo "1.2.2. Complex creation/deletion"356echo "chip0bank0_0 chip1_bank1 10-11" > "$SYSFS_AGG_DIR/new_device"357CHIPNAME=$(agg_configfs_chip_name _sysfs.0)358test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 1 || fail "chip unexpectedly dead"359test "$(agg_get_chip_label _sysfs.0)" = "$(agg_configfs_dev_name _sysfs.0)" || \360fail "label is inconsistent"361test "$(agg_get_chip_num_lines _sysfs.0)" = "3" || fail "number of lines is not 3"362test "$(agg_get_line_name _sysfs.0 0)" = "" || fail "line name is unset"363test "$(agg_get_line_name _sysfs.0 1)" = "" || fail "line name is unset"364test "$(agg_get_line_name _sysfs.0 2)" = "" || fail "line name is unset"365echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device"366test -d $CONFIGFS_AGG_DIR/_sysfs.0 && fail "_sysfs.0 unexpectedly remains"367test -d /dev/${CHIPNAME} && fail "/dev/${CHIPNAME} unexpectedly remains"368369echo "1.2.3. Asynchronous creation with deferred probe"370sim_disable_chip chip0371echo 'chip0_bank0 0' > $SYSFS_AGG_DIR/new_device372sleep 1373test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 0 || fail "chip unexpectedly alive"374sim_enable_chip chip0375sleep 1376CHIPNAME=$(agg_configfs_chip_name _sysfs.0)377test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 1 || fail "chip unexpectedly remains dead"378test "$(agg_get_chip_label _sysfs.0)" = "$(agg_configfs_dev_name _sysfs.0)" || \379fail "label is inconsistent"380test "$(agg_get_chip_num_lines _sysfs.0)" = "1" || fail "number of lines is not 1"381test "$(agg_get_line_name _sysfs.0 0)" = "" || fail "line name unexpectedly set"382echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device"383test -d $CONFIGFS_AGG_DIR/_sysfs.0 && fail "_sysfs.0 unexpectedly remains"384test -d /dev/${CHIPNAME} && fail "/dev/${CHIPNAME} unexpectedly remains"385386echo "1.2.4. Can't instantiate a chip with invalid configuration"387echo "xyz 0" > "$SYSFS_AGG_DIR/new_device"388test "$(cat $CONFIGFS_AGG_DIR/_sysfs.0/live)" = 0 || fail "chip unexpectedly alive"389echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device"390391echo "2. GPIO aggregator configuration"392393echo "2.1. Configuring aggregators instantiated via configfs"394setup_2_1() {395agg_create_chip agg0396agg_create_line agg0 line0397agg_create_line agg0 line1398agg_set_key agg0 line0 "$(sim_get_chip_label chip0 bank0)"399agg_set_key agg0 line1 "$(sim_get_chip_label chip1 bank0)"400agg_set_offset agg0 line0 1401agg_set_offset agg0 line1 3402agg_set_line_name agg0 line0 test0403agg_set_line_name agg0 line1 test1404agg_enable_chip agg0405}406teardown_2_1() {407agg_configfs_cleanup408}409410echo "2.1.1. While offline"411412echo "2.1.1.1. Line can be added/removed"413setup_2_1414agg_disable_chip agg0415agg_create_line agg0 line2416agg_set_key agg0 line2 "$(sim_get_chip_label chip0 bank1)"417agg_set_offset agg0 line2 5418agg_enable_chip agg0419test "$(agg_get_chip_num_lines agg0)" = "3" || fail "number of lines is not 1"420teardown_2_1421422echo "2.1.1.2. Line key can be modified"423setup_2_1424agg_disable_chip agg0425agg_set_key agg0 line0 "$(sim_get_chip_label chip0 bank1)"426agg_set_key agg0 line1 "$(sim_get_chip_label chip1 bank1)"427agg_enable_chip agg0428teardown_2_1429430echo "2.1.1.3. Line name can be modified"431setup_2_1432agg_disable_chip agg0433agg_set_line_name agg0 line0 new0434agg_set_line_name agg0 line1 new1435agg_enable_chip agg0436test "$(agg_get_line_name agg0 0)" = "new0" || fail "line name is unset"437test "$(agg_get_line_name agg0 1)" = "new1" || fail "line name is unset"438teardown_2_1439440echo "2.1.1.4. Line offset can be modified"441setup_2_1442agg_disable_chip agg0443agg_set_offset agg0 line0 5444agg_set_offset agg0 line1 7445agg_enable_chip agg0446teardown_2_1447448echo "2.1.1.5. Can re-enable a chip after valid reconfiguration"449setup_2_1450agg_disable_chip agg0451agg_set_key agg0 line0 "$(sim_get_chip_label chip1 bank1)"452agg_set_offset agg0 line0 15453agg_set_key agg0 line1 "$(sim_get_chip_label chip0 bank1)"454agg_set_offset agg0 line0 14455agg_create_line agg0 line2456agg_set_key agg0 line2 "$(sim_get_chip_label chip0 bank1)"457agg_set_offset agg0 line2 13458agg_enable_chip agg0459test "$(agg_get_chip_num_lines agg0)" = "3" || fail "number of lines is not 1"460teardown_2_1461462echo "2.1.1.7. Can't re-enable a chip with invalid reconfiguration"463setup_2_1464agg_disable_chip agg0465agg_set_key agg0 line0 invalidkey466echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled"467teardown_2_1468setup_2_1469agg_disable_chip agg0470agg_set_offset agg0 line0 99471echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled"472teardown_2_1473474echo "2.1.2. While online"475476echo "2.1.2.1. Can't add/remove line"477setup_2_1478mkdir "$CONFIGFS_AGG_DIR/agg0/line2" 2> /dev/null && fail "line unexpectedly added"479rmdir "$CONFIGFS_AGG_DIR/agg0/line1" 2> /dev/null && fail "line unexpectedly removed"480teardown_2_1481482echo "2.1.2.2. Can't modify line key"483setup_2_1484echo "chip1_bank1" > "$CONFIGFS_AGG_DIR/agg0/line0/key" 2> /dev/null && \485fail "lookup key unexpectedly updated"486teardown_2_1487488echo "2.1.2.3. Can't modify line name"489setup_2_1490echo "new0" > "$CONFIGFS_AGG_DIR/agg0/line0/name" 2> /dev/null && \491fail "name unexpectedly updated"492teardown_2_1493494echo "2.1.2.4. Can't modify line offset"495setup_2_1496echo "5" > "$CONFIGFS_AGG_DIR/agg0/line0/offset" 2> /dev/null && \497fail "offset unexpectedly updated"498teardown_2_1499500echo "2.2. Configuring aggregators instantiated via sysfs"501setup_2_2() {502echo "chip0_bank0 1 chip1_bank0 3" > "$SYSFS_AGG_DIR/new_device"503}504teardown_2_2() {505echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device"506}507508echo "2.2.1. While online"509510echo "2.2.1.1. Can toggle live"511setup_2_2512agg_disable_chip _sysfs.0513agg_enable_chip _sysfs.0514teardown_2_2515516echo "2.2.1.2. Can't add/remove line"517setup_2_2518mkdir "$CONFIGFS_AGG_DIR/_sysfs.0/line2" 2> /dev/null && fail "line unexpectedly added"519rmdir "$CONFIGFS_AGG_DIR/_sysfs.0/line1" 2> /dev/null && fail "line unexpectedly removed"520teardown_2_2521522echo "2.2.1.3. Can't modify line key"523setup_2_2524echo "chip1_bank1" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/key" 2> /dev/null && \525fail "lookup key unexpectedly updated"526teardown_2_2527528echo "2.2.1.4. Can't modify line name"529setup_2_2530echo "new0" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/name" 2> /dev/null && \531fail "name unexpectedly updated"532teardown_2_2533534echo "2.2.1.5. Can't modify line offset"535setup_2_2536echo "5" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/offset" 2> /dev/null && \537fail "offset unexpectedly updated"538teardown_2_2539540echo "2.2.2. While waiting for deferred probe"541542echo "2.2.2.1. Can't add/remove line despite live = 0"543sim_disable_chip chip0544setup_2_2545mkdir "$CONFIGFS_AGG_DIR/_sysfs.0/line2" 2> /dev/null && fail "line unexpectedly added"546rmdir "$CONFIGFS_AGG_DIR/_sysfs.0/line1" 2> /dev/null && fail "line unexpectedly removed"547teardown_2_2548sim_enable_chip chip0549550echo "2.2.2.2. Can't modify line key"551sim_disable_chip chip0552setup_2_2553echo "chip1_bank1" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/key" 2> /dev/null && \554fail "lookup key unexpectedly updated"555teardown_2_2556sim_enable_chip chip0557558echo "2.2.2.3. Can't modify line name"559sim_disable_chip chip0560setup_2_2561echo "new0" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/name" 2> /dev/null && \562fail "name unexpectedly updated"563teardown_2_2564sim_enable_chip chip0565566echo "2.2.2.4. Can't modify line offset"567sim_disable_chip chip0568setup_2_2569echo 5 > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/offset" 2> /dev/null && \570fail "offset unexpectedly updated"571teardown_2_2572sim_enable_chip chip0573574echo "2.2.2.5. Can't toggle live"575sim_disable_chip chip0576setup_2_2577test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 0 || fail "chip unexpectedly alive"578echo 1 > "$CONFIGFS_AGG_DIR/_sysfs.0/live" 2> /dev/null && fail "chip unexpectedly enabled"579teardown_2_2580sim_enable_chip chip0581582echo "2.2.3. While offline"583584echo "2.2.3.1. Can't add/remove line despite live = 0"585setup_2_2586agg_disable_chip _sysfs.0587mkdir "$CONFIGFS_AGG_DIR/_sysfs.0/line2" 2> /dev/null && fail "line unexpectedly added"588rmdir "$CONFIGFS_AGG_DIR/_sysfs.0/line1" 2> /dev/null && fail "line unexpectedly removed"589teardown_2_2590591echo "2.2.3.2. Line key can be modified"592setup_2_2593agg_disable_chip _sysfs.0594agg_set_key _sysfs.0 line0 "$(sim_get_chip_label chip0 bank1)"595agg_set_key _sysfs.0 line1 "$(sim_get_chip_label chip1 bank1)"596agg_enable_chip _sysfs.0597teardown_2_2598599echo "2.2.3.3. Line name can be modified"600setup_2_2601agg_disable_chip _sysfs.0602agg_set_line_name _sysfs.0 line0 new0603agg_set_line_name _sysfs.0 line1 new1604agg_enable_chip _sysfs.0605test "$(agg_get_line_name _sysfs.0 0)" = "new0" || fail "line name is unset"606test "$(agg_get_line_name _sysfs.0 1)" = "new1" || fail "line name is unset"607teardown_2_2608609echo "2.2.3.4. Line offset can be modified"610setup_2_2611agg_disable_chip _sysfs.0612agg_set_offset _sysfs.0 line0 5613agg_set_offset _sysfs.0 line1 7614agg_enable_chip _sysfs.0615teardown_2_2616617echo "2.2.3.5. Can re-enable a chip with valid reconfiguration"618setup_2_2619agg_disable_chip _sysfs.0620agg_set_key _sysfs.0 line0 "$(sim_get_chip_label chip1 bank1)"621agg_set_offset _sysfs.0 line0 15622agg_set_key _sysfs.0 line1 "$(sim_get_chip_label chip0 bank1)"623agg_set_offset _sysfs.0 line0 14624agg_enable_chip _sysfs.0625teardown_2_2626627echo "2.2.3.6. Can't re-enable a chip with invalid reconfiguration"628setup_2_2629agg_disable_chip _sysfs.0630agg_set_key _sysfs.0 line0 invalidkey631echo 1 > "$CONFIGFS_AGG_DIR/_sysfs.0/live" 2> /dev/null && fail "chip unexpectedly enabled"632teardown_2_2633setup_2_2634agg_disable_chip _sysfs.0635agg_set_offset _sysfs.0 line0 99636echo 1 > "$CONFIGFS_AGG_DIR/_sysfs.0/live" 2> /dev/null && fail "chip unexpectedly enabled"637teardown_2_2638639echo "3. Module unload"640641echo "3.1. Can't unload module if there is at least one device created via configfs"642agg_create_chip agg0643modprobe -r gpio-aggregator 2> /dev/null644test -d /sys/module/gpio_aggregator || fail "module unexpectedly unloaded"645agg_remove_chip agg0646647echo "3.2. Can unload module if there is no device created via configfs"648echo "chip0_bank0 1 chip1_bank0 3" > "$SYSFS_AGG_DIR/new_device"649modprobe -r gpio-aggregator 2> /dev/null650test -d /sys/module/gpio_aggregator && fail "module unexpectedly remains to be loaded"651modprobe gpio-aggregator 2> /dev/null652653echo "4. GPIO forwarder functional"654SETTINGS="chip0:bank0:2 chip0:bank1:4 chip1:bank0:6 chip1:bank1:8"655setup_4() {656local OFFSET=0657agg_create_chip agg0658for SETTING in $SETTINGS; do659CHIP=$(echo "$SETTING" | cut -d: -f1)660BANK=$(echo "$SETTING" | cut -d: -f2)661LINE=$(echo "$SETTING" | cut -d: -f3)662agg_create_line agg0 "line${OFFSET}"663agg_set_key agg0 "line${OFFSET}" "$(sim_get_chip_label "$CHIP" "$BANK")"664agg_set_offset agg0 "line${OFFSET}" "$LINE"665OFFSET=$(expr $OFFSET + 1)666done667agg_enable_chip agg0668}669teardown_4() {670agg_configfs_cleanup671}672673echo "4.1. Forwarding set values"674setup_4675OFFSET=0676for SETTING in $SETTINGS; do677CHIP=$(echo "$SETTING" | cut -d: -f1)678BANK=$(echo "$SETTING" | cut -d: -f2)679LINE=$(echo "$SETTING" | cut -d: -f3)680DEVNAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/dev_name")681CHIPNAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/$BANK/chip_name")682VAL_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio${LINE}/value"683test $(cat $VAL_PATH) = "0" || fail "incorrect value read from sysfs"684$BASE_DIR/gpio-mockup-cdev -s 1 "/dev/$(agg_configfs_chip_name agg0)" "$OFFSET" &685mock_pid=$!686sleep 0.1 # FIXME Any better way?687test "$(cat $VAL_PATH)" = "1" || fail "incorrect value read from sysfs"688kill "$mock_pid"689OFFSET=$(expr $OFFSET + 1)690done691teardown_4692693echo "4.2. Forwarding set config"694setup_4695OFFSET=0696for SETTING in $SETTINGS; do697CHIP=$(echo "$SETTING" | cut -d: -f1)698BANK=$(echo "$SETTING" | cut -d: -f2)699LINE=$(echo "$SETTING" | cut -d: -f3)700DEVNAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/dev_name")701CHIPNAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/$BANK/chip_name")702VAL_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio${LINE}/value"703$BASE_DIR/gpio-mockup-cdev -b pull-up "/dev/$(agg_configfs_chip_name agg0)" "$OFFSET"704test $(cat "$VAL_PATH") = "1" || fail "incorrect value read from sysfs"705OFFSET=$(expr $OFFSET + 1)706done707teardown_4708709echo "5. Race condition verification"710711echo "5.1. Stress test of new_device/delete_device and module load/unload"712for _ in $(seq 1000); do713{714echo "dummy 0" > "$SYSFS_AGG_DIR/new_device"715cat "$CONFIGFS_AGG_DIR/_sysfs.0/dev_name" > "$SYSFS_AGG_DIR/delete_device"716} 2> /dev/null717done &718writer_pid=$!719while kill -0 "$writer_pid" 2> /dev/null; do720{721modprobe gpio-aggregator722modprobe -r gpio-aggregator723} 2> /dev/null724done725726echo "GPIO $MODULE test PASS"727728729