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 <drm/ttm/ttm_device.h> 7 #include <drm/ttm/ttm_placement.h> 8 9 #include "ttm_mock_manager.h" 10 11 static inline struct ttm_mock_manager * 12 to_mock_mgr(struct ttm_resource_manager *man) 13 { 14 return container_of(man, struct ttm_mock_manager, man); 15 } 16 17 static inline struct ttm_mock_resource * 18 to_mock_mgr_resource(struct ttm_resource *res) 19 { 20 return container_of(res, struct ttm_mock_resource, base); 21 } 22 23 static int ttm_mock_manager_alloc(struct ttm_resource_manager *man, 24 struct ttm_buffer_object *bo, 25 const struct ttm_place *place, 26 struct ttm_resource **res) 27 { 28 struct ttm_mock_manager *manager = to_mock_mgr(man); 29 struct ttm_mock_resource *mock_res; 30 struct drm_buddy *mm = &manager->mm; 31 u64 lpfn, fpfn, alloc_size; 32 int err; 33 34 mock_res = kzalloc(sizeof(*mock_res), GFP_KERNEL); 35 36 if (!mock_res) 37 return -ENOMEM; 38 39 fpfn = 0; 40 lpfn = man->size; 41 42 ttm_resource_init(bo, place, &mock_res->base); 43 INIT_LIST_HEAD(&mock_res->blocks); 44 45 if (place->flags & TTM_PL_FLAG_TOPDOWN) 46 mock_res->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION; 47 48 if (place->flags & TTM_PL_FLAG_CONTIGUOUS) 49 mock_res->flags |= DRM_BUDDY_CONTIGUOUS_ALLOCATION; 50 51 alloc_size = (uint64_t)mock_res->base.size; 52 mutex_lock(&manager->lock); 53 err = drm_buddy_alloc_blocks(mm, fpfn, lpfn, alloc_size, 54 manager->default_page_size, 55 &mock_res->blocks, 56 mock_res->flags); 57 58 if (err) 59 goto error_free_blocks; 60 mutex_unlock(&manager->lock); 61 62 *res = &mock_res->base; 63 return 0; 64 65 error_free_blocks: 66 drm_buddy_free_list(mm, &mock_res->blocks, 0); 67 ttm_resource_fini(man, &mock_res->base); 68 mutex_unlock(&manager->lock); 69 70 return err; 71 } 72 73 static void ttm_mock_manager_free(struct ttm_resource_manager *man, 74 struct ttm_resource *res) 75 { 76 struct ttm_mock_manager *manager = to_mock_mgr(man); 77 struct ttm_mock_resource *mock_res = to_mock_mgr_resource(res); 78 struct drm_buddy *mm = &manager->mm; 79 80 mutex_lock(&manager->lock); 81 drm_buddy_free_list(mm, &mock_res->blocks, 0); 82 mutex_unlock(&manager->lock); 83 84 ttm_resource_fini(man, res); 85 kfree(mock_res); 86 } 87 88 static const struct ttm_resource_manager_func ttm_mock_manager_funcs = { 89 .alloc = ttm_mock_manager_alloc, 90 .free = ttm_mock_manager_free, 91 }; 92 93 int ttm_mock_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size) 94 { 95 struct ttm_mock_manager *manager; 96 struct ttm_resource_manager *base; 97 int err; 98 99 manager = kzalloc(sizeof(*manager), GFP_KERNEL); 100 if (!manager) 101 return -ENOMEM; 102 103 mutex_init(&manager->lock); 104 105 err = drm_buddy_init(&manager->mm, size, PAGE_SIZE); 106 107 if (err) { 108 kfree(manager); 109 return err; 110 } 111 112 manager->default_page_size = PAGE_SIZE; 113 base = &manager->man; 114 base->func = &ttm_mock_manager_funcs; 115 base->use_tt = true; 116 117 ttm_resource_manager_init(base, bdev, size); 118 ttm_set_driver_manager(bdev, mem_type, base); 119 ttm_resource_manager_set_used(base, true); 120 121 return 0; 122 } 123 EXPORT_SYMBOL_GPL(ttm_mock_manager_init); 124 125 void ttm_mock_manager_fini(struct ttm_device *bdev, u32 mem_type) 126 { 127 struct ttm_resource_manager *man; 128 struct ttm_mock_manager *mock_man; 129 int err; 130 131 man = ttm_manager_type(bdev, mem_type); 132 mock_man = to_mock_mgr(man); 133 134 err = ttm_resource_manager_evict_all(bdev, man); 135 if (err) 136 return; 137 138 ttm_resource_manager_set_used(man, false); 139 140 mutex_lock(&mock_man->lock); 141 drm_buddy_fini(&mock_man->mm); 142 mutex_unlock(&mock_man->lock); 143 144 ttm_set_driver_manager(bdev, mem_type, NULL); 145 } 146 EXPORT_SYMBOL_GPL(ttm_mock_manager_fini); 147 148 static int ttm_bad_manager_alloc(struct ttm_resource_manager *man, 149 struct ttm_buffer_object *bo, 150 const struct ttm_place *place, 151 struct ttm_resource **res) 152 { 153 return -ENOSPC; 154 } 155 156 static int ttm_busy_manager_alloc(struct ttm_resource_manager *man, 157 struct ttm_buffer_object *bo, 158 const struct ttm_place *place, 159 struct ttm_resource **res) 160 { 161 return -EBUSY; 162 } 163 164 static void ttm_bad_manager_free(struct ttm_resource_manager *man, 165 struct ttm_resource *res) 166 { 167 } 168 169 static bool ttm_bad_manager_compatible(struct ttm_resource_manager *man, 170 struct ttm_resource *res, 171 const struct ttm_place *place, 172 size_t size) 173 { 174 return true; 175 } 176 177 static const struct ttm_resource_manager_func ttm_bad_manager_funcs = { 178 .alloc = ttm_bad_manager_alloc, 179 .free = ttm_bad_manager_free, 180 .compatible = ttm_bad_manager_compatible 181 }; 182 183 static const struct ttm_resource_manager_func ttm_bad_busy_manager_funcs = { 184 .alloc = ttm_busy_manager_alloc, 185 .free = ttm_bad_manager_free, 186 .compatible = ttm_bad_manager_compatible 187 }; 188 189 int ttm_bad_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size) 190 { 191 struct ttm_resource_manager *man; 192 193 man = kzalloc(sizeof(*man), GFP_KERNEL); 194 if (!man) 195 return -ENOMEM; 196 197 man->func = &ttm_bad_manager_funcs; 198 199 ttm_resource_manager_init(man, bdev, size); 200 ttm_set_driver_manager(bdev, mem_type, man); 201 ttm_resource_manager_set_used(man, true); 202 203 return 0; 204 } 205 EXPORT_SYMBOL_GPL(ttm_bad_manager_init); 206 207 int ttm_busy_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size) 208 { 209 struct ttm_resource_manager *man; 210 211 ttm_bad_manager_init(bdev, mem_type, size); 212 man = ttm_manager_type(bdev, mem_type); 213 214 man->func = &ttm_bad_busy_manager_funcs; 215 216 return 0; 217 } 218 EXPORT_SYMBOL_GPL(ttm_busy_manager_init); 219 220 void ttm_bad_manager_fini(struct ttm_device *bdev, uint32_t mem_type) 221 { 222 struct ttm_resource_manager *man; 223 224 man = ttm_manager_type(bdev, mem_type); 225 226 ttm_resource_manager_set_used(man, false); 227 ttm_set_driver_manager(bdev, mem_type, NULL); 228 229 kfree(man); 230 } 231 EXPORT_SYMBOL_GPL(ttm_bad_manager_fini); 232 233 MODULE_DESCRIPTION("KUnit tests for ttm with mock resource managers"); 234 MODULE_LICENSE("GPL and additional rights"); 235