xref: /linux/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
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 *
to_mock_mgr(struct ttm_resource_manager * man)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 *
to_mock_mgr_resource(struct ttm_resource * res)18 to_mock_mgr_resource(struct ttm_resource *res)
19 {
20 	return container_of(res, struct ttm_mock_resource, base);
21 }
22 
ttm_mock_manager_alloc(struct ttm_resource_manager * man,struct ttm_buffer_object * bo,const struct ttm_place * place,struct ttm_resource ** res)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 
ttm_mock_manager_free(struct ttm_resource_manager * man,struct ttm_resource * res)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 
ttm_mock_manager_init(struct ttm_device * bdev,u32 mem_type,u32 size)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 
ttm_mock_manager_fini(struct ttm_device * bdev,u32 mem_type)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 
ttm_bad_manager_alloc(struct ttm_resource_manager * man,struct ttm_buffer_object * bo,const struct ttm_place * place,struct ttm_resource ** res)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 
ttm_busy_manager_alloc(struct ttm_resource_manager * man,struct ttm_buffer_object * bo,const struct ttm_place * place,struct ttm_resource ** res)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 
ttm_bad_manager_free(struct ttm_resource_manager * man,struct ttm_resource * res)164 static void ttm_bad_manager_free(struct ttm_resource_manager *man,
165 				 struct ttm_resource *res)
166 {
167 }
168 
ttm_bad_manager_compatible(struct ttm_resource_manager * man,struct ttm_resource * res,const struct ttm_place * place,size_t size)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 
ttm_bad_manager_init(struct ttm_device * bdev,u32 mem_type,u32 size)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 
ttm_busy_manager_init(struct ttm_device * bdev,u32 mem_type,u32 size)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 
ttm_bad_manager_fini(struct ttm_device * bdev,uint32_t mem_type)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