Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
6BASE_DIR=$(dirname "$0")
7CONFIGFS_SIM_DIR="/sys/kernel/config/gpio-sim"
8CONFIGFS_AGG_DIR="/sys/kernel/config/gpio-aggregator"
9SYSFS_AGG_DIR="/sys/bus/platform/drivers/gpio-aggregator"
10MODULE="gpio-aggregator"
11
12fail() {
13 echo "$*" >&2
14 echo "GPIO $MODULE test FAIL"
15 exit 1
16}
17
18skip() {
19 echo "$*" >&2
20 echo "GPIO $MODULE test SKIP"
21 exit 4
22}
23
24# gpio-sim
25sim_enable_chip() {
26 local CHIP=$1
27
28 echo 1 > "$CONFIGFS_SIM_DIR/$CHIP/live" || fail "Unable to enable the chip"
29}
30
31sim_disable_chip() {
32 local CHIP=$1
33
34 echo 0 > "$CONFIGFS_SIM_DIR/$CHIP/live" || fail "Unable to disable the chip"
35}
36
37sim_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
52sim_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
63agg_create_chip() {
64 local CHIP=$1
65
66 mkdir "$CONFIGFS_AGG_DIR/$CHIP"
67}
68
69agg_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
76agg_create_line() {
77 local CHIP=$1
78 local LINE=$2
79
80 mkdir "$CONFIGFS_AGG_DIR/$CHIP/$LINE"
81}
82
83agg_remove_line() {
84 local CHIP=$1
85 local LINE=$2
86
87 rmdir "$CONFIGFS_AGG_DIR/$CHIP/$LINE"
88}
89
90agg_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
98agg_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
107agg_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
115agg_enable_chip() {
116 local CHIP=$1
117
118 echo 1 > "$CONFIGFS_AGG_DIR/$CHIP/live" || fail "Unable to enable the chip"
119}
120
121agg_disable_chip() {
122 local CHIP=$1
123
124 echo 0 > "$CONFIGFS_AGG_DIR/$CHIP/live" || fail "Unable to disable the chip"
125}
126
127agg_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
142agg_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
149agg_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
164agg_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
183agg_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
190agg_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.
212modprobe gpio-sim || skip "unable to load the gpio-sim module"
213modprobe 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.
216for 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
223done
224
225# If the module was already loaded: remove all previous chips
226agg_configfs_cleanup
227sim_configfs_cleanup
228
229trap "exit 1" SIGTERM SIGINT
230trap "agg_configfs_cleanup 1; sim_configfs_cleanup 1" EXIT
231
232# Use gpio-sim chips as the test backend
233for 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"
249done
250
251echo "1. GPIO aggregator creation/deletion"
252
253echo "1.1. Creation/deletion via configfs"
254
255echo "1.1.1. Minimum creation/deletion"
256agg_create_chip agg0
257agg_create_line agg0 line0
258agg_set_key agg0 line0 "$(sim_get_chip_label chip0 bank0)"
259agg_set_offset agg0 line0 5
260agg_set_line_name agg0 line0 test0
261agg_enable_chip agg0
262test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 1 || fail "chip unexpectedly dead"
263test "$(agg_get_chip_label agg0)" = "$(agg_configfs_dev_name agg0)" || \
264 fail "label is inconsistent"
265test "$(agg_get_chip_num_lines agg0)" = "1" || fail "number of lines is not 1"
266test "$(agg_get_line_name agg0 0)" = "test0" || fail "line name is unset"
267agg_disable_chip agg0
268agg_remove_line agg0 line0
269agg_remove_chip agg0
270
271echo "1.1.2. Complex creation/deletion"
272agg_create_chip agg0
273agg_create_line agg0 line0
274agg_create_line agg0 line1
275agg_create_line agg0 line2
276agg_create_line agg0 line3
277agg_set_key agg0 line0 "$(sim_get_chip_label chip0 bank0)"
278agg_set_key agg0 line1 "$(sim_get_chip_label chip0 bank1)"
279agg_set_key agg0 line2 "$(sim_get_chip_label chip1 bank0)"
280agg_set_key agg0 line3 "$(sim_get_chip_label chip1 bank1)"
281agg_set_offset agg0 line0 1
282agg_set_offset agg0 line1 3
283agg_set_offset agg0 line2 5
284agg_set_offset agg0 line3 7
285agg_set_line_name agg0 line0 test0
286agg_set_line_name agg0 line1 test1
287agg_set_line_name agg0 line2 test2
288agg_set_line_name agg0 line3 test3
289agg_enable_chip agg0
290test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 1 || fail "chip unexpectedly dead"
291test "$(agg_get_chip_label agg0)" = "$(agg_configfs_dev_name agg0)" || \
292 fail "label is inconsistent"
293test "$(agg_get_chip_num_lines agg0)" = "4" || fail "number of lines is not 1"
294test "$(agg_get_line_name agg0 0)" = "test0" || fail "line name is unset"
295test "$(agg_get_line_name agg0 1)" = "test1" || fail "line name is unset"
296test "$(agg_get_line_name agg0 2)" = "test2" || fail "line name is unset"
297test "$(agg_get_line_name agg0 3)" = "test3" || fail "line name is unset"
298agg_disable_chip agg0
299agg_remove_line agg0 line0
300agg_remove_line agg0 line1
301agg_remove_line agg0 line2
302agg_remove_line agg0 line3
303agg_remove_chip agg0
304
305echo "1.1.3. Can't instantiate a chip without any line"
306agg_create_chip agg0
307echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled"
308test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 0 || fail "chip unexpectedly alive"
309agg_remove_chip agg0
310
311echo "1.1.4. Can't instantiate a chip with invalid configuration"
312agg_create_chip agg0
313agg_create_line agg0 line0
314agg_set_key agg0 line0 "chipX_bankX"
315agg_set_offset agg0 line0 99
316agg_set_line_name agg0 line0 test0
317echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled"
318test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 0 || fail "chip unexpectedly alive"
319agg_remove_line agg0 line0
320agg_remove_chip agg0
321
322echo "1.1.5. Can't instantiate a chip asynchronously via deferred probe"
323agg_create_chip agg0
324agg_create_line agg0 line0
325agg_set_key agg0 line0 "chip0_bank0"
326agg_set_offset agg0 line0 5
327agg_set_line_name agg0 line0 test0
328sim_disable_chip chip0
329echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled"
330test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 0 || fail "chip unexpectedly alive"
331sim_enable_chip chip0
332sleep 1
333test "$(cat "$CONFIGFS_AGG_DIR/agg0/live")" = 0 || \
334 fail "chip unexpectedly transitioned to 'live' state"
335agg_remove_line agg0 line0
336agg_remove_chip agg0
337
338echo "1.1.6. Can't instantiate a chip with _sysfs prefix"
339mkdir "$CONFIGFS_AGG_DIR/_sysfs" 2> /dev/null && fail "chip _sysfs unexpectedly created"
340mkdir "$CONFIGFS_AGG_DIR/_sysfs.foo" 2> /dev/null && fail "chip _sysfs.foo unexpectedly created"
341
342echo "1.2. Creation/deletion via sysfs"
343
344echo "1.2.1. Minimum creation/deletion"
345echo "chip0_bank0 0" > "$SYSFS_AGG_DIR/new_device"
346CHIPNAME=$(agg_configfs_chip_name _sysfs.0)
347test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 1 || fail "chip unexpectedly dead"
348test "$(agg_get_chip_label _sysfs.0)" = "$(agg_configfs_dev_name _sysfs.0)" || \
349 fail "label is inconsistent"
350test "$(agg_get_chip_num_lines _sysfs.0)" = "1" || fail "number of lines is not 1"
351test "$(agg_get_line_name _sysfs.0 0)" = "" || fail "line name is unset"
352echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device"
353test -d $CONFIGFS_AGG_DIR/_sysfs.0 && fail "_sysfs.0 unexpectedly remains"
354test -d /dev/${CHIPNAME} && fail "/dev/${CHIPNAME} unexpectedly remains"
355
356echo "1.2.2. Complex creation/deletion"
357echo "chip0bank0_0 chip1_bank1 10-11" > "$SYSFS_AGG_DIR/new_device"
358CHIPNAME=$(agg_configfs_chip_name _sysfs.0)
359test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 1 || fail "chip unexpectedly dead"
360test "$(agg_get_chip_label _sysfs.0)" = "$(agg_configfs_dev_name _sysfs.0)" || \
361 fail "label is inconsistent"
362test "$(agg_get_chip_num_lines _sysfs.0)" = "3" || fail "number of lines is not 3"
363test "$(agg_get_line_name _sysfs.0 0)" = "" || fail "line name is unset"
364test "$(agg_get_line_name _sysfs.0 1)" = "" || fail "line name is unset"
365test "$(agg_get_line_name _sysfs.0 2)" = "" || fail "line name is unset"
366echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device"
367test -d $CONFIGFS_AGG_DIR/_sysfs.0 && fail "_sysfs.0 unexpectedly remains"
368test -d /dev/${CHIPNAME} && fail "/dev/${CHIPNAME} unexpectedly remains"
369
370echo "1.2.3. Asynchronous creation with deferred probe"
371sim_disable_chip chip0
372echo 'chip0_bank0 0' > $SYSFS_AGG_DIR/new_device
373sleep 1
374test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 0 || fail "chip unexpectedly alive"
375sim_enable_chip chip0
376sleep 1
377CHIPNAME=$(agg_configfs_chip_name _sysfs.0)
378test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 1 || fail "chip unexpectedly remains dead"
379test "$(agg_get_chip_label _sysfs.0)" = "$(agg_configfs_dev_name _sysfs.0)" || \
380 fail "label is inconsistent"
381test "$(agg_get_chip_num_lines _sysfs.0)" = "1" || fail "number of lines is not 1"
382test "$(agg_get_line_name _sysfs.0 0)" = "" || fail "line name unexpectedly set"
383echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device"
384test -d $CONFIGFS_AGG_DIR/_sysfs.0 && fail "_sysfs.0 unexpectedly remains"
385test -d /dev/${CHIPNAME} && fail "/dev/${CHIPNAME} unexpectedly remains"
386
387echo "1.2.4. Can't instantiate a chip with invalid configuration"
388echo "xyz 0" > "$SYSFS_AGG_DIR/new_device"
389test "$(cat $CONFIGFS_AGG_DIR/_sysfs.0/live)" = 0 || fail "chip unexpectedly alive"
390echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device"
391
392echo "2. GPIO aggregator configuration"
393
394echo "2.1. Configuring aggregators instantiated via configfs"
395setup_2_1() {
396 agg_create_chip agg0
397 agg_create_line agg0 line0
398 agg_create_line agg0 line1
399 agg_set_key agg0 line0 "$(sim_get_chip_label chip0 bank0)"
400 agg_set_key agg0 line1 "$(sim_get_chip_label chip1 bank0)"
401 agg_set_offset agg0 line0 1
402 agg_set_offset agg0 line1 3
403 agg_set_line_name agg0 line0 test0
404 agg_set_line_name agg0 line1 test1
405 agg_enable_chip agg0
406}
407teardown_2_1() {
408 agg_configfs_cleanup
409}
410
411echo "2.1.1. While offline"
412
413echo "2.1.1.1. Line can be added/removed"
414setup_2_1
415agg_disable_chip agg0
416agg_create_line agg0 line2
417agg_set_key agg0 line2 "$(sim_get_chip_label chip0 bank1)"
418agg_set_offset agg0 line2 5
419agg_enable_chip agg0
420test "$(agg_get_chip_num_lines agg0)" = "3" || fail "number of lines is not 1"
421teardown_2_1
422
423echo "2.1.1.2. Line key can be modified"
424setup_2_1
425agg_disable_chip agg0
426agg_set_key agg0 line0 "$(sim_get_chip_label chip0 bank1)"
427agg_set_key agg0 line1 "$(sim_get_chip_label chip1 bank1)"
428agg_enable_chip agg0
429teardown_2_1
430
431echo "2.1.1.3. Line name can be modified"
432setup_2_1
433agg_disable_chip agg0
434agg_set_line_name agg0 line0 new0
435agg_set_line_name agg0 line1 new1
436agg_enable_chip agg0
437test "$(agg_get_line_name agg0 0)" = "new0" || fail "line name is unset"
438test "$(agg_get_line_name agg0 1)" = "new1" || fail "line name is unset"
439teardown_2_1
440
441echo "2.1.1.4. Line offset can be modified"
442setup_2_1
443agg_disable_chip agg0
444agg_set_offset agg0 line0 5
445agg_set_offset agg0 line1 7
446agg_enable_chip agg0
447teardown_2_1
448
449echo "2.1.1.5. Can re-enable a chip after valid reconfiguration"
450setup_2_1
451agg_disable_chip agg0
452agg_set_key agg0 line0 "$(sim_get_chip_label chip1 bank1)"
453agg_set_offset agg0 line0 15
454agg_set_key agg0 line1 "$(sim_get_chip_label chip0 bank1)"
455agg_set_offset agg0 line0 14
456agg_create_line agg0 line2
457agg_set_key agg0 line2 "$(sim_get_chip_label chip0 bank1)"
458agg_set_offset agg0 line2 13
459agg_enable_chip agg0
460test "$(agg_get_chip_num_lines agg0)" = "3" || fail "number of lines is not 1"
461teardown_2_1
462
463echo "2.1.1.7. Can't re-enable a chip with invalid reconfiguration"
464setup_2_1
465agg_disable_chip agg0
466agg_set_key agg0 line0 invalidkey
467echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled"
468teardown_2_1
469setup_2_1
470agg_disable_chip agg0
471agg_set_offset agg0 line0 99
472echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled"
473teardown_2_1
474
475echo "2.1.2. While online"
476
477echo "2.1.2.1. Can't add/remove line"
478setup_2_1
479mkdir "$CONFIGFS_AGG_DIR/agg0/line2" 2> /dev/null && fail "line unexpectedly added"
480rmdir "$CONFIGFS_AGG_DIR/agg0/line1" 2> /dev/null && fail "line unexpectedly removed"
481teardown_2_1
482
483echo "2.1.2.2. Can't modify line key"
484setup_2_1
485echo "chip1_bank1" > "$CONFIGFS_AGG_DIR/agg0/line0/key" 2> /dev/null && \
486 fail "lookup key unexpectedly updated"
487teardown_2_1
488
489echo "2.1.2.3. Can't modify line name"
490setup_2_1
491echo "new0" > "$CONFIGFS_AGG_DIR/agg0/line0/name" 2> /dev/null && \
492 fail "name unexpectedly updated"
493teardown_2_1
494
495echo "2.1.2.4. Can't modify line offset"
496setup_2_1
497echo "5" > "$CONFIGFS_AGG_DIR/agg0/line0/offset" 2> /dev/null && \
498 fail "offset unexpectedly updated"
499teardown_2_1
500
501echo "2.2. Configuring aggregators instantiated via sysfs"
502setup_2_2() {
503 echo "chip0_bank0 1 chip1_bank0 3" > "$SYSFS_AGG_DIR/new_device"
504}
505teardown_2_2() {
506 echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device"
507}
508
509echo "2.2.1. While online"
510
511echo "2.2.1.1. Can toggle live"
512setup_2_2
513agg_disable_chip _sysfs.0
514agg_enable_chip _sysfs.0
515teardown_2_2
516
517echo "2.2.1.2. Can't add/remove line"
518setup_2_2
519mkdir "$CONFIGFS_AGG_DIR/_sysfs.0/line2" 2> /dev/null && fail "line unexpectedly added"
520rmdir "$CONFIGFS_AGG_DIR/_sysfs.0/line1" 2> /dev/null && fail "line unexpectedly removed"
521teardown_2_2
522
523echo "2.2.1.3. Can't modify line key"
524setup_2_2
525echo "chip1_bank1" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/key" 2> /dev/null && \
526 fail "lookup key unexpectedly updated"
527teardown_2_2
528
529echo "2.2.1.4. Can't modify line name"
530setup_2_2
531echo "new0" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/name" 2> /dev/null && \
532 fail "name unexpectedly updated"
533teardown_2_2
534
535echo "2.2.1.5. Can't modify line offset"
536setup_2_2
537echo "5" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/offset" 2> /dev/null && \
538 fail "offset unexpectedly updated"
539teardown_2_2
540
541echo "2.2.2. While waiting for deferred probe"
542
543echo "2.2.2.1. Can't add/remove line despite live = 0"
544sim_disable_chip chip0
545setup_2_2
546mkdir "$CONFIGFS_AGG_DIR/_sysfs.0/line2" 2> /dev/null && fail "line unexpectedly added"
547rmdir "$CONFIGFS_AGG_DIR/_sysfs.0/line1" 2> /dev/null && fail "line unexpectedly removed"
548teardown_2_2
549sim_enable_chip chip0
550
551echo "2.2.2.2. Can't modify line key"
552sim_disable_chip chip0
553setup_2_2
554echo "chip1_bank1" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/key" 2> /dev/null && \
555 fail "lookup key unexpectedly updated"
556teardown_2_2
557sim_enable_chip chip0
558
559echo "2.2.2.3. Can't modify line name"
560sim_disable_chip chip0
561setup_2_2
562echo "new0" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/name" 2> /dev/null && \
563 fail "name unexpectedly updated"
564teardown_2_2
565sim_enable_chip chip0
566
567echo "2.2.2.4. Can't modify line offset"
568sim_disable_chip chip0
569setup_2_2
570echo 5 > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/offset" 2> /dev/null && \
571 fail "offset unexpectedly updated"
572teardown_2_2
573sim_enable_chip chip0
574
575echo "2.2.2.5. Can't toggle live"
576sim_disable_chip chip0
577setup_2_2
578test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 0 || fail "chip unexpectedly alive"
579echo 1 > "$CONFIGFS_AGG_DIR/_sysfs.0/live" 2> /dev/null && fail "chip unexpectedly enabled"
580teardown_2_2
581sim_enable_chip chip0
582
583echo "2.2.3. While offline"
584
585echo "2.2.3.1. Can't add/remove line despite live = 0"
586setup_2_2
587agg_disable_chip _sysfs.0
588mkdir "$CONFIGFS_AGG_DIR/_sysfs.0/line2" 2> /dev/null && fail "line unexpectedly added"
589rmdir "$CONFIGFS_AGG_DIR/_sysfs.0/line1" 2> /dev/null && fail "line unexpectedly removed"
590teardown_2_2
591
592echo "2.2.3.2. Line key can be modified"
593setup_2_2
594agg_disable_chip _sysfs.0
595agg_set_key _sysfs.0 line0 "$(sim_get_chip_label chip0 bank1)"
596agg_set_key _sysfs.0 line1 "$(sim_get_chip_label chip1 bank1)"
597agg_enable_chip _sysfs.0
598teardown_2_2
599
600echo "2.2.3.3. Line name can be modified"
601setup_2_2
602agg_disable_chip _sysfs.0
603agg_set_line_name _sysfs.0 line0 new0
604agg_set_line_name _sysfs.0 line1 new1
605agg_enable_chip _sysfs.0
606test "$(agg_get_line_name _sysfs.0 0)" = "new0" || fail "line name is unset"
607test "$(agg_get_line_name _sysfs.0 1)" = "new1" || fail "line name is unset"
608teardown_2_2
609
610echo "2.2.3.4. Line offset can be modified"
611setup_2_2
612agg_disable_chip _sysfs.0
613agg_set_offset _sysfs.0 line0 5
614agg_set_offset _sysfs.0 line1 7
615agg_enable_chip _sysfs.0
616teardown_2_2
617
618echo "2.2.3.5. Can re-enable a chip with valid reconfiguration"
619setup_2_2
620agg_disable_chip _sysfs.0
621agg_set_key _sysfs.0 line0 "$(sim_get_chip_label chip1 bank1)"
622agg_set_offset _sysfs.0 line0 15
623agg_set_key _sysfs.0 line1 "$(sim_get_chip_label chip0 bank1)"
624agg_set_offset _sysfs.0 line0 14
625agg_enable_chip _sysfs.0
626teardown_2_2
627
628echo "2.2.3.6. Can't re-enable a chip with invalid reconfiguration"
629setup_2_2
630agg_disable_chip _sysfs.0
631agg_set_key _sysfs.0 line0 invalidkey
632echo 1 > "$CONFIGFS_AGG_DIR/_sysfs.0/live" 2> /dev/null && fail "chip unexpectedly enabled"
633teardown_2_2
634setup_2_2
635agg_disable_chip _sysfs.0
636agg_set_offset _sysfs.0 line0 99
637echo 1 > "$CONFIGFS_AGG_DIR/_sysfs.0/live" 2> /dev/null && fail "chip unexpectedly enabled"
638teardown_2_2
639
640echo "3. Module unload"
641
642echo "3.1. Can't unload module if there is at least one device created via configfs"
643agg_create_chip agg0
644modprobe -r gpio-aggregator 2> /dev/null
645test -d /sys/module/gpio_aggregator || fail "module unexpectedly unloaded"
646agg_remove_chip agg0
647
648echo "3.2. Can unload module if there is no device created via configfs"
649echo "chip0_bank0 1 chip1_bank0 3" > "$SYSFS_AGG_DIR/new_device"
650modprobe -r gpio-aggregator 2> /dev/null
651test -d /sys/module/gpio_aggregator && fail "module unexpectedly remains to be loaded"
652modprobe gpio-aggregator 2> /dev/null
653
654echo "4. GPIO forwarder functional"
655SETTINGS="chip0:bank0:2 chip0:bank1:4 chip1:bank0:6 chip1:bank1:8"
656setup_4() {
657 local OFFSET=0
658 agg_create_chip agg0
659 for SETTING in $SETTINGS; do
660 CHIP=$(echo "$SETTING" | cut -d: -f1)
661 BANK=$(echo "$SETTING" | cut -d: -f2)
662 LINE=$(echo "$SETTING" | cut -d: -f3)
663 agg_create_line agg0 "line${OFFSET}"
664 agg_set_key agg0 "line${OFFSET}" "$(sim_get_chip_label "$CHIP" "$BANK")"
665 agg_set_offset agg0 "line${OFFSET}" "$LINE"
666 OFFSET=$(expr $OFFSET + 1)
667 done
668 agg_enable_chip agg0
669}
670teardown_4() {
671 agg_configfs_cleanup
672}
673
674echo "4.1. Forwarding set values"
675setup_4
676OFFSET=0
677for SETTING in $SETTINGS; do
678 CHIP=$(echo "$SETTING" | cut -d: -f1)
679 BANK=$(echo "$SETTING" | cut -d: -f2)
680 LINE=$(echo "$SETTING" | cut -d: -f3)
681 DEVNAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/dev_name")
682 CHIPNAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/$BANK/chip_name")
683 VAL_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio${LINE}/value"
684 test $(cat $VAL_PATH) = "0" || fail "incorrect value read from sysfs"
685 $BASE_DIR/gpio-mockup-cdev -s 1 "/dev/$(agg_configfs_chip_name agg0)" "$OFFSET" &
686 mock_pid=$!
687 sleep 0.1 # FIXME Any better way?
688 test "$(cat $VAL_PATH)" = "1" || fail "incorrect value read from sysfs"
689 kill "$mock_pid"
690 OFFSET=$(expr $OFFSET + 1)
691done
692teardown_4
693
694echo "4.2. Forwarding set config"
695setup_4
696OFFSET=0
697for SETTING in $SETTINGS; do
698 CHIP=$(echo "$SETTING" | cut -d: -f1)
699 BANK=$(echo "$SETTING" | cut -d: -f2)
700 LINE=$(echo "$SETTING" | cut -d: -f3)
701 DEVNAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/dev_name")
702 CHIPNAME=$(cat "$CONFIGFS_SIM_DIR/$CHIP/$BANK/chip_name")
703 VAL_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio${LINE}/value"
704 $BASE_DIR/gpio-mockup-cdev -b pull-up "/dev/$(agg_configfs_chip_name agg0)" "$OFFSET"
705 test $(cat "$VAL_PATH") = "1" || fail "incorrect value read from sysfs"
706 OFFSET=$(expr $OFFSET + 1)
707done
708teardown_4
709
710echo "5. Race condition verification"
711
712echo "5.1. Stress test of new_device/delete_device and module load/unload"
713for _ in $(seq 1000); do
714 {
715 echo "dummy 0" > "$SYSFS_AGG_DIR/new_device"
716 cat "$CONFIGFS_AGG_DIR/_sysfs.0/dev_name" > "$SYSFS_AGG_DIR/delete_device"
717 } 2> /dev/null
718done &
719writer_pid=$!
720while kill -0 "$writer_pid" 2> /dev/null; do
721 {
722 modprobe gpio-aggregator
723 modprobe -r gpio-aggregator
724 } 2> /dev/null
725done
726
727echo "GPIO $MODULE test PASS"