diff options
| author | Bhawanpreet Lakha <bhawanpreet.lakha@amd.com> | 2026-07-10 16:12:55 -0400 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2026-07-28 18:58:39 -0400 |
| commit | 3c729afe2f9a319e0852de9af460f94d1207ce1a (patch) | |
| tree | 4fc43a89918367ab1077578fab0faa66e3060a5f | |
| parent | 560ef68fec09a6fa92539eb99976e020e26148c6 (diff) | |
| download | linux-next-3c729afe2f9a319e0852de9af460f94d1207ce1a.tar.gz linux-next-3c729afe2f9a319e0852de9af460f94d1207ce1a.zip | |
drm/amd/display: Add KUnit tests for hdcp_destroy
Verify hdcp_destroy() cancels each link's delayed works, removes
the SRM sysfs file and frees the workqueue and SRM buffers. Cover
both a populated work-queue and the zero-link / NULL-SRM path.
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Fangzhi Zuo <jerry.zuo@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
| -rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_hdcp_test.c | 122 |
2 files changed, 123 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c index 896668c92888..e704b6b7fc0b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c @@ -568,6 +568,7 @@ void hdcp_destroy(struct kobject *kobj, struct hdcp_workqueue *hdcp_work) kfree(hdcp_work->srm_temp); kfree(hdcp_work); } +EXPORT_IF_KUNIT(hdcp_destroy); static bool enable_assr(void *handle, struct dc_link *link) { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_hdcp_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_hdcp_test.c index a4097a4aec26..5eace7fa4100 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_hdcp_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_hdcp_test.c @@ -7,6 +7,9 @@ #include <kunit/test.h> #include <linux/workqueue.h> +#include <linux/kobject.h> +#include <linux/slab.h> +#include <linux/sysfs.h> #include "amdgpu.h" #include "amdgpu_dm.h" @@ -1007,6 +1010,122 @@ static void dm_test_hdcp_create_workqueue_zero_max_links_returns_null(struct kun /* End of tests for hdcp_create_workqueue() */ +/* Tests for hdcp_destroy() */ + +static ssize_t test_srm_bin_read(struct file *filp, struct kobject *kobj, + const struct bin_attribute *bin_attr, char *buffer, + loff_t pos, size_t count) +{ + return 0; +} + +static ssize_t test_srm_bin_write(struct file *filp, struct kobject *kobj, + const struct bin_attribute *bin_attr, char *buffer, + loff_t pos, size_t count) +{ + return count; +} + +/** + * setup_destroy_sysfs - create a kobject with the SRM bin file attached + * @test: KUnit test context + * @work: workqueue whose attr will be registered + * + * hdcp_destroy() calls sysfs_remove_bin_file() on the first entry's attr, so + * a real kobject with the bin file created is required. Returns the kobject, + * which the caller must kobject_put() after hdcp_destroy() has run. + */ +static struct kobject *setup_destroy_sysfs(struct kunit *test, + struct hdcp_workqueue *work) +{ + struct kobject *kobj; + int ret; + + kobj = kobject_create_and_add("amdgpu_dm_hdcp_test", NULL); + KUNIT_ASSERT_NOT_NULL(test, kobj); + + sysfs_bin_attr_init(&work->attr); + work->attr.attr.name = "hdcp_srm"; + work->attr.attr.mode = 0664; + work->attr.size = 16; + work->attr.read = test_srm_bin_read; + work->attr.write = test_srm_bin_write; + + ret = sysfs_create_bin_file(kobj, &work->attr); + KUNIT_ASSERT_EQ(test, ret, 0); + + return kobj; +} + +/** + * dm_test_hdcp_destroy_frees_and_removes_sysfs - full teardown path + * @test: KUnit test context + * + * hdcp_destroy() must cancel every link's delayed works, remove the SRM + * sysfs bin file and free srm, srm_temp and the workqueue itself. The + * workqueue and SRM buffers use kzalloc() (not kunit-managed) because + * hdcp_destroy() frees them; KASAN/kmemleak validate there is no leak or + * use-after-free. + */ +static void dm_test_hdcp_destroy_frees_and_removes_sysfs(struct kunit *test) +{ + struct hdcp_workqueue *work; + struct kobject *kobj; + + work = kzalloc_obj(*work); + KUNIT_ASSERT_NOT_NULL(test, work); + + work->max_link = 1; + INIT_DELAYED_WORK(&work->callback_dwork, dummy_work_fn); + INIT_DELAYED_WORK(&work->watchdog_timer_dwork, dummy_work_fn); + INIT_DELAYED_WORK(&work->property_validate_dwork, dummy_work_fn); + + work->srm = kzalloc(16, GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, work->srm); + work->srm_temp = kzalloc(16, GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, work->srm_temp); + + kobj = setup_destroy_sysfs(test, work); + + /* Pre-schedule a delayed work to exercise the cancel path. */ + schedule_delayed_work(&work->callback_dwork, msecs_to_jiffies(10000)); + KUNIT_ASSERT_TRUE(test, delayed_work_pending(&work->callback_dwork)); + + hdcp_destroy(kobj, work); + + /* work is freed by hdcp_destroy(); only the kobject remains. */ + kobject_put(kobj); +} + +/** + * dm_test_hdcp_destroy_zero_links_null_srm - teardown with no links or SRM + * @test: KUnit test context + * + * With max_link == 0 the cancel loop is skipped, and NULL srm/srm_temp make + * the kfree() calls no-ops. hdcp_destroy() must still remove the sysfs bin + * file and free the workqueue without crashing. + */ +static void dm_test_hdcp_destroy_zero_links_null_srm(struct kunit *test) +{ + struct hdcp_workqueue *work; + struct kobject *kobj; + + work = kzalloc_obj(*work); + KUNIT_ASSERT_NOT_NULL(test, work); + + work->max_link = 0; + work->srm = NULL; + work->srm_temp = NULL; + + kobj = setup_destroy_sysfs(test, work); + + hdcp_destroy(kobj, work); + + kobject_put(kobj); +} + +/* End of tests for hdcp_destroy() */ + /* Tests for link_lock() */ /** @@ -1373,6 +1492,9 @@ static struct kunit_case dm_hdcp_test_cases[] = { KUNIT_CASE(dm_test_hdcp_update_display_disable_resets_status_and_cancels_validate), /* hdcp_create_workqueue() */ KUNIT_CASE(dm_test_hdcp_create_workqueue_zero_max_links_returns_null), + /* hdcp_destroy() */ + KUNIT_CASE(dm_test_hdcp_destroy_frees_and_removes_sysfs), + KUNIT_CASE(dm_test_hdcp_destroy_zero_links_null_srm), /* link_lock() */ KUNIT_CASE(dm_test_link_lock_locks_and_unlocks_all_links), KUNIT_CASE(dm_test_link_lock_zero_links_is_noop), |
