1 // SPDX-License-Identifier: MIT
4 * Copyright © 2019 Intel Corporation
7 #include <linux/delay.h>
8 #include <linux/dma-fence.h>
9 #include <linux/dma-fence-chain.h>
10 #include <linux/kernel.h>
11 #include <linux/kthread.h>
13 #include <linux/sched/signal.h>
14 #include <linux/slab.h>
15 #include <linux/spinlock.h>
16 #include <linux/random.h>
20 #define CHAIN_SZ (4 << 10)
22 static struct kmem_cache *slab_fences;
24 static inline struct mock_fence {
25 struct dma_fence base;
27 } *to_mock_fence(struct dma_fence *f) {
28 return container_of(f, struct mock_fence, base);
31 static const char *mock_name(struct dma_fence *f)
36 static void mock_fence_release(struct dma_fence *f)
38 kmem_cache_free(slab_fences, to_mock_fence(f));
41 static const struct dma_fence_ops mock_ops = {
42 .get_driver_name = mock_name,
43 .get_timeline_name = mock_name,
44 .release = mock_fence_release,
47 static struct dma_fence *mock_fence(void)
51 f = kmem_cache_alloc(slab_fences, GFP_KERNEL);
55 spin_lock_init(&f->lock);
56 dma_fence_init(&f->base, &mock_ops, &f->lock, 0, 0);
61 static inline struct mock_chain {
62 struct dma_fence_chain base;
63 } *to_mock_chain(struct dma_fence *f) {
64 return container_of(f, struct mock_chain, base.base);
67 static struct dma_fence *mock_chain(struct dma_fence *prev,
68 struct dma_fence *fence,
73 f = kmalloc(sizeof(*f), GFP_KERNEL);
77 dma_fence_chain_init(&f->base,
85 static int sanitycheck(void *arg)
87 struct dma_fence *f, *chain;
94 chain = mock_chain(NULL, f, 1);
101 dma_fence_put(chain);
106 struct fence_chains {
107 unsigned int chain_length;
108 struct dma_fence **fences;
109 struct dma_fence **chains;
111 struct dma_fence *tail;
114 static uint64_t seqno_inc(unsigned int i)
119 static int fence_chains_init(struct fence_chains *fc, unsigned int count,
120 uint64_t (*seqno_fn)(unsigned int))
125 fc->chains = kvmalloc_array(count, sizeof(*fc->chains),
126 GFP_KERNEL | __GFP_ZERO);
130 fc->fences = kvmalloc_array(count, sizeof(*fc->fences),
131 GFP_KERNEL | __GFP_ZERO);
138 for (i = 0; i < count; i++) {
139 fc->fences[i] = mock_fence();
140 if (!fc->fences[i]) {
145 fc->chains[i] = mock_chain(fc->tail,
148 if (!fc->chains[i]) {
153 fc->tail = fc->chains[i];
156 fc->chain_length = i;
160 for (i = 0; i < count; i++) {
161 dma_fence_put(fc->fences[i]);
162 dma_fence_put(fc->chains[i]);
170 static void fence_chains_fini(struct fence_chains *fc)
174 for (i = 0; i < fc->chain_length; i++) {
175 dma_fence_signal(fc->fences[i]);
176 dma_fence_put(fc->fences[i]);
180 for (i = 0; i < fc->chain_length; i++)
181 dma_fence_put(fc->chains[i]);
185 static int find_seqno(void *arg)
187 struct fence_chains fc;
188 struct dma_fence *fence;
192 err = fence_chains_init(&fc, 64, seqno_inc);
196 fence = dma_fence_get(fc.tail);
197 err = dma_fence_chain_find_seqno(&fence, 0);
198 dma_fence_put(fence);
200 pr_err("Reported %d for find_seqno(0)!\n", err);
204 for (i = 0; i < fc.chain_length; i++) {
205 fence = dma_fence_get(fc.tail);
206 err = dma_fence_chain_find_seqno(&fence, i + 1);
207 dma_fence_put(fence);
209 pr_err("Reported %d for find_seqno(%d:%d)!\n",
210 err, fc.chain_length + 1, i + 1);
213 if (fence != fc.chains[i]) {
214 pr_err("Incorrect fence reported by find_seqno(%d:%d)\n",
215 fc.chain_length + 1, i + 1);
220 dma_fence_get(fence);
221 err = dma_fence_chain_find_seqno(&fence, i + 1);
222 dma_fence_put(fence);
224 pr_err("Error reported for finding self\n");
227 if (fence != fc.chains[i]) {
228 pr_err("Incorrect fence reported by find self\n");
233 dma_fence_get(fence);
234 err = dma_fence_chain_find_seqno(&fence, i + 2);
235 dma_fence_put(fence);
237 pr_err("Error not reported for future fence: find_seqno(%d:%d)!\n",
243 dma_fence_get(fence);
244 err = dma_fence_chain_find_seqno(&fence, i);
245 dma_fence_put(fence);
247 pr_err("Error reported for previous fence!\n");
250 if (i > 0 && fence != fc.chains[i - 1]) {
251 pr_err("Incorrect fence reported by find_seqno(%d:%d)\n",
259 fence_chains_fini(&fc);
263 static int find_signaled(void *arg)
265 struct fence_chains fc;
266 struct dma_fence *fence;
269 err = fence_chains_init(&fc, 2, seqno_inc);
273 dma_fence_signal(fc.fences[0]);
275 fence = dma_fence_get(fc.tail);
276 err = dma_fence_chain_find_seqno(&fence, 1);
277 dma_fence_put(fence);
279 pr_err("Reported %d for find_seqno()!\n", err);
283 if (fence && fence != fc.chains[0]) {
284 pr_err("Incorrect chain-fence.seqno:%lld reported for completed seqno:1\n",
287 dma_fence_get(fence);
288 err = dma_fence_chain_find_seqno(&fence, 1);
289 dma_fence_put(fence);
291 pr_err("Reported %d for finding self!\n", err);
297 fence_chains_fini(&fc);
301 static int find_out_of_order(void *arg)
303 struct fence_chains fc;
304 struct dma_fence *fence;
307 err = fence_chains_init(&fc, 3, seqno_inc);
311 dma_fence_signal(fc.fences[1]);
313 fence = dma_fence_get(fc.tail);
314 err = dma_fence_chain_find_seqno(&fence, 2);
315 dma_fence_put(fence);
317 pr_err("Reported %d for find_seqno()!\n", err);
322 * We signaled the middle fence (2) of the 1-2-3 chain. The behavior
323 * of the dma-fence-chain is to make us wait for all the fences up to
324 * the point we want. Since fence 1 is still not signaled, this what
325 * we should get as fence to wait upon (fence 2 being garbage
326 * collected during the traversal of the chain).
328 if (fence != fc.chains[0]) {
329 pr_err("Incorrect chain-fence.seqno:%lld reported for completed seqno:2\n",
330 fence ? fence->seqno : 0);
336 fence_chains_fini(&fc);
340 static uint64_t seqno_inc2(unsigned int i)
345 static int find_gap(void *arg)
347 struct fence_chains fc;
348 struct dma_fence *fence;
352 err = fence_chains_init(&fc, 64, seqno_inc2);
356 for (i = 0; i < fc.chain_length; i++) {
357 fence = dma_fence_get(fc.tail);
358 err = dma_fence_chain_find_seqno(&fence, 2 * i + 1);
359 dma_fence_put(fence);
361 pr_err("Reported %d for find_seqno(%d:%d)!\n",
362 err, fc.chain_length + 1, 2 * i + 1);
365 if (fence != fc.chains[i]) {
366 pr_err("Incorrect fence.seqno:%lld reported by find_seqno(%d:%d)\n",
374 dma_fence_get(fence);
375 err = dma_fence_chain_find_seqno(&fence, 2 * i + 2);
376 dma_fence_put(fence);
378 pr_err("Error reported for finding self\n");
381 if (fence != fc.chains[i]) {
382 pr_err("Incorrect fence reported by find self\n");
389 fence_chains_fini(&fc);
394 struct fence_chains fc;
398 static int __find_race(void *arg)
400 struct find_race *data = arg;
403 while (!kthread_should_stop()) {
404 struct dma_fence *fence = dma_fence_get(data->fc.tail);
407 seqno = prandom_u32_max(data->fc.chain_length) + 1;
409 err = dma_fence_chain_find_seqno(&fence, seqno);
411 pr_err("Failed to find fence seqno:%d\n",
413 dma_fence_put(fence);
420 * We can only find ourselves if we are on fence we were
423 if (fence->seqno == seqno) {
424 err = dma_fence_chain_find_seqno(&fence, seqno);
426 pr_err("Reported an invalid fence for find-self:%d\n",
428 dma_fence_put(fence);
433 dma_fence_put(fence);
436 seqno = prandom_u32_max(data->fc.chain_length - 1);
437 dma_fence_signal(data->fc.fences[seqno]);
441 if (atomic_dec_and_test(&data->children))
442 wake_up_var(&data->children);
446 static int find_race(void *arg)
448 struct find_race data;
449 int ncpus = num_online_cpus();
450 struct task_struct **threads;
455 err = fence_chains_init(&data.fc, CHAIN_SZ, seqno_inc);
459 threads = kmalloc_array(ncpus, sizeof(*threads), GFP_KERNEL);
465 atomic_set(&data.children, 0);
466 for (i = 0; i < ncpus; i++) {
467 threads[i] = kthread_run(__find_race, &data, "dmabuf/%d", i);
468 if (IS_ERR(threads[i])) {
472 atomic_inc(&data.children);
473 get_task_struct(threads[i]);
476 wait_var_event_timeout(&data.children,
477 !atomic_read(&data.children),
480 for (i = 0; i < ncpus; i++) {
483 ret = kthread_stop(threads[i]);
486 put_task_struct(threads[i]);
491 for (i = 0; i < data.fc.chain_length; i++)
492 if (dma_fence_is_signaled(data.fc.fences[i]))
494 pr_info("Completed %lu cycles\n", count);
497 fence_chains_fini(&data.fc);
501 static int signal_forward(void *arg)
503 struct fence_chains fc;
507 err = fence_chains_init(&fc, 64, seqno_inc);
511 for (i = 0; i < fc.chain_length; i++) {
512 dma_fence_signal(fc.fences[i]);
514 if (!dma_fence_is_signaled(fc.chains[i])) {
515 pr_err("chain[%d] not signaled!\n", i);
520 if (i + 1 < fc.chain_length &&
521 dma_fence_is_signaled(fc.chains[i + 1])) {
522 pr_err("chain[%d] is signaled!\n", i);
529 fence_chains_fini(&fc);
533 static int signal_backward(void *arg)
535 struct fence_chains fc;
539 err = fence_chains_init(&fc, 64, seqno_inc);
543 for (i = fc.chain_length; i--; ) {
544 dma_fence_signal(fc.fences[i]);
546 if (i > 0 && dma_fence_is_signaled(fc.chains[i])) {
547 pr_err("chain[%d] is signaled!\n", i);
553 for (i = 0; i < fc.chain_length; i++) {
554 if (!dma_fence_is_signaled(fc.chains[i])) {
555 pr_err("chain[%d] was not signaled!\n", i);
562 fence_chains_fini(&fc);
566 static int __wait_fence_chains(void *arg)
568 struct fence_chains *fc = arg;
570 if (dma_fence_wait(fc->tail, false))
576 static int wait_forward(void *arg)
578 struct fence_chains fc;
579 struct task_struct *tsk;
583 err = fence_chains_init(&fc, CHAIN_SZ, seqno_inc);
587 tsk = kthread_run(__wait_fence_chains, &fc, "dmabuf/wait");
592 get_task_struct(tsk);
595 for (i = 0; i < fc.chain_length; i++)
596 dma_fence_signal(fc.fences[i]);
598 err = kthread_stop(tsk);
599 put_task_struct(tsk);
602 fence_chains_fini(&fc);
606 static int wait_backward(void *arg)
608 struct fence_chains fc;
609 struct task_struct *tsk;
613 err = fence_chains_init(&fc, CHAIN_SZ, seqno_inc);
617 tsk = kthread_run(__wait_fence_chains, &fc, "dmabuf/wait");
622 get_task_struct(tsk);
625 for (i = fc.chain_length; i--; )
626 dma_fence_signal(fc.fences[i]);
628 err = kthread_stop(tsk);
629 put_task_struct(tsk);
632 fence_chains_fini(&fc);
636 static void randomise_fences(struct fence_chains *fc)
638 unsigned int count = fc->chain_length;
640 /* Fisher-Yates shuffle courtesy of Knuth */
644 swp = prandom_u32_max(count + 1);
648 swap(fc->fences[count], fc->fences[swp]);
652 static int wait_random(void *arg)
654 struct fence_chains fc;
655 struct task_struct *tsk;
659 err = fence_chains_init(&fc, CHAIN_SZ, seqno_inc);
663 randomise_fences(&fc);
665 tsk = kthread_run(__wait_fence_chains, &fc, "dmabuf/wait");
670 get_task_struct(tsk);
673 for (i = 0; i < fc.chain_length; i++)
674 dma_fence_signal(fc.fences[i]);
676 err = kthread_stop(tsk);
677 put_task_struct(tsk);
680 fence_chains_fini(&fc);
684 int dma_fence_chain(void)
686 static const struct subtest tests[] = {
687 SUBTEST(sanitycheck),
689 SUBTEST(find_signaled),
690 SUBTEST(find_out_of_order),
693 SUBTEST(signal_forward),
694 SUBTEST(signal_backward),
695 SUBTEST(wait_forward),
696 SUBTEST(wait_backward),
697 SUBTEST(wait_random),
701 pr_info("sizeof(dma_fence_chain)=%zu\n",
702 sizeof(struct dma_fence_chain));
704 slab_fences = KMEM_CACHE(mock_fence,
705 SLAB_TYPESAFE_BY_RCU |
710 ret = subtests(tests, NULL);
712 kmem_cache_destroy(slab_fences);