Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/bash
0002 # SPDX-License-Identifier: GPL-2.0-or-later
0003 # Copyright (c) 2016 Microsemi. All Rights Reserved.
0004 #
0005 # Author: Logan Gunthorpe <logang@deltatee.com>
0006 
0007 REMOTE_HOST=
0008 LIST_DEVS=FALSE
0009 
0010 DEBUGFS=${DEBUGFS-/sys/kernel/debug}
0011 
0012 PERF_RUN_ORDER=32
0013 MAX_MW_SIZE=0
0014 RUN_DMA_TESTS=
0015 DONT_CLEANUP=
0016 MW_SIZE=65536
0017 
0018 function show_help()
0019 {
0020         echo "Usage: $0 [OPTIONS] LOCAL_DEV REMOTE_DEV"
0021         echo "Run tests on a pair of NTB endpoints."
0022         echo
0023         echo "If the NTB device loops back to the same host then,"
0024         echo "just specifying the two PCI ids on the command line is"
0025         echo "sufficient. Otherwise, if the NTB link spans two hosts"
0026         echo "use the -r option to specify the hostname for the remote"
0027         echo "device. SSH will then be used to test the remote side."
0028         echo "An SSH key between the root users of the host would then"
0029         echo "be highly recommended."
0030         echo
0031         echo "Options:"
0032         echo "  -C              don't cleanup ntb modules on exit"
0033         echo "  -h              show this help message"
0034         echo "  -l              list available local and remote PCI ids"
0035         echo "  -r REMOTE_HOST  specify the remote's hostname to connect"
0036         echo "                  to for the test (using ssh)"
0037         echo "  -m MW_SIZE      memory window size for ntb_tool"
0038         echo "                  (default: $MW_SIZE)"
0039         echo "  -d              run dma tests for ntb_perf"
0040         echo "  -p ORDER        total data order for ntb_perf"
0041         echo "                  (default: $PERF_RUN_ORDER)"
0042         echo "  -w MAX_MW_SIZE  maxmium memory window size for ntb_perf"
0043         echo
0044 }
0045 
0046 function parse_args()
0047 {
0048         OPTIND=0
0049         while getopts "b:Cdhlm:r:p:w:" opt; do
0050                 case "$opt" in
0051                 C)  DONT_CLEANUP=1 ;;
0052                 d)  RUN_DMA_TESTS=1 ;;
0053                 h)  show_help; exit 0 ;;
0054                 l)  LIST_DEVS=TRUE ;;
0055                 m)  MW_SIZE=${OPTARG} ;;
0056                 r)  REMOTE_HOST=${OPTARG} ;;
0057                 p)  PERF_RUN_ORDER=${OPTARG} ;;
0058                 w)  MAX_MW_SIZE=${OPTARG} ;;
0059                 \?)
0060                     echo "Invalid option: -$OPTARG" >&2
0061                     exit 1
0062                     ;;
0063                 esac
0064         done
0065 }
0066 
0067 parse_args "$@"
0068 shift $((OPTIND-1))
0069 LOCAL_DEV=$1
0070 shift
0071 parse_args "$@"
0072 shift $((OPTIND-1))
0073 REMOTE_DEV=$1
0074 shift
0075 parse_args "$@"
0076 
0077 set -e
0078 
0079 function _modprobe()
0080 {
0081         modprobe "$@" || return 1
0082 
0083         if [[ "$REMOTE_HOST" != "" ]]; then
0084                 ssh "$REMOTE_HOST" modprobe "$@" || return 1
0085         fi
0086 }
0087 
0088 function split_remote()
0089 {
0090         VPATH=$1
0091         REMOTE=
0092 
0093         if [[ "$VPATH" == *":/"* ]]; then
0094                 REMOTE=${VPATH%%:*}
0095                 VPATH=${VPATH#*:}
0096         fi
0097 }
0098 
0099 function read_file()
0100 {
0101         split_remote $1
0102         if [[ "$REMOTE" != "" ]]; then
0103                 ssh "$REMOTE" cat "$VPATH"
0104         else
0105                 cat "$VPATH"
0106         fi
0107 }
0108 
0109 function write_file()
0110 {
0111         split_remote $2
0112         VALUE=$1
0113 
0114         if [[ "$REMOTE" != "" ]]; then
0115                 ssh "$REMOTE" "echo \"$VALUE\" > \"$VPATH\""
0116         else
0117                 echo "$VALUE" > "$VPATH"
0118         fi
0119 }
0120 
0121 function check_file()
0122 {
0123         split_remote $1
0124 
0125         if [[ "$REMOTE" != "" ]]; then
0126                 ssh "$REMOTE" "[[ -e ${VPATH} ]]"
0127         else
0128                 [[ -e ${VPATH} ]]
0129         fi
0130 }
0131 
0132 function subdirname()
0133 {
0134         echo $(basename $(dirname $1)) 2> /dev/null
0135 }
0136 
0137 function find_pidx()
0138 {
0139         PORT=$1
0140         PPATH=$2
0141 
0142         for ((i = 0; i < 64; i++)); do
0143                 PEER_DIR="$PPATH/peer$i"
0144 
0145                 check_file ${PEER_DIR} || break
0146 
0147                 PEER_PORT=$(read_file "${PEER_DIR}/port")
0148                 if [[ ${PORT} -eq $PEER_PORT ]]; then
0149                         echo $i
0150                         return 0
0151                 fi
0152         done
0153 
0154         return 1
0155 }
0156 
0157 function port_test()
0158 {
0159         LOC=$1
0160         REM=$2
0161 
0162         echo "Running port tests on: $(basename $LOC) / $(basename $REM)"
0163 
0164         LOCAL_PORT=$(read_file "$LOC/port")
0165         REMOTE_PORT=$(read_file "$REM/port")
0166 
0167         LOCAL_PIDX=$(find_pidx ${REMOTE_PORT} "$LOC")
0168         REMOTE_PIDX=$(find_pidx ${LOCAL_PORT} "$REM")
0169 
0170         echo "Local port ${LOCAL_PORT} with index ${REMOTE_PIDX} on remote host"
0171         echo "Peer port ${REMOTE_PORT} with index ${LOCAL_PIDX} on local host"
0172 
0173         echo "  Passed"
0174 }
0175 
0176 function link_test()
0177 {
0178         LOC=$1
0179         REM=$2
0180         EXP=0
0181 
0182         echo "Running link tests on: $(subdirname $LOC) / $(subdirname $REM)"
0183 
0184         if ! write_file "N" "$LOC/../link" 2> /dev/null; then
0185                 echo "  Unsupported"
0186                 return
0187         fi
0188 
0189         write_file "N" "$LOC/link_event"
0190 
0191         if [[ $(read_file "$REM/link") != "N" ]]; then
0192                 echo "Expected link to be down in $REM/link" >&2
0193                 exit -1
0194         fi
0195 
0196         write_file "Y" "$LOC/../link"
0197 
0198         echo "  Passed"
0199 }
0200 
0201 function doorbell_test()
0202 {
0203         LOC=$1
0204         REM=$2
0205         EXP=0
0206 
0207         echo "Running db tests on: $(basename $LOC) / $(basename $REM)"
0208 
0209         DB_VALID_MASK=$(read_file "$LOC/db_valid_mask")
0210 
0211         write_file "c $DB_VALID_MASK" "$REM/db"
0212 
0213         for ((i = 0; i < 64; i++)); do
0214                 DB=$(read_file "$REM/db")
0215                 if [[ "$DB" -ne "$EXP" ]]; then
0216                         echo "Doorbell doesn't match expected value $EXP " \
0217                              "in $REM/db" >&2
0218                         exit -1
0219                 fi
0220 
0221                 let "MASK = (1 << $i) & $DB_VALID_MASK" || true
0222                 let "EXP = $EXP | $MASK" || true
0223 
0224                 write_file "s $MASK" "$LOC/peer_db"
0225         done
0226 
0227         write_file "c $DB_VALID_MASK" "$REM/db_mask"
0228         write_file $DB_VALID_MASK "$REM/db_event"
0229         write_file "s $DB_VALID_MASK" "$REM/db_mask"
0230 
0231         write_file "c $DB_VALID_MASK" "$REM/db"
0232 
0233         echo "  Passed"
0234 }
0235 
0236 function get_files_count()
0237 {
0238         NAME=$1
0239         LOC=$2
0240 
0241         split_remote $LOC
0242 
0243         if [[ "$REMOTE" == "" ]]; then
0244                 echo $(ls -1 "$VPATH"/${NAME}* 2>/dev/null | wc -l)
0245         else
0246                 echo $(ssh "$REMOTE" "ls -1 \"$VPATH\"/${NAME}* | \
0247                        wc -l" 2> /dev/null)
0248         fi
0249 }
0250 
0251 function scratchpad_test()
0252 {
0253         LOC=$1
0254         REM=$2
0255 
0256         echo "Running spad tests on: $(subdirname $LOC) / $(subdirname $REM)"
0257 
0258         CNT=$(get_files_count "spad" "$LOC")
0259 
0260         if [[ $CNT -eq 0 ]]; then
0261                 echo "  Unsupported"
0262                 return
0263         fi
0264 
0265         for ((i = 0; i < $CNT; i++)); do
0266                 VAL=$RANDOM
0267                 write_file "$VAL" "$LOC/spad$i"
0268                 RVAL=$(read_file "$REM/../spad$i")
0269 
0270                 if [[ "$VAL" -ne "$RVAL" ]]; then
0271                         echo "Scratchpad $i value $RVAL doesn't match $VAL" >&2
0272                         exit -1
0273                 fi
0274         done
0275 
0276         echo "  Passed"
0277 }
0278 
0279 function message_test()
0280 {
0281         LOC=$1
0282         REM=$2
0283 
0284         echo "Running msg tests on: $(subdirname $LOC) / $(subdirname $REM)"
0285 
0286         CNT=$(get_files_count "msg" "$LOC")
0287 
0288         if [[ $CNT -eq 0 ]]; then
0289                 echo "  Unsupported"
0290                 return
0291         fi
0292 
0293         MSG_OUTBITS_MASK=$(read_file "$LOC/../msg_inbits")
0294         MSG_INBITS_MASK=$(read_file "$REM/../msg_inbits")
0295 
0296         write_file "c $MSG_OUTBITS_MASK" "$LOC/../msg_sts"
0297         write_file "c $MSG_INBITS_MASK" "$REM/../msg_sts"
0298 
0299         for ((i = 0; i < $CNT; i++)); do
0300                 VAL=$RANDOM
0301                 write_file "$VAL" "$LOC/msg$i"
0302                 RVAL=$(read_file "$REM/../msg$i")
0303 
0304                 if [[ "$VAL" -ne "${RVAL%%<-*}" ]]; then
0305                         echo "Message $i value $RVAL doesn't match $VAL" >&2
0306                         exit -1
0307                 fi
0308         done
0309 
0310         echo "  Passed"
0311 }
0312 
0313 function get_number()
0314 {
0315         KEY=$1
0316 
0317         sed -n "s/^\(${KEY}\)[ \t]*\(0x[0-9a-fA-F]*\)\(\[p\]\)\?$/\2/p"
0318 }
0319 
0320 function mw_alloc()
0321 {
0322         IDX=$1
0323         LOC=$2
0324         REM=$3
0325 
0326         write_file $MW_SIZE "$LOC/mw_trans$IDX"
0327 
0328         INB_MW=$(read_file "$LOC/mw_trans$IDX")
0329         MW_ALIGNED_SIZE=$(echo "$INB_MW" | get_number "Window Size")
0330         MW_DMA_ADDR=$(echo "$INB_MW" | get_number "DMA Address")
0331 
0332         write_file "$MW_DMA_ADDR:$(($MW_ALIGNED_SIZE))" "$REM/peer_mw_trans$IDX"
0333 
0334         if [[ $MW_SIZE -ne $MW_ALIGNED_SIZE ]]; then
0335                 echo "MW $IDX size aligned to $MW_ALIGNED_SIZE"
0336         fi
0337 }
0338 
0339 function write_mw()
0340 {
0341         split_remote $2
0342 
0343         if [[ "$REMOTE" != "" ]]; then
0344                 ssh "$REMOTE" \
0345                         dd if=/dev/urandom "of=$VPATH" 2> /dev/null || true
0346         else
0347                 dd if=/dev/urandom "of=$VPATH" 2> /dev/null || true
0348         fi
0349 }
0350 
0351 function mw_check()
0352 {
0353         IDX=$1
0354         LOC=$2
0355         REM=$3
0356 
0357         write_mw "$LOC/mw$IDX"
0358 
0359         split_remote "$LOC/mw$IDX"
0360         if [[ "$REMOTE" == "" ]]; then
0361                 A=$VPATH
0362         else
0363                 A=/tmp/ntb_test.$$.A
0364                 ssh "$REMOTE" cat "$VPATH" > "$A"
0365         fi
0366 
0367         split_remote "$REM/peer_mw$IDX"
0368         if [[ "$REMOTE" == "" ]]; then
0369                 B=$VPATH
0370         else
0371                 B=/tmp/ntb_test.$$.B
0372                 ssh "$REMOTE" cat "$VPATH" > "$B"
0373         fi
0374 
0375         cmp -n $MW_ALIGNED_SIZE "$A" "$B"
0376         if [[ $? != 0 ]]; then
0377                 echo "Memory window $MW did not match!" >&2
0378         fi
0379 
0380         if [[ "$A" == "/tmp/*" ]]; then
0381                 rm "$A"
0382         fi
0383 
0384         if [[ "$B" == "/tmp/*" ]]; then
0385                 rm "$B"
0386         fi
0387 }
0388 
0389 function mw_free()
0390 {
0391         IDX=$1
0392         LOC=$2
0393         REM=$3
0394 
0395         write_file "$MW_DMA_ADDR:0" "$REM/peer_mw_trans$IDX"
0396 
0397         write_file 0 "$LOC/mw_trans$IDX"
0398 }
0399 
0400 function mw_test()
0401 {
0402         LOC=$1
0403         REM=$2
0404 
0405         CNT=$(get_files_count "mw_trans" "$LOC")
0406 
0407         for ((i = 0; i < $CNT; i++)); do
0408                 echo "Running mw$i tests on: $(subdirname $LOC) / " \
0409                      "$(subdirname $REM)"
0410 
0411                 mw_alloc $i $LOC $REM
0412 
0413                 mw_check $i $LOC $REM
0414 
0415                 mw_free $i $LOC  $REM
0416 
0417                 echo "  Passed"
0418         done
0419 
0420 }
0421 
0422 function pingpong_test()
0423 {
0424         LOC=$1
0425         REM=$2
0426 
0427         echo "Running ping pong tests on: $(basename $LOC) / $(basename $REM)"
0428 
0429         LOC_START=$(read_file "$LOC/count")
0430         REM_START=$(read_file "$REM/count")
0431 
0432         sleep 7
0433 
0434         LOC_END=$(read_file "$LOC/count")
0435         REM_END=$(read_file "$REM/count")
0436 
0437         if [[ $LOC_START == $LOC_END ]] || [[ $REM_START == $REM_END ]]; then
0438                 echo "Ping pong counter not incrementing!" >&2
0439                 exit 1
0440         fi
0441 
0442         echo "  Passed"
0443 }
0444 
0445 function msi_test()
0446 {
0447         LOC=$1
0448         REM=$2
0449 
0450         write_file 1 $LOC/ready
0451 
0452         echo "Running MSI interrupt tests on: $(subdirname $LOC) / $(subdirname $REM)"
0453 
0454         CNT=$(read_file "$LOC/count")
0455         for ((i = 0; i < $CNT; i++)); do
0456                 START=$(read_file $REM/../irq${i}_occurrences)
0457                 write_file $i $LOC/trigger
0458                 END=$(read_file $REM/../irq${i}_occurrences)
0459 
0460                 if [[ $(($END - $START)) != 1 ]]; then
0461                         echo "MSI did not trigger the interrupt on the remote side!" >&2
0462                         exit 1
0463                 fi
0464         done
0465 
0466         echo "  Passed"
0467 }
0468 
0469 function perf_test()
0470 {
0471         USE_DMA=$1
0472 
0473         if [[ $USE_DMA == "1" ]]; then
0474                 WITH="with"
0475         else
0476                 WITH="without"
0477         fi
0478 
0479         _modprobe ntb_perf total_order=$PERF_RUN_ORDER \
0480                 max_mw_size=$MAX_MW_SIZE use_dma=$USE_DMA
0481 
0482         echo "Running local perf test $WITH DMA"
0483         write_file "$LOCAL_PIDX" "$LOCAL_PERF/run"
0484         echo -n "  "
0485         read_file "$LOCAL_PERF/run"
0486         echo "  Passed"
0487 
0488         echo "Running remote perf test $WITH DMA"
0489         write_file "$REMOTE_PIDX" "$REMOTE_PERF/run"
0490         echo -n "  "
0491         read_file "$REMOTE_PERF/run"
0492         echo "  Passed"
0493 
0494         _modprobe -r ntb_perf
0495 }
0496 
0497 function ntb_tool_tests()
0498 {
0499         LOCAL_TOOL="$DEBUGFS/ntb_tool/$LOCAL_DEV"
0500         REMOTE_TOOL="$REMOTE_HOST:$DEBUGFS/ntb_tool/$REMOTE_DEV"
0501 
0502         echo "Starting ntb_tool tests..."
0503 
0504         _modprobe ntb_tool
0505 
0506         port_test "$LOCAL_TOOL" "$REMOTE_TOOL"
0507 
0508         LOCAL_PEER_TOOL="$LOCAL_TOOL/peer$LOCAL_PIDX"
0509         REMOTE_PEER_TOOL="$REMOTE_TOOL/peer$REMOTE_PIDX"
0510 
0511         link_test "$LOCAL_PEER_TOOL" "$REMOTE_PEER_TOOL"
0512         link_test "$REMOTE_PEER_TOOL" "$LOCAL_PEER_TOOL"
0513 
0514         #Ensure the link is up on both sides before continuing
0515         write_file "Y" "$LOCAL_PEER_TOOL/link_event"
0516         write_file "Y" "$REMOTE_PEER_TOOL/link_event"
0517 
0518         doorbell_test "$LOCAL_TOOL" "$REMOTE_TOOL"
0519         doorbell_test "$REMOTE_TOOL" "$LOCAL_TOOL"
0520 
0521         scratchpad_test "$LOCAL_PEER_TOOL" "$REMOTE_PEER_TOOL"
0522         scratchpad_test "$REMOTE_PEER_TOOL" "$LOCAL_PEER_TOOL"
0523 
0524         message_test "$LOCAL_PEER_TOOL" "$REMOTE_PEER_TOOL"
0525         message_test "$REMOTE_PEER_TOOL" "$LOCAL_PEER_TOOL"
0526 
0527         mw_test "$LOCAL_PEER_TOOL" "$REMOTE_PEER_TOOL"
0528         mw_test "$REMOTE_PEER_TOOL" "$LOCAL_PEER_TOOL"
0529 
0530         _modprobe -r ntb_tool
0531 }
0532 
0533 function ntb_pingpong_tests()
0534 {
0535         LOCAL_PP="$DEBUGFS/ntb_pingpong/$LOCAL_DEV"
0536         REMOTE_PP="$REMOTE_HOST:$DEBUGFS/ntb_pingpong/$REMOTE_DEV"
0537 
0538         echo "Starting ntb_pingpong tests..."
0539 
0540         _modprobe ntb_pingpong
0541 
0542         pingpong_test $LOCAL_PP $REMOTE_PP
0543 
0544         _modprobe -r ntb_pingpong
0545 }
0546 
0547 function ntb_msi_tests()
0548 {
0549         LOCAL_MSI="$DEBUGFS/ntb_msi_test/$LOCAL_DEV"
0550         REMOTE_MSI="$REMOTE_HOST:$DEBUGFS/ntb_msi_test/$REMOTE_DEV"
0551 
0552         echo "Starting ntb_msi_test tests..."
0553 
0554         if ! _modprobe ntb_msi_test 2> /dev/null; then
0555                 echo "  Not doing MSI tests seeing the module is not available."
0556                 return
0557         fi
0558 
0559         port_test $LOCAL_MSI $REMOTE_MSI
0560 
0561         LOCAL_PEER="$LOCAL_MSI/peer$LOCAL_PIDX"
0562         REMOTE_PEER="$REMOTE_MSI/peer$REMOTE_PIDX"
0563 
0564         msi_test $LOCAL_PEER $REMOTE_PEER
0565         msi_test $REMOTE_PEER $LOCAL_PEER
0566 
0567         _modprobe -r ntb_msi_test
0568 }
0569 
0570 function ntb_perf_tests()
0571 {
0572         LOCAL_PERF="$DEBUGFS/ntb_perf/$LOCAL_DEV"
0573         REMOTE_PERF="$REMOTE_HOST:$DEBUGFS/ntb_perf/$REMOTE_DEV"
0574 
0575         echo "Starting ntb_perf tests..."
0576 
0577         perf_test 0
0578 
0579         if [[ $RUN_DMA_TESTS ]]; then
0580                 perf_test 1
0581         fi
0582 }
0583 
0584 function cleanup()
0585 {
0586         set +e
0587         _modprobe -r ntb_tool 2> /dev/null
0588         _modprobe -r ntb_perf 2> /dev/null
0589         _modprobe -r ntb_pingpong 2> /dev/null
0590         _modprobe -r ntb_transport 2> /dev/null
0591         _modprobe -r ntb_msi_test 2> /dev/null
0592         set -e
0593 }
0594 
0595 cleanup
0596 
0597 if ! [[ $$DONT_CLEANUP ]]; then
0598         trap cleanup EXIT
0599 fi
0600 
0601 if [ "$(id -u)" != "0" ]; then
0602         echo "This script must be run as root" 1>&2
0603         exit 1
0604 fi
0605 
0606 if [[ "$LIST_DEVS" == TRUE ]]; then
0607         echo "Local Devices:"
0608         ls -1 /sys/bus/ntb/devices
0609         echo
0610 
0611         if [[ "$REMOTE_HOST" != "" ]]; then
0612                 echo "Remote Devices:"
0613                 ssh $REMOTE_HOST ls -1 /sys/bus/ntb/devices
0614         fi
0615 
0616         exit 0
0617 fi
0618 
0619 if [[ "$LOCAL_DEV" == $"" ]] || [[ "$REMOTE_DEV" == $"" ]]; then
0620         show_help
0621         exit 1
0622 fi
0623 
0624 ntb_tool_tests
0625 echo
0626 ntb_pingpong_tests
0627 echo
0628 ntb_msi_tests
0629 echo
0630 ntb_perf_tests
0631 echo