Add a new KUnit test gpu_test_buddy_addr_to_block() that validates the
gpu_buddy_allocated_addr_to_block() helper which traces a physical
address back to its allocated buddy block.

The test covers:
- Exact address matching returns the correct allocated block
- Internal offset query within an allocated block
- Query of the free companion block returns NULL
- Out-of-bounds address returns ERR_PTR(-ENXIO)

Signed-off-by: Tejas Upadhyay <[email protected]>
---
 drivers/gpu/tests/gpu_buddy_test.c | 98 ++++++++++++++++++++++++++++++
 1 file changed, 98 insertions(+)

diff --git a/drivers/gpu/tests/gpu_buddy_test.c 
b/drivers/gpu/tests/gpu_buddy_test.c
index 89698563c61b..1f4048d7c823 100644
--- a/drivers/gpu/tests/gpu_buddy_test.c
+++ b/drivers/gpu/tests/gpu_buddy_test.c
@@ -1422,6 +1422,103 @@ static void 
gpu_test_buddy_alloc_exceeds_max_order(struct kunit *test)
        gpu_buddy_fini(&mm);
 }
 
+struct test_mgr {
+       struct gpu_buddy mm; /* Buddy memory manager */
+       struct mutex lock; /* Lock to protect vram access */
+       struct list_head allocated_list; /* Safe context tracking; lives as 
long as mgr */
+};
+
+/* Action 1: Safely destroys the tracking mutex structure */
+static void kunit_action_mutex_destroy(void *lock)
+{
+       mutex_destroy((struct mutex *)lock);
+}
+
+/* Action 2: Safely tears down the initialized buddy allocator instance */
+static void kunit_action_buddy_fini(void *mm)
+{
+       gpu_buddy_fini((struct gpu_buddy *)mm);
+}
+
+/* Action 3: Safely unlocks the tracking mutex if it is currently held */
+static void kunit_action_mutex_unlock(void *lock)
+{
+       struct mutex *m = lock;
+
+       mutex_unlock(m);
+}
+
+/* Action 4: Safely frees allocated blocks using the persistent mgr context 
frame */
+static void kunit_action_free_blocks(void *mgr_ctx)
+{
+       struct test_mgr *mgr = mgr_ctx;
+
+       if (!list_empty(&mgr->allocated_list))
+               gpu_buddy_free_list(&mgr->mm, &mgr->allocated_list, 0);
+}
+
+static void gpu_test_buddy_addr_to_block(struct kunit *test)
+{
+       struct test_mgr *mgr;
+       struct gpu_buddy_block *allocated_block, *found_block;
+       u64 test_size = SZ_4M;
+       u64 chunk_size = SZ_4K;
+       u64 alloc_size = SZ_2M;
+       u64 target_addr;
+
+       mgr = kunit_kzalloc(test, sizeof(*mgr), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mgr);
+       INIT_LIST_HEAD(&mgr->allocated_list);
+
+       /* 1. Register Mutex Structure Destruction */
+       mutex_init(&mgr->lock);
+       KUNIT_ASSERT_EQ(test, kunit_add_action(test, 
kunit_action_mutex_destroy, &mgr->lock), 0);
+
+       /* 2. Register Buddy Manager Infrastructure Teardown */
+       KUNIT_ASSERT_EQ(test, gpu_buddy_init(&mgr->mm, test_size, chunk_size), 
0);
+       KUNIT_ASSERT_EQ(test, kunit_add_action(test, kunit_action_buddy_fini, 
&mgr->mm), 0);
+
+       /* Set up driver lock tracking structure hooks */
+       gpu_buddy_driver_set_lock(&mgr->mm, &mgr->lock);
+
+       /*
+        * Cleanup runs in LIFO order:
+        *   4. free_blocks  (lock held)
+        *   3. mutex_unlock
+        *   2. buddy_fini
+        *   1. mutex_destroy
+        */
+       mutex_lock(&mgr->lock);
+       KUNIT_ASSERT_EQ(test, kunit_add_action(test, kunit_action_mutex_unlock, 
&mgr->lock), 0);
+
+       /* 3. Allocate blocks and register block cleanup action inside the lock 
context */
+       KUNIT_ASSERT_EQ(test, gpu_buddy_alloc_blocks(&mgr->mm, 0, test_size, 
alloc_size,
+                                                    chunk_size, 
&mgr->allocated_list, 0), 0);
+       KUNIT_ASSERT_EQ(test, kunit_add_action(test, kunit_action_free_blocks, 
mgr), 0);
+
+       allocated_block = list_first_entry(&mgr->allocated_list, struct 
gpu_buddy_block, link);
+       KUNIT_ASSERT_EQ(test, gpu_buddy_block_size(&mgr->mm, allocated_block), 
alloc_size);
+       target_addr = gpu_buddy_block_offset(allocated_block);
+
+       /* ---------------- RUN TRACKING VALIDATIONS ---------------- */
+
+       /* Test Case 1: Exact Address Matching */
+       found_block = gpu_buddy_allocated_addr_to_block(&mgr->mm, target_addr);
+       KUNIT_EXPECT_PTR_EQ(test, found_block, allocated_block);
+
+       /* Test Case 2: Internal Footprint Offset Queries */
+       found_block = gpu_buddy_allocated_addr_to_block(&mgr->mm, target_addr + 
SZ_1M);
+       KUNIT_EXPECT_PTR_EQ(test, found_block, allocated_block);
+
+       /* Test Case 3: Free Companion Memory Queries */
+       found_block = gpu_buddy_allocated_addr_to_block(&mgr->mm, target_addr ? 
0 : alloc_size);
+       KUNIT_EXPECT_PTR_EQ(test, found_block, NULL);
+
+       /* Test Case 4: Out-of-Bounds Queries (Returns ERR_PTR(-ENXIO)) */
+       found_block = gpu_buddy_allocated_addr_to_block(&mgr->mm, test_size + 
SZ_1M);
+       KUNIT_EXPECT_PTR_EQ(test, found_block, ERR_PTR(-ENXIO));
+}
+
 static int gpu_buddy_suite_init(struct kunit_suite *suite)
 {
        while (!random_seed)
@@ -1446,6 +1543,7 @@ static struct kunit_case gpu_buddy_tests[] = {
        KUNIT_CASE(gpu_test_buddy_alloc_exceeds_max_order),
        KUNIT_CASE(gpu_test_buddy_offset_aligned_allocation),
        KUNIT_CASE(gpu_test_buddy_subtree_offset_alignment_stress),
+       KUNIT_CASE(gpu_test_buddy_addr_to_block),
        {}
 };
 
-- 
2.52.0

Reply via email to