mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 19:13:03 -04:00
drm/amd/display: Add KUnit tests for link_lock and psp SRM helpers
Cover link_lock() across all links (lock then unlock) and the max_link == 0 no-op path, checking each per-link mutex ends in the expected state. Also cover the psp_get_srm() and psp_set_srm() guard paths when the HDCP TA context is uninitialized: psp_get_srm() returns NULL and psp_set_srm() returns -EINVAL, both leaving their output parameters untouched. The post-guard paths invoke real PSP firmware and are not unit-testable in UML. 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>
This commit is contained in:
committed by
Alex Deucher
parent
f73dd04acd
commit
fad644eab1
@@ -106,7 +106,8 @@ static bool lp_atomic_write_poll_read_aux(
|
||||
return dm_atomic_write_poll_read_aux(link, write, poll, read, poll_timeout_us, poll_mask_msb);
|
||||
}
|
||||
|
||||
static uint8_t *psp_get_srm(struct psp_context *psp, uint32_t *srm_version, uint32_t *srm_size)
|
||||
STATIC_IFN_KUNIT
|
||||
uint8_t *psp_get_srm(struct psp_context *psp, uint32_t *srm_version, uint32_t *srm_size)
|
||||
{
|
||||
struct ta_hdcp_shared_memory *hdcp_cmd;
|
||||
|
||||
@@ -129,8 +130,10 @@ static uint8_t *psp_get_srm(struct psp_context *psp, uint32_t *srm_version, uint
|
||||
|
||||
return hdcp_cmd->out_msg.hdcp_get_srm.srm_buf;
|
||||
}
|
||||
EXPORT_IF_KUNIT(psp_get_srm);
|
||||
|
||||
static int psp_set_srm(struct psp_context *psp,
|
||||
STATIC_IFN_KUNIT
|
||||
int psp_set_srm(struct psp_context *psp,
|
||||
u8 *srm, uint32_t srm_size, uint32_t *srm_version)
|
||||
{
|
||||
struct ta_hdcp_shared_memory *hdcp_cmd;
|
||||
@@ -157,6 +160,7 @@ static int psp_set_srm(struct psp_context *psp,
|
||||
*srm_version = hdcp_cmd->out_msg.hdcp_set_srm.srm_version;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_IF_KUNIT(psp_set_srm);
|
||||
|
||||
STATIC_IFN_KUNIT
|
||||
void process_output(struct hdcp_workqueue *hdcp_work)
|
||||
@@ -245,7 +249,8 @@ void hdcp_get_link_display_adjustments(
|
||||
}
|
||||
EXPORT_IF_KUNIT(hdcp_get_link_display_adjustments);
|
||||
|
||||
static void link_lock(struct hdcp_workqueue *work, bool lock)
|
||||
STATIC_IFN_KUNIT
|
||||
void link_lock(struct hdcp_workqueue *work, bool lock)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -256,6 +261,7 @@ static void link_lock(struct hdcp_workqueue *work, bool lock)
|
||||
mutex_unlock(&work[i].mutex);
|
||||
}
|
||||
}
|
||||
EXPORT_IF_KUNIT(link_lock);
|
||||
|
||||
STATIC_IFN_KUNIT
|
||||
void hdcp_update_display_encryption_control(struct hdcp_workqueue *hdcp_work,
|
||||
|
||||
@@ -44,6 +44,7 @@ struct mod_hdcp_link;
|
||||
struct mod_hdcp_display;
|
||||
struct cp_psp;
|
||||
struct amdgpu_device;
|
||||
struct psp_context;
|
||||
|
||||
struct hdcp_workqueue {
|
||||
struct work_struct cpirq_work;
|
||||
@@ -113,6 +114,9 @@ void hdcp_update_display_encryption_control(struct hdcp_workqueue *hdcp_work,
|
||||
unsigned int conn_index,
|
||||
bool enable_encryption);
|
||||
void event_property_update(struct work_struct *work);
|
||||
void link_lock(struct hdcp_workqueue *work, bool lock);
|
||||
uint8_t *psp_get_srm(struct psp_context *psp, uint32_t *srm_version, uint32_t *srm_size);
|
||||
int psp_set_srm(struct psp_context *psp, u8 *srm, uint32_t srm_size, uint32_t *srm_version);
|
||||
#endif
|
||||
|
||||
#endif /* AMDGPU_DM_AMDGPU_DM_HDCP_H_ */
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <kunit/test.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_dm_hdcp.h"
|
||||
|
||||
static void dummy_work_fn(struct work_struct *work) {}
|
||||
@@ -632,6 +633,126 @@ static void dm_test_hdcp_create_workqueue_zero_max_links_returns_null(struct kun
|
||||
|
||||
/* End of tests for hdcp_create_workqueue() */
|
||||
|
||||
/* Tests for link_lock() */
|
||||
|
||||
/**
|
||||
* dm_test_link_lock_locks_and_unlocks_all_links - lock/unlock spans every link
|
||||
* @test: KUnit test context
|
||||
*
|
||||
* link_lock() should acquire the mutex of every entry from 0 to max_link
|
||||
* when locking, and release all of them when unlocking. A subsequent
|
||||
* lock/unlock cycle must succeed, proving the mutexes were left released.
|
||||
*/
|
||||
static void dm_test_link_lock_locks_and_unlocks_all_links(struct kunit *test)
|
||||
{
|
||||
const int num_links = 3;
|
||||
struct hdcp_workqueue *work;
|
||||
int i;
|
||||
|
||||
work = kunit_kcalloc(test, num_links, sizeof(*work), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, work);
|
||||
|
||||
/* max_link is read from the first element. */
|
||||
work[0].max_link = num_links;
|
||||
for (i = 0; i < num_links; i++)
|
||||
mutex_init(&work[i].mutex);
|
||||
|
||||
link_lock(work, true);
|
||||
for (i = 0; i < num_links; i++)
|
||||
KUNIT_EXPECT_TRUE(test, mutex_is_locked(&work[i].mutex));
|
||||
|
||||
link_lock(work, false);
|
||||
for (i = 0; i < num_links; i++)
|
||||
KUNIT_EXPECT_FALSE(test, mutex_is_locked(&work[i].mutex));
|
||||
|
||||
/* Mutexes must be re-acquirable after being released. */
|
||||
link_lock(work, true);
|
||||
for (i = 0; i < num_links; i++)
|
||||
KUNIT_EXPECT_TRUE(test, mutex_is_locked(&work[i].mutex));
|
||||
link_lock(work, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_link_lock_zero_links_is_noop - zero max_link touches no mutexes
|
||||
* @test: KUnit test context
|
||||
*
|
||||
* When max_link is zero, link_lock() must not touch any mutex and simply
|
||||
* return, leaving the (single) entry's mutex unlocked.
|
||||
*/
|
||||
static void dm_test_link_lock_zero_links_is_noop(struct kunit *test)
|
||||
{
|
||||
struct hdcp_workqueue *work;
|
||||
|
||||
work = kunit_kzalloc(test, sizeof(*work), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, work);
|
||||
|
||||
mutex_init(&work->mutex);
|
||||
work->max_link = 0;
|
||||
|
||||
link_lock(work, true);
|
||||
|
||||
KUNIT_EXPECT_FALSE(test, mutex_is_locked(&work->mutex));
|
||||
}
|
||||
|
||||
/* End of tests for link_lock() */
|
||||
|
||||
/* Tests for psp_get_srm() and psp_set_srm() */
|
||||
|
||||
/**
|
||||
* dm_test_psp_get_srm_uninitialized_returns_null - GET fails when TA not initialized
|
||||
* @test: KUnit test context
|
||||
*
|
||||
* When the HDCP TA context is not initialized, psp_get_srm() must take the
|
||||
* guard path and return NULL without touching the output parameters or
|
||||
* invoking the (real) firmware path.
|
||||
*/
|
||||
static void dm_test_psp_get_srm_uninitialized_returns_null(struct kunit *test)
|
||||
{
|
||||
struct psp_context *psp;
|
||||
uint32_t srm_version = 0xdead;
|
||||
uint32_t srm_size = 0xbeef;
|
||||
uint8_t *srm;
|
||||
|
||||
psp = kunit_kzalloc(test, sizeof(*psp), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, psp);
|
||||
|
||||
/* kzalloc leaves hdcp_context.context.initialized == false */
|
||||
srm = psp_get_srm(psp, &srm_version, &srm_size);
|
||||
|
||||
KUNIT_EXPECT_PTR_EQ(test, srm, NULL);
|
||||
/* Output parameters must be left untouched on the guard path. */
|
||||
KUNIT_EXPECT_EQ(test, srm_version, 0xdead);
|
||||
KUNIT_EXPECT_EQ(test, srm_size, 0xbeef);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_psp_set_srm_uninitialized_returns_einval - SET fails when TA not initialized
|
||||
* @test: KUnit test context
|
||||
*
|
||||
* When the HDCP TA context is not initialized, psp_set_srm() must take the
|
||||
* guard path and return -EINVAL without updating srm_version or invoking
|
||||
* the (real) firmware path.
|
||||
*/
|
||||
static void dm_test_psp_set_srm_uninitialized_returns_einval(struct kunit *test)
|
||||
{
|
||||
struct psp_context *psp;
|
||||
uint32_t srm_version = 0xdead;
|
||||
u8 srm_buf[4] = {0};
|
||||
int ret;
|
||||
|
||||
psp = kunit_kzalloc(test, sizeof(*psp), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, psp);
|
||||
|
||||
/* kzalloc leaves hdcp_context.context.initialized == false */
|
||||
ret = psp_set_srm(psp, srm_buf, sizeof(srm_buf), &srm_version);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, ret, -EINVAL);
|
||||
/* srm_version must be left untouched on the guard path. */
|
||||
KUNIT_EXPECT_EQ(test, srm_version, 0xdead);
|
||||
}
|
||||
|
||||
/* End of tests for psp_get_srm() and psp_set_srm() */
|
||||
|
||||
static struct kunit_case dm_hdcp_test_cases[] = {
|
||||
/* hdcp_get_content_protection_from_status() */
|
||||
KUNIT_CASE(dm_test_hdcp_get_cp_disabled_returns_desired),
|
||||
@@ -663,6 +784,12 @@ 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),
|
||||
/* link_lock() */
|
||||
KUNIT_CASE(dm_test_link_lock_locks_and_unlocks_all_links),
|
||||
KUNIT_CASE(dm_test_link_lock_zero_links_is_noop),
|
||||
/* psp_get_srm() / psp_set_srm() */
|
||||
KUNIT_CASE(dm_test_psp_get_srm_uninitialized_returns_null),
|
||||
KUNIT_CASE(dm_test_psp_set_srm_uninitialized_returns_einval),
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user