i915_sw_fence.c (14816B)
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 31static int 32fence_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 46static 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 58static void free_fence(struct i915_sw_fence *fence) 59{ 60 i915_sw_fence_fini(fence); 61 kfree(fence); 62} 63 64static 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 80static 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 96static 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 } 166err_C: 167 free_fence(C); 168err_B: 169 free_fence(B); 170err_A: 171 free_fence(A); 172 return ret; 173} 174 175static 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; 216err_B: 217 free_fence(B); 218err_A: 219 free_fence(A); 220 return ret; 221} 222 223static 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 } 294err_C: 295 free_fence(C); 296err_B: 297 free_fence(B); 298err_A: 299 free_fence(A); 300 return ret; 301} 302 303static 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 371err_C: 372 free_fence(C); 373err_B: 374 free_fence(B); 375err_A: 376 free_fence(A); 377 return ret; 378} 379 380static 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 441err_C: 442 free_fence(C); 443err_B: 444 free_fence(B); 445err_A: 446 free_fence(A); 447 return ret; 448} 449 450static 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 498err: 499 for (i = 0; i < nfences; i++) 500 free_fence(fences[i]); 501 kfree(fences); 502 return ret; 503} 504 505struct task_ipc { 506 struct work_struct work; 507 struct completion started; 508 struct i915_sw_fence *in, *out; 509 int value; 510}; 511 512static 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 523static 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); 564err_in: 565 free_fence(ipc.in); 566 return ret; 567} 568 569static int test_timer(void *arg) 570{ 571 unsigned long target, delay; 572 struct timed_fence tf; 573 574 preempt_disable(); 575 timed_fence_init(&tf, target = jiffies); 576 if (!i915_sw_fence_done(&tf.fence)) { 577 pr_err("Fence with immediate expiration not signaled\n"); 578 goto err; 579 } 580 preempt_enable(); 581 timed_fence_fini(&tf); 582 583 for_each_prime_number(delay, i915_selftest.timeout_jiffies/2) { 584 preempt_disable(); 585 timed_fence_init(&tf, target = jiffies + delay); 586 if (i915_sw_fence_done(&tf.fence)) { 587 pr_err("Fence with future expiration (%lu jiffies) already signaled\n", delay); 588 goto err; 589 } 590 preempt_enable(); 591 592 i915_sw_fence_wait(&tf.fence); 593 594 preempt_disable(); 595 if (!i915_sw_fence_done(&tf.fence)) { 596 pr_err("Fence not signaled after wait\n"); 597 goto err; 598 } 599 if (time_before(jiffies, target)) { 600 pr_err("Fence signaled too early, target=%lu, now=%lu\n", 601 target, jiffies); 602 goto err; 603 } 604 preempt_enable(); 605 timed_fence_fini(&tf); 606 } 607 608 return 0; 609 610err: 611 preempt_enable(); 612 timed_fence_fini(&tf); 613 return -EINVAL; 614} 615 616static const char *mock_name(struct dma_fence *fence) 617{ 618 return "mock"; 619} 620 621static const struct dma_fence_ops mock_fence_ops = { 622 .get_driver_name = mock_name, 623 .get_timeline_name = mock_name, 624}; 625 626static DEFINE_SPINLOCK(mock_fence_lock); 627 628static struct dma_fence *alloc_dma_fence(void) 629{ 630 struct dma_fence *dma; 631 632 dma = kmalloc(sizeof(*dma), GFP_KERNEL); 633 if (dma) 634 dma_fence_init(dma, &mock_fence_ops, &mock_fence_lock, 0, 0); 635 636 return dma; 637} 638 639static struct i915_sw_fence * 640wrap_dma_fence(struct dma_fence *dma, unsigned long delay) 641{ 642 struct i915_sw_fence *fence; 643 int err; 644 645 fence = alloc_fence(); 646 if (!fence) 647 return ERR_PTR(-ENOMEM); 648 649 err = i915_sw_fence_await_dma_fence(fence, dma, delay, GFP_NOWAIT); 650 i915_sw_fence_commit(fence); 651 if (err < 0) { 652 free_fence(fence); 653 return ERR_PTR(err); 654 } 655 656 return fence; 657} 658 659static int test_dma_fence(void *arg) 660{ 661 struct i915_sw_fence *timeout = NULL, *not = NULL; 662 unsigned long delay = i915_selftest.timeout_jiffies; 663 unsigned long end, sleep; 664 struct dma_fence *dma; 665 int err; 666 667 dma = alloc_dma_fence(); 668 if (!dma) 669 return -ENOMEM; 670 671 timeout = wrap_dma_fence(dma, delay); 672 if (IS_ERR(timeout)) { 673 err = PTR_ERR(timeout); 674 goto err; 675 } 676 677 not = wrap_dma_fence(dma, 0); 678 if (IS_ERR(not)) { 679 err = PTR_ERR(not); 680 goto err; 681 } 682 683 err = -EINVAL; 684 if (i915_sw_fence_done(timeout) || i915_sw_fence_done(not)) { 685 pr_err("Fences immediately signaled\n"); 686 goto err; 687 } 688 689 /* We round the timeout for the fence up to the next second */ 690 end = round_jiffies_up(jiffies + delay); 691 692 sleep = jiffies_to_usecs(delay) / 3; 693 usleep_range(sleep, 2 * sleep); 694 if (time_after(jiffies, end)) { 695 pr_debug("Slept too long, delay=%lu, (target=%lu, now=%lu) skipping\n", 696 delay, end, jiffies); 697 goto skip; 698 } 699 700 if (i915_sw_fence_done(timeout) || i915_sw_fence_done(not)) { 701 pr_err("Fences signaled too early\n"); 702 goto err; 703 } 704 705 if (!wait_event_timeout(timeout->wait, 706 i915_sw_fence_done(timeout), 707 2 * (end - jiffies) + 1)) { 708 pr_err("Timeout fence unsignaled!\n"); 709 goto err; 710 } 711 712 if (i915_sw_fence_done(not)) { 713 pr_err("No timeout fence signaled!\n"); 714 goto err; 715 } 716 717skip: 718 dma_fence_signal(dma); 719 720 if (!i915_sw_fence_done(timeout) || !i915_sw_fence_done(not)) { 721 pr_err("Fences unsignaled\n"); 722 goto err; 723 } 724 725 free_fence(not); 726 free_fence(timeout); 727 dma_fence_put(dma); 728 729 return 0; 730 731err: 732 dma_fence_signal(dma); 733 if (!IS_ERR_OR_NULL(timeout)) 734 free_fence(timeout); 735 if (!IS_ERR_OR_NULL(not)) 736 free_fence(not); 737 dma_fence_put(dma); 738 return err; 739} 740 741int i915_sw_fence_mock_selftests(void) 742{ 743 static const struct i915_subtest tests[] = { 744 SUBTEST(test_self), 745 SUBTEST(test_dag), 746 SUBTEST(test_AB), 747 SUBTEST(test_ABC), 748 SUBTEST(test_AB_C), 749 SUBTEST(test_C_AB), 750 SUBTEST(test_chain), 751 SUBTEST(test_ipc), 752 SUBTEST(test_timer), 753 SUBTEST(test_dma_fence), 754 }; 755 756 return i915_subtests(tests, NULL); 757}