WIP FPC-III support
[linux/fpc-iii.git] / tools / testing / selftests / ntb / ntb_test.sh
blob020137b61407983bc3b6719476497b3124a0f18b
1 #!/bin/bash
2 # SPDX-License-Identifier: GPL-2.0-or-later
3 # Copyright (c) 2016 Microsemi. All Rights Reserved.
5 # Author: Logan Gunthorpe <logang@deltatee.com>
7 REMOTE_HOST=
8 LIST_DEVS=FALSE
10 DEBUGFS=${DEBUGFS-/sys/kernel/debug}
12 PERF_RUN_ORDER=32
13 MAX_MW_SIZE=0
14 RUN_DMA_TESTS=
15 DONT_CLEANUP=
16 MW_SIZE=65536
18 function show_help()
20 echo "Usage: $0 [OPTIONS] LOCAL_DEV REMOTE_DEV"
21 echo "Run tests on a pair of NTB endpoints."
22 echo
23 echo "If the NTB device loops back to the same host then,"
24 echo "just specifying the two PCI ids on the command line is"
25 echo "sufficient. Otherwise, if the NTB link spans two hosts"
26 echo "use the -r option to specify the hostname for the remote"
27 echo "device. SSH will then be used to test the remote side."
28 echo "An SSH key between the root users of the host would then"
29 echo "be highly recommended."
30 echo
31 echo "Options:"
32 echo " -C don't cleanup ntb modules on exit"
33 echo " -h show this help message"
34 echo " -l list available local and remote PCI ids"
35 echo " -r REMOTE_HOST specify the remote's hostname to connect"
36 echo " to for the test (using ssh)"
37 echo " -m MW_SIZE memory window size for ntb_tool"
38 echo " (default: $MW_SIZE)"
39 echo " -d run dma tests for ntb_perf"
40 echo " -p ORDER total data order for ntb_perf"
41 echo " (default: $PERF_RUN_ORDER)"
42 echo " -w MAX_MW_SIZE maxmium memory window size for ntb_perf"
43 echo
46 function parse_args()
48 OPTIND=0
49 while getopts "b:Cdhlm:r:p:w:" opt; do
50 case "$opt" in
51 C) DONT_CLEANUP=1 ;;
52 d) RUN_DMA_TESTS=1 ;;
53 h) show_help; exit 0 ;;
54 l) LIST_DEVS=TRUE ;;
55 m) MW_SIZE=${OPTARG} ;;
56 r) REMOTE_HOST=${OPTARG} ;;
57 p) PERF_RUN_ORDER=${OPTARG} ;;
58 w) MAX_MW_SIZE=${OPTARG} ;;
59 \?)
60 echo "Invalid option: -$OPTARG" >&2
61 exit 1
63 esac
64 done
67 parse_args "$@"
68 shift $((OPTIND-1))
69 LOCAL_DEV=$1
70 shift
71 parse_args "$@"
72 shift $((OPTIND-1))
73 REMOTE_DEV=$1
74 shift
75 parse_args "$@"
77 set -e
79 function _modprobe()
81 modprobe "$@" || return 1
83 if [[ "$REMOTE_HOST" != "" ]]; then
84 ssh "$REMOTE_HOST" modprobe "$@" || return 1
88 function split_remote()
90 VPATH=$1
91 REMOTE=
93 if [[ "$VPATH" == *":/"* ]]; then
94 REMOTE=${VPATH%%:*}
95 VPATH=${VPATH#*:}
99 function read_file()
101 split_remote $1
102 if [[ "$REMOTE" != "" ]]; then
103 ssh "$REMOTE" cat "$VPATH"
104 else
105 cat "$VPATH"
109 function write_file()
111 split_remote $2
112 VALUE=$1
114 if [[ "$REMOTE" != "" ]]; then
115 ssh "$REMOTE" "echo \"$VALUE\" > \"$VPATH\""
116 else
117 echo "$VALUE" > "$VPATH"
121 function check_file()
123 split_remote $1
125 if [[ "$REMOTE" != "" ]]; then
126 ssh "$REMOTE" "[[ -e ${VPATH} ]]"
127 else
128 [[ -e ${VPATH} ]]
132 function subdirname()
134 echo $(basename $(dirname $1)) 2> /dev/null
137 function find_pidx()
139 PORT=$1
140 PPATH=$2
142 for ((i = 0; i < 64; i++)); do
143 PEER_DIR="$PPATH/peer$i"
145 check_file ${PEER_DIR} || break
147 PEER_PORT=$(read_file "${PEER_DIR}/port")
148 if [[ ${PORT} -eq $PEER_PORT ]]; then
149 echo $i
150 return 0
152 done
154 return 1
157 function port_test()
159 LOC=$1
160 REM=$2
162 echo "Running port tests on: $(basename $LOC) / $(basename $REM)"
164 LOCAL_PORT=$(read_file "$LOC/port")
165 REMOTE_PORT=$(read_file "$REM/port")
167 LOCAL_PIDX=$(find_pidx ${REMOTE_PORT} "$LOC")
168 REMOTE_PIDX=$(find_pidx ${LOCAL_PORT} "$REM")
170 echo "Local port ${LOCAL_PORT} with index ${REMOTE_PIDX} on remote host"
171 echo "Peer port ${REMOTE_PORT} with index ${LOCAL_PIDX} on local host"
173 echo " Passed"
176 function link_test()
178 LOC=$1
179 REM=$2
180 EXP=0
182 echo "Running link tests on: $(subdirname $LOC) / $(subdirname $REM)"
184 if ! write_file "N" "$LOC/../link" 2> /dev/null; then
185 echo " Unsupported"
186 return
189 write_file "N" "$LOC/link_event"
191 if [[ $(read_file "$REM/link") != "N" ]]; then
192 echo "Expected link to be down in $REM/link" >&2
193 exit -1
196 write_file "Y" "$LOC/../link"
198 echo " Passed"
201 function doorbell_test()
203 LOC=$1
204 REM=$2
205 EXP=0
207 echo "Running db tests on: $(basename $LOC) / $(basename $REM)"
209 DB_VALID_MASK=$(read_file "$LOC/db_valid_mask")
211 write_file "c $DB_VALID_MASK" "$REM/db"
213 for ((i = 0; i < 64; i++)); do
214 DB=$(read_file "$REM/db")
215 if [[ "$DB" -ne "$EXP" ]]; then
216 echo "Doorbell doesn't match expected value $EXP " \
217 "in $REM/db" >&2
218 exit -1
221 let "MASK = (1 << $i) & $DB_VALID_MASK" || true
222 let "EXP = $EXP | $MASK" || true
224 write_file "s $MASK" "$LOC/peer_db"
225 done
227 write_file "c $DB_VALID_MASK" "$REM/db_mask"
228 write_file $DB_VALID_MASK "$REM/db_event"
229 write_file "s $DB_VALID_MASK" "$REM/db_mask"
231 write_file "c $DB_VALID_MASK" "$REM/db"
233 echo " Passed"
236 function get_files_count()
238 NAME=$1
239 LOC=$2
241 split_remote $LOC
243 if [[ "$REMOTE" == "" ]]; then
244 echo $(ls -1 "$VPATH"/${NAME}* 2>/dev/null | wc -l)
245 else
246 echo $(ssh "$REMOTE" "ls -1 \"$VPATH\"/${NAME}* | \
247 wc -l" 2> /dev/null)
251 function scratchpad_test()
253 LOC=$1
254 REM=$2
256 echo "Running spad tests on: $(subdirname $LOC) / $(subdirname $REM)"
258 CNT=$(get_files_count "spad" "$LOC")
260 if [[ $CNT -eq 0 ]]; then
261 echo " Unsupported"
262 return
265 for ((i = 0; i < $CNT; i++)); do
266 VAL=$RANDOM
267 write_file "$VAL" "$LOC/spad$i"
268 RVAL=$(read_file "$REM/../spad$i")
270 if [[ "$VAL" -ne "$RVAL" ]]; then
271 echo "Scratchpad $i value $RVAL doesn't match $VAL" >&2
272 exit -1
274 done
276 echo " Passed"
279 function message_test()
281 LOC=$1
282 REM=$2
284 echo "Running msg tests on: $(subdirname $LOC) / $(subdirname $REM)"
286 CNT=$(get_files_count "msg" "$LOC")
288 if [[ $CNT -eq 0 ]]; then
289 echo " Unsupported"
290 return
293 MSG_OUTBITS_MASK=$(read_file "$LOC/../msg_inbits")
294 MSG_INBITS_MASK=$(read_file "$REM/../msg_inbits")
296 write_file "c $MSG_OUTBITS_MASK" "$LOC/../msg_sts"
297 write_file "c $MSG_INBITS_MASK" "$REM/../msg_sts"
299 for ((i = 0; i < $CNT; i++)); do
300 VAL=$RANDOM
301 write_file "$VAL" "$LOC/msg$i"
302 RVAL=$(read_file "$REM/../msg$i")
304 if [[ "$VAL" -ne "${RVAL%%<-*}" ]]; then
305 echo "Message $i value $RVAL doesn't match $VAL" >&2
306 exit -1
308 done
310 echo " Passed"
313 function get_number()
315 KEY=$1
317 sed -n "s/^\(${KEY}\)[ \t]*\(0x[0-9a-fA-F]*\)\(\[p\]\)\?$/\2/p"
320 function mw_alloc()
322 IDX=$1
323 LOC=$2
324 REM=$3
326 write_file $MW_SIZE "$LOC/mw_trans$IDX"
328 INB_MW=$(read_file "$LOC/mw_trans$IDX")
329 MW_ALIGNED_SIZE=$(echo "$INB_MW" | get_number "Window Size")
330 MW_DMA_ADDR=$(echo "$INB_MW" | get_number "DMA Address")
332 write_file "$MW_DMA_ADDR:$(($MW_ALIGNED_SIZE))" "$REM/peer_mw_trans$IDX"
334 if [[ $MW_SIZE -ne $MW_ALIGNED_SIZE ]]; then
335 echo "MW $IDX size aligned to $MW_ALIGNED_SIZE"
339 function write_mw()
341 split_remote $2
343 if [[ "$REMOTE" != "" ]]; then
344 ssh "$REMOTE" \
345 dd if=/dev/urandom "of=$VPATH" 2> /dev/null || true
346 else
347 dd if=/dev/urandom "of=$VPATH" 2> /dev/null || true
351 function mw_check()
353 IDX=$1
354 LOC=$2
355 REM=$3
357 write_mw "$LOC/mw$IDX"
359 split_remote "$LOC/mw$IDX"
360 if [[ "$REMOTE" == "" ]]; then
361 A=$VPATH
362 else
363 A=/tmp/ntb_test.$$.A
364 ssh "$REMOTE" cat "$VPATH" > "$A"
367 split_remote "$REM/peer_mw$IDX"
368 if [[ "$REMOTE" == "" ]]; then
369 B=$VPATH
370 else
371 B=/tmp/ntb_test.$$.B
372 ssh "$REMOTE" cat "$VPATH" > "$B"
375 cmp -n $MW_ALIGNED_SIZE "$A" "$B"
376 if [[ $? != 0 ]]; then
377 echo "Memory window $MW did not match!" >&2
380 if [[ "$A" == "/tmp/*" ]]; then
381 rm "$A"
384 if [[ "$B" == "/tmp/*" ]]; then
385 rm "$B"
389 function mw_free()
391 IDX=$1
392 LOC=$2
393 REM=$3
395 write_file "$MW_DMA_ADDR:0" "$REM/peer_mw_trans$IDX"
397 write_file 0 "$LOC/mw_trans$IDX"
400 function mw_test()
402 LOC=$1
403 REM=$2
405 CNT=$(get_files_count "mw_trans" "$LOC")
407 for ((i = 0; i < $CNT; i++)); do
408 echo "Running mw$i tests on: $(subdirname $LOC) / " \
409 "$(subdirname $REM)"
411 mw_alloc $i $LOC $REM
413 mw_check $i $LOC $REM
415 mw_free $i $LOC $REM
417 echo " Passed"
418 done
422 function pingpong_test()
424 LOC=$1
425 REM=$2
427 echo "Running ping pong tests on: $(basename $LOC) / $(basename $REM)"
429 LOC_START=$(read_file "$LOC/count")
430 REM_START=$(read_file "$REM/count")
432 sleep 7
434 LOC_END=$(read_file "$LOC/count")
435 REM_END=$(read_file "$REM/count")
437 if [[ $LOC_START == $LOC_END ]] || [[ $REM_START == $REM_END ]]; then
438 echo "Ping pong counter not incrementing!" >&2
439 exit 1
442 echo " Passed"
445 function msi_test()
447 LOC=$1
448 REM=$2
450 write_file 1 $LOC/ready
452 echo "Running MSI interrupt tests on: $(subdirname $LOC) / $(subdirname $REM)"
454 CNT=$(read_file "$LOC/count")
455 for ((i = 0; i < $CNT; i++)); do
456 START=$(read_file $REM/../irq${i}_occurrences)
457 write_file $i $LOC/trigger
458 END=$(read_file $REM/../irq${i}_occurrences)
460 if [[ $(($END - $START)) != 1 ]]; then
461 echo "MSI did not trigger the interrupt on the remote side!" >&2
462 exit 1
464 done
466 echo " Passed"
469 function perf_test()
471 USE_DMA=$1
473 if [[ $USE_DMA == "1" ]]; then
474 WITH="with"
475 else
476 WITH="without"
479 _modprobe ntb_perf total_order=$PERF_RUN_ORDER \
480 max_mw_size=$MAX_MW_SIZE use_dma=$USE_DMA
482 echo "Running local perf test $WITH DMA"
483 write_file "$LOCAL_PIDX" "$LOCAL_PERF/run"
484 echo -n " "
485 read_file "$LOCAL_PERF/run"
486 echo " Passed"
488 echo "Running remote perf test $WITH DMA"
489 write_file "$REMOTE_PIDX" "$REMOTE_PERF/run"
490 echo -n " "
491 read_file "$REMOTE_PERF/run"
492 echo " Passed"
494 _modprobe -r ntb_perf
497 function ntb_tool_tests()
499 LOCAL_TOOL="$DEBUGFS/ntb_tool/$LOCAL_DEV"
500 REMOTE_TOOL="$REMOTE_HOST:$DEBUGFS/ntb_tool/$REMOTE_DEV"
502 echo "Starting ntb_tool tests..."
504 _modprobe ntb_tool
506 port_test "$LOCAL_TOOL" "$REMOTE_TOOL"
508 LOCAL_PEER_TOOL="$LOCAL_TOOL/peer$LOCAL_PIDX"
509 REMOTE_PEER_TOOL="$REMOTE_TOOL/peer$REMOTE_PIDX"
511 link_test "$LOCAL_PEER_TOOL" "$REMOTE_PEER_TOOL"
512 link_test "$REMOTE_PEER_TOOL" "$LOCAL_PEER_TOOL"
514 #Ensure the link is up on both sides before continuing
515 write_file "Y" "$LOCAL_PEER_TOOL/link_event"
516 write_file "Y" "$REMOTE_PEER_TOOL/link_event"
518 doorbell_test "$LOCAL_TOOL" "$REMOTE_TOOL"
519 doorbell_test "$REMOTE_TOOL" "$LOCAL_TOOL"
521 scratchpad_test "$LOCAL_PEER_TOOL" "$REMOTE_PEER_TOOL"
522 scratchpad_test "$REMOTE_PEER_TOOL" "$LOCAL_PEER_TOOL"
524 message_test "$LOCAL_PEER_TOOL" "$REMOTE_PEER_TOOL"
525 message_test "$REMOTE_PEER_TOOL" "$LOCAL_PEER_TOOL"
527 mw_test "$LOCAL_PEER_TOOL" "$REMOTE_PEER_TOOL"
528 mw_test "$REMOTE_PEER_TOOL" "$LOCAL_PEER_TOOL"
530 _modprobe -r ntb_tool
533 function ntb_pingpong_tests()
535 LOCAL_PP="$DEBUGFS/ntb_pingpong/$LOCAL_DEV"
536 REMOTE_PP="$REMOTE_HOST:$DEBUGFS/ntb_pingpong/$REMOTE_DEV"
538 echo "Starting ntb_pingpong tests..."
540 _modprobe ntb_pingpong
542 pingpong_test $LOCAL_PP $REMOTE_PP
544 _modprobe -r ntb_pingpong
547 function ntb_msi_tests()
549 LOCAL_MSI="$DEBUGFS/ntb_msi_test/$LOCAL_DEV"
550 REMOTE_MSI="$REMOTE_HOST:$DEBUGFS/ntb_msi_test/$REMOTE_DEV"
552 echo "Starting ntb_msi_test tests..."
554 if ! _modprobe ntb_msi_test 2> /dev/null; then
555 echo " Not doing MSI tests seeing the module is not available."
556 return
559 port_test $LOCAL_MSI $REMOTE_MSI
561 LOCAL_PEER="$LOCAL_MSI/peer$LOCAL_PIDX"
562 REMOTE_PEER="$REMOTE_MSI/peer$REMOTE_PIDX"
564 msi_test $LOCAL_PEER $REMOTE_PEER
565 msi_test $REMOTE_PEER $LOCAL_PEER
567 _modprobe -r ntb_msi_test
570 function ntb_perf_tests()
572 LOCAL_PERF="$DEBUGFS/ntb_perf/$LOCAL_DEV"
573 REMOTE_PERF="$REMOTE_HOST:$DEBUGFS/ntb_perf/$REMOTE_DEV"
575 echo "Starting ntb_perf tests..."
577 perf_test 0
579 if [[ $RUN_DMA_TESTS ]]; then
580 perf_test 1
584 function cleanup()
586 set +e
587 _modprobe -r ntb_tool 2> /dev/null
588 _modprobe -r ntb_perf 2> /dev/null
589 _modprobe -r ntb_pingpong 2> /dev/null
590 _modprobe -r ntb_transport 2> /dev/null
591 _modprobe -r ntb_msi_test 2> /dev/null
592 set -e
595 cleanup
597 if ! [[ $$DONT_CLEANUP ]]; then
598 trap cleanup EXIT
601 if [ "$(id -u)" != "0" ]; then
602 echo "This script must be run as root" 1>&2
603 exit 1
606 if [[ "$LIST_DEVS" == TRUE ]]; then
607 echo "Local Devices:"
608 ls -1 /sys/bus/ntb/devices
609 echo
611 if [[ "$REMOTE_HOST" != "" ]]; then
612 echo "Remote Devices:"
613 ssh $REMOTE_HOST ls -1 /sys/bus/ntb/devices
616 exit 0
619 if [[ "$LOCAL_DEV" == $"" ]] || [[ "$REMOTE_DEV" == $"" ]]; then
620 show_help
621 exit 1
624 ntb_tool_tests
625 echo
626 ntb_pingpong_tests
627 echo
628 ntb_msi_tests
629 echo
630 ntb_perf_tests
631 echo