radeon_test.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. // SPDX-License-Identifier: GPL-2.0 OR MIT
  2. /*
  3. * Copyright 2009 VMware, Inc.
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a
  6. * copy of this software and associated documentation files (the "Software"),
  7. * to deal in the Software without restriction, including without limitation
  8. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. * and/or sell copies of the Software, and to permit persons to whom the
  10. * Software is furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  18. * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  19. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  20. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  21. * OTHER DEALINGS IN THE SOFTWARE.
  22. *
  23. * Authors: Michel Dänzer
  24. */
  25. #include <drm/drmP.h>
  26. #include <drm/radeon_drm.h>
  27. #include "radeon_reg.h"
  28. #include "radeon.h"
  29. #define RADEON_TEST_COPY_BLIT 1
  30. #define RADEON_TEST_COPY_DMA 0
  31. /* Test BO GTT->VRAM and VRAM->GTT GPU copies across the whole GTT aperture */
  32. static void radeon_do_test_moves(struct radeon_device *rdev, int flag)
  33. {
  34. struct radeon_bo *vram_obj = NULL;
  35. struct radeon_bo **gtt_obj = NULL;
  36. uint64_t gtt_addr, vram_addr;
  37. unsigned n, size;
  38. int i, r, ring;
  39. switch (flag) {
  40. case RADEON_TEST_COPY_DMA:
  41. ring = radeon_copy_dma_ring_index(rdev);
  42. break;
  43. case RADEON_TEST_COPY_BLIT:
  44. ring = radeon_copy_blit_ring_index(rdev);
  45. break;
  46. default:
  47. DRM_ERROR("Unknown copy method\n");
  48. return;
  49. }
  50. size = 1024 * 1024;
  51. /* Number of tests =
  52. * (Total GTT - IB pool - writeback page - ring buffers) / test size
  53. */
  54. n = rdev->mc.gtt_size - rdev->gart_pin_size;
  55. n /= size;
  56. gtt_obj = kcalloc(n, sizeof(*gtt_obj), GFP_KERNEL);
  57. if (!gtt_obj) {
  58. DRM_ERROR("Failed to allocate %d pointers\n", n);
  59. r = 1;
  60. goto out_cleanup;
  61. }
  62. r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
  63. 0, NULL, NULL, &vram_obj);
  64. if (r) {
  65. DRM_ERROR("Failed to create VRAM object\n");
  66. goto out_cleanup;
  67. }
  68. r = radeon_bo_reserve(vram_obj, false);
  69. if (unlikely(r != 0))
  70. goto out_unref;
  71. r = radeon_bo_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr);
  72. if (r) {
  73. DRM_ERROR("Failed to pin VRAM object\n");
  74. goto out_unres;
  75. }
  76. for (i = 0; i < n; i++) {
  77. void *gtt_map, *vram_map;
  78. void **gtt_start, **gtt_end;
  79. void **vram_start, **vram_end;
  80. struct radeon_fence *fence = NULL;
  81. r = radeon_bo_create(rdev, size, PAGE_SIZE, true,
  82. RADEON_GEM_DOMAIN_GTT, 0, NULL, NULL,
  83. gtt_obj + i);
  84. if (r) {
  85. DRM_ERROR("Failed to create GTT object %d\n", i);
  86. goto out_lclean;
  87. }
  88. r = radeon_bo_reserve(gtt_obj[i], false);
  89. if (unlikely(r != 0))
  90. goto out_lclean_unref;
  91. r = radeon_bo_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, &gtt_addr);
  92. if (r) {
  93. DRM_ERROR("Failed to pin GTT object %d\n", i);
  94. goto out_lclean_unres;
  95. }
  96. r = radeon_bo_kmap(gtt_obj[i], &gtt_map);
  97. if (r) {
  98. DRM_ERROR("Failed to map GTT object %d\n", i);
  99. goto out_lclean_unpin;
  100. }
  101. for (gtt_start = gtt_map, gtt_end = gtt_map + size;
  102. gtt_start < gtt_end;
  103. gtt_start++)
  104. *gtt_start = gtt_start;
  105. radeon_bo_kunmap(gtt_obj[i]);
  106. if (ring == R600_RING_TYPE_DMA_INDEX)
  107. fence = radeon_copy_dma(rdev, gtt_addr, vram_addr,
  108. size / RADEON_GPU_PAGE_SIZE,
  109. vram_obj->tbo.resv);
  110. else
  111. fence = radeon_copy_blit(rdev, gtt_addr, vram_addr,
  112. size / RADEON_GPU_PAGE_SIZE,
  113. vram_obj->tbo.resv);
  114. if (IS_ERR(fence)) {
  115. DRM_ERROR("Failed GTT->VRAM copy %d\n", i);
  116. r = PTR_ERR(fence);
  117. goto out_lclean_unpin;
  118. }
  119. r = radeon_fence_wait(fence, false);
  120. if (r) {
  121. DRM_ERROR("Failed to wait for GTT->VRAM fence %d\n", i);
  122. goto out_lclean_unpin;
  123. }
  124. radeon_fence_unref(&fence);
  125. r = radeon_bo_kmap(vram_obj, &vram_map);
  126. if (r) {
  127. DRM_ERROR("Failed to map VRAM object after copy %d\n", i);
  128. goto out_lclean_unpin;
  129. }
  130. for (gtt_start = gtt_map, gtt_end = gtt_map + size,
  131. vram_start = vram_map, vram_end = vram_map + size;
  132. vram_start < vram_end;
  133. gtt_start++, vram_start++) {
  134. if (*vram_start != gtt_start) {
  135. DRM_ERROR("Incorrect GTT->VRAM copy %d: Got 0x%p, "
  136. "expected 0x%p (GTT/VRAM offset "
  137. "0x%16llx/0x%16llx)\n",
  138. i, *vram_start, gtt_start,
  139. (unsigned long long)
  140. (gtt_addr - rdev->mc.gtt_start +
  141. (void*)gtt_start - gtt_map),
  142. (unsigned long long)
  143. (vram_addr - rdev->mc.vram_start +
  144. (void*)gtt_start - gtt_map));
  145. radeon_bo_kunmap(vram_obj);
  146. goto out_lclean_unpin;
  147. }
  148. *vram_start = vram_start;
  149. }
  150. radeon_bo_kunmap(vram_obj);
  151. if (ring == R600_RING_TYPE_DMA_INDEX)
  152. fence = radeon_copy_dma(rdev, vram_addr, gtt_addr,
  153. size / RADEON_GPU_PAGE_SIZE,
  154. vram_obj->tbo.resv);
  155. else
  156. fence = radeon_copy_blit(rdev, vram_addr, gtt_addr,
  157. size / RADEON_GPU_PAGE_SIZE,
  158. vram_obj->tbo.resv);
  159. if (IS_ERR(fence)) {
  160. DRM_ERROR("Failed VRAM->GTT copy %d\n", i);
  161. r = PTR_ERR(fence);
  162. goto out_lclean_unpin;
  163. }
  164. r = radeon_fence_wait(fence, false);
  165. if (r) {
  166. DRM_ERROR("Failed to wait for VRAM->GTT fence %d\n", i);
  167. goto out_lclean_unpin;
  168. }
  169. radeon_fence_unref(&fence);
  170. r = radeon_bo_kmap(gtt_obj[i], &gtt_map);
  171. if (r) {
  172. DRM_ERROR("Failed to map GTT object after copy %d\n", i);
  173. goto out_lclean_unpin;
  174. }
  175. for (gtt_start = gtt_map, gtt_end = gtt_map + size,
  176. vram_start = vram_map, vram_end = vram_map + size;
  177. gtt_start < gtt_end;
  178. gtt_start++, vram_start++) {
  179. if (*gtt_start != vram_start) {
  180. DRM_ERROR("Incorrect VRAM->GTT copy %d: Got 0x%p, "
  181. "expected 0x%p (VRAM/GTT offset "
  182. "0x%16llx/0x%16llx)\n",
  183. i, *gtt_start, vram_start,
  184. (unsigned long long)
  185. (vram_addr - rdev->mc.vram_start +
  186. (void*)vram_start - vram_map),
  187. (unsigned long long)
  188. (gtt_addr - rdev->mc.gtt_start +
  189. (void*)vram_start - vram_map));
  190. radeon_bo_kunmap(gtt_obj[i]);
  191. goto out_lclean_unpin;
  192. }
  193. }
  194. radeon_bo_kunmap(gtt_obj[i]);
  195. DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%llx\n",
  196. gtt_addr - rdev->mc.gtt_start);
  197. continue;
  198. out_lclean_unpin:
  199. radeon_bo_unpin(gtt_obj[i]);
  200. out_lclean_unres:
  201. radeon_bo_unreserve(gtt_obj[i]);
  202. out_lclean_unref:
  203. radeon_bo_unref(&gtt_obj[i]);
  204. out_lclean:
  205. for (--i; i >= 0; --i) {
  206. radeon_bo_unpin(gtt_obj[i]);
  207. radeon_bo_unreserve(gtt_obj[i]);
  208. radeon_bo_unref(&gtt_obj[i]);
  209. }
  210. if (fence && !IS_ERR(fence))
  211. radeon_fence_unref(&fence);
  212. break;
  213. }
  214. radeon_bo_unpin(vram_obj);
  215. out_unres:
  216. radeon_bo_unreserve(vram_obj);
  217. out_unref:
  218. radeon_bo_unref(&vram_obj);
  219. out_cleanup:
  220. kfree(gtt_obj);
  221. if (r) {
  222. pr_warn("Error while testing BO move\n");
  223. }
  224. }
  225. void radeon_test_moves(struct radeon_device *rdev)
  226. {
  227. if (rdev->asic->copy.dma)
  228. radeon_do_test_moves(rdev, RADEON_TEST_COPY_DMA);
  229. if (rdev->asic->copy.blit)
  230. radeon_do_test_moves(rdev, RADEON_TEST_COPY_BLIT);
  231. }
  232. static int radeon_test_create_and_emit_fence(struct radeon_device *rdev,
  233. struct radeon_ring *ring,
  234. struct radeon_fence **fence)
  235. {
  236. uint32_t handle = ring->idx ^ 0xdeafbeef;
  237. int r;
  238. if (ring->idx == R600_RING_TYPE_UVD_INDEX) {
  239. r = radeon_uvd_get_create_msg(rdev, ring->idx, handle, NULL);
  240. if (r) {
  241. DRM_ERROR("Failed to get dummy create msg\n");
  242. return r;
  243. }
  244. r = radeon_uvd_get_destroy_msg(rdev, ring->idx, handle, fence);
  245. if (r) {
  246. DRM_ERROR("Failed to get dummy destroy msg\n");
  247. return r;
  248. }
  249. } else if (ring->idx == TN_RING_TYPE_VCE1_INDEX ||
  250. ring->idx == TN_RING_TYPE_VCE2_INDEX) {
  251. r = radeon_vce_get_create_msg(rdev, ring->idx, handle, NULL);
  252. if (r) {
  253. DRM_ERROR("Failed to get dummy create msg\n");
  254. return r;
  255. }
  256. r = radeon_vce_get_destroy_msg(rdev, ring->idx, handle, fence);
  257. if (r) {
  258. DRM_ERROR("Failed to get dummy destroy msg\n");
  259. return r;
  260. }
  261. } else {
  262. r = radeon_ring_lock(rdev, ring, 64);
  263. if (r) {
  264. DRM_ERROR("Failed to lock ring A %d\n", ring->idx);
  265. return r;
  266. }
  267. r = radeon_fence_emit(rdev, fence, ring->idx);
  268. if (r) {
  269. DRM_ERROR("Failed to emit fence\n");
  270. radeon_ring_unlock_undo(rdev, ring);
  271. return r;
  272. }
  273. radeon_ring_unlock_commit(rdev, ring, false);
  274. }
  275. return 0;
  276. }
  277. void radeon_test_ring_sync(struct radeon_device *rdev,
  278. struct radeon_ring *ringA,
  279. struct radeon_ring *ringB)
  280. {
  281. struct radeon_fence *fence1 = NULL, *fence2 = NULL;
  282. struct radeon_semaphore *semaphore = NULL;
  283. int r;
  284. r = radeon_semaphore_create(rdev, &semaphore);
  285. if (r) {
  286. DRM_ERROR("Failed to create semaphore\n");
  287. goto out_cleanup;
  288. }
  289. r = radeon_ring_lock(rdev, ringA, 64);
  290. if (r) {
  291. DRM_ERROR("Failed to lock ring A %d\n", ringA->idx);
  292. goto out_cleanup;
  293. }
  294. radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
  295. radeon_ring_unlock_commit(rdev, ringA, false);
  296. r = radeon_test_create_and_emit_fence(rdev, ringA, &fence1);
  297. if (r)
  298. goto out_cleanup;
  299. r = radeon_ring_lock(rdev, ringA, 64);
  300. if (r) {
  301. DRM_ERROR("Failed to lock ring A %d\n", ringA->idx);
  302. goto out_cleanup;
  303. }
  304. radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
  305. radeon_ring_unlock_commit(rdev, ringA, false);
  306. r = radeon_test_create_and_emit_fence(rdev, ringA, &fence2);
  307. if (r)
  308. goto out_cleanup;
  309. mdelay(1000);
  310. if (radeon_fence_signaled(fence1)) {
  311. DRM_ERROR("Fence 1 signaled without waiting for semaphore.\n");
  312. goto out_cleanup;
  313. }
  314. r = radeon_ring_lock(rdev, ringB, 64);
  315. if (r) {
  316. DRM_ERROR("Failed to lock ring B %p\n", ringB);
  317. goto out_cleanup;
  318. }
  319. radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore);
  320. radeon_ring_unlock_commit(rdev, ringB, false);
  321. r = radeon_fence_wait(fence1, false);
  322. if (r) {
  323. DRM_ERROR("Failed to wait for sync fence 1\n");
  324. goto out_cleanup;
  325. }
  326. mdelay(1000);
  327. if (radeon_fence_signaled(fence2)) {
  328. DRM_ERROR("Fence 2 signaled without waiting for semaphore.\n");
  329. goto out_cleanup;
  330. }
  331. r = radeon_ring_lock(rdev, ringB, 64);
  332. if (r) {
  333. DRM_ERROR("Failed to lock ring B %p\n", ringB);
  334. goto out_cleanup;
  335. }
  336. radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore);
  337. radeon_ring_unlock_commit(rdev, ringB, false);
  338. r = radeon_fence_wait(fence2, false);
  339. if (r) {
  340. DRM_ERROR("Failed to wait for sync fence 1\n");
  341. goto out_cleanup;
  342. }
  343. out_cleanup:
  344. radeon_semaphore_free(rdev, &semaphore, NULL);
  345. if (fence1)
  346. radeon_fence_unref(&fence1);
  347. if (fence2)
  348. radeon_fence_unref(&fence2);
  349. if (r)
  350. pr_warn("Error while testing ring sync (%d)\n", r);
  351. }
  352. static void radeon_test_ring_sync2(struct radeon_device *rdev,
  353. struct radeon_ring *ringA,
  354. struct radeon_ring *ringB,
  355. struct radeon_ring *ringC)
  356. {
  357. struct radeon_fence *fenceA = NULL, *fenceB = NULL;
  358. struct radeon_semaphore *semaphore = NULL;
  359. bool sigA, sigB;
  360. int i, r;
  361. r = radeon_semaphore_create(rdev, &semaphore);
  362. if (r) {
  363. DRM_ERROR("Failed to create semaphore\n");
  364. goto out_cleanup;
  365. }
  366. r = radeon_ring_lock(rdev, ringA, 64);
  367. if (r) {
  368. DRM_ERROR("Failed to lock ring A %d\n", ringA->idx);
  369. goto out_cleanup;
  370. }
  371. radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
  372. radeon_ring_unlock_commit(rdev, ringA, false);
  373. r = radeon_test_create_and_emit_fence(rdev, ringA, &fenceA);
  374. if (r)
  375. goto out_cleanup;
  376. r = radeon_ring_lock(rdev, ringB, 64);
  377. if (r) {
  378. DRM_ERROR("Failed to lock ring B %d\n", ringB->idx);
  379. goto out_cleanup;
  380. }
  381. radeon_semaphore_emit_wait(rdev, ringB->idx, semaphore);
  382. radeon_ring_unlock_commit(rdev, ringB, false);
  383. r = radeon_test_create_and_emit_fence(rdev, ringB, &fenceB);
  384. if (r)
  385. goto out_cleanup;
  386. mdelay(1000);
  387. if (radeon_fence_signaled(fenceA)) {
  388. DRM_ERROR("Fence A signaled without waiting for semaphore.\n");
  389. goto out_cleanup;
  390. }
  391. if (radeon_fence_signaled(fenceB)) {
  392. DRM_ERROR("Fence B signaled without waiting for semaphore.\n");
  393. goto out_cleanup;
  394. }
  395. r = radeon_ring_lock(rdev, ringC, 64);
  396. if (r) {
  397. DRM_ERROR("Failed to lock ring B %p\n", ringC);
  398. goto out_cleanup;
  399. }
  400. radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore);
  401. radeon_ring_unlock_commit(rdev, ringC, false);
  402. for (i = 0; i < 30; ++i) {
  403. mdelay(100);
  404. sigA = radeon_fence_signaled(fenceA);
  405. sigB = radeon_fence_signaled(fenceB);
  406. if (sigA || sigB)
  407. break;
  408. }
  409. if (!sigA && !sigB) {
  410. DRM_ERROR("Neither fence A nor B has been signaled\n");
  411. goto out_cleanup;
  412. } else if (sigA && sigB) {
  413. DRM_ERROR("Both fence A and B has been signaled\n");
  414. goto out_cleanup;
  415. }
  416. DRM_INFO("Fence %c was first signaled\n", sigA ? 'A' : 'B');
  417. r = radeon_ring_lock(rdev, ringC, 64);
  418. if (r) {
  419. DRM_ERROR("Failed to lock ring B %p\n", ringC);
  420. goto out_cleanup;
  421. }
  422. radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore);
  423. radeon_ring_unlock_commit(rdev, ringC, false);
  424. mdelay(1000);
  425. r = radeon_fence_wait(fenceA, false);
  426. if (r) {
  427. DRM_ERROR("Failed to wait for sync fence A\n");
  428. goto out_cleanup;
  429. }
  430. r = radeon_fence_wait(fenceB, false);
  431. if (r) {
  432. DRM_ERROR("Failed to wait for sync fence B\n");
  433. goto out_cleanup;
  434. }
  435. out_cleanup:
  436. radeon_semaphore_free(rdev, &semaphore, NULL);
  437. if (fenceA)
  438. radeon_fence_unref(&fenceA);
  439. if (fenceB)
  440. radeon_fence_unref(&fenceB);
  441. if (r)
  442. pr_warn("Error while testing ring sync (%d)\n", r);
  443. }
  444. static bool radeon_test_sync_possible(struct radeon_ring *ringA,
  445. struct radeon_ring *ringB)
  446. {
  447. if (ringA->idx == TN_RING_TYPE_VCE2_INDEX &&
  448. ringB->idx == TN_RING_TYPE_VCE1_INDEX)
  449. return false;
  450. return true;
  451. }
  452. void radeon_test_syncing(struct radeon_device *rdev)
  453. {
  454. int i, j, k;
  455. for (i = 1; i < RADEON_NUM_RINGS; ++i) {
  456. struct radeon_ring *ringA = &rdev->ring[i];
  457. if (!ringA->ready)
  458. continue;
  459. for (j = 0; j < i; ++j) {
  460. struct radeon_ring *ringB = &rdev->ring[j];
  461. if (!ringB->ready)
  462. continue;
  463. if (!radeon_test_sync_possible(ringA, ringB))
  464. continue;
  465. DRM_INFO("Testing syncing between rings %d and %d...\n", i, j);
  466. radeon_test_ring_sync(rdev, ringA, ringB);
  467. DRM_INFO("Testing syncing between rings %d and %d...\n", j, i);
  468. radeon_test_ring_sync(rdev, ringB, ringA);
  469. for (k = 0; k < j; ++k) {
  470. struct radeon_ring *ringC = &rdev->ring[k];
  471. if (!ringC->ready)
  472. continue;
  473. if (!radeon_test_sync_possible(ringA, ringC))
  474. continue;
  475. if (!radeon_test_sync_possible(ringB, ringC))
  476. continue;
  477. DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, j, k);
  478. radeon_test_ring_sync2(rdev, ringA, ringB, ringC);
  479. DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, k, j);
  480. radeon_test_ring_sync2(rdev, ringA, ringC, ringB);
  481. DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, i, k);
  482. radeon_test_ring_sync2(rdev, ringB, ringA, ringC);
  483. DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, k, i);
  484. radeon_test_ring_sync2(rdev, ringB, ringC, ringA);
  485. DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, i, j);
  486. radeon_test_ring_sync2(rdev, ringC, ringA, ringB);
  487. DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, j, i);
  488. radeon_test_ring_sync2(rdev, ringC, ringB, ringA);
  489. }
  490. }
  491. }
  492. }