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
15static inline struct ttm_mock_manager *
16to_mock_mgr(struct ttm_resource_manager *man)
17{
18 return container_of(man, struct ttm_mock_manager, man);
19}
20
21static inline struct ttm_mock_resource *
22to_mock_mgr_resource(struct ttm_resource *res)
23{
24 return container_of(res, struct ttm_mock_resource, base);
25}
26
27static 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, res: &mock_res->base);
47 INIT_LIST_HEAD(list: &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, start: fpfn, end: lpfn, size: alloc_size,
58 min_page_size: manager->default_page_size,
59 blocks: &mock_res->blocks,
60 flags: mock_res->flags);
61
62 if (err)
63 goto error_free_blocks;
64 mutex_unlock(lock: &manager->lock);
65
66 *res = &mock_res->base;
67 return 0;
68
69error_free_blocks:
70 drm_buddy_free_list(mm, objects: &mock_res->blocks, flags: 0);
71 ttm_resource_fini(man, res: &mock_res->base);
72 mutex_unlock(lock: &manager->lock);
73
74 return err;
75}
76
77static 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, objects: &mock_res->blocks, flags: 0);
86 mutex_unlock(lock: &manager->lock);
87
88 ttm_resource_fini(man, res);
89 kfree(objp: mock_res);
90}
91
92static const struct ttm_resource_manager_func ttm_mock_manager_funcs = {
93 .alloc = ttm_mock_manager_alloc,
94 .free = ttm_mock_manager_free,
95};
96
97int 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(mm: &manager->mm, size, PAGE_SIZE);
110
111 if (err) {
112 kfree(objp: 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(man: base, bdev, size);
122 ttm_set_driver_manager(bdev, type: mem_type, manager: base);
123 ttm_resource_manager_set_used(man: base, used: true);
124
125 return 0;
126}
127EXPORT_SYMBOL_GPL(ttm_mock_manager_init);
128
129void 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, used: false);
143
144 mutex_lock(&mock_man->lock);
145 drm_buddy_fini(mm: &mock_man->mm);
146 mutex_unlock(lock: &mock_man->lock);
147
148 ttm_set_driver_manager(bdev, type: mem_type, NULL);
149}
150EXPORT_SYMBOL_GPL(ttm_mock_manager_fini);
151
152static 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
160static 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
168static void ttm_bad_manager_free(struct ttm_resource_manager *man,
169 struct ttm_resource *res)
170{
171}
172
173static 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
181static 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
187static 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
193int 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, type: mem_type, manager: man);
205 ttm_resource_manager_set_used(man, used: true);
206
207 return 0;
208}
209EXPORT_SYMBOL_GPL(ttm_bad_manager_init);
210
211int 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}
222EXPORT_SYMBOL_GPL(ttm_busy_manager_init);
223
224void 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, used: false);
231 ttm_set_driver_manager(bdev, type: mem_type, NULL);
232
233 kfree(objp: man);
234}
235EXPORT_SYMBOL_GPL(ttm_bad_manager_fini);
236
237MODULE_DESCRIPTION("KUnit tests for ttm with mock resource managers");
238MODULE_LICENSE("GPL and additional rights");
239

source code of linux/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c