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)
48 dma_fence_enable_sw_signaling(f);
54 r = dma_resv_lock(&resv, NULL);
56 pr_err("Resv locking failed\n");
58 dma_resv_unlock(&resv);
63 static int test_signaling(void *arg)
65 enum dma_resv_usage usage = (unsigned long)arg;
74 dma_fence_enable_sw_signaling(f);
77 r = dma_resv_lock(&resv, NULL);
79 pr_err("Resv locking failed\n");
83 r = dma_resv_reserve_fences(&resv, 1);
85 pr_err("Resv shared slot allocation failed\n");
89 dma_resv_add_fence(&resv, f, usage);
90 if (dma_resv_test_signaled(&resv, usage)) {
91 pr_err("Resv unexpectedly signaled\n");
96 if (!dma_resv_test_signaled(&resv, usage)) {
97 pr_err("Resv not reporting signaled\n");
102 dma_resv_unlock(&resv);
104 dma_resv_fini(&resv);
109 static int test_for_each(void *arg)
111 enum dma_resv_usage usage = (unsigned long)arg;
112 struct dma_resv_iter cursor;
113 struct dma_fence *f, *fence;
114 struct dma_resv resv;
121 dma_fence_enable_sw_signaling(f);
123 dma_resv_init(&resv);
124 r = dma_resv_lock(&resv, NULL);
126 pr_err("Resv locking failed\n");
130 r = dma_resv_reserve_fences(&resv, 1);
132 pr_err("Resv shared slot allocation failed\n");
136 dma_resv_add_fence(&resv, f, usage);
139 dma_resv_for_each_fence(&cursor, &resv, usage, fence) {
141 pr_err("More than one fence found\n");
146 pr_err("Unexpected fence\n");
150 if (dma_resv_iter_usage(&cursor) != usage) {
151 pr_err("Unexpected fence usage\n");
158 pr_err("No fence found\n");
163 dma_resv_unlock(&resv);
165 dma_resv_fini(&resv);
170 static int test_for_each_unlocked(void *arg)
172 enum dma_resv_usage usage = (unsigned long)arg;
173 struct dma_resv_iter cursor;
174 struct dma_fence *f, *fence;
175 struct dma_resv resv;
182 dma_fence_enable_sw_signaling(f);
184 dma_resv_init(&resv);
185 r = dma_resv_lock(&resv, NULL);
187 pr_err("Resv locking failed\n");
191 r = dma_resv_reserve_fences(&resv, 1);
193 pr_err("Resv shared slot allocation failed\n");
194 dma_resv_unlock(&resv);
198 dma_resv_add_fence(&resv, f, usage);
199 dma_resv_unlock(&resv);
202 dma_resv_iter_begin(&cursor, &resv, usage);
203 dma_resv_for_each_fence_unlocked(&cursor, fence) {
205 pr_err("More than one fence found\n");
209 if (!dma_resv_iter_is_restarted(&cursor)) {
210 pr_err("No restart flag\n");
214 pr_err("Unexpected fence\n");
218 if (dma_resv_iter_usage(&cursor) != usage) {
219 pr_err("Unexpected fence usage\n");
224 /* We use r as state here */
227 /* That should trigger an restart */
228 cursor.fences = (void*)~0;
229 } else if (r == -EINVAL) {
234 pr_err("No fence found\n");
236 dma_resv_iter_end(&cursor);
239 dma_resv_fini(&resv);
244 static int test_get_fences(void *arg)
246 enum dma_resv_usage usage = (unsigned long)arg;
247 struct dma_fence *f, **fences = NULL;
248 struct dma_resv resv;
255 dma_fence_enable_sw_signaling(f);
257 dma_resv_init(&resv);
258 r = dma_resv_lock(&resv, NULL);
260 pr_err("Resv locking failed\n");
264 r = dma_resv_reserve_fences(&resv, 1);
266 pr_err("Resv shared slot allocation failed\n");
267 dma_resv_unlock(&resv);
271 dma_resv_add_fence(&resv, f, usage);
272 dma_resv_unlock(&resv);
274 r = dma_resv_get_fences(&resv, usage, &i, &fences);
276 pr_err("get_fences failed\n");
280 if (i != 1 || fences[0] != f) {
281 pr_err("get_fences returned unexpected fence\n");
288 dma_fence_put(fences[i]);
291 dma_resv_fini(&resv);
298 static const struct subtest tests[] = {
299 SUBTEST(sanitycheck),
300 SUBTEST(test_signaling),
301 SUBTEST(test_for_each),
302 SUBTEST(test_for_each_unlocked),
303 SUBTEST(test_get_fences),
305 enum dma_resv_usage usage;
308 spin_lock_init(&fence_lock);
309 for (usage = DMA_RESV_USAGE_KERNEL; usage <= DMA_RESV_USAGE_BOOKKEEP;
311 r = subtests(tests, (void *)(unsigned long)usage);