1 /* SPDX-License-Identifier: MIT */
4 * Copyright © 2019 Intel Corporation
5 * Copyright © 2021 Advanced Micro Devices, Inc.
8 #include <linux/slab.h>
9 #include <linux/spinlock.h>
10 #include <linux/dma-resv.h>
14 static struct spinlock fence_lock;
16 static const char *fence_name(struct dma_fence *f)
21 static const struct dma_fence_ops fence_ops = {
22 .get_driver_name = fence_name,
23 .get_timeline_name = fence_name,
26 static struct dma_fence *alloc_fence(void)
30 f = kmalloc(sizeof(*f), GFP_KERNEL);
34 dma_fence_init(f, &fence_ops, &fence_lock, 0, 0);
38 static int sanitycheck(void *arg)
52 r = dma_resv_lock(&resv, NULL);
54 pr_err("Resv locking failed\n");
56 dma_resv_unlock(&resv);
61 static int test_signaling(void *arg, bool shared)
72 r = dma_resv_lock(&resv, NULL);
74 pr_err("Resv locking failed\n");
79 r = dma_resv_reserve_shared(&resv, 1);
81 pr_err("Resv shared slot allocation failed\n");
85 dma_resv_add_shared_fence(&resv, f);
87 dma_resv_add_excl_fence(&resv, f);
90 if (dma_resv_test_signaled(&resv, shared)) {
91 pr_err("Resv unexpectedly signaled\n");
96 if (!dma_resv_test_signaled(&resv, shared)) {
97 pr_err("Resv not reporting signaled\n");
102 dma_resv_unlock(&resv);
104 dma_resv_fini(&resv);
109 static int test_excl_signaling(void *arg)
111 return test_signaling(arg, false);
114 static int test_shared_signaling(void *arg)
116 return test_signaling(arg, true);
119 static int test_for_each(void *arg, bool shared)
121 struct dma_resv_iter cursor;
122 struct dma_fence *f, *fence;
123 struct dma_resv resv;
130 dma_resv_init(&resv);
131 r = dma_resv_lock(&resv, NULL);
133 pr_err("Resv locking failed\n");
138 r = dma_resv_reserve_shared(&resv, 1);
140 pr_err("Resv shared slot allocation failed\n");
144 dma_resv_add_shared_fence(&resv, f);
146 dma_resv_add_excl_fence(&resv, f);
150 dma_resv_for_each_fence(&cursor, &resv, shared, fence) {
152 pr_err("More than one fence found\n");
157 pr_err("Unexpected fence\n");
161 if (dma_resv_iter_is_exclusive(&cursor) != !shared) {
162 pr_err("Unexpected fence usage\n");
169 pr_err("No fence found\n");
174 dma_resv_unlock(&resv);
176 dma_resv_fini(&resv);
181 static int test_excl_for_each(void *arg)
183 return test_for_each(arg, false);
186 static int test_shared_for_each(void *arg)
188 return test_for_each(arg, true);
191 static int test_for_each_unlocked(void *arg, bool shared)
193 struct dma_resv_iter cursor;
194 struct dma_fence *f, *fence;
195 struct dma_resv resv;
202 dma_resv_init(&resv);
203 r = dma_resv_lock(&resv, NULL);
205 pr_err("Resv locking failed\n");
210 r = dma_resv_reserve_shared(&resv, 1);
212 pr_err("Resv shared slot allocation failed\n");
213 dma_resv_unlock(&resv);
217 dma_resv_add_shared_fence(&resv, f);
219 dma_resv_add_excl_fence(&resv, f);
221 dma_resv_unlock(&resv);
224 dma_resv_iter_begin(&cursor, &resv, shared);
225 dma_resv_for_each_fence_unlocked(&cursor, fence) {
227 pr_err("More than one fence found\n");
231 if (!dma_resv_iter_is_restarted(&cursor)) {
232 pr_err("No restart flag\n");
236 pr_err("Unexpected fence\n");
240 if (dma_resv_iter_is_exclusive(&cursor) != !shared) {
241 pr_err("Unexpected fence usage\n");
246 /* We use r as state here */
249 /* That should trigger an restart */
251 } else if (r == -EINVAL) {
256 pr_err("No fence found\n");
258 dma_resv_iter_end(&cursor);
261 dma_resv_fini(&resv);
266 static int test_excl_for_each_unlocked(void *arg)
268 return test_for_each_unlocked(arg, false);
271 static int test_shared_for_each_unlocked(void *arg)
273 return test_for_each_unlocked(arg, true);
276 static int test_get_fences(void *arg, bool shared)
278 struct dma_fence *f, **fences = NULL;
279 struct dma_resv resv;
286 dma_resv_init(&resv);
287 r = dma_resv_lock(&resv, NULL);
289 pr_err("Resv locking failed\n");
294 r = dma_resv_reserve_shared(&resv, 1);
296 pr_err("Resv shared slot allocation failed\n");
297 dma_resv_unlock(&resv);
301 dma_resv_add_shared_fence(&resv, f);
303 dma_resv_add_excl_fence(&resv, f);
305 dma_resv_unlock(&resv);
307 r = dma_resv_get_fences(&resv, shared, &i, &fences);
309 pr_err("get_fences failed\n");
313 if (i != 1 || fences[0] != f) {
314 pr_err("get_fences returned unexpected fence\n");
321 dma_fence_put(fences[i]);
324 dma_resv_fini(&resv);
329 static int test_excl_get_fences(void *arg)
331 return test_get_fences(arg, false);
334 static int test_shared_get_fences(void *arg)
336 return test_get_fences(arg, true);
341 static const struct subtest tests[] = {
342 SUBTEST(sanitycheck),
343 SUBTEST(test_excl_signaling),
344 SUBTEST(test_shared_signaling),
345 SUBTEST(test_excl_for_each),
346 SUBTEST(test_shared_for_each),
347 SUBTEST(test_excl_for_each_unlocked),
348 SUBTEST(test_shared_for_each_unlocked),
349 SUBTEST(test_excl_get_fences),
350 SUBTEST(test_shared_get_fences),
353 spin_lock_init(&fence_lock);
354 return subtests(tests, NULL);