1 // SPDX-License-Identifier: MIT
4 * Copyright (C) 2022 Advanced Micro Devices, Inc.
7 #include <linux/dma-fence.h>
8 #include <linux/dma-fence-array.h>
9 #include <linux/dma-fence-chain.h>
10 #include <linux/dma-fence-unwrap.h>
14 #define CHAIN_SZ (4 << 10)
17 struct dma_fence base
;
21 static const char *mock_name(struct dma_fence
*f
)
26 static const struct dma_fence_ops mock_ops
= {
27 .get_driver_name
= mock_name
,
28 .get_timeline_name
= mock_name
,
31 static struct dma_fence
*__mock_fence(u64 context
, u64 seqno
)
35 f
= kmalloc(sizeof(*f
), GFP_KERNEL
);
39 spin_lock_init(&f
->lock
);
40 dma_fence_init(&f
->base
, &mock_ops
, &f
->lock
, context
, seqno
);
45 static struct dma_fence
*mock_fence(void)
47 return __mock_fence(dma_fence_context_alloc(1), 1);
50 static struct dma_fence
*mock_array(unsigned int num_fences
, ...)
52 struct dma_fence_array
*array
;
53 struct dma_fence
**fences
;
57 fences
= kcalloc(num_fences
, sizeof(*fences
), GFP_KERNEL
);
61 va_start(valist
, num_fences
);
62 for (i
= 0; i
< num_fences
; ++i
)
63 fences
[i
] = va_arg(valist
, typeof(*fences
));
66 array
= dma_fence_array_create(num_fences
, fences
,
67 dma_fence_context_alloc(1),
77 va_start(valist
, num_fences
);
78 for (i
= 0; i
< num_fences
; ++i
)
79 dma_fence_put(va_arg(valist
, typeof(*fences
)));
84 static struct dma_fence
*mock_chain(struct dma_fence
*prev
,
85 struct dma_fence
*fence
)
87 struct dma_fence_chain
*f
;
89 f
= dma_fence_chain_alloc();
96 dma_fence_chain_init(f
, prev
, fence
, 1);
100 static int sanitycheck(void *arg
)
102 struct dma_fence
*f
, *chain
, *array
;
109 dma_fence_enable_sw_signaling(f
);
111 array
= mock_array(1, f
);
115 chain
= mock_chain(NULL
, array
);
119 dma_fence_put(chain
);
123 static int unwrap_array(void *arg
)
125 struct dma_fence
*fence
, *f1
, *f2
, *array
;
126 struct dma_fence_unwrap iter
;
133 dma_fence_enable_sw_signaling(f1
);
141 dma_fence_enable_sw_signaling(f2
);
143 array
= mock_array(2, f1
, f2
);
147 dma_fence_unwrap_for_each(fence
, &iter
, array
) {
150 } else if (fence
== f2
) {
153 pr_err("Unexpected fence!\n");
159 pr_err("Not all fences seen!\n");
163 dma_fence_put(array
);
167 static int unwrap_chain(void *arg
)
169 struct dma_fence
*fence
, *f1
, *f2
, *chain
;
170 struct dma_fence_unwrap iter
;
177 dma_fence_enable_sw_signaling(f1
);
185 dma_fence_enable_sw_signaling(f2
);
187 chain
= mock_chain(f1
, f2
);
191 dma_fence_unwrap_for_each(fence
, &iter
, chain
) {
194 } else if (fence
== f2
) {
197 pr_err("Unexpected fence!\n");
203 pr_err("Not all fences seen!\n");
207 dma_fence_put(chain
);
211 static int unwrap_chain_array(void *arg
)
213 struct dma_fence
*fence
, *f1
, *f2
, *array
, *chain
;
214 struct dma_fence_unwrap iter
;
221 dma_fence_enable_sw_signaling(f1
);
229 dma_fence_enable_sw_signaling(f2
);
231 array
= mock_array(2, f1
, f2
);
235 chain
= mock_chain(NULL
, array
);
239 dma_fence_unwrap_for_each(fence
, &iter
, chain
) {
242 } else if (fence
== f2
) {
245 pr_err("Unexpected fence!\n");
251 pr_err("Not all fences seen!\n");
255 dma_fence_put(chain
);
259 static int unwrap_merge(void *arg
)
261 struct dma_fence
*fence
, *f1
, *f2
, *f3
;
262 struct dma_fence_unwrap iter
;
269 dma_fence_enable_sw_signaling(f1
);
277 dma_fence_enable_sw_signaling(f2
);
279 f3
= dma_fence_unwrap_merge(f1
, f2
);
285 dma_fence_unwrap_for_each(fence
, &iter
, f3
) {
289 } else if (fence
== f2
) {
293 pr_err("Unexpected fence!\n");
299 pr_err("Not all fences seen!\n");
311 static int unwrap_merge_duplicate(void *arg
)
313 struct dma_fence
*fence
, *f1
, *f2
;
314 struct dma_fence_unwrap iter
;
321 dma_fence_enable_sw_signaling(f1
);
323 f2
= dma_fence_unwrap_merge(f1
, f1
);
329 dma_fence_unwrap_for_each(fence
, &iter
, f2
) {
334 pr_err("Unexpected fence!\n");
340 pr_err("Not all fences seen!\n");
350 static int unwrap_merge_seqno(void *arg
)
352 struct dma_fence
*fence
, *f1
, *f2
, *f3
, *f4
;
353 struct dma_fence_unwrap iter
;
357 ctx
[0] = dma_fence_context_alloc(1);
358 ctx
[1] = dma_fence_context_alloc(1);
360 f1
= __mock_fence(ctx
[1], 1);
364 dma_fence_enable_sw_signaling(f1
);
366 f2
= __mock_fence(ctx
[1], 2);
372 dma_fence_enable_sw_signaling(f2
);
374 f3
= __mock_fence(ctx
[0], 1);
380 dma_fence_enable_sw_signaling(f3
);
382 f4
= dma_fence_unwrap_merge(f1
, f2
, f3
);
388 dma_fence_unwrap_for_each(fence
, &iter
, f4
) {
389 if (fence
== f3
&& f2
) {
392 } else if (fence
== f2
&& !f3
) {
396 pr_err("Unexpected fence!\n");
402 pr_err("Not all fences seen!\n");
416 static int unwrap_merge_order(void *arg
)
418 struct dma_fence
*fence
, *f1
, *f2
, *a1
, *a2
, *c1
, *c2
;
419 struct dma_fence_unwrap iter
;
426 dma_fence_enable_sw_signaling(f1
);
434 dma_fence_enable_sw_signaling(f2
);
436 a1
= mock_array(2, f1
, f2
);
440 c1
= mock_chain(NULL
, dma_fence_get(f1
));
444 c2
= mock_chain(c1
, dma_fence_get(f2
));
449 * The fences in the chain are the same as in a1 but in oposite order,
450 * the dma_fence_merge() function should be able to handle that.
452 a2
= dma_fence_unwrap_merge(a1
, c2
);
454 dma_fence_unwrap_for_each(fence
, &iter
, a2
) {
458 pr_err("Unexpected order!\n");
459 } else if (fence
== f2
) {
462 pr_err("Unexpected order!\n");
464 pr_err("Unexpected fence!\n");
470 pr_err("Not all fences seen!\n");
482 static int unwrap_merge_complex(void *arg
)
484 struct dma_fence
*fence
, *f1
, *f2
, *f3
, *f4
, *f5
;
485 struct dma_fence_unwrap iter
;
492 dma_fence_enable_sw_signaling(f1
);
498 dma_fence_enable_sw_signaling(f2
);
500 f3
= dma_fence_unwrap_merge(f1
, f2
);
504 /* The resulting array has the fences in reverse */
505 f4
= mock_array(2, dma_fence_get(f2
), dma_fence_get(f1
));
509 /* Signaled fences should be filtered, the two arrays merged. */
510 f5
= dma_fence_unwrap_merge(f3
, f4
, dma_fence_get_stub());
515 dma_fence_unwrap_for_each(fence
, &iter
, f5
) {
519 } else if (fence
== f2
) {
523 pr_err("Unexpected fence!\n");
529 pr_err("Not all fences seen!\n");
545 static int unwrap_merge_complex_seqno(void *arg
)
547 struct dma_fence
*fence
, *f1
, *f2
, *f3
, *f4
, *f5
, *f6
, *f7
;
548 struct dma_fence_unwrap iter
;
552 ctx
[0] = dma_fence_context_alloc(1);
553 ctx
[1] = dma_fence_context_alloc(1);
555 f1
= __mock_fence(ctx
[0], 2);
559 dma_fence_enable_sw_signaling(f1
);
561 f2
= __mock_fence(ctx
[1], 1);
565 dma_fence_enable_sw_signaling(f2
);
567 f3
= __mock_fence(ctx
[0], 1);
571 dma_fence_enable_sw_signaling(f3
);
573 f4
= __mock_fence(ctx
[1], 2);
577 dma_fence_enable_sw_signaling(f4
);
579 f5
= mock_array(2, dma_fence_get(f1
), dma_fence_get(f2
));
583 f6
= mock_array(2, dma_fence_get(f3
), dma_fence_get(f4
));
587 f7
= dma_fence_unwrap_merge(f5
, f6
);
592 dma_fence_unwrap_for_each(fence
, &iter
, f7
) {
593 if (fence
== f1
&& f4
) {
596 } else if (fence
== f4
&& !f1
) {
600 pr_err("Unexpected fence!\n");
606 pr_err("Not all fences seen!\n");
626 int dma_fence_unwrap(void)
628 static const struct subtest tests
[] = {
629 SUBTEST(sanitycheck
),
630 SUBTEST(unwrap_array
),
631 SUBTEST(unwrap_chain
),
632 SUBTEST(unwrap_chain_array
),
633 SUBTEST(unwrap_merge
),
634 SUBTEST(unwrap_merge_duplicate
),
635 SUBTEST(unwrap_merge_seqno
),
636 SUBTEST(unwrap_merge_order
),
637 SUBTEST(unwrap_merge_complex
),
638 SUBTEST(unwrap_merge_complex_seqno
),
641 return subtests(tests
, NULL
);