1#!/bin/bash 2# Copyright (c) 2016 Microsemi. All Rights Reserved. 3# 4# This program is free software; you can redistribute it and/or 5# modify it under the terms of the GNU General Public License as 6# published by the Free Software Foundation; either version 2 of 7# the License, or (at your option) any later version. 8# 9# This program is distributed in the hope that it would be useful, 10# but WITHOUT ANY WARRANTY; without even the implied warranty of 11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12# GNU General Public License for more details. 13# 14# Author: Logan Gunthorpe <logang@deltatee.com> 15 16REMOTE_HOST= 17LIST_DEVS=FALSE 18 19DEBUGFS=${DEBUGFS-/sys/kernel/debug} 20 21DB_BITMASK=0x7FFF 22PERF_RUN_ORDER=32 23MAX_MW_SIZE=0 24RUN_DMA_TESTS= 25DONT_CLEANUP= 26MW_SIZE=65536 27 28function show_help() 29{ 30 echo "Usage: $0 [OPTIONS] LOCAL_DEV REMOTE_DEV" 31 echo "Run tests on a pair of NTB endpoints." 32 echo 33 echo "If the NTB device loops back to the same host then," 34 echo "just specifying the two PCI ids on the command line is" 35 echo "sufficient. Otherwise, if the NTB link spans two hosts" 36 echo "use the -r option to specify the hostname for the remote" 37 echo "device. SSH will then be used to test the remote side." 38 echo "An SSH key between the root users of the host would then" 39 echo "be highly recommended." 40 echo 41 echo "Options:" 42 echo " -b BITMASK doorbell clear bitmask for ntb_tool" 43 echo " -C don't cleanup ntb modules on exit" 44 echo " -d run dma tests" 45 echo " -h show this help message" 46 echo " -l list available local and remote PCI ids" 47 echo " -r REMOTE_HOST specify the remote's hostname to connect" 48 echo " to for the test (using ssh)" 49 echo " -p NUM ntb_perf run order (default: $PERF_RUN_ORDER)" 50 echo " -w max_mw_size maxmium memory window size" 51 echo 52} 53 54function parse_args() 55{ 56 OPTIND=0 57 while getopts "b:Cdhlm:r:p:w:" opt; do 58 case "$opt" in 59 b) DB_BITMASK=${OPTARG} ;; 60 C) DONT_CLEANUP=1 ;; 61 d) RUN_DMA_TESTS=1 ;; 62 h) show_help; exit 0 ;; 63 l) LIST_DEVS=TRUE ;; 64 m) MW_SIZE=${OPTARG} ;; 65 r) REMOTE_HOST=${OPTARG} ;; 66 p) PERF_RUN_ORDER=${OPTARG} ;; 67 w) MAX_MW_SIZE=${OPTARG} ;; 68 \?) 69 echo "Invalid option: -$OPTARG" >&2 70 exit 1 71 ;; 72 esac 73 done 74} 75 76parse_args "$@" 77shift $((OPTIND-1)) 78LOCAL_DEV=$1 79shift 80parse_args "$@" 81shift $((OPTIND-1)) 82REMOTE_DEV=$1 83shift 84parse_args "$@" 85 86set -e 87 88function _modprobe() 89{ 90 modprobe "$@" 91 92 if [[ "$REMOTE_HOST" != "" ]]; then 93 ssh "$REMOTE_HOST" modprobe "$@" 94 fi 95} 96 97function split_remote() 98{ 99 VPATH=$1 100 REMOTE= 101 102 if [[ "$VPATH" == *":/"* ]]; then 103 REMOTE=${VPATH%%:*} 104 VPATH=${VPATH#*:} 105 fi 106} 107 108function read_file() 109{ 110 split_remote $1 111 if [[ "$REMOTE" != "" ]]; then 112 ssh "$REMOTE" cat "$VPATH" 113 else 114 cat "$VPATH" 115 fi 116} 117 118function write_file() 119{ 120 split_remote $2 121 VALUE=$1 122 123 if [[ "$REMOTE" != "" ]]; then 124 ssh "$REMOTE" "echo \"$VALUE\" > \"$VPATH\"" 125 else 126 echo "$VALUE" > "$VPATH" 127 fi 128} 129 130function link_test() 131{ 132 LOC=$1 133 REM=$2 134 EXP=0 135 136 echo "Running link tests on: $(basename $LOC) / $(basename $REM)" 137 138 if ! write_file "N" "$LOC/link" 2> /dev/null; then 139 echo " Unsupported" 140 return 141 fi 142 143 write_file "N" "$LOC/link_event" 144 145 if [[ $(read_file "$REM/link") != "N" ]]; then 146 echo "Expected remote link to be down in $REM/link" >&2 147 exit -1 148 fi 149 150 write_file "Y" "$LOC/link" 151 write_file "Y" "$LOC/link_event" 152 153 echo " Passed" 154} 155 156function doorbell_test() 157{ 158 LOC=$1 159 REM=$2 160 EXP=0 161 162 echo "Running db tests on: $(basename $LOC) / $(basename $REM)" 163 164 write_file "c $DB_BITMASK" "$REM/db" 165 166 for ((i=1; i <= 8; i++)); do 167 let DB=$(read_file "$REM/db") || true 168 if [[ "$DB" != "$EXP" ]]; then 169 echo "Doorbell doesn't match expected value $EXP " \ 170 "in $REM/db" >&2 171 exit -1 172 fi 173 174 let "MASK=1 << ($i-1)" || true 175 let "EXP=$EXP | $MASK" || true 176 write_file "s $MASK" "$LOC/peer_db" 177 done 178 179 echo " Passed" 180} 181 182function read_spad() 183{ 184 VPATH=$1 185 IDX=$2 186 187 ROW=($(read_file "$VPATH" | grep -e "^$IDX")) 188 let VAL=${ROW[1]} || true 189 echo $VAL 190} 191 192function scratchpad_test() 193{ 194 LOC=$1 195 REM=$2 196 CNT=$(read_file "$LOC/spad" | wc -l) 197 198 echo "Running spad tests on: $(basename $LOC) / $(basename $REM)" 199 200 for ((i = 0; i < $CNT; i++)); do 201 VAL=$RANDOM 202 write_file "$i $VAL" "$LOC/peer_spad" 203 RVAL=$(read_spad "$REM/spad" $i) 204 205 if [[ "$VAL" != "$RVAL" ]]; then 206 echo "Scratchpad doesn't match expected value $VAL " \ 207 "in $REM/spad, got $RVAL" >&2 208 exit -1 209 fi 210 211 done 212 213 echo " Passed" 214} 215 216function write_mw() 217{ 218 split_remote $2 219 220 if [[ "$REMOTE" != "" ]]; then 221 ssh "$REMOTE" \ 222 dd if=/dev/urandom "of=$VPATH" 2> /dev/null || true 223 else 224 dd if=/dev/urandom "of=$VPATH" 2> /dev/null || true 225 fi 226} 227 228function mw_test() 229{ 230 IDX=$1 231 LOC=$2 232 REM=$3 233 234 echo "Running $IDX tests on: $(basename $LOC) / $(basename $REM)" 235 236 write_mw "$LOC/$IDX" 237 238 split_remote "$LOC/$IDX" 239 if [[ "$REMOTE" == "" ]]; then 240 A=$VPATH 241 else 242 A=/tmp/ntb_test.$$.A 243 ssh "$REMOTE" cat "$VPATH" > "$A" 244 fi 245 246 split_remote "$REM/peer_$IDX" 247 if [[ "$REMOTE" == "" ]]; then 248 B=$VPATH 249 else 250 B=/tmp/ntb_test.$$.B 251 ssh "$REMOTE" cat "$VPATH" > "$B" 252 fi 253 254 cmp -n $MW_SIZE "$A" "$B" 255 if [[ $? != 0 ]]; then 256 echo "Memory window $MW did not match!" >&2 257 fi 258 259 if [[ "$A" == "/tmp/*" ]]; then 260 rm "$A" 261 fi 262 263 if [[ "$B" == "/tmp/*" ]]; then 264 rm "$B" 265 fi 266 267 echo " Passed" 268} 269 270function pingpong_test() 271{ 272 LOC=$1 273 REM=$2 274 275 echo "Running ping pong tests on: $(basename $LOC) / $(basename $REM)" 276 277 LOC_START=$(read_file $LOC/count) 278 REM_START=$(read_file $REM/count) 279 280 sleep 7 281 282 LOC_END=$(read_file $LOC/count) 283 REM_END=$(read_file $REM/count) 284 285 if [[ $LOC_START == $LOC_END ]] || [[ $REM_START == $REM_END ]]; then 286 echo "Ping pong counter not incrementing!" >&2 287 exit 1 288 fi 289 290 echo " Passed" 291} 292 293function perf_test() 294{ 295 USE_DMA=$1 296 297 if [[ $USE_DMA == "1" ]]; then 298 WITH="with" 299 else 300 WITH="without" 301 fi 302 303 _modprobe ntb_perf run_order=$PERF_RUN_ORDER \ 304 max_mw_size=$MAX_MW_SIZE use_dma=$USE_DMA 305 306 echo "Running local perf test $WITH DMA" 307 write_file "" $LOCAL_PERF/run 308 echo -n " " 309 read_file $LOCAL_PERF/run 310 echo " Passed" 311 312 echo "Running remote perf test $WITH DMA" 313 write_file "" $REMOTE_PERF/run 314 echo -n " " 315 read_file $REMOTE_PERF/run 316 echo " Passed" 317 318 _modprobe -r ntb_perf 319} 320 321function ntb_tool_tests() 322{ 323 LOCAL_TOOL=$DEBUGFS/ntb_tool/$LOCAL_DEV 324 REMOTE_TOOL=$REMOTE_HOST:$DEBUGFS/ntb_tool/$REMOTE_DEV 325 326 echo "Starting ntb_tool tests..." 327 328 _modprobe ntb_tool 329 330 write_file Y $LOCAL_TOOL/link_event 331 write_file Y $REMOTE_TOOL/link_event 332 333 link_test $LOCAL_TOOL $REMOTE_TOOL 334 link_test $REMOTE_TOOL $LOCAL_TOOL 335 336 #Ensure the link is up on both sides before continuing 337 write_file Y $LOCAL_TOOL/link_event 338 write_file Y $REMOTE_TOOL/link_event 339 340 for PEER_TRANS in $(ls $LOCAL_TOOL/peer_trans*); do 341 PT=$(basename $PEER_TRANS) 342 write_file $MW_SIZE $LOCAL_TOOL/$PT 343 write_file $MW_SIZE $REMOTE_TOOL/$PT 344 done 345 346 doorbell_test $LOCAL_TOOL $REMOTE_TOOL 347 doorbell_test $REMOTE_TOOL $LOCAL_TOOL 348 scratchpad_test $LOCAL_TOOL $REMOTE_TOOL 349 scratchpad_test $REMOTE_TOOL $LOCAL_TOOL 350 351 for MW in $(ls $LOCAL_TOOL/mw*); do 352 MW=$(basename $MW) 353 354 mw_test $MW $LOCAL_TOOL $REMOTE_TOOL 355 mw_test $MW $REMOTE_TOOL $LOCAL_TOOL 356 done 357 358 _modprobe -r ntb_tool 359} 360 361function ntb_pingpong_tests() 362{ 363 LOCAL_PP=$DEBUGFS/ntb_pingpong/$LOCAL_DEV 364 REMOTE_PP=$REMOTE_HOST:$DEBUGFS/ntb_pingpong/$REMOTE_DEV 365 366 echo "Starting ntb_pingpong tests..." 367 368 _modprobe ntb_pingpong 369 370 pingpong_test $LOCAL_PP $REMOTE_PP 371 372 _modprobe -r ntb_pingpong 373} 374 375function ntb_perf_tests() 376{ 377 LOCAL_PERF=$DEBUGFS/ntb_perf/$LOCAL_DEV 378 REMOTE_PERF=$REMOTE_HOST:$DEBUGFS/ntb_perf/$REMOTE_DEV 379 380 echo "Starting ntb_perf tests..." 381 382 perf_test 0 383 384 if [[ $RUN_DMA_TESTS ]]; then 385 perf_test 1 386 fi 387} 388 389function cleanup() 390{ 391 set +e 392 _modprobe -r ntb_tool 2> /dev/null 393 _modprobe -r ntb_perf 2> /dev/null 394 _modprobe -r ntb_pingpong 2> /dev/null 395 _modprobe -r ntb_transport 2> /dev/null 396 set -e 397} 398 399cleanup 400 401if ! [[ $$DONT_CLEANUP ]]; then 402 trap cleanup EXIT 403fi 404 405if [ "$(id -u)" != "0" ]; then 406 echo "This script must be run as root" 1>&2 407 exit 1 408fi 409 410if [[ "$LIST_DEVS" == TRUE ]]; then 411 echo "Local Devices:" 412 ls -1 /sys/bus/ntb/devices 413 echo 414 415 if [[ "$REMOTE_HOST" != "" ]]; then 416 echo "Remote Devices:" 417 ssh $REMOTE_HOST ls -1 /sys/bus/ntb/devices 418 fi 419 420 exit 0 421fi 422 423if [[ "$LOCAL_DEV" == $"" ]] || [[ "$REMOTE_DEV" == $"" ]]; then 424 show_help 425 exit 1 426fi 427 428ntb_tool_tests 429echo 430ntb_pingpong_tests 431echo 432ntb_perf_tests 433echo 434