Merge branch 'linus-4.14-rc4-acp-prereq' of git://people.freedesktop.org/~agd5f/linux...
[sfrench/cifs-2.6.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 __i915_sw_fence_call
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         int ret = 0;
527
528         /* Test use of i915_sw_fence as an interprocess signaling mechanism */
529         ipc.in = alloc_fence();
530         if (!ipc.in)
531                 return -ENOMEM;
532         ipc.out = alloc_fence();
533         if (!ipc.out) {
534                 ret = -ENOMEM;
535                 goto err_in;
536         }
537
538         /* use a completion to avoid chicken-and-egg testing */
539         init_completion(&ipc.started);
540
541         ipc.value = 0;
542         INIT_WORK_ONSTACK(&ipc.work, task_ipc);
543         schedule_work(&ipc.work);
544
545         wait_for_completion(&ipc.started);
546
547         usleep_range(1000, 2000);
548         if (READ_ONCE(ipc.value)) {
549                 pr_err("worker updated value before i915_sw_fence was signaled\n");
550                 ret = -EINVAL;
551         }
552
553         i915_sw_fence_commit(ipc.in);
554         i915_sw_fence_wait(ipc.out);
555
556         if (!READ_ONCE(ipc.value)) {
557                 pr_err("worker signaled i915_sw_fence before value was posted\n");
558                 ret = -EINVAL;
559         }
560
561         flush_work(&ipc.work);
562         destroy_work_on_stack(&ipc.work);
563         free_fence(ipc.out);
564 err_in:
565         free_fence(ipc.in);
566         return ret;
567 }
568
569 static int test_timer(void *arg)
570 {
571         unsigned long target, delay;
572         struct timed_fence tf;
573
574         timed_fence_init(&tf, target = jiffies);
575         if (!i915_sw_fence_done(&tf.fence)) {
576                 pr_err("Fence with immediate expiration not signaled\n");
577                 goto err;
578         }
579         timed_fence_fini(&tf);
580
581         for_each_prime_number(delay, i915_selftest.timeout_jiffies/2) {
582                 timed_fence_init(&tf, target = jiffies + delay);
583                 if (i915_sw_fence_done(&tf.fence)) {
584                         pr_err("Fence with future expiration (%lu jiffies) already signaled\n", delay);
585                         goto err;
586                 }
587
588                 i915_sw_fence_wait(&tf.fence);
589                 if (!i915_sw_fence_done(&tf.fence)) {
590                         pr_err("Fence not signaled after wait\n");
591                         goto err;
592                 }
593                 if (time_before(jiffies, target)) {
594                         pr_err("Fence signaled too early, target=%lu, now=%lu\n",
595                                target, jiffies);
596                         goto err;
597                 }
598
599                 timed_fence_fini(&tf);
600         }
601
602         return 0;
603
604 err:
605         timed_fence_fini(&tf);
606         return -EINVAL;
607 }
608
609 int i915_sw_fence_mock_selftests(void)
610 {
611         static const struct i915_subtest tests[] = {
612                 SUBTEST(test_self),
613                 SUBTEST(test_dag),
614                 SUBTEST(test_AB),
615                 SUBTEST(test_ABC),
616                 SUBTEST(test_AB_C),
617                 SUBTEST(test_C_AB),
618                 SUBTEST(test_chain),
619                 SUBTEST(test_ipc),
620                 SUBTEST(test_timer),
621         };
622
623         return i915_subtests(tests, NULL);
624 }