Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/ttm/tests: Add test cases dependent on fence signaling

Add test cases that check how the state of dma fences in BO's
reservation object influence the ttm_bo_validation() flow. Do similar
tests for resource manager's move fence.

Signed-off-by: Karolina Stolarek <karolina.stolarek@intel.com>
Reviewed-by: Somalapuram, Amaranath <asomalap@amd.com>
Tested-by: Somalapuram, Amaranath <asomalap@amd.com>
Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/068791a27abd05bf2605f23cc31864a22c20b308.1718192625.git.karolina.stolarek@intel.com

authored by

Karolina Stolarek and committed by
Arunpravin Paneer Selvam
8eda41df 32d618e9

+305
+305
drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
··· 2 2 /* 3 3 * Copyright © 2023 Intel Corporation 4 4 */ 5 + #include <linux/delay.h> 6 + #include <linux/kthread.h> 5 7 6 8 #include <drm/ttm/ttm_resource.h> 7 9 #include <drm/ttm/ttm_placement.h> ··· 15 13 #define BO_SIZE SZ_4K 16 14 #define MANAGER_SIZE SZ_1M 17 15 16 + static struct spinlock fence_lock; 17 + 18 18 struct ttm_bo_validate_test_case { 19 19 const char *description; 20 20 enum ttm_bo_type bo_type; 21 21 u32 mem_type; 22 22 bool with_ttm; 23 + bool no_gpu_wait; 23 24 }; 24 25 25 26 static struct ttm_placement *ttm_placement_kunit_init(struct kunit *test, ··· 38 33 placement->placement = places; 39 34 40 35 return placement; 36 + } 37 + 38 + static const char *fence_name(struct dma_fence *f) 39 + { 40 + return "ttm-bo-validate-fence"; 41 + } 42 + 43 + static const struct dma_fence_ops fence_ops = { 44 + .get_driver_name = fence_name, 45 + .get_timeline_name = fence_name, 46 + }; 47 + 48 + static struct dma_fence *alloc_mock_fence(struct kunit *test) 49 + { 50 + struct dma_fence *fence; 51 + 52 + fence = kunit_kzalloc(test, sizeof(*fence), GFP_KERNEL); 53 + KUNIT_ASSERT_NOT_NULL(test, fence); 54 + 55 + dma_fence_init(fence, &fence_ops, &fence_lock, 0, 0); 56 + 57 + return fence; 58 + } 59 + 60 + static void dma_resv_kunit_active_fence_init(struct kunit *test, 61 + struct dma_resv *resv, 62 + enum dma_resv_usage usage) 63 + { 64 + struct dma_fence *fence; 65 + 66 + fence = alloc_mock_fence(test); 67 + dma_fence_enable_sw_signaling(fence); 68 + 69 + dma_resv_lock(resv, NULL); 70 + dma_resv_reserve_fences(resv, 1); 71 + dma_resv_add_fence(resv, fence, usage); 72 + dma_resv_unlock(resv); 41 73 } 42 74 43 75 static void ttm_bo_validate_case_desc(const struct ttm_bo_validate_test_case *t, ··· 501 459 ttm_mock_manager_fini(priv->ttm_dev, tmp_mem); 502 460 } 503 461 462 + static const struct ttm_bo_validate_test_case ttm_bo_no_placement_cases[] = { 463 + { 464 + .description = "Buffer object in system domain, no page vector", 465 + }, 466 + { 467 + .description = "Buffer object in system domain with an existing page vector", 468 + .with_ttm = true, 469 + }, 470 + }; 471 + 472 + KUNIT_ARRAY_PARAM(ttm_bo_no_placement, ttm_bo_no_placement_cases, 473 + ttm_bo_validate_case_desc); 474 + 475 + static void ttm_bo_validate_no_placement_signaled(struct kunit *test) 476 + { 477 + const struct ttm_bo_validate_test_case *params = test->param_value; 478 + enum ttm_bo_type bo_type = ttm_bo_type_device; 479 + struct ttm_test_devices *priv = test->priv; 480 + u32 size = ALIGN(BO_SIZE, PAGE_SIZE); 481 + struct ttm_operation_ctx ctx = { }; 482 + u32 mem_type = TTM_PL_SYSTEM; 483 + struct ttm_resource_manager *man; 484 + struct ttm_placement *placement; 485 + struct ttm_buffer_object *bo; 486 + struct ttm_place *place; 487 + struct ttm_tt *old_tt; 488 + u32 flags; 489 + int err; 490 + 491 + place = ttm_place_kunit_init(test, mem_type, 0); 492 + man = ttm_manager_type(priv->ttm_dev, mem_type); 493 + 494 + bo = ttm_bo_kunit_init(test, test->priv, size, NULL); 495 + bo->type = bo_type; 496 + 497 + if (params->with_ttm) { 498 + old_tt = priv->ttm_dev->funcs->ttm_tt_create(bo, 0); 499 + ttm_pool_alloc(&priv->ttm_dev->pool, old_tt, &ctx); 500 + bo->ttm = old_tt; 501 + } 502 + 503 + err = ttm_resource_alloc(bo, place, &bo->resource); 504 + KUNIT_EXPECT_EQ(test, err, 0); 505 + KUNIT_ASSERT_EQ(test, man->usage, size); 506 + 507 + placement = kunit_kzalloc(test, sizeof(*placement), GFP_KERNEL); 508 + KUNIT_ASSERT_NOT_NULL(test, placement); 509 + 510 + ttm_bo_reserve(bo, false, false, NULL); 511 + err = ttm_bo_validate(bo, placement, &ctx); 512 + ttm_bo_unreserve(bo); 513 + 514 + KUNIT_EXPECT_EQ(test, err, 0); 515 + KUNIT_ASSERT_EQ(test, man->usage, 0); 516 + KUNIT_ASSERT_NOT_NULL(test, bo->ttm); 517 + KUNIT_EXPECT_EQ(test, ctx.bytes_moved, 0); 518 + 519 + if (params->with_ttm) { 520 + flags = bo->ttm->page_flags; 521 + 522 + KUNIT_ASSERT_PTR_EQ(test, bo->ttm, old_tt); 523 + KUNIT_ASSERT_FALSE(test, flags & TTM_TT_FLAG_PRIV_POPULATED); 524 + KUNIT_ASSERT_TRUE(test, flags & TTM_TT_FLAG_ZERO_ALLOC); 525 + } 526 + 527 + ttm_bo_put(bo); 528 + } 529 + 530 + static int threaded_dma_resv_signal(void *arg) 531 + { 532 + struct ttm_buffer_object *bo = arg; 533 + struct dma_resv *resv = bo->base.resv; 534 + struct dma_resv_iter cursor; 535 + struct dma_fence *fence; 536 + 537 + dma_resv_iter_begin(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP); 538 + dma_resv_for_each_fence_unlocked(&cursor, fence) { 539 + dma_fence_signal(fence); 540 + } 541 + dma_resv_iter_end(&cursor); 542 + 543 + return 0; 544 + } 545 + 546 + static void ttm_bo_validate_no_placement_not_signaled(struct kunit *test) 547 + { 548 + const struct ttm_bo_validate_test_case *params = test->param_value; 549 + enum dma_resv_usage usage = DMA_RESV_USAGE_BOOKKEEP; 550 + u32 size = ALIGN(BO_SIZE, PAGE_SIZE); 551 + struct ttm_operation_ctx ctx = { }; 552 + u32 mem_type = TTM_PL_SYSTEM; 553 + struct ttm_placement *placement; 554 + struct ttm_buffer_object *bo; 555 + struct task_struct *task; 556 + struct ttm_place *place; 557 + int err; 558 + 559 + place = ttm_place_kunit_init(test, mem_type, 0); 560 + 561 + bo = ttm_bo_kunit_init(test, test->priv, size, NULL); 562 + bo->type = params->bo_type; 563 + 564 + err = ttm_resource_alloc(bo, place, &bo->resource); 565 + KUNIT_EXPECT_EQ(test, err, 0); 566 + 567 + placement = kunit_kzalloc(test, sizeof(*placement), GFP_KERNEL); 568 + KUNIT_ASSERT_NOT_NULL(test, placement); 569 + 570 + /* Create an active fence to simulate a non-idle resv object */ 571 + spin_lock_init(&fence_lock); 572 + dma_resv_kunit_active_fence_init(test, bo->base.resv, usage); 573 + 574 + task = kthread_create(threaded_dma_resv_signal, bo, "dma-resv-signal"); 575 + if (IS_ERR(task)) 576 + KUNIT_FAIL(test, "Couldn't create dma resv signal task\n"); 577 + 578 + wake_up_process(task); 579 + ttm_bo_reserve(bo, false, false, NULL); 580 + err = ttm_bo_validate(bo, placement, &ctx); 581 + ttm_bo_unreserve(bo); 582 + 583 + KUNIT_EXPECT_EQ(test, err, 0); 584 + KUNIT_ASSERT_NOT_NULL(test, bo->ttm); 585 + KUNIT_ASSERT_NULL(test, bo->resource); 586 + KUNIT_ASSERT_NULL(test, bo->bulk_move); 587 + KUNIT_EXPECT_EQ(test, ctx.bytes_moved, 0); 588 + 589 + if (bo->type != ttm_bo_type_sg) 590 + KUNIT_ASSERT_PTR_EQ(test, bo->base.resv, &bo->base._resv); 591 + 592 + /* Make sure we have an idle object at this point */ 593 + dma_resv_wait_timeout(bo->base.resv, usage, false, MAX_SCHEDULE_TIMEOUT); 594 + 595 + ttm_bo_put(bo); 596 + } 597 + 598 + static void ttm_bo_validate_move_fence_signaled(struct kunit *test) 599 + { 600 + enum ttm_bo_type bo_type = ttm_bo_type_device; 601 + struct ttm_test_devices *priv = test->priv; 602 + u32 size = ALIGN(BO_SIZE, PAGE_SIZE); 603 + struct ttm_operation_ctx ctx = { }; 604 + u32 mem_type = TTM_PL_SYSTEM; 605 + struct ttm_resource_manager *man; 606 + struct ttm_placement *placement; 607 + struct ttm_buffer_object *bo; 608 + struct ttm_place *place; 609 + int err; 610 + 611 + man = ttm_manager_type(priv->ttm_dev, mem_type); 612 + man->move = dma_fence_get_stub(); 613 + 614 + bo = ttm_bo_kunit_init(test, test->priv, size, NULL); 615 + bo->type = bo_type; 616 + 617 + place = ttm_place_kunit_init(test, mem_type, 0); 618 + placement = ttm_placement_kunit_init(test, place, 1); 619 + 620 + ttm_bo_reserve(bo, false, false, NULL); 621 + err = ttm_bo_validate(bo, placement, &ctx); 622 + ttm_bo_unreserve(bo); 623 + 624 + KUNIT_EXPECT_EQ(test, err, 0); 625 + KUNIT_EXPECT_EQ(test, bo->resource->mem_type, mem_type); 626 + KUNIT_EXPECT_EQ(test, ctx.bytes_moved, size); 627 + 628 + ttm_bo_put(bo); 629 + dma_fence_put(man->move); 630 + } 631 + 632 + static const struct ttm_bo_validate_test_case ttm_bo_validate_wait_cases[] = { 633 + { 634 + .description = "Waits for GPU", 635 + .no_gpu_wait = false, 636 + }, 637 + { 638 + .description = "Tries to lock straight away", 639 + .no_gpu_wait = true, 640 + }, 641 + }; 642 + 643 + KUNIT_ARRAY_PARAM(ttm_bo_validate_wait, ttm_bo_validate_wait_cases, 644 + ttm_bo_validate_case_desc); 645 + 646 + static int threaded_fence_signal(void *arg) 647 + { 648 + struct dma_fence *fence = arg; 649 + 650 + msleep(20); 651 + 652 + return dma_fence_signal(fence); 653 + } 654 + 655 + static void ttm_bo_validate_move_fence_not_signaled(struct kunit *test) 656 + { 657 + const struct ttm_bo_validate_test_case *params = test->param_value; 658 + struct ttm_operation_ctx ctx_init = { }, 659 + ctx_val = { .no_wait_gpu = params->no_gpu_wait }; 660 + u32 fst_mem = TTM_PL_VRAM, snd_mem = TTM_PL_VRAM + 1; 661 + struct ttm_placement *placement_init, *placement_val; 662 + enum ttm_bo_type bo_type = ttm_bo_type_device; 663 + struct ttm_test_devices *priv = test->priv; 664 + u32 size = ALIGN(BO_SIZE, PAGE_SIZE); 665 + struct ttm_place *init_place, places[2]; 666 + struct ttm_resource_manager *man; 667 + struct ttm_buffer_object *bo; 668 + struct task_struct *task; 669 + int err; 670 + 671 + init_place = ttm_place_kunit_init(test, TTM_PL_SYSTEM, 0); 672 + placement_init = ttm_placement_kunit_init(test, init_place, 1); 673 + 674 + bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL); 675 + KUNIT_ASSERT_NOT_NULL(test, bo); 676 + 677 + drm_gem_private_object_init(priv->drm, &bo->base, size); 678 + 679 + err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement_init, 680 + PAGE_SIZE, &ctx_init, NULL, NULL, 681 + &dummy_ttm_bo_destroy); 682 + KUNIT_EXPECT_EQ(test, err, 0); 683 + 684 + ttm_mock_manager_init(priv->ttm_dev, fst_mem, MANAGER_SIZE); 685 + ttm_mock_manager_init(priv->ttm_dev, snd_mem, MANAGER_SIZE); 686 + 687 + places[0] = (struct ttm_place){ .mem_type = fst_mem, .flags = TTM_PL_FLAG_DESIRED }; 688 + places[1] = (struct ttm_place){ .mem_type = snd_mem, .flags = TTM_PL_FLAG_FALLBACK }; 689 + placement_val = ttm_placement_kunit_init(test, places, 2); 690 + 691 + spin_lock_init(&fence_lock); 692 + man = ttm_manager_type(priv->ttm_dev, fst_mem); 693 + man->move = alloc_mock_fence(test); 694 + 695 + task = kthread_create(threaded_fence_signal, man->move, "move-fence-signal"); 696 + if (IS_ERR(task)) 697 + KUNIT_FAIL(test, "Couldn't create move fence signal task\n"); 698 + 699 + wake_up_process(task); 700 + err = ttm_bo_validate(bo, placement_val, &ctx_val); 701 + dma_resv_unlock(bo->base.resv); 702 + 703 + dma_fence_wait_timeout(man->move, false, MAX_SCHEDULE_TIMEOUT); 704 + 705 + KUNIT_EXPECT_EQ(test, err, 0); 706 + KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, size); 707 + 708 + if (params->no_gpu_wait) 709 + KUNIT_EXPECT_EQ(test, bo->resource->mem_type, snd_mem); 710 + else 711 + KUNIT_EXPECT_EQ(test, bo->resource->mem_type, fst_mem); 712 + 713 + ttm_bo_put(bo); 714 + ttm_mock_manager_fini(priv->ttm_dev, fst_mem); 715 + ttm_mock_manager_fini(priv->ttm_dev, snd_mem); 716 + } 717 + 504 718 static struct kunit_case ttm_bo_validate_test_cases[] = { 505 719 KUNIT_CASE_PARAM(ttm_bo_init_reserved_sys_man, ttm_bo_types_gen_params), 506 720 KUNIT_CASE_PARAM(ttm_bo_init_reserved_mock_man, ttm_bo_types_gen_params), ··· 769 471 KUNIT_CASE(ttm_bo_validate_pinned), 770 472 KUNIT_CASE(ttm_bo_validate_busy_placement), 771 473 KUNIT_CASE_PARAM(ttm_bo_validate_multihop, ttm_bo_types_gen_params), 474 + KUNIT_CASE_PARAM(ttm_bo_validate_no_placement_signaled, 475 + ttm_bo_no_placement_gen_params), 476 + KUNIT_CASE_PARAM(ttm_bo_validate_no_placement_not_signaled, 477 + ttm_bo_types_gen_params), 478 + KUNIT_CASE(ttm_bo_validate_move_fence_signaled), 479 + KUNIT_CASE_PARAM(ttm_bo_validate_move_fence_not_signaled, 480 + ttm_bo_validate_wait_gen_params), 772 481 {} 773 482 }; 774 483