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