ttm_resource_test.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. // SPDX-License-Identifier: GPL-2.0 AND MIT
  2. /*
  3. * Copyright © 2023 Intel Corporation
  4. */
  5. #include <drm/ttm/ttm_resource.h>
  6. #include "ttm_kunit_helpers.h"
  7. #define RES_SIZE SZ_4K
  8. #define TTM_PRIV_DUMMY_REG (TTM_NUM_MEM_TYPES - 1)
  9. struct ttm_resource_test_case {
  10. const char *description;
  11. u32 mem_type;
  12. u32 flags;
  13. };
  14. struct ttm_resource_test_priv {
  15. struct ttm_test_devices *devs;
  16. struct ttm_buffer_object *bo;
  17. struct ttm_place *place;
  18. };
  19. static const struct ttm_resource_manager_func ttm_resource_manager_mock_funcs = { };
  20. static int ttm_resource_test_init(struct kunit *test)
  21. {
  22. struct ttm_resource_test_priv *priv;
  23. priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
  24. KUNIT_ASSERT_NOT_NULL(test, priv);
  25. priv->devs = ttm_test_devices_all(test);
  26. KUNIT_ASSERT_NOT_NULL(test, priv->devs);
  27. test->priv = priv;
  28. return 0;
  29. }
  30. static void ttm_resource_test_fini(struct kunit *test)
  31. {
  32. struct ttm_resource_test_priv *priv = test->priv;
  33. ttm_test_devices_put(test, priv->devs);
  34. }
  35. static void ttm_init_test_mocks(struct kunit *test,
  36. struct ttm_resource_test_priv *priv,
  37. u32 mem_type, u32 flags)
  38. {
  39. size_t size = RES_SIZE;
  40. /* Make sure we have what we need for a good BO mock */
  41. KUNIT_ASSERT_NOT_NULL(test, priv->devs->ttm_dev);
  42. priv->bo = ttm_bo_kunit_init(test, priv->devs, size, NULL);
  43. priv->place = ttm_place_kunit_init(test, mem_type, flags);
  44. }
  45. static void ttm_init_test_manager(struct kunit *test,
  46. struct ttm_resource_test_priv *priv,
  47. u32 mem_type)
  48. {
  49. struct ttm_device *ttm_dev = priv->devs->ttm_dev;
  50. struct ttm_resource_manager *man;
  51. size_t size = SZ_16K;
  52. man = kunit_kzalloc(test, sizeof(*man), GFP_KERNEL);
  53. KUNIT_ASSERT_NOT_NULL(test, man);
  54. man->use_tt = false;
  55. man->func = &ttm_resource_manager_mock_funcs;
  56. ttm_resource_manager_init(man, ttm_dev, size);
  57. ttm_set_driver_manager(ttm_dev, mem_type, man);
  58. ttm_resource_manager_set_used(man, true);
  59. }
  60. static const struct ttm_resource_test_case ttm_resource_cases[] = {
  61. {
  62. .description = "Init resource in TTM_PL_SYSTEM",
  63. .mem_type = TTM_PL_SYSTEM,
  64. },
  65. {
  66. .description = "Init resource in TTM_PL_VRAM",
  67. .mem_type = TTM_PL_VRAM,
  68. },
  69. {
  70. .description = "Init resource in a private placement",
  71. .mem_type = TTM_PRIV_DUMMY_REG,
  72. },
  73. {
  74. .description = "Init resource in TTM_PL_SYSTEM, set placement flags",
  75. .mem_type = TTM_PL_SYSTEM,
  76. .flags = TTM_PL_FLAG_TOPDOWN,
  77. },
  78. };
  79. static void ttm_resource_case_desc(const struct ttm_resource_test_case *t, char *desc)
  80. {
  81. strscpy(desc, t->description, KUNIT_PARAM_DESC_SIZE);
  82. }
  83. KUNIT_ARRAY_PARAM(ttm_resource, ttm_resource_cases, ttm_resource_case_desc);
  84. static void ttm_resource_init_basic(struct kunit *test)
  85. {
  86. const struct ttm_resource_test_case *params = test->param_value;
  87. struct ttm_resource_test_priv *priv = test->priv;
  88. struct ttm_resource *res;
  89. struct ttm_buffer_object *bo;
  90. struct ttm_place *place;
  91. struct ttm_resource_manager *man;
  92. u64 expected_usage;
  93. ttm_init_test_mocks(test, priv, params->mem_type, params->flags);
  94. bo = priv->bo;
  95. place = priv->place;
  96. if (params->mem_type > TTM_PL_SYSTEM)
  97. ttm_init_test_manager(test, priv, params->mem_type);
  98. res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL);
  99. KUNIT_ASSERT_NOT_NULL(test, res);
  100. man = ttm_manager_type(priv->devs->ttm_dev, place->mem_type);
  101. expected_usage = man->usage + RES_SIZE;
  102. KUNIT_ASSERT_TRUE(test, list_empty(&man->lru[bo->priority]));
  103. ttm_resource_init(bo, place, res);
  104. KUNIT_ASSERT_EQ(test, res->start, 0);
  105. KUNIT_ASSERT_EQ(test, res->size, RES_SIZE);
  106. KUNIT_ASSERT_EQ(test, res->mem_type, place->mem_type);
  107. KUNIT_ASSERT_EQ(test, res->placement, place->flags);
  108. KUNIT_ASSERT_PTR_EQ(test, res->bo, bo);
  109. KUNIT_ASSERT_NULL(test, res->bus.addr);
  110. KUNIT_ASSERT_EQ(test, res->bus.offset, 0);
  111. KUNIT_ASSERT_FALSE(test, res->bus.is_iomem);
  112. KUNIT_ASSERT_EQ(test, res->bus.caching, ttm_cached);
  113. KUNIT_ASSERT_EQ(test, man->usage, expected_usage);
  114. KUNIT_ASSERT_TRUE(test, list_is_singular(&man->lru[bo->priority]));
  115. ttm_resource_fini(man, res);
  116. }
  117. static void ttm_resource_init_pinned(struct kunit *test)
  118. {
  119. struct ttm_resource_test_priv *priv = test->priv;
  120. struct ttm_resource *res;
  121. struct ttm_buffer_object *bo;
  122. struct ttm_place *place;
  123. struct ttm_resource_manager *man;
  124. ttm_init_test_mocks(test, priv, TTM_PL_SYSTEM, 0);
  125. bo = priv->bo;
  126. place = priv->place;
  127. man = ttm_manager_type(priv->devs->ttm_dev, place->mem_type);
  128. res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL);
  129. KUNIT_ASSERT_NOT_NULL(test, res);
  130. KUNIT_ASSERT_TRUE(test, list_empty(&bo->bdev->unevictable));
  131. dma_resv_lock(bo->base.resv, NULL);
  132. ttm_bo_pin(bo);
  133. ttm_resource_init(bo, place, res);
  134. KUNIT_ASSERT_TRUE(test, list_is_singular(&bo->bdev->unevictable));
  135. ttm_bo_unpin(bo);
  136. ttm_resource_fini(man, res);
  137. dma_resv_unlock(bo->base.resv);
  138. KUNIT_ASSERT_TRUE(test, list_empty(&bo->bdev->unevictable));
  139. }
  140. static void ttm_resource_fini_basic(struct kunit *test)
  141. {
  142. struct ttm_resource_test_priv *priv = test->priv;
  143. struct ttm_resource *res;
  144. struct ttm_buffer_object *bo;
  145. struct ttm_place *place;
  146. struct ttm_resource_manager *man;
  147. ttm_init_test_mocks(test, priv, TTM_PL_SYSTEM, 0);
  148. bo = priv->bo;
  149. place = priv->place;
  150. man = ttm_manager_type(priv->devs->ttm_dev, place->mem_type);
  151. res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL);
  152. KUNIT_ASSERT_NOT_NULL(test, res);
  153. ttm_resource_init(bo, place, res);
  154. ttm_resource_fini(man, res);
  155. KUNIT_ASSERT_TRUE(test, list_empty(&res->lru.link));
  156. KUNIT_ASSERT_EQ(test, man->usage, 0);
  157. }
  158. static void ttm_resource_manager_init_basic(struct kunit *test)
  159. {
  160. struct ttm_resource_test_priv *priv = test->priv;
  161. struct ttm_resource_manager *man;
  162. size_t size = SZ_16K;
  163. int i;
  164. man = kunit_kzalloc(test, sizeof(*man), GFP_KERNEL);
  165. KUNIT_ASSERT_NOT_NULL(test, man);
  166. ttm_resource_manager_init(man, priv->devs->ttm_dev, size);
  167. KUNIT_ASSERT_PTR_EQ(test, man->bdev, priv->devs->ttm_dev);
  168. KUNIT_ASSERT_EQ(test, man->size, size);
  169. KUNIT_ASSERT_EQ(test, man->usage, 0);
  170. for (i = 0; i < TTM_NUM_MOVE_FENCES; i++)
  171. KUNIT_ASSERT_NULL(test, man->eviction_fences[i]);
  172. for (int i = 0; i < TTM_MAX_BO_PRIORITY; ++i)
  173. KUNIT_ASSERT_TRUE(test, list_empty(&man->lru[i]));
  174. }
  175. static void ttm_resource_manager_usage_basic(struct kunit *test)
  176. {
  177. struct ttm_resource_test_priv *priv = test->priv;
  178. struct ttm_resource *res;
  179. struct ttm_buffer_object *bo;
  180. struct ttm_place *place;
  181. struct ttm_resource_manager *man;
  182. u64 actual_usage;
  183. ttm_init_test_mocks(test, priv, TTM_PL_SYSTEM, TTM_PL_FLAG_TOPDOWN);
  184. bo = priv->bo;
  185. place = priv->place;
  186. res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL);
  187. KUNIT_ASSERT_NOT_NULL(test, res);
  188. man = ttm_manager_type(priv->devs->ttm_dev, place->mem_type);
  189. ttm_resource_init(bo, place, res);
  190. actual_usage = ttm_resource_manager_usage(man);
  191. KUNIT_ASSERT_EQ(test, actual_usage, RES_SIZE);
  192. ttm_resource_fini(man, res);
  193. }
  194. static void ttm_resource_manager_set_used_basic(struct kunit *test)
  195. {
  196. struct ttm_resource_test_priv *priv = test->priv;
  197. struct ttm_resource_manager *man;
  198. man = ttm_manager_type(priv->devs->ttm_dev, TTM_PL_SYSTEM);
  199. KUNIT_ASSERT_TRUE(test, man->use_type);
  200. ttm_resource_manager_set_used(man, false);
  201. KUNIT_ASSERT_FALSE(test, man->use_type);
  202. }
  203. static void ttm_sys_man_alloc_basic(struct kunit *test)
  204. {
  205. struct ttm_resource_test_priv *priv = test->priv;
  206. struct ttm_resource_manager *man;
  207. struct ttm_buffer_object *bo;
  208. struct ttm_place *place;
  209. struct ttm_resource *res;
  210. u32 mem_type = TTM_PL_SYSTEM;
  211. int ret;
  212. ttm_init_test_mocks(test, priv, mem_type, 0);
  213. bo = priv->bo;
  214. place = priv->place;
  215. man = ttm_manager_type(priv->devs->ttm_dev, mem_type);
  216. ret = man->func->alloc(man, bo, place, &res);
  217. KUNIT_ASSERT_EQ(test, ret, 0);
  218. KUNIT_ASSERT_EQ(test, res->size, RES_SIZE);
  219. KUNIT_ASSERT_EQ(test, res->mem_type, mem_type);
  220. KUNIT_ASSERT_PTR_EQ(test, res->bo, bo);
  221. ttm_resource_fini(man, res);
  222. }
  223. static void ttm_sys_man_free_basic(struct kunit *test)
  224. {
  225. struct ttm_resource_test_priv *priv = test->priv;
  226. struct ttm_resource_manager *man;
  227. struct ttm_buffer_object *bo;
  228. struct ttm_place *place;
  229. struct ttm_resource *res;
  230. u32 mem_type = TTM_PL_SYSTEM;
  231. ttm_init_test_mocks(test, priv, mem_type, 0);
  232. bo = priv->bo;
  233. place = priv->place;
  234. res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL);
  235. KUNIT_ASSERT_NOT_NULL(test, res);
  236. ttm_resource_alloc(bo, place, &res, NULL);
  237. man = ttm_manager_type(priv->devs->ttm_dev, mem_type);
  238. man->func->free(man, res);
  239. KUNIT_ASSERT_TRUE(test, list_empty(&man->lru[bo->priority]));
  240. KUNIT_ASSERT_EQ(test, man->usage, 0);
  241. }
  242. static struct kunit_case ttm_resource_test_cases[] = {
  243. KUNIT_CASE_PARAM(ttm_resource_init_basic, ttm_resource_gen_params),
  244. KUNIT_CASE(ttm_resource_init_pinned),
  245. KUNIT_CASE(ttm_resource_fini_basic),
  246. KUNIT_CASE(ttm_resource_manager_init_basic),
  247. KUNIT_CASE(ttm_resource_manager_usage_basic),
  248. KUNIT_CASE(ttm_resource_manager_set_used_basic),
  249. KUNIT_CASE(ttm_sys_man_alloc_basic),
  250. KUNIT_CASE(ttm_sys_man_free_basic),
  251. {}
  252. };
  253. static struct kunit_suite ttm_resource_test_suite = {
  254. .name = "ttm_resource",
  255. .init = ttm_resource_test_init,
  256. .exit = ttm_resource_test_fini,
  257. .test_cases = ttm_resource_test_cases,
  258. };
  259. kunit_test_suites(&ttm_resource_test_suite);
  260. MODULE_DESCRIPTION("KUnit tests for ttm_resource and ttm_sys_man APIs");
  261. MODULE_LICENSE("GPL and additional rights");