1 // SPDX-License-Identifier: GPL-2.0 AND MIT 2 /* 3 * Copyright © 2023 Intel Corporation 4 */ 5 #include <drm/ttm/ttm_resource.h> 6 7 #include "ttm_kunit_helpers.h" 8 9 #define RES_SIZE SZ_4K 10 #define TTM_PRIV_DUMMY_REG (TTM_NUM_MEM_TYPES - 1) 11 12 struct ttm_resource_test_case { 13 const char *description; 14 u32 mem_type; 15 u32 flags; 16 }; 17 18 struct ttm_resource_test_priv { 19 struct ttm_test_devices *devs; 20 struct ttm_buffer_object *bo; 21 struct ttm_place *place; 22 }; 23 24 static const struct ttm_resource_manager_func ttm_resource_manager_mock_funcs = { }; 25 26 static 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 41 static 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 48 static 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 61 static 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 80 static 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 100 static 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 105 KUNIT_ARRAY_PARAM(ttm_resource, ttm_resource_cases, ttm_resource_case_desc); 106 107 static 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 151 static 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->unevictable)); 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->unevictable)); 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->unevictable)); 179 } 180 181 static 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 205 static 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 int i; 211 212 man = kunit_kzalloc(test, sizeof(*man), GFP_KERNEL); 213 KUNIT_ASSERT_NOT_NULL(test, man); 214 215 ttm_resource_manager_init(man, priv->devs->ttm_dev, size); 216 217 KUNIT_ASSERT_PTR_EQ(test, man->bdev, priv->devs->ttm_dev); 218 KUNIT_ASSERT_EQ(test, man->size, size); 219 KUNIT_ASSERT_EQ(test, man->usage, 0); 220 for (i = 0; i < TTM_NUM_MOVE_FENCES; i++) 221 KUNIT_ASSERT_NULL(test, man->eviction_fences[i]); 222 223 for (int i = 0; i < TTM_MAX_BO_PRIORITY; ++i) 224 KUNIT_ASSERT_TRUE(test, list_empty(&man->lru[i])); 225 } 226 227 static void ttm_resource_manager_usage_basic(struct kunit *test) 228 { 229 struct ttm_resource_test_priv *priv = test->priv; 230 struct ttm_resource *res; 231 struct ttm_buffer_object *bo; 232 struct ttm_place *place; 233 struct ttm_resource_manager *man; 234 u64 actual_usage; 235 236 ttm_init_test_mocks(test, priv, TTM_PL_SYSTEM, TTM_PL_FLAG_TOPDOWN); 237 bo = priv->bo; 238 place = priv->place; 239 240 res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL); 241 KUNIT_ASSERT_NOT_NULL(test, res); 242 243 man = ttm_manager_type(priv->devs->ttm_dev, place->mem_type); 244 245 ttm_resource_init(bo, place, res); 246 actual_usage = ttm_resource_manager_usage(man); 247 248 KUNIT_ASSERT_EQ(test, actual_usage, RES_SIZE); 249 250 ttm_resource_fini(man, res); 251 } 252 253 static void ttm_resource_manager_set_used_basic(struct kunit *test) 254 { 255 struct ttm_resource_test_priv *priv = test->priv; 256 struct ttm_resource_manager *man; 257 258 man = ttm_manager_type(priv->devs->ttm_dev, TTM_PL_SYSTEM); 259 KUNIT_ASSERT_TRUE(test, man->use_type); 260 261 ttm_resource_manager_set_used(man, false); 262 KUNIT_ASSERT_FALSE(test, man->use_type); 263 } 264 265 static void ttm_sys_man_alloc_basic(struct kunit *test) 266 { 267 struct ttm_resource_test_priv *priv = test->priv; 268 struct ttm_resource_manager *man; 269 struct ttm_buffer_object *bo; 270 struct ttm_place *place; 271 struct ttm_resource *res; 272 u32 mem_type = TTM_PL_SYSTEM; 273 int ret; 274 275 ttm_init_test_mocks(test, priv, mem_type, 0); 276 bo = priv->bo; 277 place = priv->place; 278 279 man = ttm_manager_type(priv->devs->ttm_dev, mem_type); 280 ret = man->func->alloc(man, bo, place, &res); 281 282 KUNIT_ASSERT_EQ(test, ret, 0); 283 KUNIT_ASSERT_EQ(test, res->size, RES_SIZE); 284 KUNIT_ASSERT_EQ(test, res->mem_type, mem_type); 285 KUNIT_ASSERT_PTR_EQ(test, res->bo, bo); 286 287 ttm_resource_fini(man, res); 288 } 289 290 static void ttm_sys_man_free_basic(struct kunit *test) 291 { 292 struct ttm_resource_test_priv *priv = test->priv; 293 struct ttm_resource_manager *man; 294 struct ttm_buffer_object *bo; 295 struct ttm_place *place; 296 struct ttm_resource *res; 297 u32 mem_type = TTM_PL_SYSTEM; 298 299 ttm_init_test_mocks(test, priv, mem_type, 0); 300 bo = priv->bo; 301 place = priv->place; 302 303 res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL); 304 KUNIT_ASSERT_NOT_NULL(test, res); 305 306 ttm_resource_alloc(bo, place, &res, NULL); 307 308 man = ttm_manager_type(priv->devs->ttm_dev, mem_type); 309 man->func->free(man, res); 310 311 KUNIT_ASSERT_TRUE(test, list_empty(&man->lru[bo->priority])); 312 KUNIT_ASSERT_EQ(test, man->usage, 0); 313 } 314 315 static struct kunit_case ttm_resource_test_cases[] = { 316 KUNIT_CASE_PARAM(ttm_resource_init_basic, ttm_resource_gen_params), 317 KUNIT_CASE(ttm_resource_init_pinned), 318 KUNIT_CASE(ttm_resource_fini_basic), 319 KUNIT_CASE(ttm_resource_manager_init_basic), 320 KUNIT_CASE(ttm_resource_manager_usage_basic), 321 KUNIT_CASE(ttm_resource_manager_set_used_basic), 322 KUNIT_CASE(ttm_sys_man_alloc_basic), 323 KUNIT_CASE(ttm_sys_man_free_basic), 324 {} 325 }; 326 327 static struct kunit_suite ttm_resource_test_suite = { 328 .name = "ttm_resource", 329 .init = ttm_resource_test_init, 330 .exit = ttm_resource_test_fini, 331 .test_cases = ttm_resource_test_cases, 332 }; 333 334 kunit_test_suites(&ttm_resource_test_suite); 335 336 MODULE_DESCRIPTION("KUnit tests for ttm_resource and ttm_sys_man APIs"); 337 MODULE_LICENSE("GPL and additional rights"); 338