Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/gpio/gpio-aggregator.sh
26285 views
1
#!/bin/sh
2
# SPDX-License-Identifier: GPL-2.0
3
# Copyright (C) 2025 Bartosz Golaszewski <[email protected]>
4
# Copyright (C) 2025 Koichiro Den <[email protected]>
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.1.6. Can't instantiate a chip with _sysfs prefix"
339
mkdir "$CONFIGFS_AGG_DIR/_sysfs" 2> /dev/null && fail "chip _sysfs unexpectedly created"
340
mkdir "$CONFIGFS_AGG_DIR/_sysfs.foo" 2> /dev/null && fail "chip _sysfs.foo unexpectedly created"
341
342
echo "1.2. Creation/deletion via sysfs"
343
344
echo "1.2.1. Minimum creation/deletion"
345
echo "chip0_bank0 0" > "$SYSFS_AGG_DIR/new_device"
346
CHIPNAME=$(agg_configfs_chip_name _sysfs.0)
347
test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 1 || fail "chip unexpectedly dead"
348
test "$(agg_get_chip_label _sysfs.0)" = "$(agg_configfs_dev_name _sysfs.0)" || \
349
fail "label is inconsistent"
350
test "$(agg_get_chip_num_lines _sysfs.0)" = "1" || fail "number of lines is not 1"
351
test "$(agg_get_line_name _sysfs.0 0)" = "" || fail "line name is unset"
352
echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device"
353
test -d $CONFIGFS_AGG_DIR/_sysfs.0 && fail "_sysfs.0 unexpectedly remains"
354
test -d /dev/${CHIPNAME} && fail "/dev/${CHIPNAME} unexpectedly remains"
355
356
echo "1.2.2. Complex creation/deletion"
357
echo "chip0bank0_0 chip1_bank1 10-11" > "$SYSFS_AGG_DIR/new_device"
358
CHIPNAME=$(agg_configfs_chip_name _sysfs.0)
359
test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 1 || fail "chip unexpectedly dead"
360
test "$(agg_get_chip_label _sysfs.0)" = "$(agg_configfs_dev_name _sysfs.0)" || \
361
fail "label is inconsistent"
362
test "$(agg_get_chip_num_lines _sysfs.0)" = "3" || fail "number of lines is not 3"
363
test "$(agg_get_line_name _sysfs.0 0)" = "" || fail "line name is unset"
364
test "$(agg_get_line_name _sysfs.0 1)" = "" || fail "line name is unset"
365
test "$(agg_get_line_name _sysfs.0 2)" = "" || fail "line name is unset"
366
echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device"
367
test -d $CONFIGFS_AGG_DIR/_sysfs.0 && fail "_sysfs.0 unexpectedly remains"
368
test -d /dev/${CHIPNAME} && fail "/dev/${CHIPNAME} unexpectedly remains"
369
370
echo "1.2.3. Asynchronous creation with deferred probe"
371
sim_disable_chip chip0
372
echo 'chip0_bank0 0' > $SYSFS_AGG_DIR/new_device
373
sleep 1
374
test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 0 || fail "chip unexpectedly alive"
375
sim_enable_chip chip0
376
sleep 1
377
CHIPNAME=$(agg_configfs_chip_name _sysfs.0)
378
test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 1 || fail "chip unexpectedly remains dead"
379
test "$(agg_get_chip_label _sysfs.0)" = "$(agg_configfs_dev_name _sysfs.0)" || \
380
fail "label is inconsistent"
381
test "$(agg_get_chip_num_lines _sysfs.0)" = "1" || fail "number of lines is not 1"
382
test "$(agg_get_line_name _sysfs.0 0)" = "" || fail "line name unexpectedly set"
383
echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device"
384
test -d $CONFIGFS_AGG_DIR/_sysfs.0 && fail "_sysfs.0 unexpectedly remains"
385
test -d /dev/${CHIPNAME} && fail "/dev/${CHIPNAME} unexpectedly remains"
386
387
echo "1.2.4. Can't instantiate a chip with invalid configuration"
388
echo "xyz 0" > "$SYSFS_AGG_DIR/new_device"
389
test "$(cat $CONFIGFS_AGG_DIR/_sysfs.0/live)" = 0 || fail "chip unexpectedly alive"
390
echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device"
391
392
echo "2. GPIO aggregator configuration"
393
394
echo "2.1. Configuring aggregators instantiated via configfs"
395
setup_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
}
407
teardown_2_1() {
408
agg_configfs_cleanup
409
}
410
411
echo "2.1.1. While offline"
412
413
echo "2.1.1.1. Line can be added/removed"
414
setup_2_1
415
agg_disable_chip agg0
416
agg_create_line agg0 line2
417
agg_set_key agg0 line2 "$(sim_get_chip_label chip0 bank1)"
418
agg_set_offset agg0 line2 5
419
agg_enable_chip agg0
420
test "$(agg_get_chip_num_lines agg0)" = "3" || fail "number of lines is not 1"
421
teardown_2_1
422
423
echo "2.1.1.2. Line key can be modified"
424
setup_2_1
425
agg_disable_chip agg0
426
agg_set_key agg0 line0 "$(sim_get_chip_label chip0 bank1)"
427
agg_set_key agg0 line1 "$(sim_get_chip_label chip1 bank1)"
428
agg_enable_chip agg0
429
teardown_2_1
430
431
echo "2.1.1.3. Line name can be modified"
432
setup_2_1
433
agg_disable_chip agg0
434
agg_set_line_name agg0 line0 new0
435
agg_set_line_name agg0 line1 new1
436
agg_enable_chip agg0
437
test "$(agg_get_line_name agg0 0)" = "new0" || fail "line name is unset"
438
test "$(agg_get_line_name agg0 1)" = "new1" || fail "line name is unset"
439
teardown_2_1
440
441
echo "2.1.1.4. Line offset can be modified"
442
setup_2_1
443
agg_disable_chip agg0
444
agg_set_offset agg0 line0 5
445
agg_set_offset agg0 line1 7
446
agg_enable_chip agg0
447
teardown_2_1
448
449
echo "2.1.1.5. Can re-enable a chip after valid reconfiguration"
450
setup_2_1
451
agg_disable_chip agg0
452
agg_set_key agg0 line0 "$(sim_get_chip_label chip1 bank1)"
453
agg_set_offset agg0 line0 15
454
agg_set_key agg0 line1 "$(sim_get_chip_label chip0 bank1)"
455
agg_set_offset agg0 line0 14
456
agg_create_line agg0 line2
457
agg_set_key agg0 line2 "$(sim_get_chip_label chip0 bank1)"
458
agg_set_offset agg0 line2 13
459
agg_enable_chip agg0
460
test "$(agg_get_chip_num_lines agg0)" = "3" || fail "number of lines is not 1"
461
teardown_2_1
462
463
echo "2.1.1.7. Can't re-enable a chip with invalid reconfiguration"
464
setup_2_1
465
agg_disable_chip agg0
466
agg_set_key agg0 line0 invalidkey
467
echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled"
468
teardown_2_1
469
setup_2_1
470
agg_disable_chip agg0
471
agg_set_offset agg0 line0 99
472
echo 1 > "$CONFIGFS_AGG_DIR/agg0/live" 2> /dev/null && fail "chip unexpectedly enabled"
473
teardown_2_1
474
475
echo "2.1.2. While online"
476
477
echo "2.1.2.1. Can't add/remove line"
478
setup_2_1
479
mkdir "$CONFIGFS_AGG_DIR/agg0/line2" 2> /dev/null && fail "line unexpectedly added"
480
rmdir "$CONFIGFS_AGG_DIR/agg0/line1" 2> /dev/null && fail "line unexpectedly removed"
481
teardown_2_1
482
483
echo "2.1.2.2. Can't modify line key"
484
setup_2_1
485
echo "chip1_bank1" > "$CONFIGFS_AGG_DIR/agg0/line0/key" 2> /dev/null && \
486
fail "lookup key unexpectedly updated"
487
teardown_2_1
488
489
echo "2.1.2.3. Can't modify line name"
490
setup_2_1
491
echo "new0" > "$CONFIGFS_AGG_DIR/agg0/line0/name" 2> /dev/null && \
492
fail "name unexpectedly updated"
493
teardown_2_1
494
495
echo "2.1.2.4. Can't modify line offset"
496
setup_2_1
497
echo "5" > "$CONFIGFS_AGG_DIR/agg0/line0/offset" 2> /dev/null && \
498
fail "offset unexpectedly updated"
499
teardown_2_1
500
501
echo "2.2. Configuring aggregators instantiated via sysfs"
502
setup_2_2() {
503
echo "chip0_bank0 1 chip1_bank0 3" > "$SYSFS_AGG_DIR/new_device"
504
}
505
teardown_2_2() {
506
echo "$(agg_configfs_dev_name _sysfs.0)" > "$SYSFS_AGG_DIR/delete_device"
507
}
508
509
echo "2.2.1. While online"
510
511
echo "2.2.1.1. Can toggle live"
512
setup_2_2
513
agg_disable_chip _sysfs.0
514
agg_enable_chip _sysfs.0
515
teardown_2_2
516
517
echo "2.2.1.2. Can't add/remove line"
518
setup_2_2
519
mkdir "$CONFIGFS_AGG_DIR/_sysfs.0/line2" 2> /dev/null && fail "line unexpectedly added"
520
rmdir "$CONFIGFS_AGG_DIR/_sysfs.0/line1" 2> /dev/null && fail "line unexpectedly removed"
521
teardown_2_2
522
523
echo "2.2.1.3. Can't modify line key"
524
setup_2_2
525
echo "chip1_bank1" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/key" 2> /dev/null && \
526
fail "lookup key unexpectedly updated"
527
teardown_2_2
528
529
echo "2.2.1.4. Can't modify line name"
530
setup_2_2
531
echo "new0" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/name" 2> /dev/null && \
532
fail "name unexpectedly updated"
533
teardown_2_2
534
535
echo "2.2.1.5. Can't modify line offset"
536
setup_2_2
537
echo "5" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/offset" 2> /dev/null && \
538
fail "offset unexpectedly updated"
539
teardown_2_2
540
541
echo "2.2.2. While waiting for deferred probe"
542
543
echo "2.2.2.1. Can't add/remove line despite live = 0"
544
sim_disable_chip chip0
545
setup_2_2
546
mkdir "$CONFIGFS_AGG_DIR/_sysfs.0/line2" 2> /dev/null && fail "line unexpectedly added"
547
rmdir "$CONFIGFS_AGG_DIR/_sysfs.0/line1" 2> /dev/null && fail "line unexpectedly removed"
548
teardown_2_2
549
sim_enable_chip chip0
550
551
echo "2.2.2.2. Can't modify line key"
552
sim_disable_chip chip0
553
setup_2_2
554
echo "chip1_bank1" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/key" 2> /dev/null && \
555
fail "lookup key unexpectedly updated"
556
teardown_2_2
557
sim_enable_chip chip0
558
559
echo "2.2.2.3. Can't modify line name"
560
sim_disable_chip chip0
561
setup_2_2
562
echo "new0" > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/name" 2> /dev/null && \
563
fail "name unexpectedly updated"
564
teardown_2_2
565
sim_enable_chip chip0
566
567
echo "2.2.2.4. Can't modify line offset"
568
sim_disable_chip chip0
569
setup_2_2
570
echo 5 > "$CONFIGFS_AGG_DIR/_sysfs.0/line0/offset" 2> /dev/null && \
571
fail "offset unexpectedly updated"
572
teardown_2_2
573
sim_enable_chip chip0
574
575
echo "2.2.2.5. Can't toggle live"
576
sim_disable_chip chip0
577
setup_2_2
578
test "$(cat "$CONFIGFS_AGG_DIR/_sysfs.0/live")" = 0 || fail "chip unexpectedly alive"
579
echo 1 > "$CONFIGFS_AGG_DIR/_sysfs.0/live" 2> /dev/null && fail "chip unexpectedly enabled"
580
teardown_2_2
581
sim_enable_chip chip0
582
583
echo "2.2.3. While offline"
584
585
echo "2.2.3.1. Can't add/remove line despite live = 0"
586
setup_2_2
587
agg_disable_chip _sysfs.0
588
mkdir "$CONFIGFS_AGG_DIR/_sysfs.0/line2" 2> /dev/null && fail "line unexpectedly added"
589
rmdir "$CONFIGFS_AGG_DIR/_sysfs.0/line1" 2> /dev/null && fail "line unexpectedly removed"
590
teardown_2_2
591
592
echo "2.2.3.2. Line key can be modified"
593
setup_2_2
594
agg_disable_chip _sysfs.0
595
agg_set_key _sysfs.0 line0 "$(sim_get_chip_label chip0 bank1)"
596
agg_set_key _sysfs.0 line1 "$(sim_get_chip_label chip1 bank1)"
597
agg_enable_chip _sysfs.0
598
teardown_2_2
599
600
echo "2.2.3.3. Line name can be modified"
601
setup_2_2
602
agg_disable_chip _sysfs.0
603
agg_set_line_name _sysfs.0 line0 new0
604
agg_set_line_name _sysfs.0 line1 new1
605
agg_enable_chip _sysfs.0
606
test "$(agg_get_line_name _sysfs.0 0)" = "new0" || fail "line name is unset"
607
test "$(agg_get_line_name _sysfs.0 1)" = "new1" || fail "line name is unset"
608
teardown_2_2
609
610
echo "2.2.3.4. Line offset can be modified"
611
setup_2_2
612
agg_disable_chip _sysfs.0
613
agg_set_offset _sysfs.0 line0 5
614
agg_set_offset _sysfs.0 line1 7
615
agg_enable_chip _sysfs.0
616
teardown_2_2
617
618
echo "2.2.3.5. Can re-enable a chip with valid reconfiguration"
619
setup_2_2
620
agg_disable_chip _sysfs.0
621
agg_set_key _sysfs.0 line0 "$(sim_get_chip_label chip1 bank1)"
622
agg_set_offset _sysfs.0 line0 15
623
agg_set_key _sysfs.0 line1 "$(sim_get_chip_label chip0 bank1)"
624
agg_set_offset _sysfs.0 line0 14
625
agg_enable_chip _sysfs.0
626
teardown_2_2
627
628
echo "2.2.3.6. Can't re-enable a chip with invalid reconfiguration"
629
setup_2_2
630
agg_disable_chip _sysfs.0
631
agg_set_key _sysfs.0 line0 invalidkey
632
echo 1 > "$CONFIGFS_AGG_DIR/_sysfs.0/live" 2> /dev/null && fail "chip unexpectedly enabled"
633
teardown_2_2
634
setup_2_2
635
agg_disable_chip _sysfs.0
636
agg_set_offset _sysfs.0 line0 99
637
echo 1 > "$CONFIGFS_AGG_DIR/_sysfs.0/live" 2> /dev/null && fail "chip unexpectedly enabled"
638
teardown_2_2
639
640
echo "3. Module unload"
641
642
echo "3.1. Can't unload module if there is at least one device created via configfs"
643
agg_create_chip agg0
644
modprobe -r gpio-aggregator 2> /dev/null
645
test -d /sys/module/gpio_aggregator || fail "module unexpectedly unloaded"
646
agg_remove_chip agg0
647
648
echo "3.2. Can unload module if there is no device created via configfs"
649
echo "chip0_bank0 1 chip1_bank0 3" > "$SYSFS_AGG_DIR/new_device"
650
modprobe -r gpio-aggregator 2> /dev/null
651
test -d /sys/module/gpio_aggregator && fail "module unexpectedly remains to be loaded"
652
modprobe gpio-aggregator 2> /dev/null
653
654
echo "4. GPIO forwarder functional"
655
SETTINGS="chip0:bank0:2 chip0:bank1:4 chip1:bank0:6 chip1:bank1:8"
656
setup_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
}
670
teardown_4() {
671
agg_configfs_cleanup
672
}
673
674
echo "4.1. Forwarding set values"
675
setup_4
676
OFFSET=0
677
for 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)
691
done
692
teardown_4
693
694
echo "4.2. Forwarding set config"
695
setup_4
696
OFFSET=0
697
for 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)
707
done
708
teardown_4
709
710
echo "5. Race condition verification"
711
712
echo "5.1. Stress test of new_device/delete_device and module load/unload"
713
for _ 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
718
done &
719
writer_pid=$!
720
while kill -0 "$writer_pid" 2> /dev/null; do
721
{
722
modprobe gpio-aggregator
723
modprobe -r gpio-aggregator
724
} 2> /dev/null
725
done
726
727
echo "GPIO $MODULE test PASS"
728
729