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