From: Ray Wu <ray.wu@amd.com>
To: <amd-gfx@lists.freedesktop.org>
Cc: Harry Wentland <harry.wentland@amd.com>,
Leo Li <sunpeng.li@amd.com>,
Aurabindo Pillai <aurabindo.pillai@amd.com>,
Roman Li <roman.li@amd.com>, Wayne Lin <wayne.lin@amd.com>,
Tom Chung <chiahsuan.chung@amd.com>,
"Fangzhi Zuo" <jerry.zuo@amd.com>,
Dan Wheeler <daniel.wheeler@amd.com>, Ray Wu <Ray.Wu@amd.com>,
Ivan Lipski <ivan.lipski@amd.com>, Alex Hung <alex.hung@amd.com>,
James Lin <PingLei.Lin@amd.com>,
Chenyu Chen <Chen-Yu.Chen@amd.com>,
Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>,
Ray Wu <ray.wu@amd.com>
Subject: [PATCH 07/40] drm/amd/display: Test plane update adapter
Date: Wed, 2 Sep 2026 12:58:29 +0800 [thread overview]
Message-ID: <20260902050411.3473916-8-ray.wu@amd.com> (raw)
In-Reply-To: <20260902050411.3473916-1-ray.wu@amd.com>
From: Alex Hung <alex.hung@amd.com>
[Why]
Add KUnit tests for update_planes_and_stream_adapter() covering
descending plane sorting, argument forwarding, call ordering, and
DC failure propagation.
[How]
Extend the existing DM KUnit ops table with the two DC calls and use
spies to observe inputs and ordering. Reuse one ops installer for the
adapter and MMHUB tests.
Assisted-by: Copilot:Claude-Opus-5 GPT-5.6 Sol
Reviewed-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Ray Wu <ray.wu@amd.com>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 37 ++++--
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 15 +++
.../display/amdgpu_dm/tests/amdgpu_dm_test.c | 123 +++++++++++++++++-
3 files changed, 158 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index bd087155aac2..0eb813206837 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -253,6 +253,16 @@ STATIC_IFN_KUNIT int dm_plane_layer_index_cmp(const void *a, const void *b)
}
EXPORT_IF_KUNIT(dm_plane_layer_index_cmp);
+#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
+static const struct amdgpu_dm_kunit_ops *amdgpu_dm_ops;
+
+#define dm_post_update_surfaces_to_stream amdgpu_dm_ops->post_update_surfaces_to_stream
+#define dm_update_planes_and_stream amdgpu_dm_ops->update_planes_and_stream
+#else
+#define dm_post_update_surfaces_to_stream dc_post_update_surfaces_to_stream
+#define dm_update_planes_and_stream dc_update_planes_and_stream
+#endif
+
/**
* update_planes_and_stream_adapter() - Send planes to be updated in DC
*
@@ -270,12 +280,13 @@ EXPORT_IF_KUNIT(dm_plane_layer_index_cmp);
* @array_of_surface_update: dc surface update pointer
*
*/
-static inline bool update_planes_and_stream_adapter(struct dc *dc,
- int update_type,
- int planes_count,
- struct dc_stream_state *stream,
- struct dc_stream_update *stream_update,
- struct dc_surface_update *array_of_surface_update)
+STATIC_IFN_KUNIT INLINE_IFN_KUNIT
+bool update_planes_and_stream_adapter(struct dc *dc,
+ int update_type,
+ int planes_count,
+ struct dc_stream_state *stream,
+ struct dc_stream_update *stream_update,
+ struct dc_surface_update *array_of_surface_update)
{
sort(array_of_surface_update, planes_count,
sizeof(*array_of_surface_update), dm_plane_layer_index_cmp, NULL);
@@ -283,14 +294,15 @@ static inline bool update_planes_and_stream_adapter(struct dc *dc,
/*
* Previous frame finished and HW is ready for optimization.
*/
- dc_post_update_surfaces_to_stream(dc);
+ dm_post_update_surfaces_to_stream(dc);
- return dc_update_planes_and_stream(dc,
+ return dm_update_planes_and_stream(dc,
array_of_surface_update,
planes_count,
stream,
stream_update);
}
+EXPORT_IF_KUNIT(update_planes_and_stream_adapter);
STATIC_IFN_KUNIT int dm_set_clockgating_state(struct amdgpu_ip_block *ip_block,
enum amd_clockgating_state state)
@@ -312,6 +324,9 @@ STATIC_IFN_KUNIT int dm_early_init(struct amdgpu_ip_block *ip_block);
#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
static const struct amdgpu_dm_kunit_ops amdgpu_dm_default_ops = {
.gmc_pd_addr = amdgpu_gmc_pd_addr,
+ .post_update_surfaces_to_stream = dc_post_update_surfaces_to_stream,
+ .update_planes_and_stream = dc_update_planes_and_stream,
+ .atomic_helper_suspend = drm_atomic_helper_suspend,
};
static const struct amdgpu_dm_kunit_ops *amdgpu_dm_ops = &amdgpu_dm_default_ops;
@@ -322,9 +337,11 @@ void amdgpu_dm_kunit_set_ops(const struct amdgpu_dm_kunit_ops *ops)
}
EXPORT_IF_KUNIT(amdgpu_dm_kunit_set_ops);
-#define dm_gmc_pd_addr amdgpu_dm_ops->gmc_pd_addr
+#define dm_gmc_pd_addr amdgpu_dm_ops->gmc_pd_addr
+#define dm_atomic_helper_suspend amdgpu_dm_ops->atomic_helper_suspend
#else
-#define dm_gmc_pd_addr amdgpu_gmc_pd_addr
+#define dm_gmc_pd_addr amdgpu_gmc_pd_addr
+#define dm_atomic_helper_suspend drm_atomic_helper_suspend
#endif
/* Allocate memory for FBC compressed data */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 645b39e4223b..df2e4d60e85a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -86,7 +86,9 @@ struct dc;
struct amdgpu_bo;
struct dmub_srv;
struct dc_plane_state;
+struct dc_stream_state;
struct dc_stream_update;
+struct dc_surface_update;
struct dmub_notification;
struct dmub_cmd_fused_request;
@@ -1215,6 +1217,12 @@ int dm_sw_fini(struct amdgpu_ip_block *ip_block);
int dm_oem_i2c_hw_init(struct amdgpu_device *adev);
void dm_gpureset_commit_state(struct dc_state *dc_state, struct amdgpu_display_manager *dm);
int dm_plane_layer_index_cmp(const void *a, const void *b);
+bool update_planes_and_stream_adapter(struct dc *dc,
+ int update_type,
+ int planes_count,
+ struct dc_stream_state *stream,
+ struct dc_stream_update *stream_update,
+ struct dc_surface_update *array_of_surface_update);
int fill_plane_color_attributes(const struct drm_plane_state *plane_state,
const enum surface_pixel_format format,
enum dc_color_space *color_space);
@@ -1244,6 +1252,13 @@ void amdgpu_dm_services_kunit_set_ops(const struct amdgpu_dm_services_kunit_ops
struct amdgpu_dm_kunit_ops {
uint64_t (*gmc_pd_addr)(struct amdgpu_bo *bo);
+ void (*post_update_surfaces_to_stream)(struct dc *dc);
+ bool (*update_planes_and_stream)(struct dc *dc,
+ struct dc_surface_update *surface_updates,
+ int surface_count,
+ struct dc_stream_state *dc_stream,
+ struct dc_stream_update *stream_update);
+ struct drm_atomic_commit *(*atomic_helper_suspend)(struct drm_device *dev);
};
void amdgpu_dm_kunit_set_ops(const struct amdgpu_dm_kunit_ops *ops);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
index 7a79aee057f8..ed53bfa5a8c3 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
@@ -327,6 +327,119 @@ static void dm_test_plane_layer_index_cmp_ascending(struct kunit *test)
KUNIT_EXPECT_LT(test, dm_plane_layer_index_cmp(&sa, &sb), 0);
}
+struct dm_test_plane_update_ops_ctx {
+ struct dc *dc;
+ struct dc_surface_update *surface_updates;
+ struct dc_stream_state *stream;
+ struct dc_stream_update *stream_update;
+ int surface_count;
+ unsigned int call_seq;
+ unsigned int post_update_seq;
+ unsigned int update_seq;
+ bool update_ret;
+};
+
+static struct dm_test_plane_update_ops_ctx dm_test_plane_update_ctx;
+
+static void dm_test_post_update_surfaces_to_stream(struct dc *dc)
+{
+ dm_test_plane_update_ctx.dc = dc;
+ dm_test_plane_update_ctx.post_update_seq = ++dm_test_plane_update_ctx.call_seq;
+}
+
+static bool dm_test_update_planes_and_stream(struct dc *dc,
+ struct dc_surface_update *surface_updates,
+ int surface_count,
+ struct dc_stream_state *dc_stream,
+ struct dc_stream_update *stream_update)
+{
+ dm_test_plane_update_ctx.dc = dc;
+ dm_test_plane_update_ctx.surface_updates = surface_updates;
+ dm_test_plane_update_ctx.surface_count = surface_count;
+ dm_test_plane_update_ctx.stream = dc_stream;
+ dm_test_plane_update_ctx.stream_update = stream_update;
+ dm_test_plane_update_ctx.update_seq = ++dm_test_plane_update_ctx.call_seq;
+
+ return dm_test_plane_update_ctx.update_ret;
+}
+
+static const struct amdgpu_dm_kunit_ops dm_test_plane_update_ops = {
+ .post_update_surfaces_to_stream = dm_test_post_update_surfaces_to_stream,
+ .update_planes_and_stream = dm_test_update_planes_and_stream,
+};
+
+static void dm_test_restore_dm_ops(void *ctx)
+{
+ amdgpu_dm_kunit_set_ops(NULL);
+}
+
+static void dm_test_install_dm_ops(struct kunit *test,
+ const struct amdgpu_dm_kunit_ops *ops)
+{
+ amdgpu_dm_kunit_set_ops(ops);
+ KUNIT_ASSERT_EQ(test,
+ kunit_add_action_or_reset(test, dm_test_restore_dm_ops, NULL), 0);
+}
+
+/**
+ * dm_test_update_planes_adapter_sorts_and_forwards - Test sorting and call order
+ * @test: The KUnit test context
+ */
+static void dm_test_update_planes_adapter_sorts_and_forwards(struct kunit *test)
+{
+ struct dc_surface_update *updates;
+ struct dc_plane_state *planes;
+ struct dc_stream_update *stream_update;
+ struct dc_stream_state *stream;
+ struct dc *dc;
+
+ updates = kunit_kcalloc(test, 3, sizeof(*updates), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, updates);
+ planes = kunit_kcalloc(test, 3, sizeof(*planes), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, planes);
+ stream_update = kunit_kzalloc(test, sizeof(*stream_update), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, stream_update);
+ stream = dm_kunit_alloc_stream(test, NULL);
+ dc = dm_kunit_alloc_dc_with_ctx(test);
+
+ planes[0].layer_index = 1;
+ planes[1].layer_index = 5;
+ planes[2].layer_index = 3;
+ updates[0].surface = &planes[0];
+ updates[1].surface = &planes[1];
+ updates[2].surface = &planes[2];
+ dm_test_plane_update_ctx = (struct dm_test_plane_update_ops_ctx) {
+ .update_ret = true,
+ };
+ dm_test_install_dm_ops(test, &dm_test_plane_update_ops);
+
+ KUNIT_EXPECT_TRUE(test, update_planes_and_stream_adapter(dc, UPDATE_TYPE_FAST, 3,
+ stream, stream_update, updates));
+ KUNIT_EXPECT_EQ(test, updates[0].surface->layer_index, 5);
+ KUNIT_EXPECT_EQ(test, updates[1].surface->layer_index, 3);
+ KUNIT_EXPECT_EQ(test, updates[2].surface->layer_index, 1);
+ KUNIT_EXPECT_PTR_EQ(test, dm_test_plane_update_ctx.dc, dc);
+ KUNIT_EXPECT_PTR_EQ(test, dm_test_plane_update_ctx.surface_updates, &updates[0]);
+ KUNIT_EXPECT_EQ(test, dm_test_plane_update_ctx.surface_count, 3);
+ KUNIT_EXPECT_PTR_EQ(test, dm_test_plane_update_ctx.stream, stream);
+ KUNIT_EXPECT_PTR_EQ(test, dm_test_plane_update_ctx.stream_update, stream_update);
+ KUNIT_EXPECT_LT(test, dm_test_plane_update_ctx.post_update_seq,
+ dm_test_plane_update_ctx.update_seq);
+}
+
+/**
+ * dm_test_update_planes_adapter_propagates_failure - Test DC failure is returned
+ * @test: The KUnit test context
+ */
+static void dm_test_update_planes_adapter_propagates_failure(struct kunit *test)
+{
+ dm_test_plane_update_ctx = (struct dm_test_plane_update_ops_ctx) { 0 };
+ dm_test_install_dm_ops(test, &dm_test_plane_update_ops);
+
+ KUNIT_EXPECT_FALSE(test, update_planes_and_stream_adapter(NULL, UPDATE_TYPE_FAST, 0,
+ NULL, NULL, NULL));
+}
+
/* Tests for fill_plane_color_attributes() */
/**
@@ -3422,11 +3535,6 @@ static const struct amdgpu_dm_kunit_ops dm_test_dm_ops = {
.gmc_pd_addr = dm_test_gmc_pd_addr,
};
-static void dm_test_restore_dm_ops(void *ctx)
-{
- amdgpu_dm_kunit_set_ops(NULL);
-}
-
/*
* A device whose AGP aperture is disabled (bot above top), so the frame buffer
* alone decides the logical address range.
@@ -3435,8 +3543,7 @@ static struct amdgpu_device *dm_test_mmhub_adev(struct kunit *test)
{
struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
- amdgpu_dm_kunit_set_ops(&dm_test_dm_ops);
- KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, dm_test_restore_dm_ops, NULL), 0);
+ dm_test_install_dm_ops(test, &dm_test_dm_ops);
adev->gmc.agp_start = 0x2000000;
adev->gmc.agp_end = 0x1000000;
@@ -4868,6 +4975,8 @@ static struct kunit_case amdgpu_dm_tests[] = {
KUNIT_CASE(dm_test_plane_layer_index_cmp_equal),
KUNIT_CASE(dm_test_plane_layer_index_cmp_descending),
KUNIT_CASE(dm_test_plane_layer_index_cmp_ascending),
+ KUNIT_CASE(dm_test_update_planes_adapter_sorts_and_forwards),
+ KUNIT_CASE(dm_test_update_planes_adapter_propagates_failure),
/* fill_plane_color_attributes */
KUNIT_CASE(dm_test_fill_color_attr_rgb_format),
KUNIT_CASE(dm_test_fill_color_attr_bt601_full),
--
2.43.0
next prev parent reply other threads:[~2026-09-02 5:05 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-02 4:58 [PATCH 00/40] DC Patches September 7, 2026 Ray Wu
2026-09-02 4:58 ` [PATCH 01/40] drm/amd/display: Ensure requested LSDMA BW is within the SOP bound Ray Wu
2026-09-02 4:58 ` [PATCH 02/40] drm/amd/display: Refactor DC_SEND_CURSOR_INFO_TO_DMU to drop pipe_ctx Ray Wu
2026-09-02 4:58 ` [PATCH 03/40] drm/amd/display: Test vblank IRQ handling Ray Wu
2026-09-02 4:58 ` [PATCH 04/40] drm/amd/display: Test self refresh entry Ray Wu
2026-09-02 4:58 ` [PATCH 05/40] drm/amd/display: Test GPU reset helpers Ray Wu
2026-09-02 4:58 ` [PATCH 06/40] drm/amd/display: Add override for LSDMA BW in QoS table Ray Wu
2026-09-02 4:58 ` Ray Wu [this message]
2026-09-02 4:58 ` [PATCH 08/40] drm/amd/display: Test MST resume guards Ray Wu
2026-09-02 4:58 ` [PATCH 09/40] drm/amd/display: Test cached suspend state Ray Wu
2026-09-02 4:58 ` [PATCH 10/40] drm/amd/display: Test writeback state transitions Ray Wu
2026-09-02 4:58 ` [PATCH 11/40] drm/amd/display: Test atomic validation guards Ray Wu
2026-09-02 4:58 ` [PATCH 12/40] drm/amd/display: Cover dm_restore_drm_connector_state Ray Wu
2026-09-02 4:58 ` [PATCH 13/40] drm/amd/display: Cover EDID CEA parsing helpers Ray Wu
2026-09-02 4:58 ` [PATCH 14/40] drm/amd/display: Make sure streamclk gating is off when enabling streamclk Ray Wu
2026-09-02 4:58 ` [PATCH 15/40] drm/amd/display: Remove unnecessary includes Ray Wu
2026-09-02 4:58 ` [PATCH 16/40] drm/amd/display: Set mpc_tree_params->opp_id during OPP resource construct Ray Wu
2026-09-02 4:58 ` [PATCH 17/40] drm/amd/display: Add override capability for UTM table params Ray Wu
2026-09-02 4:58 ` [PATCH 18/40] drm/amd/display: Add immediate restore to FAMS2 for DRR Ray Wu
2026-09-02 4:58 ` [PATCH 19/40] drm/amd/display: Fix missing APG regs for DCN60 HDMI Ray Wu
2026-09-02 4:58 ` [PATCH 20/40] drm/amd/display: Exit IPS before connector detection on resume Ray Wu
2026-09-02 4:58 ` [PATCH 21/40] drm/amd/display: Fix HF-VSDB DSC bpc detection to be cumulative Ray Wu
2026-09-02 4:58 ` [PATCH 22/40] drm/amd/display: Fix unused params in flip sched Ray Wu
2026-09-02 4:58 ` [PATCH 23/40] drm/amd/display: Enable FW locality check in DCN6 Ray Wu
2026-09-02 4:58 ` [PATCH 24/40] drm/amd/display: Fix DC Hub reference frequency assert range Ray Wu
2026-09-02 4:58 ` [PATCH 25/40] drm/amd/display: Dump clock registers in HW init instead of SW init Ray Wu
2026-09-02 4:58 ` [PATCH 26/40] drm/amd/display: Validate irq source in DM IRQ handler Ray Wu
2026-09-02 4:58 ` [PATCH 27/40] drm/amd/display: Test DM IRQ handler source guard Ray Wu
2026-09-02 4:58 ` [PATCH 28/40] Revert "drm/amd/display: Fix CalculateFlipSchedule Calculation" Ray Wu
2026-09-02 4:58 ` [PATCH 29/40] drm/amd/display: Set DISPCLK per surface in DML Ray Wu
2026-09-02 4:58 ` [PATCH 30/40] drm/amd/display: Update Urgent Burst Calculation To Account For Unbounded Requests Ray Wu
2026-09-02 4:58 ` [PATCH 31/40] drm/amd/display: Add stressed peak bandwidth probe with DMA contention Ray Wu
2026-09-02 4:58 ` [PATCH 32/40] Revert "drm/amd/display: Unify CalculateFlipSchedule Logic" Ray Wu
2026-09-02 4:58 ` [PATCH 33/40] drm/amd/display: Add dml2_core_dcn6_calcs function pointer table Ray Wu
2026-09-02 4:58 ` [PATCH 34/40] drm/amd/display: Route DCN6 mode support calcs through " Ray Wu
2026-09-02 4:58 ` [PATCH 35/40] drm/amd/display: Route DCN6 mode programming " Ray Wu
2026-09-02 4:58 ` [PATCH 36/40] drm/amd/display: Update DML fields used for mode support Ray Wu
2026-09-02 4:58 ` [PATCH 37/40] drm/amd/display: Fix NULL deref of new_stream->sink in VTEM guard Ray Wu
2026-09-02 4:59 ` [PATCH 38/40] drm/amd/display: Fix signedness mismatches in cm3 Ray Wu
2026-09-02 4:59 ` [PATCH 39/40] drm/amd/display: [FW Promotion] Release 0.1.74.0 Ray Wu
2026-09-02 4:59 ` [PATCH 40/40] drm/amd/display: Promote DC to 3.2.397 Ray Wu
2026-09-09 13:17 ` [PATCH 00/40] DC Patches September 7, 2026 Wheeler, Daniel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260902050411.3473916-8-ray.wu@amd.com \
--to=ray.wu@amd.com \
--cc=Chen-Yu.Chen@amd.com \
--cc=PingLei.Lin@amd.com \
--cc=alex.hung@amd.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=aurabindo.pillai@amd.com \
--cc=bhawanpreet.lakha@amd.com \
--cc=chiahsuan.chung@amd.com \
--cc=daniel.wheeler@amd.com \
--cc=harry.wentland@amd.com \
--cc=ivan.lipski@amd.com \
--cc=jerry.zuo@amd.com \
--cc=roman.li@amd.com \
--cc=sunpeng.li@amd.com \
--cc=wayne.lin@amd.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.