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