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
);