ttm_bo_test.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. // SPDX-License-Identifier: GPL-2.0 AND MIT
  2. /*
  3. * Copyright © 2023 Intel Corporation
  4. */
  5. #include <linux/dma-resv.h>
  6. #include <linux/kthread.h>
  7. #include <linux/delay.h>
  8. #include <linux/timer.h>
  9. #include <linux/jiffies.h>
  10. #include <linux/mutex.h>
  11. #include <linux/ww_mutex.h>
  12. #include <drm/ttm/ttm_resource.h>
  13. #include <drm/ttm/ttm_placement.h>
  14. #include <drm/ttm/ttm_tt.h>
  15. #include "ttm_kunit_helpers.h"
  16. #define BO_SIZE SZ_8K
  17. #ifdef CONFIG_PREEMPT_RT
  18. #define ww_mutex_base_lock(b) rt_mutex_lock(b)
  19. #else
  20. #define ww_mutex_base_lock(b) mutex_lock(b)
  21. #endif
  22. struct ttm_bo_test_case {
  23. const char *description;
  24. bool interruptible;
  25. bool no_wait;
  26. };
  27. static const struct ttm_bo_test_case ttm_bo_reserved_cases[] = {
  28. {
  29. .description = "Cannot be interrupted and sleeps",
  30. .interruptible = false,
  31. .no_wait = false,
  32. },
  33. {
  34. .description = "Cannot be interrupted, locks straight away",
  35. .interruptible = false,
  36. .no_wait = true,
  37. },
  38. {
  39. .description = "Can be interrupted, sleeps",
  40. .interruptible = true,
  41. .no_wait = false,
  42. },
  43. };
  44. static void ttm_bo_init_case_desc(const struct ttm_bo_test_case *t,
  45. char *desc)
  46. {
  47. strscpy(desc, t->description, KUNIT_PARAM_DESC_SIZE);
  48. }
  49. KUNIT_ARRAY_PARAM(ttm_bo_reserve, ttm_bo_reserved_cases, ttm_bo_init_case_desc);
  50. static void ttm_bo_reserve_optimistic_no_ticket(struct kunit *test)
  51. {
  52. const struct ttm_bo_test_case *params = test->param_value;
  53. struct ttm_buffer_object *bo;
  54. int err;
  55. bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
  56. err = ttm_bo_reserve(bo, params->interruptible, params->no_wait, NULL);
  57. KUNIT_ASSERT_EQ(test, err, 0);
  58. dma_resv_unlock(bo->base.resv);
  59. }
  60. static void ttm_bo_reserve_locked_no_sleep(struct kunit *test)
  61. {
  62. struct ttm_buffer_object *bo;
  63. bool interruptible = false;
  64. bool no_wait = true;
  65. int err;
  66. bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
  67. /* Let's lock it beforehand */
  68. dma_resv_lock(bo->base.resv, NULL);
  69. err = ttm_bo_reserve(bo, interruptible, no_wait, NULL);
  70. dma_resv_unlock(bo->base.resv);
  71. KUNIT_ASSERT_EQ(test, err, -EBUSY);
  72. }
  73. static void ttm_bo_reserve_no_wait_ticket(struct kunit *test)
  74. {
  75. struct ttm_buffer_object *bo;
  76. struct ww_acquire_ctx ctx;
  77. bool interruptible = false;
  78. bool no_wait = true;
  79. int err;
  80. ww_acquire_init(&ctx, &reservation_ww_class);
  81. bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
  82. err = ttm_bo_reserve(bo, interruptible, no_wait, &ctx);
  83. KUNIT_ASSERT_EQ(test, err, -EBUSY);
  84. ww_acquire_fini(&ctx);
  85. }
  86. static void ttm_bo_reserve_double_resv(struct kunit *test)
  87. {
  88. struct ttm_buffer_object *bo;
  89. struct ww_acquire_ctx ctx;
  90. bool interruptible = false;
  91. bool no_wait = false;
  92. int err;
  93. ww_acquire_init(&ctx, &reservation_ww_class);
  94. bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
  95. err = ttm_bo_reserve(bo, interruptible, no_wait, &ctx);
  96. KUNIT_ASSERT_EQ(test, err, 0);
  97. err = ttm_bo_reserve(bo, interruptible, no_wait, &ctx);
  98. dma_resv_unlock(bo->base.resv);
  99. ww_acquire_fini(&ctx);
  100. KUNIT_ASSERT_EQ(test, err, -EALREADY);
  101. }
  102. /*
  103. * A test case heavily inspired by ww_test_edeadlk_normal(). It injects
  104. * a deadlock by manipulating the sequence number of the context that holds
  105. * dma_resv lock of bo2 so the other context is "wounded" and has to back off
  106. * (indicated by -EDEADLK). The subtest checks if ttm_bo_reserve() properly
  107. * propagates that error.
  108. */
  109. static void ttm_bo_reserve_deadlock(struct kunit *test)
  110. {
  111. struct ttm_buffer_object *bo1, *bo2;
  112. struct ww_acquire_ctx ctx1, ctx2;
  113. bool interruptible = false;
  114. bool no_wait = false;
  115. int err;
  116. bo1 = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
  117. bo2 = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
  118. ww_acquire_init(&ctx1, &reservation_ww_class);
  119. ww_mutex_base_lock(&bo2->base.resv->lock.base);
  120. /* The deadlock will be caught by WW mutex, don't warn about it */
  121. lock_release(&bo2->base.resv->lock.base.dep_map, 1);
  122. bo2->base.resv->lock.ctx = &ctx2;
  123. ctx2 = ctx1;
  124. ctx2.stamp--; /* Make the context holding the lock younger */
  125. err = ttm_bo_reserve(bo1, interruptible, no_wait, &ctx1);
  126. KUNIT_ASSERT_EQ(test, err, 0);
  127. err = ttm_bo_reserve(bo2, interruptible, no_wait, &ctx1);
  128. KUNIT_ASSERT_EQ(test, err, -EDEADLK);
  129. dma_resv_unlock(bo1->base.resv);
  130. ww_acquire_fini(&ctx1);
  131. }
  132. #if IS_BUILTIN(CONFIG_DRM_TTM_KUNIT_TEST)
  133. struct signal_timer {
  134. struct timer_list timer;
  135. struct ww_acquire_ctx *ctx;
  136. };
  137. static void signal_for_ttm_bo_reserve(struct timer_list *t)
  138. {
  139. struct signal_timer *s_timer = timer_container_of(s_timer, t, timer);
  140. struct task_struct *task = s_timer->ctx->task;
  141. do_send_sig_info(SIGTERM, SEND_SIG_PRIV, task, PIDTYPE_PID);
  142. }
  143. static int threaded_ttm_bo_reserve(void *arg)
  144. {
  145. struct ttm_buffer_object *bo = arg;
  146. struct signal_timer s_timer;
  147. struct ww_acquire_ctx ctx;
  148. bool interruptible = true;
  149. bool no_wait = false;
  150. int err;
  151. ww_acquire_init(&ctx, &reservation_ww_class);
  152. /* Prepare a signal that will interrupt the reservation attempt */
  153. timer_setup_on_stack(&s_timer.timer, &signal_for_ttm_bo_reserve, 0);
  154. s_timer.ctx = &ctx;
  155. mod_timer(&s_timer.timer, msecs_to_jiffies(100));
  156. err = ttm_bo_reserve(bo, interruptible, no_wait, &ctx);
  157. timer_delete_sync(&s_timer.timer);
  158. timer_destroy_on_stack(&s_timer.timer);
  159. ww_acquire_fini(&ctx);
  160. return err;
  161. }
  162. static void ttm_bo_reserve_interrupted(struct kunit *test)
  163. {
  164. struct ttm_buffer_object *bo;
  165. struct task_struct *task;
  166. int err;
  167. bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
  168. task = kthread_create(threaded_ttm_bo_reserve, bo, "ttm-bo-reserve");
  169. if (IS_ERR(task))
  170. KUNIT_FAIL(test, "Couldn't create ttm bo reserve task\n");
  171. /* Take a lock so the threaded reserve has to wait */
  172. dma_resv_lock(bo->base.resv, NULL);
  173. wake_up_process(task);
  174. msleep(20);
  175. err = kthread_stop(task);
  176. dma_resv_unlock(bo->base.resv);
  177. KUNIT_ASSERT_EQ(test, err, -ERESTARTSYS);
  178. }
  179. #endif /* IS_BUILTIN(CONFIG_DRM_TTM_KUNIT_TEST) */
  180. static void ttm_bo_unreserve_basic(struct kunit *test)
  181. {
  182. struct ttm_test_devices *priv = test->priv;
  183. struct ttm_buffer_object *bo;
  184. struct ttm_device *ttm_dev;
  185. struct ttm_resource *res1, *res2;
  186. struct ttm_place *place;
  187. struct ttm_resource_manager *man;
  188. unsigned int bo_prio = TTM_MAX_BO_PRIORITY - 1;
  189. u32 mem_type = TTM_PL_SYSTEM;
  190. int err;
  191. place = ttm_place_kunit_init(test, mem_type, 0);
  192. ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
  193. KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
  194. err = ttm_device_kunit_init(priv, ttm_dev, 0);
  195. KUNIT_ASSERT_EQ(test, err, 0);
  196. priv->ttm_dev = ttm_dev;
  197. bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
  198. bo->priority = bo_prio;
  199. err = ttm_resource_alloc(bo, place, &res1, NULL);
  200. KUNIT_ASSERT_EQ(test, err, 0);
  201. bo->resource = res1;
  202. /* Add a dummy resource to populate LRU */
  203. ttm_resource_alloc(bo, place, &res2, NULL);
  204. dma_resv_lock(bo->base.resv, NULL);
  205. ttm_bo_unreserve(bo);
  206. man = ttm_manager_type(priv->ttm_dev, mem_type);
  207. KUNIT_ASSERT_EQ(test,
  208. list_is_last(&res1->lru.link, &man->lru[bo->priority]), 1);
  209. ttm_resource_free(bo, &res2);
  210. ttm_resource_free(bo, &res1);
  211. }
  212. static void ttm_bo_unreserve_pinned(struct kunit *test)
  213. {
  214. struct ttm_test_devices *priv = test->priv;
  215. struct ttm_buffer_object *bo;
  216. struct ttm_device *ttm_dev;
  217. struct ttm_resource *res1, *res2;
  218. struct ttm_place *place;
  219. u32 mem_type = TTM_PL_SYSTEM;
  220. int err;
  221. ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
  222. KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
  223. err = ttm_device_kunit_init(priv, ttm_dev, 0);
  224. KUNIT_ASSERT_EQ(test, err, 0);
  225. priv->ttm_dev = ttm_dev;
  226. bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
  227. place = ttm_place_kunit_init(test, mem_type, 0);
  228. dma_resv_lock(bo->base.resv, NULL);
  229. ttm_bo_pin(bo);
  230. err = ttm_resource_alloc(bo, place, &res1, NULL);
  231. KUNIT_ASSERT_EQ(test, err, 0);
  232. bo->resource = res1;
  233. /* Add a dummy resource to the pinned list */
  234. err = ttm_resource_alloc(bo, place, &res2, NULL);
  235. KUNIT_ASSERT_EQ(test, err, 0);
  236. KUNIT_ASSERT_EQ(test,
  237. list_is_last(&res2->lru.link, &priv->ttm_dev->unevictable), 1);
  238. ttm_bo_unreserve(bo);
  239. KUNIT_ASSERT_EQ(test,
  240. list_is_last(&res1->lru.link, &priv->ttm_dev->unevictable), 1);
  241. ttm_resource_free(bo, &res1);
  242. ttm_resource_free(bo, &res2);
  243. }
  244. static void ttm_bo_unreserve_bulk(struct kunit *test)
  245. {
  246. struct ttm_test_devices *priv = test->priv;
  247. struct ttm_lru_bulk_move lru_bulk_move;
  248. struct ttm_lru_bulk_move_pos *pos;
  249. struct ttm_buffer_object *bo1, *bo2;
  250. struct ttm_resource *res1, *res2;
  251. struct ttm_device *ttm_dev;
  252. struct ttm_place *place;
  253. struct dma_resv *resv;
  254. u32 mem_type = TTM_PL_SYSTEM;
  255. unsigned int bo_priority = 0;
  256. int err;
  257. ttm_lru_bulk_move_init(&lru_bulk_move);
  258. place = ttm_place_kunit_init(test, mem_type, 0);
  259. ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
  260. KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
  261. resv = kunit_kzalloc(test, sizeof(*resv), GFP_KERNEL);
  262. KUNIT_ASSERT_NOT_NULL(test, resv);
  263. err = ttm_device_kunit_init(priv, ttm_dev, 0);
  264. KUNIT_ASSERT_EQ(test, err, 0);
  265. priv->ttm_dev = ttm_dev;
  266. dma_resv_init(resv);
  267. bo1 = ttm_bo_kunit_init(test, test->priv, BO_SIZE, resv);
  268. bo2 = ttm_bo_kunit_init(test, test->priv, BO_SIZE, resv);
  269. dma_resv_lock(bo1->base.resv, NULL);
  270. ttm_bo_set_bulk_move(bo1, &lru_bulk_move);
  271. dma_resv_unlock(bo1->base.resv);
  272. err = ttm_resource_alloc(bo1, place, &res1, NULL);
  273. KUNIT_ASSERT_EQ(test, err, 0);
  274. bo1->resource = res1;
  275. dma_resv_lock(bo2->base.resv, NULL);
  276. ttm_bo_set_bulk_move(bo2, &lru_bulk_move);
  277. dma_resv_unlock(bo2->base.resv);
  278. err = ttm_resource_alloc(bo2, place, &res2, NULL);
  279. KUNIT_ASSERT_EQ(test, err, 0);
  280. bo2->resource = res2;
  281. ttm_bo_reserve(bo1, false, false, NULL);
  282. ttm_bo_unreserve(bo1);
  283. pos = &lru_bulk_move.pos[mem_type][bo_priority];
  284. KUNIT_ASSERT_PTR_EQ(test, res1, pos->last);
  285. ttm_resource_free(bo1, &res1);
  286. ttm_resource_free(bo2, &res2);
  287. dma_resv_fini(resv);
  288. }
  289. static void ttm_bo_fini_basic(struct kunit *test)
  290. {
  291. struct ttm_test_devices *priv = test->priv;
  292. struct ttm_buffer_object *bo;
  293. struct ttm_resource *res;
  294. struct ttm_device *ttm_dev;
  295. struct ttm_place *place;
  296. u32 mem_type = TTM_PL_SYSTEM;
  297. int err;
  298. place = ttm_place_kunit_init(test, mem_type, 0);
  299. ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
  300. KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
  301. err = ttm_device_kunit_init(priv, ttm_dev, 0);
  302. KUNIT_ASSERT_EQ(test, err, 0);
  303. priv->ttm_dev = ttm_dev;
  304. bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
  305. bo->type = ttm_bo_type_device;
  306. err = ttm_resource_alloc(bo, place, &res, NULL);
  307. KUNIT_ASSERT_EQ(test, err, 0);
  308. bo->resource = res;
  309. dma_resv_lock(bo->base.resv, NULL);
  310. err = ttm_tt_create(bo, false);
  311. dma_resv_unlock(bo->base.resv);
  312. KUNIT_EXPECT_EQ(test, err, 0);
  313. ttm_bo_fini(bo);
  314. }
  315. static const char *mock_name(struct dma_fence *f)
  316. {
  317. return "kunit-ttm-bo-put";
  318. }
  319. static const struct dma_fence_ops mock_fence_ops = {
  320. .get_driver_name = mock_name,
  321. .get_timeline_name = mock_name,
  322. };
  323. static void ttm_bo_fini_shared_resv(struct kunit *test)
  324. {
  325. struct ttm_test_devices *priv = test->priv;
  326. struct ttm_buffer_object *bo;
  327. struct dma_resv *external_resv;
  328. struct dma_fence *fence;
  329. /* A dummy DMA fence lock */
  330. spinlock_t fence_lock;
  331. struct ttm_device *ttm_dev;
  332. int err;
  333. ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
  334. KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
  335. err = ttm_device_kunit_init(priv, ttm_dev, 0);
  336. KUNIT_ASSERT_EQ(test, err, 0);
  337. priv->ttm_dev = ttm_dev;
  338. external_resv = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
  339. KUNIT_ASSERT_NOT_NULL(test, external_resv);
  340. dma_resv_init(external_resv);
  341. fence = kunit_kzalloc(test, sizeof(*fence), GFP_KERNEL);
  342. KUNIT_ASSERT_NOT_NULL(test, fence);
  343. spin_lock_init(&fence_lock);
  344. dma_fence_init(fence, &mock_fence_ops, &fence_lock, 0, 0);
  345. dma_resv_lock(external_resv, NULL);
  346. dma_resv_reserve_fences(external_resv, 1);
  347. dma_resv_add_fence(external_resv, fence, DMA_RESV_USAGE_BOOKKEEP);
  348. dma_resv_unlock(external_resv);
  349. dma_fence_signal(fence);
  350. bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
  351. bo->type = ttm_bo_type_device;
  352. bo->base.resv = external_resv;
  353. ttm_bo_fini(bo);
  354. }
  355. static void ttm_bo_pin_basic(struct kunit *test)
  356. {
  357. struct ttm_test_devices *priv = test->priv;
  358. struct ttm_buffer_object *bo;
  359. struct ttm_device *ttm_dev;
  360. unsigned int no_pins = 3;
  361. int err;
  362. ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
  363. KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
  364. err = ttm_device_kunit_init(priv, ttm_dev, 0);
  365. KUNIT_ASSERT_EQ(test, err, 0);
  366. priv->ttm_dev = ttm_dev;
  367. bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
  368. for (int i = 0; i < no_pins; i++) {
  369. dma_resv_lock(bo->base.resv, NULL);
  370. ttm_bo_pin(bo);
  371. dma_resv_unlock(bo->base.resv);
  372. }
  373. KUNIT_ASSERT_EQ(test, bo->pin_count, no_pins);
  374. }
  375. static void ttm_bo_pin_unpin_resource(struct kunit *test)
  376. {
  377. struct ttm_test_devices *priv = test->priv;
  378. struct ttm_lru_bulk_move lru_bulk_move;
  379. struct ttm_lru_bulk_move_pos *pos;
  380. struct ttm_buffer_object *bo;
  381. struct ttm_resource *res;
  382. struct ttm_device *ttm_dev;
  383. struct ttm_place *place;
  384. u32 mem_type = TTM_PL_SYSTEM;
  385. unsigned int bo_priority = 0;
  386. int err;
  387. ttm_lru_bulk_move_init(&lru_bulk_move);
  388. place = ttm_place_kunit_init(test, mem_type, 0);
  389. ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
  390. KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
  391. err = ttm_device_kunit_init(priv, ttm_dev, 0);
  392. KUNIT_ASSERT_EQ(test, err, 0);
  393. priv->ttm_dev = ttm_dev;
  394. bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
  395. err = ttm_resource_alloc(bo, place, &res, NULL);
  396. KUNIT_ASSERT_EQ(test, err, 0);
  397. bo->resource = res;
  398. dma_resv_lock(bo->base.resv, NULL);
  399. ttm_bo_set_bulk_move(bo, &lru_bulk_move);
  400. ttm_bo_pin(bo);
  401. dma_resv_unlock(bo->base.resv);
  402. pos = &lru_bulk_move.pos[mem_type][bo_priority];
  403. KUNIT_ASSERT_EQ(test, bo->pin_count, 1);
  404. KUNIT_ASSERT_NULL(test, pos->first);
  405. KUNIT_ASSERT_NULL(test, pos->last);
  406. dma_resv_lock(bo->base.resv, NULL);
  407. ttm_bo_unpin(bo);
  408. dma_resv_unlock(bo->base.resv);
  409. KUNIT_ASSERT_PTR_EQ(test, res, pos->last);
  410. KUNIT_ASSERT_EQ(test, bo->pin_count, 0);
  411. ttm_resource_free(bo, &res);
  412. }
  413. static void ttm_bo_multiple_pin_one_unpin(struct kunit *test)
  414. {
  415. struct ttm_test_devices *priv = test->priv;
  416. struct ttm_lru_bulk_move lru_bulk_move;
  417. struct ttm_lru_bulk_move_pos *pos;
  418. struct ttm_buffer_object *bo;
  419. struct ttm_resource *res;
  420. struct ttm_device *ttm_dev;
  421. struct ttm_place *place;
  422. u32 mem_type = TTM_PL_SYSTEM;
  423. unsigned int bo_priority = 0;
  424. int err;
  425. ttm_lru_bulk_move_init(&lru_bulk_move);
  426. place = ttm_place_kunit_init(test, mem_type, 0);
  427. ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
  428. KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
  429. err = ttm_device_kunit_init(priv, ttm_dev, 0);
  430. KUNIT_ASSERT_EQ(test, err, 0);
  431. priv->ttm_dev = ttm_dev;
  432. bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
  433. err = ttm_resource_alloc(bo, place, &res, NULL);
  434. KUNIT_ASSERT_EQ(test, err, 0);
  435. bo->resource = res;
  436. dma_resv_lock(bo->base.resv, NULL);
  437. ttm_bo_set_bulk_move(bo, &lru_bulk_move);
  438. /* Multiple pins */
  439. ttm_bo_pin(bo);
  440. ttm_bo_pin(bo);
  441. dma_resv_unlock(bo->base.resv);
  442. pos = &lru_bulk_move.pos[mem_type][bo_priority];
  443. KUNIT_ASSERT_EQ(test, bo->pin_count, 2);
  444. KUNIT_ASSERT_NULL(test, pos->first);
  445. KUNIT_ASSERT_NULL(test, pos->last);
  446. dma_resv_lock(bo->base.resv, NULL);
  447. ttm_bo_unpin(bo);
  448. dma_resv_unlock(bo->base.resv);
  449. KUNIT_ASSERT_EQ(test, bo->pin_count, 1);
  450. KUNIT_ASSERT_NULL(test, pos->first);
  451. KUNIT_ASSERT_NULL(test, pos->last);
  452. dma_resv_lock(bo->base.resv, NULL);
  453. ttm_bo_unpin(bo);
  454. dma_resv_unlock(bo->base.resv);
  455. ttm_resource_free(bo, &res);
  456. }
  457. static struct kunit_case ttm_bo_test_cases[] = {
  458. KUNIT_CASE_PARAM(ttm_bo_reserve_optimistic_no_ticket,
  459. ttm_bo_reserve_gen_params),
  460. KUNIT_CASE(ttm_bo_reserve_locked_no_sleep),
  461. KUNIT_CASE(ttm_bo_reserve_no_wait_ticket),
  462. KUNIT_CASE(ttm_bo_reserve_double_resv),
  463. #if IS_BUILTIN(CONFIG_DRM_TTM_KUNIT_TEST)
  464. KUNIT_CASE(ttm_bo_reserve_interrupted),
  465. #endif
  466. KUNIT_CASE(ttm_bo_reserve_deadlock),
  467. KUNIT_CASE(ttm_bo_unreserve_basic),
  468. KUNIT_CASE(ttm_bo_unreserve_pinned),
  469. KUNIT_CASE(ttm_bo_unreserve_bulk),
  470. KUNIT_CASE(ttm_bo_fini_basic),
  471. KUNIT_CASE(ttm_bo_fini_shared_resv),
  472. KUNIT_CASE(ttm_bo_pin_basic),
  473. KUNIT_CASE(ttm_bo_pin_unpin_resource),
  474. KUNIT_CASE(ttm_bo_multiple_pin_one_unpin),
  475. {}
  476. };
  477. static struct kunit_suite ttm_bo_test_suite = {
  478. .name = "ttm_bo",
  479. .init = ttm_test_devices_init,
  480. .exit = ttm_test_devices_fini,
  481. .test_cases = ttm_bo_test_cases,
  482. };
  483. kunit_test_suites(&ttm_bo_test_suite);
  484. MODULE_DESCRIPTION("KUnit tests for ttm_bo APIs");
  485. MODULE_LICENSE("GPL and additional rights");