]> Git Repo - J-linux.git/blob - drivers/gpu/drm/i915/selftests/i915_sw_fence.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / gpu / drm / i915 / selftests / i915_sw_fence.c
1 /*
2  * Copyright © 2017 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  */
24
25 #include <linux/completion.h>
26 #include <linux/delay.h>
27 #include <linux/prime_numbers.h>
28
29 #include "../i915_selftest.h"
30
31 static int
32 fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
33 {
34         switch (state) {
35         case FENCE_COMPLETE:
36                 break;
37
38         case FENCE_FREE:
39                 /* Leave the fence for the caller to free it after testing */
40                 break;
41         }
42
43         return NOTIFY_DONE;
44 }
45
46 static struct i915_sw_fence *alloc_fence(void)
47 {
48         struct i915_sw_fence *fence;
49
50         fence = kmalloc(sizeof(*fence), GFP_KERNEL);
51         if (!fence)
52                 return NULL;
53
54         i915_sw_fence_init(fence, fence_notify);
55         return fence;
56 }
57
58 static void free_fence(struct i915_sw_fence *fence)
59 {
60         i915_sw_fence_fini(fence);
61         kfree(fence);
62 }
63
64 static int __test_self(struct i915_sw_fence *fence)
65 {
66         if (i915_sw_fence_done(fence))
67                 return -EINVAL;
68
69         i915_sw_fence_commit(fence);
70         if (!i915_sw_fence_done(fence))
71                 return -EINVAL;
72
73         i915_sw_fence_wait(fence);
74         if (!i915_sw_fence_done(fence))
75                 return -EINVAL;
76
77         return 0;
78 }
79
80 static int test_self(void *arg)
81 {
82         struct i915_sw_fence *fence;
83         int ret;
84
85         /* Test i915_sw_fence signaling and completion testing */
86         fence = alloc_fence();
87         if (!fence)
88                 return -ENOMEM;
89
90         ret = __test_self(fence);
91
92         free_fence(fence);
93         return ret;
94 }
95
96 static int test_dag(void *arg)
97 {
98         struct i915_sw_fence *A, *B, *C;
99         int ret = -EINVAL;
100
101         /* Test detection of cycles within the i915_sw_fence graphs */
102         if (!IS_ENABLED(CONFIG_DRM_I915_SW_FENCE_CHECK_DAG))
103                 return 0;
104
105         A = alloc_fence();
106         if (!A)
107                 return -ENOMEM;
108
109         if (i915_sw_fence_await_sw_fence_gfp(A, A, GFP_KERNEL) != -EINVAL) {
110                 pr_err("recursive cycle not detected (AA)\n");
111                 goto err_A;
112         }
113
114         B = alloc_fence();
115         if (!B) {
116                 ret = -ENOMEM;
117                 goto err_A;
118         }
119
120         i915_sw_fence_await_sw_fence_gfp(A, B, GFP_KERNEL);
121         if (i915_sw_fence_await_sw_fence_gfp(B, A, GFP_KERNEL) != -EINVAL) {
122                 pr_err("single depth cycle not detected (BAB)\n");
123                 goto err_B;
124         }
125
126         C = alloc_fence();
127         if (!C) {
128                 ret = -ENOMEM;
129                 goto err_B;
130         }
131
132         if (i915_sw_fence_await_sw_fence_gfp(B, C, GFP_KERNEL) == -EINVAL) {
133                 pr_err("invalid cycle detected\n");
134                 goto err_C;
135         }
136         if (i915_sw_fence_await_sw_fence_gfp(C, B, GFP_KERNEL) != -EINVAL) {
137                 pr_err("single depth cycle not detected (CBC)\n");
138                 goto err_C;
139         }
140         if (i915_sw_fence_await_sw_fence_gfp(C, A, GFP_KERNEL) != -EINVAL) {
141                 pr_err("cycle not detected (BA, CB, AC)\n");
142                 goto err_C;
143         }
144         if (i915_sw_fence_await_sw_fence_gfp(A, C, GFP_KERNEL) == -EINVAL) {
145                 pr_err("invalid cycle detected\n");
146                 goto err_C;
147         }
148
149         i915_sw_fence_commit(A);
150         i915_sw_fence_commit(B);
151         i915_sw_fence_commit(C);
152
153         ret = 0;
154         if (!i915_sw_fence_done(C)) {
155                 pr_err("fence C not done\n");
156                 ret = -EINVAL;
157         }
158         if (!i915_sw_fence_done(B)) {
159                 pr_err("fence B not done\n");
160                 ret = -EINVAL;
161         }
162         if (!i915_sw_fence_done(A)) {
163                 pr_err("fence A not done\n");
164                 ret = -EINVAL;
165         }
166 err_C:
167         free_fence(C);
168 err_B:
169         free_fence(B);
170 err_A:
171         free_fence(A);
172         return ret;
173 }
174
175 static int test_AB(void *arg)
176 {
177         struct i915_sw_fence *A, *B;
178         int ret;
179
180         /* Test i915_sw_fence (A) waiting on an event source (B) */
181         A = alloc_fence();
182         if (!A)
183                 return -ENOMEM;
184         B = alloc_fence();
185         if (!B) {
186                 ret = -ENOMEM;
187                 goto err_A;
188         }
189
190         ret = i915_sw_fence_await_sw_fence_gfp(A, B, GFP_KERNEL);
191         if (ret < 0)
192                 goto err_B;
193         if (ret == 0) {
194                 pr_err("Incorrectly reported fence A was complete before await\n");
195                 ret = -EINVAL;
196                 goto err_B;
197         }
198
199         ret = -EINVAL;
200         i915_sw_fence_commit(A);
201         if (i915_sw_fence_done(A))
202                 goto err_B;
203
204         i915_sw_fence_commit(B);
205         if (!i915_sw_fence_done(B)) {
206                 pr_err("Fence B is not done\n");
207                 goto err_B;
208         }
209
210         if (!i915_sw_fence_done(A)) {
211                 pr_err("Fence A is not done\n");
212                 goto err_B;
213         }
214
215         ret = 0;
216 err_B:
217         free_fence(B);
218 err_A:
219         free_fence(A);
220         return ret;
221 }
222
223 static int test_ABC(void *arg)
224 {
225         struct i915_sw_fence *A, *B, *C;
226         int ret;
227
228         /* Test a chain of fences, A waits on B who waits on C */
229         A = alloc_fence();
230         if (!A)
231                 return -ENOMEM;
232
233         B = alloc_fence();
234         if (!B) {
235                 ret = -ENOMEM;
236                 goto err_A;
237         }
238
239         C = alloc_fence();
240         if (!C) {
241                 ret = -ENOMEM;
242                 goto err_B;
243         }
244
245         ret = i915_sw_fence_await_sw_fence_gfp(A, B, GFP_KERNEL);
246         if (ret < 0)
247                 goto err_C;
248         if (ret == 0) {
249                 pr_err("Incorrectly reported fence B was complete before await\n");
250                 goto err_C;
251         }
252
253         ret = i915_sw_fence_await_sw_fence_gfp(B, C, GFP_KERNEL);
254         if (ret < 0)
255                 goto err_C;
256         if (ret == 0) {
257                 pr_err("Incorrectly reported fence C was complete before await\n");
258                 goto err_C;
259         }
260
261         ret = -EINVAL;
262         i915_sw_fence_commit(A);
263         if (i915_sw_fence_done(A)) {
264                 pr_err("Fence A completed early\n");
265                 goto err_C;
266         }
267
268         i915_sw_fence_commit(B);
269         if (i915_sw_fence_done(B)) {
270                 pr_err("Fence B completed early\n");
271                 goto err_C;
272         }
273
274         if (i915_sw_fence_done(A)) {
275                 pr_err("Fence A completed early (after signaling B)\n");
276                 goto err_C;
277         }
278
279         i915_sw_fence_commit(C);
280
281         ret = 0;
282         if (!i915_sw_fence_done(C)) {
283                 pr_err("Fence C not done\n");
284                 ret = -EINVAL;
285         }
286         if (!i915_sw_fence_done(B)) {
287                 pr_err("Fence B not done\n");
288                 ret = -EINVAL;
289         }
290         if (!i915_sw_fence_done(A)) {
291                 pr_err("Fence A not done\n");
292                 ret = -EINVAL;
293         }
294 err_C:
295         free_fence(C);
296 err_B:
297         free_fence(B);
298 err_A:
299         free_fence(A);
300         return ret;
301 }
302
303 static int test_AB_C(void *arg)
304 {
305         struct i915_sw_fence *A, *B, *C;
306         int ret = -EINVAL;
307
308         /* Test multiple fences (AB) waiting on a single event (C) */
309         A = alloc_fence();
310         if (!A)
311                 return -ENOMEM;
312
313         B = alloc_fence();
314         if (!B) {
315                 ret = -ENOMEM;
316                 goto err_A;
317         }
318
319         C = alloc_fence();
320         if (!C) {
321                 ret = -ENOMEM;
322                 goto err_B;
323         }
324
325         ret = i915_sw_fence_await_sw_fence_gfp(A, C, GFP_KERNEL);
326         if (ret < 0)
327                 goto err_C;
328         if (ret == 0) {
329                 ret = -EINVAL;
330                 goto err_C;
331         }
332
333         ret = i915_sw_fence_await_sw_fence_gfp(B, C, GFP_KERNEL);
334         if (ret < 0)
335                 goto err_C;
336         if (ret == 0) {
337                 ret = -EINVAL;
338                 goto err_C;
339         }
340
341         i915_sw_fence_commit(A);
342         i915_sw_fence_commit(B);
343
344         ret = 0;
345         if (i915_sw_fence_done(A)) {
346                 pr_err("Fence A completed early\n");
347                 ret = -EINVAL;
348         }
349
350         if (i915_sw_fence_done(B)) {
351                 pr_err("Fence B completed early\n");
352                 ret = -EINVAL;
353         }
354
355         i915_sw_fence_commit(C);
356         if (!i915_sw_fence_done(C)) {
357                 pr_err("Fence C not done\n");
358                 ret = -EINVAL;
359         }
360
361         if (!i915_sw_fence_done(B)) {
362                 pr_err("Fence B not done\n");
363                 ret = -EINVAL;
364         }
365
366         if (!i915_sw_fence_done(A)) {
367                 pr_err("Fence A not done\n");
368                 ret = -EINVAL;
369         }
370
371 err_C:
372         free_fence(C);
373 err_B:
374         free_fence(B);
375 err_A:
376         free_fence(A);
377         return ret;
378 }
379
380 static int test_C_AB(void *arg)
381 {
382         struct i915_sw_fence *A, *B, *C;
383         int ret;
384
385         /* Test multiple event sources (A,B) for a single fence (C) */
386         A = alloc_fence();
387         if (!A)
388                 return -ENOMEM;
389
390         B = alloc_fence();
391         if (!B) {
392                 ret = -ENOMEM;
393                 goto err_A;
394         }
395
396         C = alloc_fence();
397         if (!C) {
398                 ret = -ENOMEM;
399                 goto err_B;
400         }
401
402         ret = i915_sw_fence_await_sw_fence_gfp(C, A, GFP_KERNEL);
403         if (ret < 0)
404                 goto err_C;
405         if (ret == 0) {
406                 ret = -EINVAL;
407                 goto err_C;
408         }
409
410         ret = i915_sw_fence_await_sw_fence_gfp(C, B, GFP_KERNEL);
411         if (ret < 0)
412                 goto err_C;
413         if (ret == 0) {
414                 ret = -EINVAL;
415                 goto err_C;
416         }
417
418         ret = 0;
419         i915_sw_fence_commit(C);
420         if (i915_sw_fence_done(C))
421                 ret = -EINVAL;
422
423         i915_sw_fence_commit(A);
424         i915_sw_fence_commit(B);
425
426         if (!i915_sw_fence_done(A)) {
427                 pr_err("Fence A not done\n");
428                 ret = -EINVAL;
429         }
430
431         if (!i915_sw_fence_done(B)) {
432                 pr_err("Fence B not done\n");
433                 ret = -EINVAL;
434         }
435
436         if (!i915_sw_fence_done(C)) {
437                 pr_err("Fence C not done\n");
438                 ret = -EINVAL;
439         }
440
441 err_C:
442         free_fence(C);
443 err_B:
444         free_fence(B);
445 err_A:
446         free_fence(A);
447         return ret;
448 }
449
450 static int test_chain(void *arg)
451 {
452         int nfences = 4096;
453         struct i915_sw_fence **fences;
454         int ret, i;
455
456         /* Test a long chain of fences */
457         fences = kmalloc_array(nfences, sizeof(*fences), GFP_KERNEL);
458         if (!fences)
459                 return -ENOMEM;
460
461         for (i = 0; i < nfences; i++) {
462                 fences[i] = alloc_fence();
463                 if (!fences[i]) {
464                         nfences = i;
465                         ret = -ENOMEM;
466                         goto err;
467                 }
468
469                 if (i > 0) {
470                         ret = i915_sw_fence_await_sw_fence_gfp(fences[i],
471                                                                fences[i - 1],
472                                                                GFP_KERNEL);
473                         if (ret < 0) {
474                                 nfences = i + 1;
475                                 goto err;
476                         }
477
478                         i915_sw_fence_commit(fences[i]);
479                 }
480         }
481
482         ret = 0;
483         for (i = nfences; --i; ) {
484                 if (i915_sw_fence_done(fences[i])) {
485                         if (ret == 0)
486                                 pr_err("Fence[%d] completed early\n", i);
487                         ret = -EINVAL;
488                 }
489         }
490         i915_sw_fence_commit(fences[0]);
491         for (i = 0; ret == 0 && i < nfences; i++) {
492                 if (!i915_sw_fence_done(fences[i])) {
493                         pr_err("Fence[%d] is not done\n", i);
494                         ret = -EINVAL;
495                 }
496         }
497
498 err:
499         for (i = 0; i < nfences; i++)
500                 free_fence(fences[i]);
501         kfree(fences);
502         return ret;
503 }
504
505 struct task_ipc {
506         struct work_struct work;
507         struct completion started;
508         struct i915_sw_fence *in, *out;
509         int value;
510 };
511
512 static void task_ipc(struct work_struct *work)
513 {
514         struct task_ipc *ipc = container_of(work, typeof(*ipc), work);
515
516         complete(&ipc->started);
517
518         i915_sw_fence_wait(ipc->in);
519         smp_store_mb(ipc->value, 1);
520         i915_sw_fence_commit(ipc->out);
521 }
522
523 static int test_ipc(void *arg)
524 {
525         struct task_ipc ipc;
526         struct workqueue_struct *wq;
527         int ret = 0;
528
529         wq = alloc_workqueue("i1915-selftest", 0, 0);
530         if (wq == NULL)
531                 return -ENOMEM;
532
533         /* Test use of i915_sw_fence as an interprocess signaling mechanism */
534         ipc.in = alloc_fence();
535         if (!ipc.in) {
536                 ret = -ENOMEM;
537                 goto err_work;
538         }
539         ipc.out = alloc_fence();
540         if (!ipc.out) {
541                 ret = -ENOMEM;
542                 goto err_in;
543         }
544
545         /* use a completion to avoid chicken-and-egg testing */
546         init_completion(&ipc.started);
547
548         ipc.value = 0;
549         INIT_WORK_ONSTACK(&ipc.work, task_ipc);
550         queue_work(wq, &ipc.work);
551
552         wait_for_completion(&ipc.started);
553
554         usleep_range(1000, 2000);
555         if (READ_ONCE(ipc.value)) {
556                 pr_err("worker updated value before i915_sw_fence was signaled\n");
557                 ret = -EINVAL;
558         }
559
560         i915_sw_fence_commit(ipc.in);
561         i915_sw_fence_wait(ipc.out);
562
563         if (!READ_ONCE(ipc.value)) {
564                 pr_err("worker signaled i915_sw_fence before value was posted\n");
565                 ret = -EINVAL;
566         }
567
568         flush_work(&ipc.work);
569         destroy_work_on_stack(&ipc.work);
570         free_fence(ipc.out);
571 err_in:
572         free_fence(ipc.in);
573 err_work:
574         destroy_workqueue(wq);
575
576         return ret;
577 }
578
579 static int test_timer(void *arg)
580 {
581         unsigned long target, delay;
582         struct timed_fence tf;
583
584         preempt_disable();
585         timed_fence_init(&tf, target = jiffies);
586         if (!i915_sw_fence_done(&tf.fence)) {
587                 pr_err("Fence with immediate expiration not signaled\n");
588                 goto err;
589         }
590         preempt_enable();
591         timed_fence_fini(&tf);
592
593         for_each_prime_number(delay, i915_selftest.timeout_jiffies/2) {
594                 preempt_disable();
595                 timed_fence_init(&tf, target = jiffies + delay);
596                 if (i915_sw_fence_done(&tf.fence)) {
597                         pr_err("Fence with future expiration (%lu jiffies) already signaled\n", delay);
598                         goto err;
599                 }
600                 preempt_enable();
601
602                 i915_sw_fence_wait(&tf.fence);
603
604                 preempt_disable();
605                 if (!i915_sw_fence_done(&tf.fence)) {
606                         pr_err("Fence not signaled after wait\n");
607                         goto err;
608                 }
609                 if (time_before(jiffies, target)) {
610                         pr_err("Fence signaled too early, target=%lu, now=%lu\n",
611                                target, jiffies);
612                         goto err;
613                 }
614                 preempt_enable();
615                 timed_fence_fini(&tf);
616         }
617
618         return 0;
619
620 err:
621         preempt_enable();
622         timed_fence_fini(&tf);
623         return -EINVAL;
624 }
625
626 static const char *mock_name(struct dma_fence *fence)
627 {
628         return "mock";
629 }
630
631 static const struct dma_fence_ops mock_fence_ops = {
632         .get_driver_name = mock_name,
633         .get_timeline_name = mock_name,
634 };
635
636 static DEFINE_SPINLOCK(mock_fence_lock);
637
638 static struct dma_fence *alloc_dma_fence(void)
639 {
640         struct dma_fence *dma;
641
642         dma = kmalloc(sizeof(*dma), GFP_KERNEL);
643         if (dma)
644                 dma_fence_init(dma, &mock_fence_ops, &mock_fence_lock, 0, 0);
645
646         return dma;
647 }
648
649 static struct i915_sw_fence *
650 wrap_dma_fence(struct dma_fence *dma, unsigned long delay)
651 {
652         struct i915_sw_fence *fence;
653         int err;
654
655         fence = alloc_fence();
656         if (!fence)
657                 return ERR_PTR(-ENOMEM);
658
659         err = i915_sw_fence_await_dma_fence(fence, dma, delay, GFP_NOWAIT);
660         i915_sw_fence_commit(fence);
661         if (err < 0) {
662                 free_fence(fence);
663                 return ERR_PTR(err);
664         }
665
666         return fence;
667 }
668
669 static int test_dma_fence(void *arg)
670 {
671         struct i915_sw_fence *timeout = NULL, *not = NULL;
672         unsigned long delay = i915_selftest.timeout_jiffies;
673         unsigned long end, sleep;
674         struct dma_fence *dma;
675         int err;
676
677         dma = alloc_dma_fence();
678         if (!dma)
679                 return -ENOMEM;
680
681         timeout = wrap_dma_fence(dma, delay);
682         if (IS_ERR(timeout)) {
683                 err = PTR_ERR(timeout);
684                 goto err;
685         }
686
687         not = wrap_dma_fence(dma, 0);
688         if (IS_ERR(not)) {
689                 err = PTR_ERR(not);
690                 goto err;
691         }
692
693         err = -EINVAL;
694         if (i915_sw_fence_done(timeout) || i915_sw_fence_done(not)) {
695                 pr_err("Fences immediately signaled\n");
696                 goto err;
697         }
698
699         /* We round the timeout for the fence up to the next second */
700         end = round_jiffies_up(jiffies + delay);
701
702         sleep = jiffies_to_usecs(delay) / 3;
703         usleep_range(sleep, 2 * sleep);
704         if (time_after(jiffies, end)) {
705                 pr_debug("Slept too long, delay=%lu, (target=%lu, now=%lu) skipping\n",
706                          delay, end, jiffies);
707                 goto skip;
708         }
709
710         if (i915_sw_fence_done(timeout) || i915_sw_fence_done(not)) {
711                 pr_err("Fences signaled too early\n");
712                 goto err;
713         }
714
715         if (!wait_event_timeout(timeout->wait,
716                                 i915_sw_fence_done(timeout),
717                                 2 * (end - jiffies) + 1)) {
718                 pr_err("Timeout fence unsignaled!\n");
719                 goto err;
720         }
721
722         if (i915_sw_fence_done(not)) {
723                 pr_err("No timeout fence signaled!\n");
724                 goto err;
725         }
726
727 skip:
728         dma_fence_signal(dma);
729
730         if (!i915_sw_fence_done(timeout) || !i915_sw_fence_done(not)) {
731                 pr_err("Fences unsignaled\n");
732                 goto err;
733         }
734
735         free_fence(not);
736         free_fence(timeout);
737         dma_fence_put(dma);
738
739         return 0;
740
741 err:
742         dma_fence_signal(dma);
743         if (!IS_ERR_OR_NULL(timeout))
744                 free_fence(timeout);
745         if (!IS_ERR_OR_NULL(not))
746                 free_fence(not);
747         dma_fence_put(dma);
748         return err;
749 }
750
751 int i915_sw_fence_mock_selftests(void)
752 {
753         static const struct i915_subtest tests[] = {
754                 SUBTEST(test_self),
755                 SUBTEST(test_dag),
756                 SUBTEST(test_AB),
757                 SUBTEST(test_ABC),
758                 SUBTEST(test_AB_C),
759                 SUBTEST(test_C_AB),
760                 SUBTEST(test_chain),
761                 SUBTEST(test_ipc),
762                 SUBTEST(test_timer),
763                 SUBTEST(test_dma_fence),
764         };
765
766         return i915_subtests(tests, NULL);
767 }
This page took 0.073014 seconds and 4 git commands to generate.