Merge branch 'for-4.13-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
[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
28 #include "../i915_selftest.h"
29
30 static int __i915_sw_fence_call
31 fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
32 {
33         switch (state) {
34         case FENCE_COMPLETE:
35                 break;
36
37         case FENCE_FREE:
38                 /* Leave the fence for the caller to free it after testing */
39                 break;
40         }
41
42         return NOTIFY_DONE;
43 }
44
45 static struct i915_sw_fence *alloc_fence(void)
46 {
47         struct i915_sw_fence *fence;
48
49         fence = kmalloc(sizeof(*fence), GFP_KERNEL);
50         if (!fence)
51                 return NULL;
52
53         i915_sw_fence_init(fence, fence_notify);
54         return fence;
55 }
56
57 static void free_fence(struct i915_sw_fence *fence)
58 {
59         i915_sw_fence_fini(fence);
60         kfree(fence);
61 }
62
63 static int __test_self(struct i915_sw_fence *fence)
64 {
65         if (i915_sw_fence_done(fence))
66                 return -EINVAL;
67
68         i915_sw_fence_commit(fence);
69         if (!i915_sw_fence_done(fence))
70                 return -EINVAL;
71
72         i915_sw_fence_wait(fence);
73         if (!i915_sw_fence_done(fence))
74                 return -EINVAL;
75
76         return 0;
77 }
78
79 static int test_self(void *arg)
80 {
81         struct i915_sw_fence *fence;
82         int ret;
83
84         /* Test i915_sw_fence signaling and completion testing */
85         fence = alloc_fence();
86         if (!fence)
87                 return -ENOMEM;
88
89         ret = __test_self(fence);
90
91         free_fence(fence);
92         return ret;
93 }
94
95 static int test_dag(void *arg)
96 {
97         struct i915_sw_fence *A, *B, *C;
98         int ret = -EINVAL;
99
100         /* Test detection of cycles within the i915_sw_fence graphs */
101         if (!IS_ENABLED(CONFIG_DRM_I915_SW_FENCE_CHECK_DAG))
102                 return 0;
103
104         A = alloc_fence();
105         if (!A)
106                 return -ENOMEM;
107
108         if (i915_sw_fence_await_sw_fence_gfp(A, A, GFP_KERNEL) != -EINVAL) {
109                 pr_err("recursive cycle not detected (AA)\n");
110                 goto err_A;
111         }
112
113         B = alloc_fence();
114         if (!B) {
115                 ret = -ENOMEM;
116                 goto err_A;
117         }
118
119         i915_sw_fence_await_sw_fence_gfp(A, B, GFP_KERNEL);
120         if (i915_sw_fence_await_sw_fence_gfp(B, A, GFP_KERNEL) != -EINVAL) {
121                 pr_err("single depth cycle not detected (BAB)\n");
122                 goto err_B;
123         }
124
125         C = alloc_fence();
126         if (!C) {
127                 ret = -ENOMEM;
128                 goto err_B;
129         }
130
131         if (i915_sw_fence_await_sw_fence_gfp(B, C, GFP_KERNEL) == -EINVAL) {
132                 pr_err("invalid cycle detected\n");
133                 goto err_C;
134         }
135         if (i915_sw_fence_await_sw_fence_gfp(C, B, GFP_KERNEL) != -EINVAL) {
136                 pr_err("single depth cycle not detected (CBC)\n");
137                 goto err_C;
138         }
139         if (i915_sw_fence_await_sw_fence_gfp(C, A, GFP_KERNEL) != -EINVAL) {
140                 pr_err("cycle not detected (BA, CB, AC)\n");
141                 goto err_C;
142         }
143         if (i915_sw_fence_await_sw_fence_gfp(A, C, GFP_KERNEL) == -EINVAL) {
144                 pr_err("invalid cycle detected\n");
145                 goto err_C;
146         }
147
148         i915_sw_fence_commit(A);
149         i915_sw_fence_commit(B);
150         i915_sw_fence_commit(C);
151
152         ret = 0;
153         if (!i915_sw_fence_done(C)) {
154                 pr_err("fence C not done\n");
155                 ret = -EINVAL;
156         }
157         if (!i915_sw_fence_done(B)) {
158                 pr_err("fence B not done\n");
159                 ret = -EINVAL;
160         }
161         if (!i915_sw_fence_done(A)) {
162                 pr_err("fence A not done\n");
163                 ret = -EINVAL;
164         }
165 err_C:
166         free_fence(C);
167 err_B:
168         free_fence(B);
169 err_A:
170         free_fence(A);
171         return ret;
172 }
173
174 static int test_AB(void *arg)
175 {
176         struct i915_sw_fence *A, *B;
177         int ret;
178
179         /* Test i915_sw_fence (A) waiting on an event source (B) */
180         A = alloc_fence();
181         if (!A)
182                 return -ENOMEM;
183         B = alloc_fence();
184         if (!B) {
185                 ret = -ENOMEM;
186                 goto err_A;
187         }
188
189         ret = i915_sw_fence_await_sw_fence_gfp(A, B, GFP_KERNEL);
190         if (ret < 0)
191                 goto err_B;
192         if (ret == 0) {
193                 pr_err("Incorrectly reported fence A was complete before await\n");
194                 ret = -EINVAL;
195                 goto err_B;
196         }
197
198         ret = -EINVAL;
199         i915_sw_fence_commit(A);
200         if (i915_sw_fence_done(A))
201                 goto err_B;
202
203         i915_sw_fence_commit(B);
204         if (!i915_sw_fence_done(B)) {
205                 pr_err("Fence B is not done\n");
206                 goto err_B;
207         }
208
209         if (!i915_sw_fence_done(A)) {
210                 pr_err("Fence A is not done\n");
211                 goto err_B;
212         }
213
214         ret = 0;
215 err_B:
216         free_fence(B);
217 err_A:
218         free_fence(A);
219         return ret;
220 }
221
222 static int test_ABC(void *arg)
223 {
224         struct i915_sw_fence *A, *B, *C;
225         int ret;
226
227         /* Test a chain of fences, A waits on B who waits on C */
228         A = alloc_fence();
229         if (!A)
230                 return -ENOMEM;
231
232         B = alloc_fence();
233         if (!B) {
234                 ret = -ENOMEM;
235                 goto err_A;
236         }
237
238         C = alloc_fence();
239         if (!C) {
240                 ret = -ENOMEM;
241                 goto err_B;
242         }
243
244         ret = i915_sw_fence_await_sw_fence_gfp(A, B, GFP_KERNEL);
245         if (ret < 0)
246                 goto err_C;
247         if (ret == 0) {
248                 pr_err("Incorrectly reported fence B was complete before await\n");
249                 goto err_C;
250         }
251
252         ret = i915_sw_fence_await_sw_fence_gfp(B, C, GFP_KERNEL);
253         if (ret < 0)
254                 goto err_C;
255         if (ret == 0) {
256                 pr_err("Incorrectly reported fence C was complete before await\n");
257                 goto err_C;
258         }
259
260         ret = -EINVAL;
261         i915_sw_fence_commit(A);
262         if (i915_sw_fence_done(A)) {
263                 pr_err("Fence A completed early\n");
264                 goto err_C;
265         }
266
267         i915_sw_fence_commit(B);
268         if (i915_sw_fence_done(B)) {
269                 pr_err("Fence B completed early\n");
270                 goto err_C;
271         }
272
273         if (i915_sw_fence_done(A)) {
274                 pr_err("Fence A completed early (after signaling B)\n");
275                 goto err_C;
276         }
277
278         i915_sw_fence_commit(C);
279
280         ret = 0;
281         if (!i915_sw_fence_done(C)) {
282                 pr_err("Fence C not done\n");
283                 ret = -EINVAL;
284         }
285         if (!i915_sw_fence_done(B)) {
286                 pr_err("Fence B not done\n");
287                 ret = -EINVAL;
288         }
289         if (!i915_sw_fence_done(A)) {
290                 pr_err("Fence A not done\n");
291                 ret = -EINVAL;
292         }
293 err_C:
294         free_fence(C);
295 err_B:
296         free_fence(B);
297 err_A:
298         free_fence(A);
299         return ret;
300 }
301
302 static int test_AB_C(void *arg)
303 {
304         struct i915_sw_fence *A, *B, *C;
305         int ret = -EINVAL;
306
307         /* Test multiple fences (AB) waiting on a single event (C) */
308         A = alloc_fence();
309         if (!A)
310                 return -ENOMEM;
311
312         B = alloc_fence();
313         if (!B) {
314                 ret = -ENOMEM;
315                 goto err_A;
316         }
317
318         C = alloc_fence();
319         if (!C) {
320                 ret = -ENOMEM;
321                 goto err_B;
322         }
323
324         ret = i915_sw_fence_await_sw_fence_gfp(A, C, GFP_KERNEL);
325         if (ret < 0)
326                 goto err_C;
327         if (ret == 0) {
328                 ret = -EINVAL;
329                 goto err_C;
330         }
331
332         ret = i915_sw_fence_await_sw_fence_gfp(B, C, GFP_KERNEL);
333         if (ret < 0)
334                 goto err_C;
335         if (ret == 0) {
336                 ret = -EINVAL;
337                 goto err_C;
338         }
339
340         i915_sw_fence_commit(A);
341         i915_sw_fence_commit(B);
342
343         ret = 0;
344         if (i915_sw_fence_done(A)) {
345                 pr_err("Fence A completed early\n");
346                 ret = -EINVAL;
347         }
348
349         if (i915_sw_fence_done(B)) {
350                 pr_err("Fence B completed early\n");
351                 ret = -EINVAL;
352         }
353
354         i915_sw_fence_commit(C);
355         if (!i915_sw_fence_done(C)) {
356                 pr_err("Fence C not done\n");
357                 ret = -EINVAL;
358         }
359
360         if (!i915_sw_fence_done(B)) {
361                 pr_err("Fence B not done\n");
362                 ret = -EINVAL;
363         }
364
365         if (!i915_sw_fence_done(A)) {
366                 pr_err("Fence A not done\n");
367                 ret = -EINVAL;
368         }
369
370 err_C:
371         free_fence(C);
372 err_B:
373         free_fence(B);
374 err_A:
375         free_fence(A);
376         return ret;
377 }
378
379 static int test_C_AB(void *arg)
380 {
381         struct i915_sw_fence *A, *B, *C;
382         int ret;
383
384         /* Test multiple event sources (A,B) for a single fence (C) */
385         A = alloc_fence();
386         if (!A)
387                 return -ENOMEM;
388
389         B = alloc_fence();
390         if (!B) {
391                 ret = -ENOMEM;
392                 goto err_A;
393         }
394
395         C = alloc_fence();
396         if (!C) {
397                 ret = -ENOMEM;
398                 goto err_B;
399         }
400
401         ret = i915_sw_fence_await_sw_fence_gfp(C, A, GFP_KERNEL);
402         if (ret < 0)
403                 goto err_C;
404         if (ret == 0) {
405                 ret = -EINVAL;
406                 goto err_C;
407         }
408
409         ret = i915_sw_fence_await_sw_fence_gfp(C, B, GFP_KERNEL);
410         if (ret < 0)
411                 goto err_C;
412         if (ret == 0) {
413                 ret = -EINVAL;
414                 goto err_C;
415         }
416
417         ret = 0;
418         i915_sw_fence_commit(C);
419         if (i915_sw_fence_done(C))
420                 ret = -EINVAL;
421
422         i915_sw_fence_commit(A);
423         i915_sw_fence_commit(B);
424
425         if (!i915_sw_fence_done(A)) {
426                 pr_err("Fence A not done\n");
427                 ret = -EINVAL;
428         }
429
430         if (!i915_sw_fence_done(B)) {
431                 pr_err("Fence B not done\n");
432                 ret = -EINVAL;
433         }
434
435         if (!i915_sw_fence_done(C)) {
436                 pr_err("Fence C not done\n");
437                 ret = -EINVAL;
438         }
439
440 err_C:
441         free_fence(C);
442 err_B:
443         free_fence(B);
444 err_A:
445         free_fence(A);
446         return ret;
447 }
448
449 static int test_chain(void *arg)
450 {
451         int nfences = 4096;
452         struct i915_sw_fence **fences;
453         int ret, i;
454
455         /* Test a long chain of fences */
456         fences = kmalloc_array(nfences, sizeof(*fences), GFP_KERNEL);
457         if (!fences)
458                 return -ENOMEM;
459
460         for (i = 0; i < nfences; i++) {
461                 fences[i] = alloc_fence();
462                 if (!fences[i]) {
463                         nfences = i;
464                         ret = -ENOMEM;
465                         goto err;
466                 }
467
468                 if (i > 0) {
469                         ret = i915_sw_fence_await_sw_fence_gfp(fences[i],
470                                                                fences[i - 1],
471                                                                GFP_KERNEL);
472                         if (ret < 0) {
473                                 nfences = i + 1;
474                                 goto err;
475                         }
476
477                         i915_sw_fence_commit(fences[i]);
478                 }
479         }
480
481         ret = 0;
482         for (i = nfences; --i; ) {
483                 if (i915_sw_fence_done(fences[i])) {
484                         if (ret == 0)
485                                 pr_err("Fence[%d] completed early\n", i);
486                         ret = -EINVAL;
487                 }
488         }
489         i915_sw_fence_commit(fences[0]);
490         for (i = 0; ret == 0 && i < nfences; i++) {
491                 if (!i915_sw_fence_done(fences[i])) {
492                         pr_err("Fence[%d] is not done\n", i);
493                         ret = -EINVAL;
494                 }
495         }
496
497 err:
498         for (i = 0; i < nfences; i++)
499                 free_fence(fences[i]);
500         kfree(fences);
501         return ret;
502 }
503
504 struct task_ipc {
505         struct work_struct work;
506         struct completion started;
507         struct i915_sw_fence *in, *out;
508         int value;
509 };
510
511 static void task_ipc(struct work_struct *work)
512 {
513         struct task_ipc *ipc = container_of(work, typeof(*ipc), work);
514
515         complete(&ipc->started);
516
517         i915_sw_fence_wait(ipc->in);
518         smp_store_mb(ipc->value, 1);
519         i915_sw_fence_commit(ipc->out);
520 }
521
522 static int test_ipc(void *arg)
523 {
524         struct task_ipc ipc;
525         int ret = 0;
526
527         /* Test use of i915_sw_fence as an interprocess signaling mechanism */
528         ipc.in = alloc_fence();
529         if (!ipc.in)
530                 return -ENOMEM;
531         ipc.out = alloc_fence();
532         if (!ipc.out) {
533                 ret = -ENOMEM;
534                 goto err_in;
535         }
536
537         /* use a completion to avoid chicken-and-egg testing */
538         init_completion(&ipc.started);
539
540         ipc.value = 0;
541         INIT_WORK_ONSTACK(&ipc.work, task_ipc);
542         schedule_work(&ipc.work);
543
544         wait_for_completion(&ipc.started);
545
546         usleep_range(1000, 2000);
547         if (READ_ONCE(ipc.value)) {
548                 pr_err("worker updated value before i915_sw_fence was signaled\n");
549                 ret = -EINVAL;
550         }
551
552         i915_sw_fence_commit(ipc.in);
553         i915_sw_fence_wait(ipc.out);
554
555         if (!READ_ONCE(ipc.value)) {
556                 pr_err("worker signaled i915_sw_fence before value was posted\n");
557                 ret = -EINVAL;
558         }
559
560         flush_work(&ipc.work);
561         destroy_work_on_stack(&ipc.work);
562         free_fence(ipc.out);
563 err_in:
564         free_fence(ipc.in);
565         return ret;
566 }
567
568 int i915_sw_fence_mock_selftests(void)
569 {
570         static const struct i915_subtest tests[] = {
571                 SUBTEST(test_self),
572                 SUBTEST(test_dag),
573                 SUBTEST(test_AB),
574                 SUBTEST(test_ABC),
575                 SUBTEST(test_AB_C),
576                 SUBTEST(test_C_AB),
577                 SUBTEST(test_chain),
578                 SUBTEST(test_ipc),
579         };
580
581         return i915_subtests(tests, NULL);
582 }