From: Alex Hung <[email protected]>

[WHAT]
Add a KUnit test for dm_helpers_allocate_gpu_mem() and
dm_helpers_free_gpu_mem() that allocates a DMUB tracebuffer and frees it
again, checking the returned CPU pointer and GPU address.

[HOW]
amdgpu_bo_create_kernel() and amdgpu_bo_free_kernel() need a live TTM
device, so both are replaced by a fake through the existing
amdgpu_dm_services KUnit operations table.

Assisted-by: Copilot:Claude-Opus-5
Reviewed-by: Bhawanpreet Lakha <[email protected]>
Signed-off-by: Alex Hung <[email protected]>
Signed-off-by: Ivan Lipski <[email protected]>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +
 .../amdgpu_dm/tests/amdgpu_dm_helpers_test.c  | 93 +++++++++++++++++++
 2 files changed, 95 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 29f254cafae4e..0344ce5ce816b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -1442,6 +1442,7 @@ void *dm_helpers_allocate_gpu_mem(
 
        return dm_allocate_gpu_mem(adev, type, size, addr);
 }
+EXPORT_IF_KUNIT(dm_helpers_allocate_gpu_mem);
 
 void dm_helpers_free_gpu_mem(
                struct dc_context *ctx,
@@ -1452,6 +1453,7 @@ void dm_helpers_free_gpu_mem(
 
        dm_free_gpu_mem(adev, type, pvMem);
 }
+EXPORT_IF_KUNIT(dm_helpers_free_gpu_mem);
 
 bool dm_helpers_dmub_outbox_interrupt_control(struct dc_context *ctx, bool 
enable)
 {
diff --git 
a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c
index 0314ebb5c8aea..11a5e8f307354 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c
@@ -3906,6 +3906,97 @@ static void 
dm_test_submit_i2c_over_aux_unimplemented(struct kunit *test)
                                                                sizeof(buffer), 
true));
 }
 
+/* Tests for dm_helpers_allocate_gpu_mem() and dm_helpers_free_gpu_mem() */
+
+/*
+ * Fake buffer object allocator: amdgpu_bo_create_kernel() and
+ * amdgpu_bo_free_kernel() need a live TTM device, so dm_allocate_gpu_mem() is
+ * routed through this fake.
+ */
+
+#define DM_TEST_FAKE_GPU_ADDR  0x1234ABCD0000ULL
+
+struct dm_test_bo_ctx {
+       void *cpu_ptr;
+       unsigned int create_calls;
+       unsigned int free_calls;
+       unsigned long create_size;
+       u32 create_domain;
+};
+
+static struct dm_test_bo_ctx dm_test_bo;
+
+static int dm_test_bo_create_kernel(struct amdgpu_device *adev, unsigned long 
size,
+                                   int align, u32 domain, struct amdgpu_bo 
**bo_ptr,
+                                   u64 *gpu_addr, void **cpu_addr)
+{
+       dm_test_bo.create_calls++;
+       dm_test_bo.create_size = size;
+       dm_test_bo.create_domain = domain;
+
+       *gpu_addr = DM_TEST_FAKE_GPU_ADDR;
+       *cpu_addr = dm_test_bo.cpu_ptr;
+
+       return 0;
+}
+
+static void dm_test_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr, void 
**cpu_addr)
+{
+       dm_test_bo.free_calls++;
+
+       *bo = NULL;
+       *gpu_addr = 0;
+       *cpu_addr = NULL;
+}
+
+static const struct amdgpu_dm_services_kunit_ops dm_test_services_ops = {
+       .bo_create_kernel = dm_test_bo_create_kernel,
+       .bo_free_kernel = dm_test_bo_free_kernel,
+};
+
+/**
+ * dm_test_gpu_mem_alloc_and_free - Test the GPU memory helper wrappers
+ * @test: The KUnit test context
+ *
+ * Both helpers only unwrap the device from the DC context and forward to
+ * dm_allocate_gpu_mem()/dm_free_gpu_mem().
+ */
+static void dm_test_gpu_mem_alloc_and_free(struct kunit *test)
+{
+       struct amdgpu_device *adev;
+       struct dc_context *ctx;
+       long long addr = 0;
+       void *cpu_ptr;
+       void *mem;
+
+       adev = dm_kunit_alloc_adev(test);
+       KUNIT_ASSERT_NOT_NULL(test, adev);
+       ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+       cpu_ptr = kunit_kzalloc(test, PAGE_SIZE, GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, cpu_ptr);
+
+       ctx->driver_context = adev;
+       INIT_LIST_HEAD(&adev->dm.da_list);
+       dm_test_bo = (struct dm_test_bo_ctx) { .cpu_ptr = cpu_ptr };
+       amdgpu_dm_services_kunit_set_ops(&dm_test_services_ops);
+
+       mem = dm_helpers_allocate_gpu_mem(ctx, DC_MEM_ALLOC_TYPE_GART, 4096, 
&addr);
+
+       KUNIT_EXPECT_PTR_EQ(test, mem, cpu_ptr);
+       KUNIT_EXPECT_EQ(test, addr, (long long)DM_TEST_FAKE_GPU_ADDR);
+       KUNIT_EXPECT_EQ(test, dm_test_bo.create_calls, 1U);
+       KUNIT_EXPECT_EQ(test, dm_test_bo.create_size, 4096UL);
+       KUNIT_EXPECT_EQ(test, dm_test_bo.create_domain, 
(u32)AMDGPU_GEM_DOMAIN_GTT);
+
+       dm_helpers_free_gpu_mem(ctx, DC_MEM_ALLOC_TYPE_GART, mem);
+
+       KUNIT_EXPECT_EQ(test, dm_test_bo.free_calls, 1U);
+       KUNIT_EXPECT_TRUE(test, list_empty(&adev->dm.da_list));
+
+       amdgpu_dm_services_kunit_set_ops(NULL);
+}
+
 static struct kunit_case amdgpu_dm_helpers_test_cases[] = {
        /* edid_extract_panel_id */
        KUNIT_CASE(dm_test_edid_extract_panel_id_basic),
@@ -4096,6 +4187,8 @@ static struct kunit_case amdgpu_dm_helpers_test_cases[] = 
{
        KUNIT_CASE(dm_test_dp_handle_test_pattern_no_pipe),
        /* dm_helpers_submit_i2c_over_aux */
        KUNIT_CASE(dm_test_submit_i2c_over_aux_unimplemented),
+       /* dm_helpers_allocate_gpu_mem / dm_helpers_free_gpu_mem */
+       KUNIT_CASE(dm_test_gpu_mem_alloc_and_free),
        {}
 };
 
-- 
2.43.0

Reply via email to