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