drm/amd/display: Add KUnit tests for amdgpu_dm_dmub

Add KUnit tests for amdgpu_dm_dmub.c covering the following
functions:

- dm_register_dmub_notify_callback(): NULL callback rejection,
  out-of-range type, valid registration with offload flag
- dm_dmub_aux_setconfig_callback(): copy and complete on AUX
  reply, non-AUX skip, NULL dm_notify, SET_CONFIG reply
- dm_dmub_aux_fused_io_callback(): copy reply and complete,
  max ddc_line boundary
- dm_get_default_ips_mode(): IPS mode per DCN version (3.5,
  3.5.1, 3.6, 4.2), disabled for older ASICs, default enabled
  for unhandled newer ASICs
- dm_dmub_hw_init(): early returns for no dmub_srv, no fb_info,
  no firmware
- dm_dmub_hw_resume(): no-op when dmub_srv is NULL
- dm_dmub_sw_init(): returns 0 for unsupported ASIC
- dm_init_microcode(): returns 0 for unsupported ASIC

Assisted-by: Copilot:Claude-Opus-4.6
Reviewed-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Alex Hung
2026-04-29 21:28:36 -06:00
committed by Alex Deucher
parent c71a6dc1cf
commit 829e9b68ea
3 changed files with 610 additions and 0 deletions

View File

@@ -38,6 +38,7 @@
#include "amdgpu_ucode.h"
#include "amdgpu_dm.h"
#include "amdgpu_dm_dmub.h"
#include "amdgpu_dm_kunit_helpers.h"
#include <linux/component.h>
#include <linux/firmware.h>
@@ -80,6 +81,7 @@ void dm_dmub_aux_setconfig_callback(struct amdgpu_device *adev,
if (notify->type == DMUB_NOTIFICATION_AUX_REPLY)
complete(&adev->dm.dmub_aux_transfer_done);
}
EXPORT_IF_KUNIT(dm_dmub_aux_setconfig_callback);
void dm_dmub_aux_fused_io_callback(struct amdgpu_device *adev,
struct dmub_notification *notify)
@@ -103,6 +105,7 @@ void dm_dmub_aux_fused_io_callback(struct amdgpu_device *adev,
memcpy(sync->reply_data, req, sizeof(*req));
complete(&sync->replied);
}
EXPORT_IF_KUNIT(dm_dmub_aux_fused_io_callback);
/**
* dm_register_dmub_notify_callback - Sets callback for DMUB notify
@@ -129,6 +132,7 @@ bool dm_register_dmub_notify_callback(struct amdgpu_device *adev,
return true;
}
EXPORT_IF_KUNIT(dm_register_dmub_notify_callback);
int dm_dmub_hw_init(struct amdgpu_device *adev)
{
@@ -318,6 +322,7 @@ int dm_dmub_hw_init(struct amdgpu_device *adev)
return 0;
}
EXPORT_IF_KUNIT(dm_dmub_hw_init);
void dm_dmub_hw_resume(struct amdgpu_device *adev)
{
@@ -347,6 +352,7 @@ void dm_dmub_hw_resume(struct amdgpu_device *adev)
drm_err(adev_to_drm(adev), "DMUB interface failed to initialize: status=%d\n", r);
}
}
EXPORT_IF_KUNIT(dm_dmub_hw_resume);
static enum dmub_status
dm_dmub_send_vbios_gpint_command(struct amdgpu_device *adev,
@@ -460,6 +466,7 @@ enum dmub_ips_disable_type dm_get_default_ips_mode(
return ret;
}
EXPORT_IF_KUNIT(dm_get_default_ips_mode);
static uint32_t amdgpu_dm_dmub_reg_read(void *ctx, uint32_t address)
{
@@ -677,6 +684,7 @@ int dm_dmub_sw_init(struct amdgpu_device *adev)
return 0;
}
EXPORT_IF_KUNIT(dm_dmub_sw_init);
int dm_init_microcode(struct amdgpu_device *adev)
{
@@ -749,6 +757,7 @@ int dm_init_microcode(struct amdgpu_device *adev)
"%s", fw_name_dmub);
return r;
}
EXPORT_IF_KUNIT(dm_init_microcode);
int amdgpu_dm_process_dmub_aux_transfer_sync(
struct dc_context *ctx,

View File

@@ -17,6 +17,7 @@ obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_audio_test.o
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_color_test.o
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_colorop_test.o
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_backlight_test.o
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_dmub_test.o
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_psr_test.o
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_replay_test.o
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_ism_test.o

View File

@@ -0,0 +1,600 @@
// SPDX-License-Identifier: GPL-2.0 OR MIT
/*
* KUnit tests for amdgpu_dm_dmub.c
*
* Copyright 2026 Advanced Micro Devices, Inc.
*/
#include <kunit/test.h>
#include "dc.h"
#include "dc/inc/core_types.h"
#include "amdgpu_mode.h"
#include "amdgpu_dm.h"
#include "dmub/dmub_srv.h"
#include "amdgpu_dm_dmub.h"
/* Tests for dm_register_dmub_notify_callback() */
static void dummy_callback(struct amdgpu_device *adev,
struct dmub_notification *notify)
{
}
/**
* dm_test_register_dmub_notify_callback_null_callback - Test null callback is rejected
* @test: The KUnit test context
*/
static void dm_test_register_dmub_notify_callback_null_callback(struct kunit *test)
{
struct amdgpu_device *adev;
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
KUNIT_EXPECT_FALSE(test, dm_register_dmub_notify_callback(adev,
DMUB_NOTIFICATION_AUX_REPLY, NULL, false));
}
/**
* dm_test_register_dmub_notify_callback_type_out_of_range - Test out-of-range type is rejected
* @test: The KUnit test context
*/
static void dm_test_register_dmub_notify_callback_type_out_of_range(struct kunit *test)
{
struct amdgpu_device *adev;
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
KUNIT_EXPECT_FALSE(test, dm_register_dmub_notify_callback(adev,
AMDGPU_DMUB_NOTIFICATION_MAX, dummy_callback, false));
}
/**
* dm_test_register_dmub_notify_callback_valid - Test Register dmub notify callback valid
* @test: The KUnit test context
*/
static void dm_test_register_dmub_notify_callback_valid(struct kunit *test)
{
struct amdgpu_device *adev;
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
KUNIT_EXPECT_TRUE(test, dm_register_dmub_notify_callback(adev,
DMUB_NOTIFICATION_AUX_REPLY, dummy_callback, true));
KUNIT_EXPECT_TRUE(test,
adev->dm.dmub_callback[DMUB_NOTIFICATION_AUX_REPLY] == dummy_callback);
KUNIT_EXPECT_TRUE(test,
adev->dm.dmub_thread_offload[DMUB_NOTIFICATION_AUX_REPLY]);
}
/**
* dm_test_register_dmub_notify_callback_offload_false - Test registration with offload disabled
* @test: The KUnit test context
*/
static void dm_test_register_dmub_notify_callback_offload_false(struct kunit *test)
{
struct amdgpu_device *adev;
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
KUNIT_EXPECT_TRUE(test, dm_register_dmub_notify_callback(adev,
DMUB_NOTIFICATION_HPD, dummy_callback, false));
KUNIT_EXPECT_TRUE(test,
adev->dm.dmub_callback[DMUB_NOTIFICATION_HPD] == dummy_callback);
KUNIT_EXPECT_FALSE(test,
adev->dm.dmub_thread_offload[DMUB_NOTIFICATION_HPD]);
}
/* Tests for dm_dmub_aux_setconfig_callback() */
/**
* dm_test_dmub_aux_setconfig_callback_copies_and_completes - Test copy and complete on AUX reply
* @test: The KUnit test context
*/
static void dm_test_dmub_aux_setconfig_callback_copies_and_completes(struct kunit *test)
{
struct amdgpu_device *adev;
struct dmub_notification *dm_notify;
struct dmub_notification notify = {};
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
dm_notify = kunit_kzalloc(test, sizeof(*dm_notify), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_notify);
init_completion(&adev->dm.dmub_aux_transfer_done);
adev->dm.dmub_notify = dm_notify;
notify.type = DMUB_NOTIFICATION_AUX_REPLY;
notify.result = AUX_RET_SUCCESS;
notify.aux_reply.command = 0xA5;
notify.aux_reply.length = 3;
notify.aux_reply.data[0] = 0x11;
notify.aux_reply.data[1] = 0x22;
notify.aux_reply.data[2] = 0x33;
dm_dmub_aux_setconfig_callback(adev, &notify);
KUNIT_EXPECT_EQ(test, dm_notify->type, notify.type);
KUNIT_EXPECT_EQ(test, dm_notify->result, notify.result);
KUNIT_EXPECT_EQ(test, dm_notify->aux_reply.command, notify.aux_reply.command);
KUNIT_EXPECT_EQ(test, dm_notify->aux_reply.length, notify.aux_reply.length);
KUNIT_EXPECT_EQ(test, dm_notify->aux_reply.data[0], notify.aux_reply.data[0]);
KUNIT_EXPECT_EQ(test, dm_notify->aux_reply.data[1], notify.aux_reply.data[1]);
KUNIT_EXPECT_EQ(test, dm_notify->aux_reply.data[2], notify.aux_reply.data[2]);
KUNIT_EXPECT_TRUE(test, completion_done(&adev->dm.dmub_aux_transfer_done));
}
/**
* dm_test_dmub_aux_setconfig_callback_non_aux_no_complete - Test non-AUX type skips completion
* @test: The KUnit test context
*/
static void dm_test_dmub_aux_setconfig_callback_non_aux_no_complete(struct kunit *test)
{
struct amdgpu_device *adev;
struct dmub_notification *dm_notify;
struct dmub_notification notify = {};
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
dm_notify = kunit_kzalloc(test, sizeof(*dm_notify), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_notify);
init_completion(&adev->dm.dmub_aux_transfer_done);
adev->dm.dmub_notify = dm_notify;
notify.type = DMUB_NOTIFICATION_HPD;
notify.result = AUX_RET_ERROR_TIMEOUT;
dm_dmub_aux_setconfig_callback(adev, &notify);
KUNIT_EXPECT_EQ(test, dm_notify->type, notify.type);
KUNIT_EXPECT_FALSE(test, completion_done(&adev->dm.dmub_aux_transfer_done));
}
/**
* dm_test_dmub_aux_setconfig_callback_aux_with_null_dm_notify - Test AUX with NULL dm_notify
* @test: The KUnit test context
*/
static void dm_test_dmub_aux_setconfig_callback_aux_with_null_dm_notify(struct kunit *test)
{
struct amdgpu_device *adev;
struct dmub_notification notify = {};
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
init_completion(&adev->dm.dmub_aux_transfer_done);
adev->dm.dmub_notify = NULL;
notify.type = DMUB_NOTIFICATION_AUX_REPLY;
dm_dmub_aux_setconfig_callback(adev, &notify);
KUNIT_EXPECT_TRUE(test, completion_done(&adev->dm.dmub_aux_transfer_done));
}
/**
* dm_test_dmub_aux_setconfig_callback_set_config_reply - Test SET_CONFIG reply copies status
* @test: The KUnit test context
*/
static void dm_test_dmub_aux_setconfig_callback_set_config_reply(struct kunit *test)
{
struct amdgpu_device *adev;
struct dmub_notification *dm_notify;
struct dmub_notification notify = {};
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
dm_notify = kunit_kzalloc(test, sizeof(*dm_notify), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_notify);
init_completion(&adev->dm.dmub_aux_transfer_done);
adev->dm.dmub_notify = dm_notify;
notify.type = DMUB_NOTIFICATION_SET_CONFIG_REPLY;
notify.sc_status = SET_CONFIG_RX_TIMEOUT;
dm_dmub_aux_setconfig_callback(adev, &notify);
KUNIT_EXPECT_EQ(test, dm_notify->type, notify.type);
KUNIT_EXPECT_EQ(test, dm_notify->sc_status, notify.sc_status);
KUNIT_EXPECT_FALSE(test, completion_done(&adev->dm.dmub_aux_transfer_done));
}
/* Tests for dm_dmub_aux_fused_io_callback() */
/**
* dm_test_dmub_aux_fused_io_callback_copies_reply_and_completes - Test copy and complete
* @test: The KUnit test context
*/
static void dm_test_dmub_aux_fused_io_callback_copies_reply_and_completes(struct kunit *test)
{
struct amdgpu_device *adev;
struct dmub_notification notify = {};
struct dmub_cmd_fused_request *reply;
u32 reply_ddc_line;
u32 notify_ddc_line;
u32 reply_address;
u32 notify_address;
u32 reply_length;
u32 notify_length;
uint8_t ddc_line = 2;
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
init_completion(&adev->dm.fused_io[ddc_line].replied);
notify.fused_request.identifier = 0x34;
notify.fused_request.status = FUSED_REQUEST_STATUS_SUCCESS;
notify.fused_request.u.aux.ddc_line = ddc_line;
notify.fused_request.u.aux.address = 0x50;
notify.fused_request.u.aux.length = 4;
dm_dmub_aux_fused_io_callback(adev, &notify);
KUNIT_EXPECT_TRUE(test, completion_done(&adev->dm.fused_io[ddc_line].replied));
reply = (struct dmub_cmd_fused_request *)adev->dm.fused_io[ddc_line].reply_data;
reply_ddc_line = reply->u.aux.ddc_line;
notify_ddc_line = notify.fused_request.u.aux.ddc_line;
reply_address = reply->u.aux.address;
notify_address = notify.fused_request.u.aux.address;
reply_length = reply->u.aux.length;
notify_length = notify.fused_request.u.aux.length;
KUNIT_EXPECT_EQ(test, reply->identifier, notify.fused_request.identifier);
KUNIT_EXPECT_EQ(test, reply->status, notify.fused_request.status);
KUNIT_EXPECT_EQ(test, reply_ddc_line, notify_ddc_line);
KUNIT_EXPECT_EQ(test, reply_address, notify_address);
KUNIT_EXPECT_EQ(test, reply_length, notify_length);
}
/**
* dm_test_dmub_aux_fused_io_callback_max_ddc_line - Test Dmub aux fused io callback max ddc line
* @test: The KUnit test context
*/
static void dm_test_dmub_aux_fused_io_callback_max_ddc_line(struct kunit *test)
{
struct amdgpu_device *adev;
struct dmub_notification notify = {};
struct dmub_cmd_fused_request *reply;
u32 reply_ddc_line;
u32 notify_ddc_line;
uint8_t ddc_line;
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
ddc_line = ARRAY_SIZE(adev->dm.fused_io) - 1;
init_completion(&adev->dm.fused_io[ddc_line].replied);
notify.fused_request.identifier = 0x56;
notify.fused_request.status = FUSED_REQUEST_STATUS_SUCCESS;
notify.fused_request.u.aux.ddc_line = ddc_line;
notify.fused_request.u.aux.address = 0x50;
notify.fused_request.u.aux.length = 1;
dm_dmub_aux_fused_io_callback(adev, &notify);
KUNIT_EXPECT_TRUE(test, completion_done(&adev->dm.fused_io[ddc_line].replied));
reply = (struct dmub_cmd_fused_request *)adev->dm.fused_io[ddc_line].reply_data;
reply_ddc_line = reply->u.aux.ddc_line;
notify_ddc_line = notify.fused_request.u.aux.ddc_line;
KUNIT_EXPECT_EQ(test, reply->identifier, notify.fused_request.identifier);
KUNIT_EXPECT_EQ(test, reply_ddc_line, notify_ddc_line);
}
/* Tests for dm_get_default_ips_mode() */
/**
* dm_test_get_default_ips_mode_dcn35 - Test Get default ips mode dcn35
* @test: The KUnit test context
*/
static void dm_test_get_default_ips_mode_dcn35(struct kunit *test)
{
struct amdgpu_device *adev;
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
adev->ip_versions[DCE_HWIP][0] = IP_VERSION(3, 5, 0);
KUNIT_EXPECT_EQ(test, dm_get_default_ips_mode(adev),
DMUB_IPS_RCG_IN_ACTIVE_IPS2_IN_OFF);
}
/**
* dm_test_get_default_ips_mode_dcn351 - Test Get default ips mode dcn351
* @test: The KUnit test context
*/
static void dm_test_get_default_ips_mode_dcn351(struct kunit *test)
{
struct amdgpu_device *adev;
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
adev->ip_versions[DCE_HWIP][0] = IP_VERSION(3, 5, 1);
KUNIT_EXPECT_EQ(test, dm_get_default_ips_mode(adev),
DMUB_IPS_RCG_IN_ACTIVE_IPS2_IN_OFF);
}
/**
* dm_test_get_default_ips_mode_dcn36 - Test Get default ips mode dcn36
* @test: The KUnit test context
*/
static void dm_test_get_default_ips_mode_dcn36(struct kunit *test)
{
struct amdgpu_device *adev;
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
adev->ip_versions[DCE_HWIP][0] = IP_VERSION(3, 6, 0);
KUNIT_EXPECT_EQ(test, dm_get_default_ips_mode(adev),
DMUB_IPS_RCG_IN_ACTIVE_IPS2_IN_OFF);
}
/**
* dm_test_get_default_ips_mode_dcn42 - Test Get default ips mode dcn42
* @test: The KUnit test context
*/
static void dm_test_get_default_ips_mode_dcn42(struct kunit *test)
{
struct amdgpu_device *adev;
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
adev->ip_versions[DCE_HWIP][0] = IP_VERSION(4, 2, 0);
KUNIT_EXPECT_EQ(test, dm_get_default_ips_mode(adev),
DMUB_IPS_DISABLE_ALL);
}
/**
* dm_test_get_default_ips_mode_older_than_dcn35 - Test Get default ips mode older than dcn35
* @test: The KUnit test context
*/
static void dm_test_get_default_ips_mode_older_than_dcn35(struct kunit *test)
{
struct amdgpu_device *adev;
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
adev->ip_versions[DCE_HWIP][0] = IP_VERSION(3, 2, 0);
KUNIT_EXPECT_EQ(test, dm_get_default_ips_mode(adev),
DMUB_IPS_DISABLE_ALL);
}
/**
* dm_test_get_default_ips_mode_newer_default - Test Get default ips mode newer default
* @test: The KUnit test context
*/
static void dm_test_get_default_ips_mode_newer_default(struct kunit *test)
{
struct amdgpu_device *adev;
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
/* DCN 4.0.1 is >= 3.5 but has no explicit case, returns ENABLE */
adev->ip_versions[DCE_HWIP][0] = IP_VERSION(4, 0, 1);
KUNIT_EXPECT_EQ(test, dm_get_default_ips_mode(adev),
DMUB_IPS_ENABLE);
}
/* Tests for dm_dmub_hw_init() */
/*
* Build an amdgpu_device with the minimal dc/res_pool pointers that
* dm_dmub_hw_init() and dm_dmub_hw_resume() dereference before their
* early-return checks.
*/
static struct amdgpu_device *dm_test_alloc_adev_with_dc(struct kunit *test)
{
struct amdgpu_device *adev;
struct dc *dc;
struct resource_pool *res_pool;
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc);
res_pool = kunit_kzalloc(test, sizeof(*res_pool), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res_pool);
dc->res_pool = res_pool;
adev->dm.dc = dc;
return adev;
}
/**
* dm_test_dmub_hw_init_no_dmub_srv - Test hw init returns 0 when DMUB unsupported
* @test: The KUnit test context
*
* When adev->dm.dmub_srv is NULL the ASIC does not support DMUB and
* dm_dmub_hw_init() should return 0 without touching the hardware.
*/
static void dm_test_dmub_hw_init_no_dmub_srv(struct kunit *test)
{
struct amdgpu_device *adev = dm_test_alloc_adev_with_dc(test);
adev->dm.dmub_srv = NULL;
KUNIT_EXPECT_EQ(test, dm_dmub_hw_init(adev), 0);
}
/**
* dm_test_dmub_hw_init_no_fb_info - Test hw init fails without framebuffer info
* @test: The KUnit test context
*
* With a DMUB service present but no framebuffer info, dm_dmub_hw_init()
* should return -EINVAL.
*/
static void dm_test_dmub_hw_init_no_fb_info(struct kunit *test)
{
struct amdgpu_device *adev = dm_test_alloc_adev_with_dc(test);
struct dmub_srv *dmub_srv;
dmub_srv = kunit_kzalloc(test, sizeof(*dmub_srv), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dmub_srv);
adev->dm.dmub_srv = dmub_srv;
adev->dm.dmub_fb_info = NULL;
KUNIT_EXPECT_EQ(test, dm_dmub_hw_init(adev), -EINVAL);
}
/**
* dm_test_dmub_hw_init_no_firmware - Test hw init fails without firmware
* @test: The KUnit test context
*
* With a DMUB service and framebuffer info present but no firmware,
* dm_dmub_hw_init() should return -EINVAL.
*/
static void dm_test_dmub_hw_init_no_firmware(struct kunit *test)
{
struct amdgpu_device *adev = dm_test_alloc_adev_with_dc(test);
struct dmub_srv *dmub_srv;
struct dmub_srv_fb_info *fb_info;
dmub_srv = kunit_kzalloc(test, sizeof(*dmub_srv), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dmub_srv);
fb_info = kunit_kzalloc(test, sizeof(*fb_info), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fb_info);
adev->dm.dmub_srv = dmub_srv;
adev->dm.dmub_fb_info = fb_info;
adev->dm.dmub_fw = NULL;
KUNIT_EXPECT_EQ(test, dm_dmub_hw_init(adev), -EINVAL);
}
/* Tests for dm_dmub_hw_resume() */
/**
* dm_test_dmub_hw_resume_no_dmub_srv - Test hw resume is a no-op when DMUB unsupported
* @test: The KUnit test context
*
* When adev->dm.dmub_srv is NULL, dm_dmub_hw_resume() should return early
* without dereferencing the (absent) DMUB service.
*/
static void dm_test_dmub_hw_resume_no_dmub_srv(struct kunit *test)
{
struct amdgpu_device *adev = dm_test_alloc_adev_with_dc(test);
adev->dm.dmub_srv = NULL;
/* Must not crash. */
dm_dmub_hw_resume(adev);
}
/* Tests for dm_dmub_sw_init() */
/**
* dm_test_dmub_sw_init_unsupported_asic - Test sw init returns 0 for unsupported ASIC
* @test: The KUnit test context
*
* For an IP version with no DMUB support, dm_dmub_sw_init() should return 0
* before attempting to access the firmware.
*/
static void dm_test_dmub_sw_init_unsupported_asic(struct kunit *test)
{
struct amdgpu_device *adev;
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
adev->ip_versions[DCE_HWIP][0] = IP_VERSION(1, 0, 0);
KUNIT_EXPECT_EQ(test, dm_dmub_sw_init(adev), 0);
}
/* Tests for dm_init_microcode() */
/**
* dm_test_init_microcode_unsupported_asic - Test microcode init returns 0 for unsupported ASIC
* @test: The KUnit test context
*
* For an IP version with no DMUB support, dm_init_microcode() should return 0
* without requesting any firmware.
*/
static void dm_test_init_microcode_unsupported_asic(struct kunit *test)
{
struct amdgpu_device *adev;
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
adev->ip_versions[DCE_HWIP][0] = IP_VERSION(1, 0, 0);
KUNIT_EXPECT_EQ(test, dm_init_microcode(adev), 0);
}
static struct kunit_case amdgpu_dm_dmub_tests[] = {
/* dm_register_dmub_notify_callback() */
KUNIT_CASE(dm_test_register_dmub_notify_callback_null_callback),
KUNIT_CASE(dm_test_register_dmub_notify_callback_type_out_of_range),
KUNIT_CASE(dm_test_register_dmub_notify_callback_valid),
KUNIT_CASE(dm_test_register_dmub_notify_callback_offload_false),
/* dm_dmub_aux_setconfig_callback() */
KUNIT_CASE(dm_test_dmub_aux_setconfig_callback_copies_and_completes),
KUNIT_CASE(dm_test_dmub_aux_setconfig_callback_non_aux_no_complete),
KUNIT_CASE(dm_test_dmub_aux_setconfig_callback_aux_with_null_dm_notify),
KUNIT_CASE(dm_test_dmub_aux_setconfig_callback_set_config_reply),
/* dm_dmub_aux_fused_io_callback() */
KUNIT_CASE(dm_test_dmub_aux_fused_io_callback_copies_reply_and_completes),
KUNIT_CASE(dm_test_dmub_aux_fused_io_callback_max_ddc_line),
/* dm_get_default_ips_mode() */
KUNIT_CASE(dm_test_get_default_ips_mode_dcn35),
KUNIT_CASE(dm_test_get_default_ips_mode_dcn351),
KUNIT_CASE(dm_test_get_default_ips_mode_dcn36),
KUNIT_CASE(dm_test_get_default_ips_mode_dcn42),
KUNIT_CASE(dm_test_get_default_ips_mode_older_than_dcn35),
KUNIT_CASE(dm_test_get_default_ips_mode_newer_default),
/* dm_dmub_hw_init() */
KUNIT_CASE(dm_test_dmub_hw_init_no_dmub_srv),
KUNIT_CASE(dm_test_dmub_hw_init_no_fb_info),
KUNIT_CASE(dm_test_dmub_hw_init_no_firmware),
/* dm_dmub_hw_resume() */
KUNIT_CASE(dm_test_dmub_hw_resume_no_dmub_srv),
/* dm_dmub_sw_init() */
KUNIT_CASE(dm_test_dmub_sw_init_unsupported_asic),
/* dm_init_microcode() */
KUNIT_CASE(dm_test_init_microcode_unsupported_asic),
{}
};
static struct kunit_suite amdgpu_dm_dmub_test_suite = {
.name = "amdgpu_dm_dmub",
.test_cases = amdgpu_dm_dmub_tests,
};
kunit_test_suite(amdgpu_dm_dmub_test_suite);
MODULE_AUTHOR("AMD");
MODULE_DESCRIPTION("KUnit tests for amdgpu_dm_dmub");
MODULE_LICENSE("Dual MIT/GPL");