ttm_resource_test.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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->pinned));
  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->pinned));
  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->pinned));
  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. man = kunit_kzalloc(test, sizeof(*man), GFP_KERNEL);
  164. KUNIT_ASSERT_NOT_NULL(test, man);
  165. ttm_resource_manager_init(man, priv->devs->ttm_dev, size);
  166. KUNIT_ASSERT_PTR_EQ(test, man->bdev, priv->devs->ttm_dev);
  167. KUNIT_ASSERT_EQ(test, man->size, size);
  168. KUNIT_ASSERT_EQ(test, man->usage, 0);
  169. KUNIT_ASSERT_NULL(test, man->move);
  170. KUNIT_ASSERT_NOT_NULL(test, &man->move_lock);
  171. for (int i = 0; i < TTM_MAX_BO_PRIORITY; ++i)
  172. KUNIT_ASSERT_TRUE(test, list_empty(&man->lru[i]));
  173. }
  174. static void ttm_resource_manager_usage_basic(struct kunit *test)
  175. {
  176. struct ttm_resource_test_priv *priv = test->priv;
  177. struct ttm_resource *res;
  178. struct ttm_buffer_object *bo;
  179. struct ttm_place *place;
  180. struct ttm_resource_manager *man;
  181. u64 actual_usage;
  182. ttm_init_test_mocks(test, priv, TTM_PL_SYSTEM, TTM_PL_FLAG_TOPDOWN);
  183. bo = priv->bo;
  184. place = priv->place;
  185. res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL);
  186. KUNIT_ASSERT_NOT_NULL(test, res);
  187. man = ttm_manager_type(priv->devs->ttm_dev, place->mem_type);
  188. ttm_resource_init(bo, place, res);
  189. actual_usage = ttm_resource_manager_usage(man);
  190. KUNIT_ASSERT_EQ(test, actual_usage, RES_SIZE);
  191. ttm_resource_fini(man, res);
  192. }
  193. static void ttm_resource_manager_set_used_basic(struct kunit *test)
  194. {
  195. struct ttm_resource_test_priv *priv = test->priv;
  196. struct ttm_resource_manager *man;
  197. man = ttm_manager_type(priv->devs->ttm_dev, TTM_PL_SYSTEM);
  198. KUNIT_ASSERT_TRUE(test, man->use_type);
  199. ttm_resource_manager_set_used(man, false);
  200. KUNIT_ASSERT_FALSE(test, man->use_type);
  201. }
  202. static void ttm_sys_man_alloc_basic(struct kunit *test)
  203. {
  204. struct ttm_resource_test_priv *priv = test->priv;
  205. struct ttm_resource_manager *man;
  206. struct ttm_buffer_object *bo;
  207. struct ttm_place *place;
  208. struct ttm_resource *res;
  209. u32 mem_type = TTM_PL_SYSTEM;
  210. int ret;
  211. ttm_init_test_mocks(test, priv, mem_type, 0);
  212. bo = priv->bo;
  213. place = priv->place;
  214. man = ttm_manager_type(priv->devs->ttm_dev, mem_type);
  215. ret = man->func->alloc(man, bo, place, &res);
  216. KUNIT_ASSERT_EQ(test, ret, 0);
  217. KUNIT_ASSERT_EQ(test, res->size, RES_SIZE);
  218. KUNIT_ASSERT_EQ(test, res->mem_type, mem_type);
  219. KUNIT_ASSERT_PTR_EQ(test, res->bo, bo);
  220. ttm_resource_fini(man, res);
  221. }
  222. static void ttm_sys_man_free_basic(struct kunit *test)
  223. {
  224. struct ttm_resource_test_priv *priv = test->priv;
  225. struct ttm_resource_manager *man;
  226. struct ttm_buffer_object *bo;
  227. struct ttm_place *place;
  228. struct ttm_resource *res;
  229. u32 mem_type = TTM_PL_SYSTEM;
  230. ttm_init_test_mocks(test, priv, mem_type, 0);
  231. bo = priv->bo;
  232. place = priv->place;
  233. res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL);
  234. KUNIT_ASSERT_NOT_NULL(test, res);
  235. ttm_resource_alloc(bo, place, &res);
  236. man = ttm_manager_type(priv->devs->ttm_dev, mem_type);
  237. man->func->free(man, res);
  238. KUNIT_ASSERT_TRUE(test, list_empty(&man->lru[bo->priority]));
  239. KUNIT_ASSERT_EQ(test, man->usage, 0);
  240. }
  241. static struct kunit_case ttm_resource_test_cases[] = {
  242. KUNIT_CASE_PARAM(ttm_resource_init_basic, ttm_resource_gen_params),
  243. KUNIT_CASE(ttm_resource_init_pinned),
  244. KUNIT_CASE(ttm_resource_fini_basic),
  245. KUNIT_CASE(ttm_resource_manager_init_basic),
  246. KUNIT_CASE(ttm_resource_manager_usage_basic),
  247. KUNIT_CASE(ttm_resource_manager_set_used_basic),
  248. KUNIT_CASE(ttm_sys_man_alloc_basic),
  249. KUNIT_CASE(ttm_sys_man_free_basic),
  250. {}
  251. };
  252. static struct kunit_suite ttm_resource_test_suite = {
  253. .name = "ttm_resource",
  254. .init = ttm_resource_test_init,
  255. .exit = ttm_resource_test_fini,
  256. .test_cases = ttm_resource_test_cases,
  257. };
  258. kunit_test_suites(&ttm_resource_test_suite);
  259. MODULE_DESCRIPTION("KUnit tests for ttm_resource and ttm_sys_man APIs");
  260. MODULE_LICENSE("GPL and additional rights");