xref: /linux/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c (revision 815e260a18a3af4dab59025ee99a7156c0e8b5e0)
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