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