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 }
583