ntb_test.sh 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. #!/bin/bash
  2. # SPDX-License-Identifier: GPL-2.0-or-later
  3. # Copyright (c) 2016 Microsemi. All Rights Reserved.
  4. #
  5. # Author: Logan Gunthorpe <logang@deltatee.com>
  6. REMOTE_HOST=
  7. LIST_DEVS=FALSE
  8. DEBUGFS=${DEBUGFS-/sys/kernel/debug}
  9. PERF_RUN_ORDER=32
  10. MAX_MW_SIZE=0
  11. RUN_DMA_TESTS=
  12. DONT_CLEANUP=
  13. MW_SIZE=65536
  14. function show_help()
  15. {
  16. echo "Usage: $0 [OPTIONS] LOCAL_DEV REMOTE_DEV"
  17. echo "Run tests on a pair of NTB endpoints."
  18. echo
  19. echo "If the NTB device loops back to the same host then,"
  20. echo "just specifying the two PCI ids on the command line is"
  21. echo "sufficient. Otherwise, if the NTB link spans two hosts"
  22. echo "use the -r option to specify the hostname for the remote"
  23. echo "device. SSH will then be used to test the remote side."
  24. echo "An SSH key between the root users of the host would then"
  25. echo "be highly recommended."
  26. echo
  27. echo "Options:"
  28. echo " -C don't cleanup ntb modules on exit"
  29. echo " -h show this help message"
  30. echo " -l list available local and remote PCI ids"
  31. echo " -r REMOTE_HOST specify the remote's hostname to connect"
  32. echo " to for the test (using ssh)"
  33. echo " -m MW_SIZE memory window size for ntb_tool"
  34. echo " (default: $MW_SIZE)"
  35. echo " -d run dma tests for ntb_perf"
  36. echo " -p ORDER total data order for ntb_perf"
  37. echo " (default: $PERF_RUN_ORDER)"
  38. echo " -w MAX_MW_SIZE maxmium memory window size for ntb_perf"
  39. echo
  40. }
  41. function parse_args()
  42. {
  43. OPTIND=0
  44. while getopts "b:Cdhlm:r:p:w:" opt; do
  45. case "$opt" in
  46. C) DONT_CLEANUP=1 ;;
  47. d) RUN_DMA_TESTS=1 ;;
  48. h) show_help; exit 0 ;;
  49. l) LIST_DEVS=TRUE ;;
  50. m) MW_SIZE=${OPTARG} ;;
  51. r) REMOTE_HOST=${OPTARG} ;;
  52. p) PERF_RUN_ORDER=${OPTARG} ;;
  53. w) MAX_MW_SIZE=${OPTARG} ;;
  54. \?)
  55. echo "Invalid option: -$OPTARG" >&2
  56. exit 1
  57. ;;
  58. esac
  59. done
  60. }
  61. parse_args "$@"
  62. shift $((OPTIND-1))
  63. LOCAL_DEV=$1
  64. shift
  65. parse_args "$@"
  66. shift $((OPTIND-1))
  67. REMOTE_DEV=$1
  68. shift
  69. parse_args "$@"
  70. set -e
  71. function _modprobe()
  72. {
  73. modprobe "$@" || return 1
  74. if [[ "$REMOTE_HOST" != "" ]]; then
  75. ssh "$REMOTE_HOST" modprobe "$@" || return 1
  76. fi
  77. }
  78. function split_remote()
  79. {
  80. VPATH=$1
  81. REMOTE=
  82. if [[ "$VPATH" == *":/"* ]]; then
  83. REMOTE=${VPATH%%:*}
  84. VPATH=${VPATH#*:}
  85. fi
  86. }
  87. function read_file()
  88. {
  89. split_remote $1
  90. if [[ "$REMOTE" != "" ]]; then
  91. ssh "$REMOTE" cat "$VPATH"
  92. else
  93. cat "$VPATH"
  94. fi
  95. }
  96. function write_file()
  97. {
  98. split_remote $2
  99. VALUE=$1
  100. if [[ "$REMOTE" != "" ]]; then
  101. ssh "$REMOTE" "echo \"$VALUE\" > \"$VPATH\""
  102. else
  103. echo "$VALUE" > "$VPATH"
  104. fi
  105. }
  106. function check_file()
  107. {
  108. split_remote $1
  109. if [[ "$REMOTE" != "" ]]; then
  110. ssh "$REMOTE" "[[ -e ${VPATH} ]]"
  111. else
  112. [[ -e ${VPATH} ]]
  113. fi
  114. }
  115. function subdirname()
  116. {
  117. echo $(basename $(dirname $1)) 2> /dev/null
  118. }
  119. function find_pidx()
  120. {
  121. PORT=$1
  122. PPATH=$2
  123. for ((i = 0; i < 64; i++)); do
  124. PEER_DIR="$PPATH/peer$i"
  125. check_file ${PEER_DIR} || break
  126. PEER_PORT=$(read_file "${PEER_DIR}/port")
  127. if [[ ${PORT} -eq $PEER_PORT ]]; then
  128. echo $i
  129. return 0
  130. fi
  131. done
  132. return 1
  133. }
  134. function port_test()
  135. {
  136. LOC=$1
  137. REM=$2
  138. echo "Running port tests on: $(basename $LOC) / $(basename $REM)"
  139. LOCAL_PORT=$(read_file "$LOC/port")
  140. REMOTE_PORT=$(read_file "$REM/port")
  141. LOCAL_PIDX=$(find_pidx ${REMOTE_PORT} "$LOC")
  142. REMOTE_PIDX=$(find_pidx ${LOCAL_PORT} "$REM")
  143. echo "Local port ${LOCAL_PORT} with index ${REMOTE_PIDX} on remote host"
  144. echo "Peer port ${REMOTE_PORT} with index ${LOCAL_PIDX} on local host"
  145. echo " Passed"
  146. }
  147. function link_test()
  148. {
  149. LOC=$1
  150. REM=$2
  151. EXP=0
  152. echo "Running link tests on: $(subdirname $LOC) / $(subdirname $REM)"
  153. if ! write_file "N" "$LOC/../link" 2> /dev/null; then
  154. echo " Unsupported"
  155. return
  156. fi
  157. write_file "N" "$LOC/link_event"
  158. if [[ $(read_file "$REM/link") != "N" ]]; then
  159. echo "Expected link to be down in $REM/link" >&2
  160. exit -1
  161. fi
  162. write_file "Y" "$LOC/../link"
  163. echo " Passed"
  164. }
  165. function doorbell_test()
  166. {
  167. LOC=$1
  168. REM=$2
  169. EXP=0
  170. echo "Running db tests on: $(basename $LOC) / $(basename $REM)"
  171. DB_VALID_MASK=$(read_file "$LOC/db_valid_mask")
  172. write_file "c $DB_VALID_MASK" "$REM/db"
  173. for ((i = 0; i < 64; i++)); do
  174. DB=$(read_file "$REM/db")
  175. if [[ "$DB" -ne "$EXP" ]]; then
  176. echo "Doorbell doesn't match expected value $EXP " \
  177. "in $REM/db" >&2
  178. exit -1
  179. fi
  180. let "MASK = (1 << $i) & $DB_VALID_MASK" || true
  181. let "EXP = $EXP | $MASK" || true
  182. write_file "s $MASK" "$LOC/peer_db"
  183. done
  184. write_file "c $DB_VALID_MASK" "$REM/db_mask"
  185. write_file $DB_VALID_MASK "$REM/db_event"
  186. write_file "s $DB_VALID_MASK" "$REM/db_mask"
  187. write_file "c $DB_VALID_MASK" "$REM/db"
  188. echo " Passed"
  189. }
  190. function get_files_count()
  191. {
  192. NAME=$1
  193. LOC=$2
  194. split_remote $LOC
  195. if [[ "$REMOTE" == "" ]]; then
  196. echo $(ls -1 "$VPATH"/${NAME}* 2>/dev/null | wc -l)
  197. else
  198. echo $(ssh "$REMOTE" "ls -1 \"$VPATH\"/${NAME}* | \
  199. wc -l" 2> /dev/null)
  200. fi
  201. }
  202. function scratchpad_test()
  203. {
  204. LOC=$1
  205. REM=$2
  206. echo "Running spad tests on: $(subdirname $LOC) / $(subdirname $REM)"
  207. CNT=$(get_files_count "spad" "$LOC")
  208. if [[ $CNT -eq 0 ]]; then
  209. echo " Unsupported"
  210. return
  211. fi
  212. for ((i = 0; i < $CNT; i++)); do
  213. VAL=$RANDOM
  214. write_file "$VAL" "$LOC/spad$i"
  215. RVAL=$(read_file "$REM/../spad$i")
  216. if [[ "$VAL" -ne "$RVAL" ]]; then
  217. echo "Scratchpad $i value $RVAL doesn't match $VAL" >&2
  218. exit -1
  219. fi
  220. done
  221. echo " Passed"
  222. }
  223. function message_test()
  224. {
  225. LOC=$1
  226. REM=$2
  227. echo "Running msg tests on: $(subdirname $LOC) / $(subdirname $REM)"
  228. CNT=$(get_files_count "msg" "$LOC")
  229. if [[ $CNT -eq 0 ]]; then
  230. echo " Unsupported"
  231. return
  232. fi
  233. MSG_OUTBITS_MASK=$(read_file "$LOC/../msg_inbits")
  234. MSG_INBITS_MASK=$(read_file "$REM/../msg_inbits")
  235. write_file "c $MSG_OUTBITS_MASK" "$LOC/../msg_sts"
  236. write_file "c $MSG_INBITS_MASK" "$REM/../msg_sts"
  237. for ((i = 0; i < $CNT; i++)); do
  238. VAL=$RANDOM
  239. write_file "$VAL" "$LOC/msg$i"
  240. RVAL=$(read_file "$REM/../msg$i")
  241. if [[ "$VAL" -ne "${RVAL%%<-*}" ]]; then
  242. echo "Message $i value $RVAL doesn't match $VAL" >&2
  243. exit -1
  244. fi
  245. done
  246. echo " Passed"
  247. }
  248. function get_number()
  249. {
  250. KEY=$1
  251. sed -n "s/^\(${KEY}\)[ \t]*\(0x[0-9a-fA-F]*\)\(\[p\]\)\?$/\2/p"
  252. }
  253. function mw_alloc()
  254. {
  255. IDX=$1
  256. LOC=$2
  257. REM=$3
  258. write_file $MW_SIZE "$LOC/mw_trans$IDX"
  259. INB_MW=$(read_file "$LOC/mw_trans$IDX")
  260. MW_ALIGNED_SIZE=$(echo "$INB_MW" | get_number "Window Size")
  261. MW_DMA_ADDR=$(echo "$INB_MW" | get_number "DMA Address")
  262. write_file "$MW_DMA_ADDR:$(($MW_ALIGNED_SIZE))" "$REM/peer_mw_trans$IDX"
  263. if [[ $MW_SIZE -ne $MW_ALIGNED_SIZE ]]; then
  264. echo "MW $IDX size aligned to $MW_ALIGNED_SIZE"
  265. fi
  266. }
  267. function write_mw()
  268. {
  269. split_remote $2
  270. if [[ "$REMOTE" != "" ]]; then
  271. ssh "$REMOTE" \
  272. dd if=/dev/urandom "of=$VPATH" 2> /dev/null || true
  273. else
  274. dd if=/dev/urandom "of=$VPATH" 2> /dev/null || true
  275. fi
  276. }
  277. function mw_check()
  278. {
  279. IDX=$1
  280. LOC=$2
  281. REM=$3
  282. write_mw "$LOC/mw$IDX"
  283. split_remote "$LOC/mw$IDX"
  284. if [[ "$REMOTE" == "" ]]; then
  285. A=$VPATH
  286. else
  287. A=/tmp/ntb_test.$$.A
  288. ssh "$REMOTE" cat "$VPATH" > "$A"
  289. fi
  290. split_remote "$REM/peer_mw$IDX"
  291. if [[ "$REMOTE" == "" ]]; then
  292. B=$VPATH
  293. else
  294. B=/tmp/ntb_test.$$.B
  295. ssh "$REMOTE" cat "$VPATH" > "$B"
  296. fi
  297. cmp -n $MW_ALIGNED_SIZE "$A" "$B"
  298. if [[ $? != 0 ]]; then
  299. echo "Memory window $MW did not match!" >&2
  300. fi
  301. if [[ "$A" == "/tmp/*" ]]; then
  302. rm "$A"
  303. fi
  304. if [[ "$B" == "/tmp/*" ]]; then
  305. rm "$B"
  306. fi
  307. }
  308. function mw_free()
  309. {
  310. IDX=$1
  311. LOC=$2
  312. REM=$3
  313. write_file "$MW_DMA_ADDR:0" "$REM/peer_mw_trans$IDX"
  314. write_file 0 "$LOC/mw_trans$IDX"
  315. }
  316. function mw_test()
  317. {
  318. LOC=$1
  319. REM=$2
  320. CNT=$(get_files_count "mw_trans" "$LOC")
  321. for ((i = 0; i < $CNT; i++)); do
  322. echo "Running mw$i tests on: $(subdirname $LOC) / " \
  323. "$(subdirname $REM)"
  324. mw_alloc $i $LOC $REM
  325. mw_check $i $LOC $REM
  326. mw_free $i $LOC $REM
  327. echo " Passed"
  328. done
  329. }
  330. function pingpong_test()
  331. {
  332. LOC=$1
  333. REM=$2
  334. echo "Running ping pong tests on: $(basename $LOC) / $(basename $REM)"
  335. LOC_START=$(read_file "$LOC/count")
  336. REM_START=$(read_file "$REM/count")
  337. sleep 7
  338. LOC_END=$(read_file "$LOC/count")
  339. REM_END=$(read_file "$REM/count")
  340. if [[ $LOC_START == $LOC_END ]] || [[ $REM_START == $REM_END ]]; then
  341. echo "Ping pong counter not incrementing!" >&2
  342. exit 1
  343. fi
  344. echo " Passed"
  345. }
  346. function msi_test()
  347. {
  348. LOC=$1
  349. REM=$2
  350. write_file 1 $LOC/ready
  351. echo "Running MSI interrupt tests on: $(subdirname $LOC) / $(subdirname $REM)"
  352. CNT=$(read_file "$LOC/count")
  353. for ((i = 0; i < $CNT; i++)); do
  354. START=$(read_file $REM/../irq${i}_occurrences)
  355. write_file $i $LOC/trigger
  356. END=$(read_file $REM/../irq${i}_occurrences)
  357. if [[ $(($END - $START)) != 1 ]]; then
  358. echo "MSI did not trigger the interrupt on the remote side!" >&2
  359. exit 1
  360. fi
  361. done
  362. echo " Passed"
  363. }
  364. function perf_test()
  365. {
  366. USE_DMA=$1
  367. if [[ $USE_DMA == "1" ]]; then
  368. WITH="with"
  369. else
  370. WITH="without"
  371. fi
  372. _modprobe ntb_perf total_order=$PERF_RUN_ORDER \
  373. max_mw_size=$MAX_MW_SIZE use_dma=$USE_DMA
  374. echo "Running local perf test $WITH DMA"
  375. write_file "$LOCAL_PIDX" "$LOCAL_PERF/run"
  376. echo -n " "
  377. read_file "$LOCAL_PERF/run"
  378. echo " Passed"
  379. echo "Running remote perf test $WITH DMA"
  380. write_file "$REMOTE_PIDX" "$REMOTE_PERF/run"
  381. echo -n " "
  382. read_file "$REMOTE_PERF/run"
  383. echo " Passed"
  384. _modprobe -r ntb_perf
  385. }
  386. function ntb_tool_tests()
  387. {
  388. LOCAL_TOOL="$DEBUGFS/ntb_tool/$LOCAL_DEV"
  389. REMOTE_TOOL="$REMOTE_HOST:$DEBUGFS/ntb_tool/$REMOTE_DEV"
  390. echo "Starting ntb_tool tests..."
  391. _modprobe ntb_tool
  392. port_test "$LOCAL_TOOL" "$REMOTE_TOOL"
  393. LOCAL_PEER_TOOL="$LOCAL_TOOL/peer$LOCAL_PIDX"
  394. REMOTE_PEER_TOOL="$REMOTE_TOOL/peer$REMOTE_PIDX"
  395. link_test "$LOCAL_PEER_TOOL" "$REMOTE_PEER_TOOL"
  396. link_test "$REMOTE_PEER_TOOL" "$LOCAL_PEER_TOOL"
  397. #Ensure the link is up on both sides before continuing
  398. write_file "Y" "$LOCAL_PEER_TOOL/link_event"
  399. write_file "Y" "$REMOTE_PEER_TOOL/link_event"
  400. doorbell_test "$LOCAL_TOOL" "$REMOTE_TOOL"
  401. doorbell_test "$REMOTE_TOOL" "$LOCAL_TOOL"
  402. scratchpad_test "$LOCAL_PEER_TOOL" "$REMOTE_PEER_TOOL"
  403. scratchpad_test "$REMOTE_PEER_TOOL" "$LOCAL_PEER_TOOL"
  404. message_test "$LOCAL_PEER_TOOL" "$REMOTE_PEER_TOOL"
  405. message_test "$REMOTE_PEER_TOOL" "$LOCAL_PEER_TOOL"
  406. mw_test "$LOCAL_PEER_TOOL" "$REMOTE_PEER_TOOL"
  407. mw_test "$REMOTE_PEER_TOOL" "$LOCAL_PEER_TOOL"
  408. _modprobe -r ntb_tool
  409. }
  410. function ntb_pingpong_tests()
  411. {
  412. LOCAL_PP="$DEBUGFS/ntb_pingpong/$LOCAL_DEV"
  413. REMOTE_PP="$REMOTE_HOST:$DEBUGFS/ntb_pingpong/$REMOTE_DEV"
  414. echo "Starting ntb_pingpong tests..."
  415. _modprobe ntb_pingpong
  416. pingpong_test $LOCAL_PP $REMOTE_PP
  417. _modprobe -r ntb_pingpong
  418. }
  419. function ntb_msi_tests()
  420. {
  421. LOCAL_MSI="$DEBUGFS/ntb_msi_test/$LOCAL_DEV"
  422. REMOTE_MSI="$REMOTE_HOST:$DEBUGFS/ntb_msi_test/$REMOTE_DEV"
  423. echo "Starting ntb_msi_test tests..."
  424. if ! _modprobe ntb_msi_test 2> /dev/null; then
  425. echo " Not doing MSI tests seeing the module is not available."
  426. return
  427. fi
  428. port_test $LOCAL_MSI $REMOTE_MSI
  429. LOCAL_PEER="$LOCAL_MSI/peer$LOCAL_PIDX"
  430. REMOTE_PEER="$REMOTE_MSI/peer$REMOTE_PIDX"
  431. msi_test $LOCAL_PEER $REMOTE_PEER
  432. msi_test $REMOTE_PEER $LOCAL_PEER
  433. _modprobe -r ntb_msi_test
  434. }
  435. function ntb_perf_tests()
  436. {
  437. LOCAL_PERF="$DEBUGFS/ntb_perf/$LOCAL_DEV"
  438. REMOTE_PERF="$REMOTE_HOST:$DEBUGFS/ntb_perf/$REMOTE_DEV"
  439. echo "Starting ntb_perf tests..."
  440. perf_test 0
  441. if [[ $RUN_DMA_TESTS ]]; then
  442. perf_test 1
  443. fi
  444. }
  445. function cleanup()
  446. {
  447. set +e
  448. _modprobe -r ntb_tool 2> /dev/null
  449. _modprobe -r ntb_perf 2> /dev/null
  450. _modprobe -r ntb_pingpong 2> /dev/null
  451. _modprobe -r ntb_transport 2> /dev/null
  452. _modprobe -r ntb_msi_test 2> /dev/null
  453. set -e
  454. }
  455. cleanup
  456. if ! [[ $$DONT_CLEANUP ]]; then
  457. trap cleanup EXIT
  458. fi
  459. if [ "$(id -u)" != "0" ]; then
  460. echo "This script must be run as root" 1>&2
  461. exit 1
  462. fi
  463. if [[ "$LIST_DEVS" == TRUE ]]; then
  464. echo "Local Devices:"
  465. ls -1 /sys/bus/ntb/devices
  466. echo
  467. if [[ "$REMOTE_HOST" != "" ]]; then
  468. echo "Remote Devices:"
  469. ssh $REMOTE_HOST ls -1 /sys/bus/ntb/devices
  470. fi
  471. exit 0
  472. fi
  473. if [[ "$LOCAL_DEV" == $"" ]] || [[ "$REMOTE_DEV" == $"" ]]; then
  474. show_help
  475. exit 1
  476. fi
  477. ntb_tool_tests
  478. echo
  479. ntb_pingpong_tests
  480. echo
  481. ntb_msi_tests
  482. echo
  483. ntb_perf_tests
  484. echo