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