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