From: Alex Hung <[email protected]> Add KUnit coverage for functions in amdgpu_dm_crtc.c: - amdgpu_dm_crtc_modeset_required: verify active+needs_modeset combinations (mode_changed, active_changed, connectors_changed) - amdgpu_dm_crtc_vrr_active_irq: verify all VRR state enum values - amdgpu_dm_crtc_vrr_active: verify all VRR state enum values - amdgpu_dm_is_headless: null adev, no connectors, writeback-only, disconnected display, connected display, and mixed connector cases - amdgpu_dm_crtc_helper_mode_fixup: verify it accepts the mode - amdgpu_dm_crtc_set_vupdate_irq: verify the otg_inst == -1 early return using a DRM mock device - idle_create_workqueue: verify the idle workqueue is allocated and initialized in a disabled, non-running state
Assisted-by: Copilot:Claude-Opus-4.8 Reviewed-by: Bhawanpreet Lakha <[email protected]> Signed-off-by: Alex Hung <[email protected]> Signed-off-by: Chenyu Chen <[email protected]> --- .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 14 +- .../amd/display/amdgpu_dm/amdgpu_dm_crtc.h | 6 + .../drm/amd/display/amdgpu_dm/tests/Makefile | 1 + .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c | 532 ++++++++++++++++++ 4 files changed, 550 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c index efb19f675b0c..c9916ed0ddc1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c @@ -34,6 +34,7 @@ #include "amdgpu_dm_plane.h" #include "amdgpu_dm_trace.h" #include "amdgpu_dm_debugfs.h" +#include "amdgpu_dm_kunit_helpers.h" #include "modules/inc/mod_power.h" #define HPD_DETECTION_PERIOD_uS 2000000 @@ -65,6 +66,7 @@ bool amdgpu_dm_crtc_modeset_required(struct drm_crtc_state *crtc_state, { return crtc_state->active && drm_atomic_crtc_needs_modeset(crtc_state); } +EXPORT_IF_KUNIT(amdgpu_dm_crtc_modeset_required); bool amdgpu_dm_crtc_vrr_active_irq(struct amdgpu_crtc *acrtc) @@ -74,6 +76,7 @@ bool amdgpu_dm_crtc_vrr_active_irq(struct amdgpu_crtc *acrtc) acrtc->dm_irq_params.freesync_config.state == VRR_STATE_ACTIVE_FIXED; } +EXPORT_IF_KUNIT(amdgpu_dm_crtc_vrr_active_irq); int amdgpu_dm_crtc_set_vupdate_irq(struct drm_crtc *crtc, bool enable) { @@ -93,12 +96,14 @@ int amdgpu_dm_crtc_set_vupdate_irq(struct drm_crtc *crtc, bool enable) acrtc->crtc_id, enable ? "en" : "dis", rc); return rc; } +EXPORT_IF_KUNIT(amdgpu_dm_crtc_set_vupdate_irq); bool amdgpu_dm_crtc_vrr_active(const struct dm_crtc_state *dm_state) { return dm_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE || dm_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED; } +EXPORT_IF_KUNIT(amdgpu_dm_crtc_vrr_active); /** * amdgpu_dm_crtc_set_static_screen_optimze() - Toggle static screen optimizations. @@ -156,6 +161,7 @@ bool amdgpu_dm_is_headless(struct amdgpu_device *adev) drm_connector_list_iter_end(&iter); return is_headless; } +EXPORT_IF_KUNIT(amdgpu_dm_is_headless); static void amdgpu_dm_idle_worker(struct work_struct *work) { @@ -207,6 +213,7 @@ struct idle_workqueue *idle_create_workqueue(struct amdgpu_device *adev) return idle_work; } +EXPORT_IF_KUNIT(idle_create_workqueue); static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work) { @@ -595,12 +602,13 @@ static void amdgpu_dm_crtc_update_crtc_active_planes(struct drm_crtc *crtc, amdgpu_dm_crtc_count_crtc_active_planes(new_crtc_state); } -static bool amdgpu_dm_crtc_helper_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +STATIC_IFN_KUNIT bool amdgpu_dm_crtc_helper_mode_fixup(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { return true; } +EXPORT_IF_KUNIT(amdgpu_dm_crtc_helper_mode_fixup); static int amdgpu_dm_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h index e9fb52f0e66d..d8b004f613ab 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h @@ -42,6 +42,12 @@ int amdgpu_dm_crtc_set_vupdate_irq(struct drm_crtc *crtc, bool enable); bool amdgpu_dm_crtc_vrr_active_irq(struct amdgpu_crtc *acrtc); +#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST) +bool amdgpu_dm_crtc_helper_mode_fixup(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); +#endif + bool amdgpu_dm_crtc_vrr_active(const struct dm_crtc_state *dm_state); int amdgpu_dm_crtc_enable_vblank(struct drm_crtc *crtc); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile index 583604914753..cde8f7748bc5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile @@ -27,3 +27,4 @@ obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_wb_test.o obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_mst_types_test.o obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_pp_smu_test.o obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_test.o +obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_crtc_test.o diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c new file mode 100644 index 000000000000..c83bd3e074f1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c @@ -0,0 +1,532 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT +/* + * KUnit tests for amdgpu_dm_crtc.c + * + * Copyright 2026 Advanced Micro Devices, Inc. + */ + +#include <kunit/test.h> +#include <drm/drm_atomic.h> +#include <drm/drm_connector.h> +#include <drm/drm_kunit_helpers.h> + +#include "dc.h" +#include "amdgpu.h" +#include "amdgpu_mode.h" +#include "amdgpu_dm.h" +#include "amdgpu_dm_crtc.h" +#include "amdgpu_dm_irq_params.h" + +/* Tests for amdgpu_dm_crtc_modeset_required() */ + +/** + * dm_test_crtc_modeset_required_active_mode_changed - Test Crtc modeset required active mode changed + * @test: The KUnit test context + */ +static void dm_test_crtc_modeset_required_active_mode_changed(struct kunit *test) +{ + struct drm_crtc_state state = {}; + + state.active = true; + state.mode_changed = true; + + KUNIT_EXPECT_TRUE(test, + amdgpu_dm_crtc_modeset_required(&state, NULL, NULL)); +} + +/** + * dm_test_crtc_modeset_required_active_active_changed - Test Crtc modeset required active active changed + * @test: The KUnit test context + */ +static void dm_test_crtc_modeset_required_active_active_changed(struct kunit *test) +{ + struct drm_crtc_state state = {}; + + state.active = true; + state.active_changed = true; + + KUNIT_EXPECT_TRUE(test, + amdgpu_dm_crtc_modeset_required(&state, NULL, NULL)); +} + +/** + * dm_test_crtc_modeset_required_active_connectors_changed - Test Crtc modeset required active connectors changed + * @test: The KUnit test context + */ +static void dm_test_crtc_modeset_required_active_connectors_changed(struct kunit *test) +{ + struct drm_crtc_state state = {}; + + state.active = true; + state.connectors_changed = true; + + KUNIT_EXPECT_TRUE(test, + amdgpu_dm_crtc_modeset_required(&state, NULL, NULL)); +} + +/** + * dm_test_crtc_modeset_required_inactive - Test Crtc modeset required inactive + * @test: The KUnit test context + */ +static void dm_test_crtc_modeset_required_inactive(struct kunit *test) +{ + struct drm_crtc_state state = {}; + + state.active = false; + state.mode_changed = true; + + KUNIT_EXPECT_FALSE(test, + amdgpu_dm_crtc_modeset_required(&state, NULL, NULL)); +} + +/** + * dm_test_crtc_modeset_required_no_changes - Test Crtc modeset required no changes + * @test: The KUnit test context + */ +static void dm_test_crtc_modeset_required_no_changes(struct kunit *test) +{ + struct drm_crtc_state state = {}; + + state.active = true; + state.mode_changed = false; + state.active_changed = false; + state.connectors_changed = false; + + KUNIT_EXPECT_FALSE(test, + amdgpu_dm_crtc_modeset_required(&state, NULL, NULL)); +} + +/* Tests for amdgpu_dm_crtc_vrr_active_irq() */ + +/** + * dm_test_crtc_vrr_active_irq_variable - Test Crtc vrr active irq variable + * @test: The KUnit test context + */ +static void dm_test_crtc_vrr_active_irq_variable(struct kunit *test) +{ + struct amdgpu_crtc *acrtc = kunit_kzalloc(test, sizeof(*acrtc), + GFP_KERNEL); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc); + + acrtc->dm_irq_params.freesync_config.state = VRR_STATE_ACTIVE_VARIABLE; + + KUNIT_EXPECT_TRUE(test, amdgpu_dm_crtc_vrr_active_irq(acrtc)); +} + +/** + * dm_test_crtc_vrr_active_irq_fixed - Test Crtc vrr active irq fixed + * @test: The KUnit test context + */ +static void dm_test_crtc_vrr_active_irq_fixed(struct kunit *test) +{ + struct amdgpu_crtc *acrtc = kunit_kzalloc(test, sizeof(*acrtc), + GFP_KERNEL); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc); + + acrtc->dm_irq_params.freesync_config.state = VRR_STATE_ACTIVE_FIXED; + + KUNIT_EXPECT_TRUE(test, amdgpu_dm_crtc_vrr_active_irq(acrtc)); +} + +/** + * dm_test_crtc_vrr_active_irq_inactive - Test Crtc vrr active irq inactive + * @test: The KUnit test context + */ +static void dm_test_crtc_vrr_active_irq_inactive(struct kunit *test) +{ + struct amdgpu_crtc *acrtc = kunit_kzalloc(test, sizeof(*acrtc), + GFP_KERNEL); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc); + + acrtc->dm_irq_params.freesync_config.state = VRR_STATE_INACTIVE; + + KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_vrr_active_irq(acrtc)); +} + +/** + * dm_test_crtc_vrr_active_irq_disabled - Test Crtc vrr active irq disabled + * @test: The KUnit test context + */ +static void dm_test_crtc_vrr_active_irq_disabled(struct kunit *test) +{ + struct amdgpu_crtc *acrtc = kunit_kzalloc(test, sizeof(*acrtc), + GFP_KERNEL); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc); + + acrtc->dm_irq_params.freesync_config.state = VRR_STATE_DISABLED; + + KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_vrr_active_irq(acrtc)); +} + +/** + * dm_test_crtc_vrr_active_irq_unsupported - Test Crtc vrr active irq unsupported + * @test: The KUnit test context + */ +static void dm_test_crtc_vrr_active_irq_unsupported(struct kunit *test) +{ + struct amdgpu_crtc *acrtc = kunit_kzalloc(test, sizeof(*acrtc), + GFP_KERNEL); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc); + + acrtc->dm_irq_params.freesync_config.state = VRR_STATE_UNSUPPORTED; + + KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_vrr_active_irq(acrtc)); +} + +/* Tests for amdgpu_dm_crtc_vrr_active() */ + +/** + * dm_test_crtc_vrr_active_variable - Test Crtc vrr active variable + * @test: The KUnit test context + */ +static void dm_test_crtc_vrr_active_variable(struct kunit *test) +{ + struct dm_crtc_state *dm_state = kunit_kzalloc(test, + sizeof(*dm_state), + GFP_KERNEL); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state); + + dm_state->freesync_config.state = VRR_STATE_ACTIVE_VARIABLE; + + KUNIT_EXPECT_TRUE(test, amdgpu_dm_crtc_vrr_active(dm_state)); +} + +/** + * dm_test_crtc_vrr_active_fixed - Test Crtc vrr active fixed + * @test: The KUnit test context + */ +static void dm_test_crtc_vrr_active_fixed(struct kunit *test) +{ + struct dm_crtc_state *dm_state = kunit_kzalloc(test, + sizeof(*dm_state), + GFP_KERNEL); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state); + + dm_state->freesync_config.state = VRR_STATE_ACTIVE_FIXED; + + KUNIT_EXPECT_TRUE(test, amdgpu_dm_crtc_vrr_active(dm_state)); +} + +/** + * dm_test_crtc_vrr_active_inactive - Test Crtc vrr active inactive + * @test: The KUnit test context + */ +static void dm_test_crtc_vrr_active_inactive(struct kunit *test) +{ + struct dm_crtc_state *dm_state = kunit_kzalloc(test, + sizeof(*dm_state), + GFP_KERNEL); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state); + + dm_state->freesync_config.state = VRR_STATE_INACTIVE; + + KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_vrr_active(dm_state)); +} + +/** + * dm_test_crtc_vrr_active_disabled - Test Crtc vrr active disabled + * @test: The KUnit test context + */ +static void dm_test_crtc_vrr_active_disabled(struct kunit *test) +{ + struct dm_crtc_state *dm_state = kunit_kzalloc(test, + sizeof(*dm_state), + GFP_KERNEL); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state); + + dm_state->freesync_config.state = VRR_STATE_DISABLED; + + KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_vrr_active(dm_state)); +} + +/** + * dm_test_crtc_vrr_active_unsupported - Test Crtc vrr active unsupported + * @test: The KUnit test context + */ +static void dm_test_crtc_vrr_active_unsupported(struct kunit *test) +{ + struct dm_crtc_state *dm_state = kunit_kzalloc(test, + sizeof(*dm_state), + GFP_KERNEL); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state); + + dm_state->freesync_config.state = VRR_STATE_UNSUPPORTED; + + KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_vrr_active(dm_state)); +} + +/* Tests for amdgpu_dm_is_headless() */ + +static void dm_test_add_connector(struct drm_device *dev, + struct drm_connector *connector, + int connector_type, + enum drm_connector_status status) +{ + INIT_LIST_HEAD(&connector->head); + kref_init(&connector->base.refcount); + connector->connector_type = connector_type; + connector->status = status; + list_add_tail(&connector->head, &dev->mode_config.connector_list); +} + +/** + * dm_test_crtc_is_headless_null_adev - Test Crtc is headless null adev + * @test: The KUnit test context + */ +static void dm_test_crtc_is_headless_null_adev(struct kunit *test) +{ + KUNIT_EXPECT_TRUE(test, amdgpu_dm_is_headless(NULL)); +} + +/** + * dm_test_crtc_is_headless_no_connectors - Test Crtc is headless no connectors + * @test: The KUnit test context + */ +static void dm_test_crtc_is_headless_no_connectors(struct kunit *test) +{ + struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); + struct drm_device *dev = kunit_kzalloc(test, sizeof(*dev), GFP_KERNEL); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + + INIT_LIST_HEAD(&dev->mode_config.connector_list); + spin_lock_init(&dev->mode_config.connector_list_lock); + adev->dm.ddev = dev; + + KUNIT_EXPECT_TRUE(test, amdgpu_dm_is_headless(adev)); +} + +/** + * dm_test_crtc_is_headless_writeback_only - Test Crtc is headless writeback only + * @test: The KUnit test context + */ +static void dm_test_crtc_is_headless_writeback_only(struct kunit *test) +{ + struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); + struct drm_device *dev = kunit_kzalloc(test, sizeof(*dev), GFP_KERNEL); + struct drm_connector *wb = kunit_kzalloc(test, sizeof(*wb), GFP_KERNEL); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, wb); + + INIT_LIST_HEAD(&dev->mode_config.connector_list); + spin_lock_init(&dev->mode_config.connector_list_lock); + adev->dm.ddev = dev; + + dm_test_add_connector(dev, wb, DRM_MODE_CONNECTOR_WRITEBACK, + connector_status_connected); + + KUNIT_EXPECT_TRUE(test, amdgpu_dm_is_headless(adev)); +} + +/** + * dm_test_crtc_is_headless_disconnected_display - Test Crtc is headless disconnected display + * @test: The KUnit test context + */ +static void dm_test_crtc_is_headless_disconnected_display(struct kunit *test) +{ + struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); + struct drm_device *dev = kunit_kzalloc(test, sizeof(*dev), GFP_KERNEL); + struct drm_connector *display = kunit_kzalloc(test, sizeof(*display), GFP_KERNEL); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, display); + + INIT_LIST_HEAD(&dev->mode_config.connector_list); + spin_lock_init(&dev->mode_config.connector_list_lock); + adev->dm.ddev = dev; + + dm_test_add_connector(dev, display, DRM_MODE_CONNECTOR_HDMIA, + connector_status_disconnected); + + KUNIT_EXPECT_TRUE(test, amdgpu_dm_is_headless(adev)); +} + +/** + * dm_test_crtc_is_headless_connected_display - Test Crtc is headless connected display + * @test: The KUnit test context + */ +static void dm_test_crtc_is_headless_connected_display(struct kunit *test) +{ + struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); + struct drm_device *dev = kunit_kzalloc(test, sizeof(*dev), GFP_KERNEL); + struct drm_connector *display = kunit_kzalloc(test, sizeof(*display), GFP_KERNEL); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, display); + + INIT_LIST_HEAD(&dev->mode_config.connector_list); + spin_lock_init(&dev->mode_config.connector_list_lock); + adev->dm.ddev = dev; + + dm_test_add_connector(dev, display, DRM_MODE_CONNECTOR_HDMIA, + connector_status_connected); + + KUNIT_EXPECT_FALSE(test, amdgpu_dm_is_headless(adev)); +} + +/** + * dm_test_crtc_is_headless_mixed_connectors - Test headless skips WB and finds display + * @test: The KUnit test context + */ +static void dm_test_crtc_is_headless_mixed_connectors(struct kunit *test) +{ + struct amdgpu_device *adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); + struct drm_device *dev = kunit_kzalloc(test, sizeof(*dev), GFP_KERNEL); + struct drm_connector *wb = kunit_kzalloc(test, sizeof(*wb), GFP_KERNEL); + struct drm_connector *display = kunit_kzalloc(test, sizeof(*display), GFP_KERNEL); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, wb); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, display); + + INIT_LIST_HEAD(&dev->mode_config.connector_list); + spin_lock_init(&dev->mode_config.connector_list_lock); + adev->dm.ddev = dev; + + dm_test_add_connector(dev, wb, DRM_MODE_CONNECTOR_WRITEBACK, + connector_status_connected); + dm_test_add_connector(dev, display, DRM_MODE_CONNECTOR_DisplayPort, + connector_status_connected); + + KUNIT_EXPECT_FALSE(test, amdgpu_dm_is_headless(adev)); +} + +/* Tests for amdgpu_dm_crtc_helper_mode_fixup() */ + +/** + * dm_test_crtc_helper_mode_fixup_returns_true - Test mode_fixup accepts mode + * @test: The KUnit test context + */ +static void dm_test_crtc_helper_mode_fixup_returns_true(struct kunit *test) +{ + struct drm_display_mode mode = { 0 }; + struct drm_display_mode adjusted_mode = { 0 }; + + KUNIT_EXPECT_TRUE(test, + amdgpu_dm_crtc_helper_mode_fixup(NULL, &mode, &adjusted_mode)); +} + +/* Tests for amdgpu_dm_crtc_set_vupdate_irq() */ + +/** + * dm_test_crtc_set_vupdate_irq_no_otg - Test vupdate irq with unassigned OTG + * @test: The KUnit test context + * + * When the CRTC has no OTG instance assigned (otg_inst == -1) the function + * must return 0 immediately without touching the DC interrupt state. + */ +static void dm_test_crtc_set_vupdate_irq_no_otg(struct kunit *test) +{ + struct amdgpu_crtc *acrtc; + struct amdgpu_device *adev; + struct drm_device *drm; + struct device *dev; + + dev = drm_kunit_helper_alloc_device(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + + drm = __drm_kunit_helper_alloc_drm_device(test, dev, + sizeof(*adev), + offsetof(struct amdgpu_device, ddev), + DRIVER_MODESET); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm); + adev = drm_to_adev(drm); + + acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc); + + acrtc->base.dev = drm; + acrtc->otg_inst = -1; + + KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, true), 0); + KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, false), 0); +} + +/* Tests for idle_create_workqueue() */ + +/** + * dm_test_idle_create_workqueue - Test idle workqueue creation + * @test: The KUnit test context + * + * Verify that idle_create_workqueue() allocates an idle workqueue tied to the + * device's display manager and initializes it in a disabled, non-running state. + */ +static void dm_test_idle_create_workqueue(struct kunit *test) +{ + struct amdgpu_device *adev; + struct idle_workqueue *idle_work; + + adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev); + + idle_work = idle_create_workqueue(adev); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, idle_work); + + KUNIT_EXPECT_PTR_EQ(test, idle_work->dm, &adev->dm); + KUNIT_EXPECT_FALSE(test, idle_work->enable); + KUNIT_EXPECT_FALSE(test, idle_work->running); + + kfree(idle_work); +} + +static struct kunit_case amdgpu_dm_crtc_tests[] = { + /* amdgpu_dm_crtc_modeset_required */ + KUNIT_CASE(dm_test_crtc_modeset_required_active_mode_changed), + KUNIT_CASE(dm_test_crtc_modeset_required_active_active_changed), + KUNIT_CASE(dm_test_crtc_modeset_required_active_connectors_changed), + KUNIT_CASE(dm_test_crtc_modeset_required_inactive), + KUNIT_CASE(dm_test_crtc_modeset_required_no_changes), + /* amdgpu_dm_crtc_vrr_active_irq */ + KUNIT_CASE(dm_test_crtc_vrr_active_irq_variable), + KUNIT_CASE(dm_test_crtc_vrr_active_irq_fixed), + KUNIT_CASE(dm_test_crtc_vrr_active_irq_inactive), + KUNIT_CASE(dm_test_crtc_vrr_active_irq_disabled), + KUNIT_CASE(dm_test_crtc_vrr_active_irq_unsupported), + /* amdgpu_dm_crtc_vrr_active */ + KUNIT_CASE(dm_test_crtc_vrr_active_variable), + KUNIT_CASE(dm_test_crtc_vrr_active_fixed), + KUNIT_CASE(dm_test_crtc_vrr_active_inactive), + KUNIT_CASE(dm_test_crtc_vrr_active_disabled), + KUNIT_CASE(dm_test_crtc_vrr_active_unsupported), + /* amdgpu_dm_is_headless */ + KUNIT_CASE(dm_test_crtc_is_headless_null_adev), + KUNIT_CASE(dm_test_crtc_is_headless_no_connectors), + KUNIT_CASE(dm_test_crtc_is_headless_writeback_only), + KUNIT_CASE(dm_test_crtc_is_headless_disconnected_display), + KUNIT_CASE(dm_test_crtc_is_headless_connected_display), + KUNIT_CASE(dm_test_crtc_is_headless_mixed_connectors), + /* amdgpu_dm_crtc_helper_mode_fixup */ + KUNIT_CASE(dm_test_crtc_helper_mode_fixup_returns_true), + /* amdgpu_dm_crtc_set_vupdate_irq */ + KUNIT_CASE(dm_test_crtc_set_vupdate_irq_no_otg), + /* idle_create_workqueue */ + KUNIT_CASE(dm_test_idle_create_workqueue), + {} +}; + +static struct kunit_suite amdgpu_dm_crtc_test_suite = { + .name = "amdgpu_dm_crtc", + .test_cases = amdgpu_dm_crtc_tests, +}; + +kunit_test_suite(amdgpu_dm_crtc_test_suite); + +MODULE_AUTHOR("AMD"); +MODULE_DESCRIPTION("KUnit tests for amdgpu_dm_crtc"); +MODULE_LICENSE("Dual MIT/GPL"); -- 2.43.0
