* [PATCH v9 0/6] DRM scheduler kunit tests
@ 2025-03-18 13:37 Tvrtko Ursulin
2025-03-18 13:37 ` [PATCH v9 1/6] drm: Move some options to separate new Kconfig Tvrtko Ursulin
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Tvrtko Ursulin @ 2025-03-18 13:37 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
There has repeatedly been quite a bit of apprehension when any change to the DRM
scheduler is proposed, with two main reasons being code base is considered
fragile, not well understood and not very well documented, and secondly the lack
of systematic testing outside the vendor specific tests suites and/or test
farms.
This series is an attempt to dislodge this status quo by adding some unit tests
using the kunit framework.
General approach is that there is a mock "hardware" backend which can be
controlled from tests, which in turn allows exercising various scheduler code
paths.
Only some simple basic tests get added in the series and hopefully it is easy to
understand what tests are doing.
An obligatory "screenshot" for reference:
[14:09:05] ============ drm_sched_basic_tests (3 subtests) ============
[14:09:06] [PASSED] drm_sched_basic_submit
[14:09:06] ================== drm_sched_basic_test ===================
[14:09:06] [PASSED] A queue of jobs in a single entity
[14:09:06] [PASSED] A chain of dependent jobs across multiple entities
[14:09:06] [PASSED] Multiple independent job queues
[14:09:06] [PASSED] Multiple inter-dependent job queues
[14:09:07] ============== [PASSED] drm_sched_basic_test ===============
[14:09:07] [PASSED] drm_sched_basic_entity_cleanup
[14:09:07] ============== [PASSED] drm_sched_basic_tests ==============
[14:09:07] ======== drm_sched_basic_timeout_tests (1 subtest) =========
[14:09:08] [PASSED] drm_sched_basic_timeout
[14:09:08] ========== [PASSED] drm_sched_basic_timeout_tests ==========
[14:09:08] ======= drm_sched_basic_priority_tests (2 subtests) ========
[14:09:10] [PASSED] drm_sched_priorities
[14:09:10] [PASSED] drm_sched_change_priority
[14:09:10] ========= [PASSED] drm_sched_basic_priority_tests ==========
[14:09:10] ====== drm_sched_basic_modify_sched_tests (1 subtest) ======
[14:09:11] [PASSED] drm_sched_test_modify_sched
[14:09:11] ======= [PASSED] drm_sched_basic_modify_sched_tests ========
[14:09:11] ======== drm_sched_basic_credits_tests (1 subtest) =========
[14:09:12] [PASSED] drm_sched_test_credits
[14:09:12] ========== [PASSED] drm_sched_basic_credits_tests ==========
[14:09:12] ============================================================
[14:09:12] Testing complete. Ran 11 tests: passed: 11
[14:09:13] Elapsed time: 13.539s total, 0.001s configuring, 3.004s building, 10.462s running
v2:
* Parameterize a bunch of similar tests.
* Improve test commentary.
* Rename TDR test to timeout. (Christian)
* Improve quality and consistency of naming. (Philipp)
RFC v2 -> series v1:
* Rebased for drm_sched_init changes.
* Fixed modular build.
* Added some comments.
* Filename renames. (Philipp)
v2:
* Dealt with a bunch of checkpatch warnings.
v3:
* Some mock API renames, kerneldoc grammar fixes and indentation fixes.
v4:
* Fix use after free caused by relying on scheduler fence for querying status.
* Kerneldoc fixes.
v5:
* Cleanup in-flight jobs on scheduler shutdown.
* Change hang_limit to 1.
v6:
* Use KUNIT_ASSERT_TRUE/FALSE.
* Fixed patch titles.
* Added credit_limit test.
* Added CONFIG_DRM_SCHED_KUNIT_TEST_ASPIRATIONAL.
v7:
* v6 omitted to send the first patch by mistake.
v8:
* Removed CONFIG_DRM_SCHED_KUNIT_TEST_ASPIRATIONAL for now.
* Added Christian's acks.
v9:
* Fixed a potential memory leak caused by a race condition on mock scheduler
shutdown. In order to reliably clean up everything, we have keep track of
jobs even past the signalling stage, all until either DRM sched core managed
to run the ->free_job() callback, or until mock scheduler teardown from the
test.
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@kernel.org>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <phasta@kernel.org>
Tvrtko Ursulin (6):
drm: Move some options to separate new Kconfig
drm/sched: Add scheduler unit testing infrastructure and some basic
tests
drm/sched: Add a simple timeout test
drm/sched: Add basic priority tests
drm/sched: Add a basic test for modifying entities scheduler list
drm/sched: Add a basic test for checking credit limit
drivers/gpu/drm/Kconfig | 109 +---
drivers/gpu/drm/Kconfig.debug | 115 +++++
drivers/gpu/drm/scheduler/.kunitconfig | 12 +
drivers/gpu/drm/scheduler/Makefile | 2 +
drivers/gpu/drm/scheduler/tests/Makefile | 7 +
.../gpu/drm/scheduler/tests/mock_scheduler.c | 359 +++++++++++++
drivers/gpu/drm/scheduler/tests/sched_tests.h | 226 +++++++++
drivers/gpu/drm/scheduler/tests/tests_basic.c | 476 ++++++++++++++++++
8 files changed, 1202 insertions(+), 104 deletions(-)
create mode 100644 drivers/gpu/drm/Kconfig.debug
create mode 100644 drivers/gpu/drm/scheduler/.kunitconfig
create mode 100644 drivers/gpu/drm/scheduler/tests/Makefile
create mode 100644 drivers/gpu/drm/scheduler/tests/mock_scheduler.c
create mode 100644 drivers/gpu/drm/scheduler/tests/sched_tests.h
create mode 100644 drivers/gpu/drm/scheduler/tests/tests_basic.c
--
2.48.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v9 1/6] drm: Move some options to separate new Kconfig
2025-03-18 13:37 [PATCH v9 0/6] DRM scheduler kunit tests Tvrtko Ursulin
@ 2025-03-18 13:37 ` Tvrtko Ursulin
2025-03-24 9:03 ` Philipp Stanner
2025-03-18 13:37 ` [PATCH v9 2/6] drm/sched: Add scheduler unit testing infrastructure and some basic tests Tvrtko Ursulin
` (4 subsequent siblings)
5 siblings, 1 reply; 8+ messages in thread
From: Tvrtko Ursulin @ 2025-03-18 13:37 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
Move some options out into a new debug specific kconfig file in order to
make things a bit cleaner.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@kernel.org>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <phasta@kernel.org>
Acked-by: Christian König <christian.koenig@amd.com>
---
drivers/gpu/drm/Kconfig | 109 ++--------------------------------
drivers/gpu/drm/Kconfig.debug | 103 ++++++++++++++++++++++++++++++++
2 files changed, 108 insertions(+), 104 deletions(-)
create mode 100644 drivers/gpu/drm/Kconfig.debug
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 1be14d8634f4..d32d70c3ddf1 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -26,6 +26,11 @@ menuconfig DRM
details. You should also select and configure AGP
(/dev/agpgart) support if it is available for your platform.
+menu "DRM debugging options"
+depends on DRM
+source "drivers/gpu/drm/Kconfig.debug"
+endmenu
+
if DRM
config DRM_MIPI_DBI
@@ -37,65 +42,6 @@ config DRM_MIPI_DSI
bool
depends on DRM
-config DRM_DEBUG_MM
- bool "Insert extra checks and debug info into the DRM range managers"
- default n
- depends on DRM
- depends on STACKTRACE_SUPPORT
- select STACKDEPOT
- help
- Enable allocation tracking of memory manager and leak detection on
- shutdown.
-
- Recommended for driver developers only.
-
- If in doubt, say "N".
-
-config DRM_USE_DYNAMIC_DEBUG
- bool "use dynamic debug to implement drm.debug"
- default n
- depends on BROKEN
- depends on DRM
- depends on DYNAMIC_DEBUG || DYNAMIC_DEBUG_CORE
- depends on JUMP_LABEL
- help
- Use dynamic-debug to avoid drm_debug_enabled() runtime overheads.
- Due to callsite counts in DRM drivers (~4k in amdgpu) and 56
- bytes per callsite, the .data costs can be substantial, and
- are therefore configurable.
-
-config DRM_KUNIT_TEST_HELPERS
- tristate
- depends on DRM && KUNIT
- select DRM_KMS_HELPER
- help
- KUnit Helpers for KMS drivers.
-
-config DRM_KUNIT_TEST
- tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS
- depends on DRM && KUNIT && MMU
- select DRM_BUDDY
- select DRM_DISPLAY_DP_HELPER
- select DRM_DISPLAY_HDMI_STATE_HELPER
- select DRM_DISPLAY_HELPER
- select DRM_EXEC
- select DRM_EXPORT_FOR_TESTS if m
- select DRM_GEM_SHMEM_HELPER
- select DRM_KUNIT_TEST_HELPERS
- select DRM_LIB_RANDOM
- select PRIME_NUMBERS
- default KUNIT_ALL_TESTS
- help
- This builds unit tests for DRM. This option is not useful for
- distributions or general kernels, but only for kernel
- developers working on DRM and associated drivers.
-
- For more information on KUnit and unit tests in general,
- please refer to the KUnit documentation in
- Documentation/dev-tools/kunit/.
-
- If in doubt, say "N".
-
config DRM_KMS_HELPER
tristate
depends on DRM
@@ -247,23 +193,6 @@ config DRM_TTM
GPU memory types. Will be enabled automatically if a device driver
uses it.
-config DRM_TTM_KUNIT_TEST
- tristate "KUnit tests for TTM" if !KUNIT_ALL_TESTS
- default n
- depends on DRM && KUNIT && MMU && (UML || COMPILE_TEST)
- select DRM_TTM
- select DRM_BUDDY
- select DRM_EXPORT_FOR_TESTS if m
- select DRM_KUNIT_TEST_HELPERS
- default KUNIT_ALL_TESTS
- help
- Enables unit tests for TTM, a GPU memory manager subsystem used
- to manage memory buffers. This option is mostly useful for kernel
- developers. It depends on (UML || COMPILE_TEST) since no other driver
- which uses TTM can be loaded while running the tests.
-
- If in doubt, say "N".
-
config DRM_EXEC
tristate
depends on DRM
@@ -474,9 +403,6 @@ config DRM_HYPERV
If M is selected the module will be called hyperv_drm.
-config DRM_EXPORT_FOR_TESTS
- bool
-
# Separate option as not all DRM drivers use it
config DRM_PANEL_BACKLIGHT_QUIRKS
tristate
@@ -489,31 +415,6 @@ config DRM_PRIVACY_SCREEN
bool
default n
-config DRM_WERROR
- bool "Compile the drm subsystem with warnings as errors"
- depends on DRM && EXPERT
- depends on !WERROR
- default n
- help
- A kernel build should not cause any compiler warnings, and this
- enables the '-Werror' flag to enforce that rule in the drm subsystem.
-
- The drm subsystem enables more warnings than the kernel default, so
- this config option is disabled by default.
-
- If in doubt, say N.
-
-config DRM_HEADER_TEST
- bool "Ensure DRM headers are self-contained and pass kernel-doc"
- depends on DRM && EXPERT
- default n
- help
- Ensure the DRM subsystem headers both under drivers/gpu/drm and
- include/drm compile, are self-contained, have header guards, and have
- no kernel-doc warnings.
-
- If in doubt, say N.
-
endif
# Separate option because drm_panel_orientation_quirks.c is shared with fbdev
diff --git a/drivers/gpu/drm/Kconfig.debug b/drivers/gpu/drm/Kconfig.debug
new file mode 100644
index 000000000000..601d7e07d421
--- /dev/null
+++ b/drivers/gpu/drm/Kconfig.debug
@@ -0,0 +1,103 @@
+config DRM_USE_DYNAMIC_DEBUG
+ bool "use dynamic debug to implement drm.debug"
+ default n
+ depends on BROKEN
+ depends on DRM
+ depends on DYNAMIC_DEBUG || DYNAMIC_DEBUG_CORE
+ depends on JUMP_LABEL
+ help
+ Use dynamic-debug to avoid drm_debug_enabled() runtime overheads.
+ Due to callsite counts in DRM drivers (~4k in amdgpu) and 56
+ bytes per callsite, the .data costs can be substantial, and
+ are therefore configurable.
+
+config DRM_WERROR
+ bool "Compile the drm subsystem with warnings as errors"
+ depends on DRM && EXPERT
+ depends on !WERROR
+ default n
+ help
+ A kernel build should not cause any compiler warnings, and this
+ enables the '-Werror' flag to enforce that rule in the drm subsystem.
+
+ The drm subsystem enables more warnings than the kernel default, so
+ this config option is disabled by default.
+
+ If in doubt, say N.
+
+config DRM_HEADER_TEST
+ bool "Ensure DRM headers are self-contained and pass kernel-doc"
+ depends on DRM && EXPERT
+ default n
+ help
+ Ensure the DRM subsystem headers both under drivers/gpu/drm and
+ include/drm compile, are self-contained, have header guards, and have
+ no kernel-doc warnings.
+
+ If in doubt, say N.
+
+config DRM_DEBUG_MM
+ bool "Insert extra checks and debug info into the DRM range managers"
+ default n
+ depends on DRM
+ depends on STACKTRACE_SUPPORT
+ select STACKDEPOT
+ help
+ Enable allocation tracking of memory manager and leak detection on
+ shutdown.
+
+ Recommended for driver developers only.
+
+ If in doubt, say "N".
+
+config DRM_KUNIT_TEST_HELPERS
+ tristate
+ depends on DRM && KUNIT
+ select DRM_KMS_HELPER
+ help
+ KUnit Helpers for KMS drivers.
+
+config DRM_KUNIT_TEST
+ tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS
+ depends on DRM && KUNIT && MMU
+ select DRM_BUDDY
+ select DRM_DISPLAY_DP_HELPER
+ select DRM_DISPLAY_HDMI_STATE_HELPER
+ select DRM_DISPLAY_HELPER
+ select DRM_EXEC
+ select DRM_EXPORT_FOR_TESTS if m
+ select DRM_GEM_SHMEM_HELPER
+ select DRM_KUNIT_TEST_HELPERS
+ select DRM_LIB_RANDOM
+ select PRIME_NUMBERS
+ default KUNIT_ALL_TESTS
+ help
+ This builds unit tests for DRM. This option is not useful for
+ distributions or general kernels, but only for kernel
+ developers working on DRM and associated drivers.
+
+ For more information on KUnit and unit tests in general,
+ please refer to the KUnit documentation in
+ Documentation/dev-tools/kunit/.
+
+ If in doubt, say "N".
+
+config DRM_TTM_KUNIT_TEST
+ tristate "KUnit tests for TTM" if !KUNIT_ALL_TESTS
+ default n
+ depends on DRM && KUNIT && MMU && (UML || COMPILE_TEST)
+ select DRM_TTM
+ select DRM_BUDDY
+ select DRM_EXPORT_FOR_TESTS if m
+ select DRM_KUNIT_TEST_HELPERS
+ default KUNIT_ALL_TESTS
+ help
+ Enables unit tests for TTM, a GPU memory manager subsystem used
+ to manage memory buffers. This option is mostly useful for kernel
+ developers. It depends on (UML || COMPILE_TEST) since no other driver
+ which uses TTM can be loaded while running the tests.
+
+ If in doubt, say "N".
+
+config DRM_EXPORT_FOR_TESTS
+ bool
--
2.48.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v9 2/6] drm/sched: Add scheduler unit testing infrastructure and some basic tests
2025-03-18 13:37 [PATCH v9 0/6] DRM scheduler kunit tests Tvrtko Ursulin
2025-03-18 13:37 ` [PATCH v9 1/6] drm: Move some options to separate new Kconfig Tvrtko Ursulin
@ 2025-03-18 13:37 ` Tvrtko Ursulin
2025-03-18 13:37 ` [PATCH v9 3/6] drm/sched: Add a simple timeout test Tvrtko Ursulin
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Tvrtko Ursulin @ 2025-03-18 13:37 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Philipp Stanner, Christian König,
Danilo Krummrich, Matthew Brost
Implement a mock scheduler backend and add some basic test to exercise the
core scheduler code paths.
Mock backend (kind of like a very simple mock GPU) can either process jobs
by tests manually advancing the "timeline" job at a time, or alternatively
jobs can be configured with a time duration in which case they get
completed asynchronously from the unit test code.
Core scheduler classes are subclassed to support this mock implementation.
The tests added are just a few simple submission patterns.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Suggested-by: Philipp Stanner <phasta@kernel.org>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@kernel.org>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <phasta@kernel.org>
Acked-by: Christian König <christian.koenig@amd.com>
---
drivers/gpu/drm/Kconfig.debug | 12 +
drivers/gpu/drm/scheduler/.kunitconfig | 12 +
drivers/gpu/drm/scheduler/Makefile | 2 +
drivers/gpu/drm/scheduler/tests/Makefile | 7 +
.../gpu/drm/scheduler/tests/mock_scheduler.c | 354 ++++++++++++++++++
drivers/gpu/drm/scheduler/tests/sched_tests.h | 224 +++++++++++
drivers/gpu/drm/scheduler/tests/tests_basic.c | 198 ++++++++++
7 files changed, 809 insertions(+)
create mode 100644 drivers/gpu/drm/scheduler/.kunitconfig
create mode 100644 drivers/gpu/drm/scheduler/tests/Makefile
create mode 100644 drivers/gpu/drm/scheduler/tests/mock_scheduler.c
create mode 100644 drivers/gpu/drm/scheduler/tests/sched_tests.h
create mode 100644 drivers/gpu/drm/scheduler/tests/tests_basic.c
diff --git a/drivers/gpu/drm/Kconfig.debug b/drivers/gpu/drm/Kconfig.debug
index 601d7e07d421..6fd4c5669400 100644
--- a/drivers/gpu/drm/Kconfig.debug
+++ b/drivers/gpu/drm/Kconfig.debug
@@ -99,5 +99,17 @@ config DRM_TTM_KUNIT_TEST
If in doubt, say "N".
+config DRM_SCHED_KUNIT_TEST
+ tristate "KUnit tests for the DRM scheduler" if !KUNIT_ALL_TESTS
+ select DRM_SCHED
+ depends on DRM && KUNIT
+ default KUNIT_ALL_TESTS
+ help
+ Choose this option to build unit tests for the DRM scheduler.
+
+ Recommended for driver developers only.
+
+ If in doubt, say "N".
+
config DRM_EXPORT_FOR_TESTS
bool
diff --git a/drivers/gpu/drm/scheduler/.kunitconfig b/drivers/gpu/drm/scheduler/.kunitconfig
new file mode 100644
index 000000000000..cece53609fcf
--- /dev/null
+++ b/drivers/gpu/drm/scheduler/.kunitconfig
@@ -0,0 +1,12 @@
+CONFIG_KUNIT=y
+CONFIG_DRM=y
+CONFIG_DRM_SCHED_KUNIT_TEST=y
+CONFIG_EXPERT=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_LOCK_DEBUGGING_SUPPORT=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_LOCKDEP=y
+CONFIG_DEBUG_LOCKDEP=y
+CONFIG_DEBUG_LIST=y
diff --git a/drivers/gpu/drm/scheduler/Makefile b/drivers/gpu/drm/scheduler/Makefile
index 53863621829f..6e13e4c63e9d 100644
--- a/drivers/gpu/drm/scheduler/Makefile
+++ b/drivers/gpu/drm/scheduler/Makefile
@@ -23,3 +23,5 @@
gpu-sched-y := sched_main.o sched_fence.o sched_entity.o
obj-$(CONFIG_DRM_SCHED) += gpu-sched.o
+
+obj-$(CONFIG_DRM_SCHED_KUNIT_TEST) += tests/
diff --git a/drivers/gpu/drm/scheduler/tests/Makefile b/drivers/gpu/drm/scheduler/tests/Makefile
new file mode 100644
index 000000000000..5bf707bad373
--- /dev/null
+++ b/drivers/gpu/drm/scheduler/tests/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+
+drm-sched-tests-y := \
+ mock_scheduler.o \
+ tests_basic.o
+
+obj-$(CONFIG_DRM_SCHED_KUNIT_TEST) += drm-sched-tests.o
diff --git a/drivers/gpu/drm/scheduler/tests/mock_scheduler.c b/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
new file mode 100644
index 000000000000..d039f873cc11
--- /dev/null
+++ b/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
@@ -0,0 +1,354 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2025 Valve Corporation */
+
+#include "sched_tests.h"
+
+/*
+ * Here we implement the mock "GPU" (or the scheduler backend) which is used by
+ * the DRM scheduler unit tests in order to exercise the core functionality.
+ *
+ * Test cases are implemented in a separate file.
+ */
+
+/**
+ * drm_mock_sched_entity_new - Create a new mock scheduler entity
+ *
+ * @test: KUnit test owning the entity
+ * @priority: Scheduling priority
+ * @sched: Mock scheduler on which the entity can be scheduled
+ *
+ * Returns: New mock scheduler entity with allocation managed by the test
+ */
+struct drm_mock_sched_entity *
+drm_mock_sched_entity_new(struct kunit *test,
+ enum drm_sched_priority priority,
+ struct drm_mock_scheduler *sched)
+{
+ struct drm_mock_sched_entity *entity;
+ struct drm_gpu_scheduler *drm_sched;
+ int ret;
+
+ entity = kunit_kzalloc(test, sizeof(*entity), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, entity);
+
+ drm_sched = &sched->base;
+ ret = drm_sched_entity_init(&entity->base,
+ priority,
+ &drm_sched, 1,
+ NULL);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ entity->test = test;
+
+ return entity;
+}
+
+/**
+ * drm_mock_sched_entity_free - Destroys a mock scheduler entity
+ *
+ * @entity: Entity to destroy
+ *
+ * To be used from the test cases once done with the entity.
+ */
+void drm_mock_sched_entity_free(struct drm_mock_sched_entity *entity)
+{
+ drm_sched_entity_destroy(&entity->base);
+}
+
+static void drm_mock_sched_job_complete(struct drm_mock_sched_job *job)
+{
+ struct drm_mock_scheduler *sched =
+ drm_sched_to_mock_sched(job->base.sched);
+
+ lockdep_assert_held(&sched->lock);
+
+ job->flags |= DRM_MOCK_SCHED_JOB_DONE;
+ list_move_tail(&job->link, &sched->done_list);
+ dma_fence_signal(&job->hw_fence);
+ complete(&job->done);
+}
+
+static enum hrtimer_restart
+drm_mock_sched_job_signal_timer(struct hrtimer *hrtimer)
+{
+ struct drm_mock_sched_job *job =
+ container_of(hrtimer, typeof(*job), timer);
+ struct drm_mock_scheduler *sched =
+ drm_sched_to_mock_sched(job->base.sched);
+ struct drm_mock_sched_job *next;
+ ktime_t now = ktime_get();
+ unsigned long flags;
+ LIST_HEAD(signal);
+
+ spin_lock_irqsave(&sched->lock, flags);
+ list_for_each_entry_safe(job, next, &sched->job_list, link) {
+ if (!job->duration_us)
+ break;
+
+ if (ktime_before(now, job->finish_at))
+ break;
+
+ sched->hw_timeline.cur_seqno = job->hw_fence.seqno;
+ drm_mock_sched_job_complete(job);
+ }
+ spin_unlock_irqrestore(&sched->lock, flags);
+
+ return HRTIMER_NORESTART;
+}
+
+/**
+ * drm_mock_sched_job_new - Create a new mock scheduler job
+ *
+ * @test: KUnit test owning the job
+ * @entity: Scheduler entity of the job
+ *
+ * Returns: New mock scheduler job with allocation managed by the test
+ */
+struct drm_mock_sched_job *
+drm_mock_sched_job_new(struct kunit *test,
+ struct drm_mock_sched_entity *entity)
+{
+ struct drm_mock_sched_job *job;
+ int ret;
+
+ job = kunit_kzalloc(test, sizeof(*job), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, job);
+
+ ret = drm_sched_job_init(&job->base,
+ &entity->base,
+ 1,
+ NULL);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ job->test = test;
+
+ init_completion(&job->done);
+ spin_lock_init(&job->lock);
+ INIT_LIST_HEAD(&job->link);
+ hrtimer_init(&job->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+ job->timer.function = drm_mock_sched_job_signal_timer;
+
+ return job;
+}
+
+static const char *drm_mock_sched_hw_fence_driver_name(struct dma_fence *fence)
+{
+ return "drm_mock_sched";
+}
+
+static const char *
+drm_mock_sched_hw_fence_timeline_name(struct dma_fence *fence)
+{
+ struct drm_mock_sched_job *job =
+ container_of(fence, typeof(*job), hw_fence);
+
+ return (const char *)job->base.sched->name;
+}
+
+static void drm_mock_sched_hw_fence_release(struct dma_fence *fence)
+{
+ struct drm_mock_sched_job *job =
+ container_of(fence, typeof(*job), hw_fence);
+
+ hrtimer_cancel(&job->timer);
+
+ /* Containing job is freed by the kunit framework */
+}
+
+static const struct dma_fence_ops drm_mock_sched_hw_fence_ops = {
+ .get_driver_name = drm_mock_sched_hw_fence_driver_name,
+ .get_timeline_name = drm_mock_sched_hw_fence_timeline_name,
+ .release = drm_mock_sched_hw_fence_release,
+};
+
+static struct dma_fence *mock_sched_run_job(struct drm_sched_job *sched_job)
+{
+ struct drm_mock_scheduler *sched =
+ drm_sched_to_mock_sched(sched_job->sched);
+ struct drm_mock_sched_job *job = drm_sched_job_to_mock_job(sched_job);
+
+ dma_fence_init(&job->hw_fence,
+ &drm_mock_sched_hw_fence_ops,
+ &job->lock,
+ sched->hw_timeline.context,
+ atomic_inc_return(&sched->hw_timeline.next_seqno));
+
+ dma_fence_get(&job->hw_fence); /* Reference for the job_list */
+
+ spin_lock_irq(&sched->lock);
+ if (job->duration_us) {
+ ktime_t prev_finish_at = 0;
+
+ if (!list_empty(&sched->job_list)) {
+ struct drm_mock_sched_job *prev =
+ list_last_entry(&sched->job_list, typeof(*prev),
+ link);
+
+ prev_finish_at = prev->finish_at;
+ }
+
+ if (!prev_finish_at)
+ prev_finish_at = ktime_get();
+
+ job->finish_at = ktime_add_us(prev_finish_at, job->duration_us);
+ }
+ list_add_tail(&job->link, &sched->job_list);
+ if (job->finish_at)
+ hrtimer_start(&job->timer, job->finish_at, HRTIMER_MODE_ABS);
+ spin_unlock_irq(&sched->lock);
+
+ return &job->hw_fence;
+}
+
+static enum drm_gpu_sched_stat
+mock_sched_timedout_job(struct drm_sched_job *sched_job)
+{
+ return DRM_GPU_SCHED_STAT_ENODEV;
+}
+
+static void mock_sched_free_job(struct drm_sched_job *sched_job)
+{
+ struct drm_mock_scheduler *sched =
+ drm_sched_to_mock_sched(sched_job->sched);
+ struct drm_mock_sched_job *job = drm_sched_job_to_mock_job(sched_job);
+ unsigned long flags;
+
+ /* Remove from the scheduler done list. */
+ spin_lock_irqsave(&sched->lock, flags);
+ list_del(&job->link);
+ spin_unlock_irqrestore(&sched->lock, flags);
+ dma_fence_put(&job->hw_fence);
+
+ drm_sched_job_cleanup(sched_job);
+
+ /* Mock job itself is freed by the kunit framework. */
+}
+
+static const struct drm_sched_backend_ops drm_mock_scheduler_ops = {
+ .run_job = mock_sched_run_job,
+ .timedout_job = mock_sched_timedout_job,
+ .free_job = mock_sched_free_job
+};
+
+/**
+ * drm_mock_sched_new - Create a new mock scheduler
+ *
+ * @test: KUnit test owning the job
+ *
+ * Returns: New mock scheduler with allocation managed by the test
+ */
+struct drm_mock_scheduler *drm_mock_sched_new(struct kunit *test)
+{
+ struct drm_sched_init_args args = {
+ .ops = &drm_mock_scheduler_ops,
+ .num_rqs = DRM_SCHED_PRIORITY_COUNT,
+ .credit_limit = U32_MAX,
+ .hang_limit = 1,
+ .timeout = MAX_SCHEDULE_TIMEOUT,
+ .name = "drm-mock-scheduler",
+ };
+ struct drm_mock_scheduler *sched;
+ int ret;
+
+ sched = kunit_kzalloc(test, sizeof(*sched), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, sched);
+
+ ret = drm_sched_init(&sched->base, &args);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ sched->test = test;
+ sched->hw_timeline.context = dma_fence_context_alloc(1);
+ atomic_set(&sched->hw_timeline.next_seqno, 0);
+ INIT_LIST_HEAD(&sched->job_list);
+ INIT_LIST_HEAD(&sched->done_list);
+ spin_lock_init(&sched->lock);
+
+ return sched;
+}
+
+/**
+ * drm_mock_sched_fini - Destroys a mock scheduler
+ *
+ * @sched: Scheduler to destroy
+ *
+ * To be used from the test cases once done with the scheduler.
+ */
+void drm_mock_sched_fini(struct drm_mock_scheduler *sched)
+{
+ struct drm_mock_sched_job *job, *next;
+ unsigned long flags;
+ LIST_HEAD(list);
+
+ drm_sched_wqueue_stop(&sched->base);
+
+ /* Force complete all unfinished jobs. */
+ spin_lock_irqsave(&sched->lock, flags);
+ list_for_each_entry_safe(job, next, &sched->job_list, link)
+ list_move_tail(&job->link, &list);
+ spin_unlock_irqrestore(&sched->lock, flags);
+
+ list_for_each_entry(job, &list, link)
+ hrtimer_cancel(&job->timer);
+
+ spin_lock_irqsave(&sched->lock, flags);
+ list_for_each_entry_safe(job, next, &list, link)
+ drm_mock_sched_job_complete(job);
+ spin_unlock_irqrestore(&sched->lock, flags);
+
+ /*
+ * Free completed jobs and jobs not yet processed by the DRM scheduler
+ * free worker.
+ */
+ spin_lock_irqsave(&sched->lock, flags);
+ list_for_each_entry_safe(job, next, &sched->done_list, link)
+ list_move_tail(&job->link, &list);
+ spin_unlock_irqrestore(&sched->lock, flags);
+
+ list_for_each_entry_safe(job, next, &list, link)
+ mock_sched_free_job(&job->base);
+
+ drm_sched_fini(&sched->base);
+}
+
+/**
+ * drm_mock_sched_advance - Advances the mock scheduler timeline
+ *
+ * @sched: Scheduler timeline to advance
+ * @num: By how many jobs to advance
+ *
+ * Advancing the scheduler timeline by a number of seqnos will trigger
+ * signalling of the hardware fences and unlinking the jobs from the internal
+ * scheduler tracking.
+ *
+ * This can be used from test cases which want complete control of the simulated
+ * job execution timing. For example submitting one job with no set duration
+ * would never complete it before test cases advances the timeline by one.
+ */
+unsigned int drm_mock_sched_advance(struct drm_mock_scheduler *sched,
+ unsigned int num)
+{
+ struct drm_mock_sched_job *job, *next;
+ unsigned int found = 0;
+ unsigned long flags;
+ LIST_HEAD(signal);
+
+ spin_lock_irqsave(&sched->lock, flags);
+ if (WARN_ON_ONCE(sched->hw_timeline.cur_seqno + num <
+ sched->hw_timeline.cur_seqno))
+ goto unlock;
+ sched->hw_timeline.cur_seqno += num;
+ list_for_each_entry_safe(job, next, &sched->job_list, link) {
+ if (sched->hw_timeline.cur_seqno < job->hw_fence.seqno)
+ break;
+
+ drm_mock_sched_job_complete(job);
+ found++;
+ }
+unlock:
+ spin_unlock_irqrestore(&sched->lock, flags);
+
+ return found;
+}
+
+MODULE_DESCRIPTION("DRM mock scheduler and tests");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/scheduler/tests/sched_tests.h b/drivers/gpu/drm/scheduler/tests/sched_tests.h
new file mode 100644
index 000000000000..31aaba3443fa
--- /dev/null
+++ b/drivers/gpu/drm/scheduler/tests/sched_tests.h
@@ -0,0 +1,224 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2025 Valve Corporation */
+
+#ifndef _SCHED_TESTS_H_
+#define _SCHED_TESTS_H_
+
+#include <kunit/test.h>
+#include <linux/atomic.h>
+#include <linux/completion.h>
+#include <linux/dma-fence.h>
+#include <linux/hrtimer.h>
+#include <linux/ktime.h>
+#include <linux/list.h>
+#include <linux/atomic.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+
+#include <drm/gpu_scheduler.h>
+
+/*
+ * DOC: Mock DRM scheduler data structures
+ *
+ * drm_mock_* data structures are used to implement a mock "GPU".
+ *
+ * They subclass the core DRM scheduler objects and add their data on top, which
+ * enables tracking the submitted jobs and simulating their execution with the
+ * attributes as specified by the test case.
+ */
+
+/**
+ * struct drm_mock_scheduler - implements a trivial mock GPU execution engine
+ *
+ * @base: DRM scheduler base class
+ * @test: Backpointer to owning the kunit test case
+ * @lock: Lock to protect the simulated @hw_timeline, @job_list and @done_list
+ * @job_list: List of jobs submitted to the mock GPU
+ * @done_list: List of jobs completed by the mock GPU
+ * @hw_timeline: Simulated hardware timeline has a @context, @next_seqno and
+ * @cur_seqno for implementing a struct dma_fence signaling the
+ * simulated job completion.
+ *
+ * Trivial mock GPU execution engine tracks submitted jobs and enables
+ * completing them strictly in submission order.
+ */
+struct drm_mock_scheduler {
+ struct drm_gpu_scheduler base;
+
+ struct kunit *test;
+
+ spinlock_t lock;
+ struct list_head job_list;
+ struct list_head done_list;
+
+ struct {
+ u64 context;
+ atomic_t next_seqno;
+ unsigned int cur_seqno;
+ } hw_timeline;
+};
+
+/**
+ * struct drm_mock_sched_entity - implements a mock GPU sched entity
+ *
+ * @base: DRM scheduler entity base class
+ * @test: Backpointer to owning the kunit test case
+ *
+ * Mock GPU sched entity is used by the test cases to submit jobs to the mock
+ * scheduler.
+ */
+struct drm_mock_sched_entity {
+ struct drm_sched_entity base;
+
+ struct kunit *test;
+};
+
+/**
+ * struct drm_mock_sched_job - implements a mock GPU job
+ *
+ * @base: DRM sched job base class
+ * @done: Completion signaling job completion.
+ * @flags: Flags designating job state.
+ * @link: List head element used by job tracking by the drm_mock_scheduler
+ * @timer: Timer used for simulating job execution duration
+ * @duration_us: Simulated job duration in micro seconds, or zero if in manual
+ * timeline advance mode
+ * @finish_at: Absolute time when the jobs with set duration will complete
+ * @lock: Lock used for @hw_fence
+ * @hw_fence: Fence returned to DRM scheduler as the hardware fence
+ * @test: Backpointer to owning the kunit test case
+ *
+ * Mock GPU sched job is used by the test cases to submit jobs to the mock
+ * scheduler.
+ */
+struct drm_mock_sched_job {
+ struct drm_sched_job base;
+
+ struct completion done;
+
+#define DRM_MOCK_SCHED_JOB_DONE 0x1
+ unsigned long flags;
+
+ struct list_head link;
+ struct hrtimer timer;
+
+ unsigned int duration_us;
+ ktime_t finish_at;
+
+ spinlock_t lock;
+ struct dma_fence hw_fence;
+
+ struct kunit *test;
+};
+
+static inline struct drm_mock_scheduler *
+drm_sched_to_mock_sched(struct drm_gpu_scheduler *sched)
+{
+ return container_of(sched, struct drm_mock_scheduler, base);
+};
+
+static inline struct drm_mock_sched_entity *
+drm_sched_entity_to_mock_entity(struct drm_sched_entity *sched_entity)
+{
+ return container_of(sched_entity, struct drm_mock_sched_entity, base);
+};
+
+static inline struct drm_mock_sched_job *
+drm_sched_job_to_mock_job(struct drm_sched_job *sched_job)
+{
+ return container_of(sched_job, struct drm_mock_sched_job, base);
+};
+
+struct drm_mock_scheduler *drm_mock_sched_new(struct kunit *test);
+void drm_mock_sched_fini(struct drm_mock_scheduler *sched);
+unsigned int drm_mock_sched_advance(struct drm_mock_scheduler *sched,
+ unsigned int num);
+
+struct drm_mock_sched_entity *
+drm_mock_sched_entity_new(struct kunit *test,
+ enum drm_sched_priority priority,
+ struct drm_mock_scheduler *sched);
+void drm_mock_sched_entity_free(struct drm_mock_sched_entity *entity);
+
+struct drm_mock_sched_job *
+drm_mock_sched_job_new(struct kunit *test,
+ struct drm_mock_sched_entity *entity);
+
+/**
+ * drm_mock_sched_job_submit - Arm and submit a job in one go
+ *
+ * @job: Job to arm and submit
+ */
+static inline void drm_mock_sched_job_submit(struct drm_mock_sched_job *job)
+{
+ drm_sched_job_arm(&job->base);
+ drm_sched_entity_push_job(&job->base);
+}
+
+/**
+ * drm_mock_sched_job_set_duration_us - Set a job duration
+ *
+ * @job: Job to set the duration for
+ * @duration_us: Duration in micro seconds
+ *
+ * Jobs with duration set will be automatically completed by the mock scheduler
+ * as the timeline progresses, unless a job without a set duration is
+ * encountered in the timelime in which case calling drm_mock_sched_advance()
+ * will be required to bump the timeline.
+ */
+static inline void
+drm_mock_sched_job_set_duration_us(struct drm_mock_sched_job *job,
+ unsigned int duration_us)
+{
+ job->duration_us = duration_us;
+}
+
+/**
+ * drm_mock_sched_job_is_finished - Check if a job is finished
+ *
+ * @job: Job to check
+ *
+ * Returns: true if finished
+ */
+static inline bool
+drm_mock_sched_job_is_finished(struct drm_mock_sched_job *job)
+{
+ return job->flags & DRM_MOCK_SCHED_JOB_DONE;
+}
+
+/**
+ * drm_mock_sched_job_wait_finished - Wait until a job is finished
+ *
+ * @job: Job to wait for
+ * @timeout: Wait time in jiffies
+ *
+ * Returns: true if finished within the timeout provided, otherwise false
+ */
+static inline bool
+drm_mock_sched_job_wait_finished(struct drm_mock_sched_job *job, long timeout)
+{
+ if (job->flags & DRM_MOCK_SCHED_JOB_DONE)
+ return true;
+
+ return wait_for_completion_timeout(&job->done, timeout) != 0;
+}
+
+/**
+ * drm_mock_sched_job_wait_scheduled - Wait until a job is scheduled
+ *
+ * @job: Job to wait for
+ * @timeout: Wait time in jiffies
+ *
+ * Returns: true if scheduled within the timeout provided, otherwise false
+ */
+static inline bool
+drm_mock_sched_job_wait_scheduled(struct drm_mock_sched_job *job, long timeout)
+{
+ KUNIT_ASSERT_EQ(job->test, job->flags & DRM_MOCK_SCHED_JOB_DONE, 0);
+
+ return dma_fence_wait_timeout(&job->base.s_fence->scheduled,
+ false,
+ timeout) != 0;
+}
+
+#endif
diff --git a/drivers/gpu/drm/scheduler/tests/tests_basic.c b/drivers/gpu/drm/scheduler/tests/tests_basic.c
new file mode 100644
index 000000000000..c06672e13cf6
--- /dev/null
+++ b/drivers/gpu/drm/scheduler/tests/tests_basic.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2025 Valve Corporation */
+
+#include "sched_tests.h"
+
+/*
+ * DRM scheduler basic tests should check the basic functional correctness of
+ * the scheduler, including some very light smoke testing. More targeted tests,
+ * for example focusing on testing specific bugs and other more complicated test
+ * scenarios, should be implemented in separate source units.
+ */
+
+static int drm_sched_basic_init(struct kunit *test)
+{
+ test->priv = drm_mock_sched_new(test);
+
+ return 0;
+}
+
+static void drm_sched_basic_exit(struct kunit *test)
+{
+ struct drm_mock_scheduler *sched = test->priv;
+
+ drm_mock_sched_fini(sched);
+}
+
+static void drm_sched_basic_submit(struct kunit *test)
+{
+ struct drm_mock_scheduler *sched = test->priv;
+ struct drm_mock_sched_entity *entity;
+ struct drm_mock_sched_job *job;
+ unsigned int i;
+ bool done;
+
+ /*
+ * Submit one job to the scheduler and verify that it gets scheduled
+ * and completed only when the mock hw backend processes it.
+ */
+
+ entity = drm_mock_sched_entity_new(test,
+ DRM_SCHED_PRIORITY_NORMAL,
+ sched);
+ job = drm_mock_sched_job_new(test, entity);
+
+ drm_mock_sched_job_submit(job);
+
+ done = drm_mock_sched_job_wait_scheduled(job, HZ);
+ KUNIT_ASSERT_TRUE(test, done);
+
+ done = drm_mock_sched_job_wait_finished(job, HZ / 2);
+ KUNIT_ASSERT_FALSE(test, done);
+
+ i = drm_mock_sched_advance(sched, 1);
+ KUNIT_ASSERT_EQ(test, i, 1);
+
+ done = drm_mock_sched_job_wait_finished(job, HZ);
+ KUNIT_ASSERT_TRUE(test, done);
+
+ drm_mock_sched_entity_free(entity);
+}
+
+struct drm_sched_basic_params {
+ const char *description;
+ unsigned int queue_depth;
+ unsigned int num_entities;
+ unsigned int job_us;
+ bool dep_chain;
+};
+
+static const struct drm_sched_basic_params drm_sched_basic_cases[] = {
+ {
+ .description = "A queue of jobs in a single entity",
+ .queue_depth = 100,
+ .job_us = 1000,
+ .num_entities = 1,
+ },
+ {
+ .description = "A chain of dependent jobs across multiple entities",
+ .queue_depth = 100,
+ .job_us = 1000,
+ .num_entities = 1,
+ .dep_chain = true,
+ },
+ {
+ .description = "Multiple independent job queues",
+ .queue_depth = 100,
+ .job_us = 1000,
+ .num_entities = 4,
+ },
+ {
+ .description = "Multiple inter-dependent job queues",
+ .queue_depth = 100,
+ .job_us = 1000,
+ .num_entities = 4,
+ .dep_chain = true,
+ },
+};
+
+static void
+drm_sched_basic_desc(const struct drm_sched_basic_params *params, char *desc)
+{
+ strscpy(desc, params->description, KUNIT_PARAM_DESC_SIZE);
+}
+
+KUNIT_ARRAY_PARAM(drm_sched_basic, drm_sched_basic_cases, drm_sched_basic_desc);
+
+static void drm_sched_basic_test(struct kunit *test)
+{
+ const struct drm_sched_basic_params *params = test->param_value;
+ struct drm_mock_scheduler *sched = test->priv;
+ struct drm_mock_sched_job *job, *prev = NULL;
+ struct drm_mock_sched_entity **entity;
+ unsigned int i, cur_ent = 0;
+ bool done;
+
+ entity = kunit_kcalloc(test, params->num_entities, sizeof(*entity),
+ GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, entity);
+
+ for (i = 0; i < params->num_entities; i++)
+ entity[i] = drm_mock_sched_entity_new(test,
+ DRM_SCHED_PRIORITY_NORMAL,
+ sched);
+
+ for (i = 0; i < params->queue_depth; i++) {
+ job = drm_mock_sched_job_new(test, entity[cur_ent++]);
+ cur_ent %= params->num_entities;
+ drm_mock_sched_job_set_duration_us(job, params->job_us);
+ if (params->dep_chain && prev)
+ drm_sched_job_add_dependency(&job->base,
+ dma_fence_get(&prev->base.s_fence->finished));
+ drm_mock_sched_job_submit(job);
+ prev = job;
+ }
+
+ done = drm_mock_sched_job_wait_finished(job, HZ);
+ KUNIT_ASSERT_TRUE(test, done);
+
+ for (i = 0; i < params->num_entities; i++)
+ drm_mock_sched_entity_free(entity[i]);
+}
+
+static void drm_sched_basic_entity_cleanup(struct kunit *test)
+{
+ struct drm_mock_sched_job *job, *mid, *prev = NULL;
+ struct drm_mock_scheduler *sched = test->priv;
+ struct drm_mock_sched_entity *entity[4];
+ const unsigned int qd = 100;
+ unsigned int i, cur_ent = 0;
+ bool done;
+
+ /*
+ * Submit a queue of jobs across different entities with an explicit
+ * chain of dependencies between them and trigger entity cleanup while
+ * the queue is still being processed.
+ */
+
+ for (i = 0; i < ARRAY_SIZE(entity); i++)
+ entity[i] = drm_mock_sched_entity_new(test,
+ DRM_SCHED_PRIORITY_NORMAL,
+ sched);
+
+ for (i = 0; i < qd; i++) {
+ job = drm_mock_sched_job_new(test, entity[cur_ent++]);
+ cur_ent %= ARRAY_SIZE(entity);
+ drm_mock_sched_job_set_duration_us(job, 1000);
+ if (prev)
+ drm_sched_job_add_dependency(&job->base,
+ dma_fence_get(&prev->base.s_fence->finished));
+ drm_mock_sched_job_submit(job);
+ if (i == qd / 2)
+ mid = job;
+ prev = job;
+ }
+
+ done = drm_mock_sched_job_wait_finished(mid, HZ);
+ KUNIT_ASSERT_TRUE(test, done);
+
+ /* Exit with half of the queue still pending to be executed. */
+ for (i = 0; i < ARRAY_SIZE(entity); i++)
+ drm_mock_sched_entity_free(entity[i]);
+}
+
+static struct kunit_case drm_sched_basic_tests[] = {
+ KUNIT_CASE(drm_sched_basic_submit),
+ KUNIT_CASE_PARAM(drm_sched_basic_test, drm_sched_basic_gen_params),
+ KUNIT_CASE(drm_sched_basic_entity_cleanup),
+ {}
+};
+
+static struct kunit_suite drm_sched_basic = {
+ .name = "drm_sched_basic_tests",
+ .init = drm_sched_basic_init,
+ .exit = drm_sched_basic_exit,
+ .test_cases = drm_sched_basic_tests,
+};
+
+kunit_test_suite(drm_sched_basic);
--
2.48.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v9 3/6] drm/sched: Add a simple timeout test
2025-03-18 13:37 [PATCH v9 0/6] DRM scheduler kunit tests Tvrtko Ursulin
2025-03-18 13:37 ` [PATCH v9 1/6] drm: Move some options to separate new Kconfig Tvrtko Ursulin
2025-03-18 13:37 ` [PATCH v9 2/6] drm/sched: Add scheduler unit testing infrastructure and some basic tests Tvrtko Ursulin
@ 2025-03-18 13:37 ` Tvrtko Ursulin
2025-03-18 13:38 ` [PATCH v9 4/6] drm/sched: Add basic priority tests Tvrtko Ursulin
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Tvrtko Ursulin @ 2025-03-18 13:37 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
Add a very simple timeout test which submits a single job and verifies
that the timeout handling will run if the backend failed to complete the
job in time.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@kernel.org>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <phasta@kernel.org>
Acked-by: Christian König <christian.koenig@amd.com>
---
.../gpu/drm/scheduler/tests/mock_scheduler.c | 11 +++-
drivers/gpu/drm/scheduler/tests/sched_tests.h | 4 +-
drivers/gpu/drm/scheduler/tests/tests_basic.c | 64 ++++++++++++++++++-
3 files changed, 73 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/scheduler/tests/mock_scheduler.c b/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
index d039f873cc11..61efc96e6e41 100644
--- a/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
+++ b/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
@@ -203,7 +203,11 @@ static struct dma_fence *mock_sched_run_job(struct drm_sched_job *sched_job)
static enum drm_gpu_sched_stat
mock_sched_timedout_job(struct drm_sched_job *sched_job)
{
- return DRM_GPU_SCHED_STAT_ENODEV;
+ struct drm_mock_sched_job *job = drm_sched_job_to_mock_job(sched_job);
+
+ job->flags |= DRM_MOCK_SCHED_JOB_TIMEDOUT;
+
+ return DRM_GPU_SCHED_STAT_NOMINAL;
}
static void mock_sched_free_job(struct drm_sched_job *sched_job)
@@ -234,17 +238,18 @@ static const struct drm_sched_backend_ops drm_mock_scheduler_ops = {
* drm_mock_sched_new - Create a new mock scheduler
*
* @test: KUnit test owning the job
+ * @timeout: Job timeout to set
*
* Returns: New mock scheduler with allocation managed by the test
*/
-struct drm_mock_scheduler *drm_mock_sched_new(struct kunit *test)
+struct drm_mock_scheduler *drm_mock_sched_new(struct kunit *test, long timeout)
{
struct drm_sched_init_args args = {
.ops = &drm_mock_scheduler_ops,
.num_rqs = DRM_SCHED_PRIORITY_COUNT,
.credit_limit = U32_MAX,
.hang_limit = 1,
- .timeout = MAX_SCHEDULE_TIMEOUT,
+ .timeout = timeout,
.name = "drm-mock-scheduler",
};
struct drm_mock_scheduler *sched;
diff --git a/drivers/gpu/drm/scheduler/tests/sched_tests.h b/drivers/gpu/drm/scheduler/tests/sched_tests.h
index 31aaba3443fa..27caf8285fb7 100644
--- a/drivers/gpu/drm/scheduler/tests/sched_tests.h
+++ b/drivers/gpu/drm/scheduler/tests/sched_tests.h
@@ -97,6 +97,7 @@ struct drm_mock_sched_job {
struct completion done;
#define DRM_MOCK_SCHED_JOB_DONE 0x1
+#define DRM_MOCK_SCHED_JOB_TIMEDOUT 0x2
unsigned long flags;
struct list_head link;
@@ -129,7 +130,8 @@ drm_sched_job_to_mock_job(struct drm_sched_job *sched_job)
return container_of(sched_job, struct drm_mock_sched_job, base);
};
-struct drm_mock_scheduler *drm_mock_sched_new(struct kunit *test);
+struct drm_mock_scheduler *drm_mock_sched_new(struct kunit *test,
+ long timeout);
void drm_mock_sched_fini(struct drm_mock_scheduler *sched);
unsigned int drm_mock_sched_advance(struct drm_mock_scheduler *sched,
unsigned int num);
diff --git a/drivers/gpu/drm/scheduler/tests/tests_basic.c b/drivers/gpu/drm/scheduler/tests/tests_basic.c
index c06672e13cf6..0e1fa4767b0d 100644
--- a/drivers/gpu/drm/scheduler/tests/tests_basic.c
+++ b/drivers/gpu/drm/scheduler/tests/tests_basic.c
@@ -12,7 +12,7 @@
static int drm_sched_basic_init(struct kunit *test)
{
- test->priv = drm_mock_sched_new(test);
+ test->priv = drm_mock_sched_new(test, MAX_SCHEDULE_TIMEOUT);
return 0;
}
@@ -24,6 +24,13 @@ static void drm_sched_basic_exit(struct kunit *test)
drm_mock_sched_fini(sched);
}
+static int drm_sched_timeout_init(struct kunit *test)
+{
+ test->priv = drm_mock_sched_new(test, HZ);
+
+ return 0;
+}
+
static void drm_sched_basic_submit(struct kunit *test)
{
struct drm_mock_scheduler *sched = test->priv;
@@ -195,4 +202,57 @@ static struct kunit_suite drm_sched_basic = {
.test_cases = drm_sched_basic_tests,
};
-kunit_test_suite(drm_sched_basic);
+static void drm_sched_basic_timeout(struct kunit *test)
+{
+ struct drm_mock_scheduler *sched = test->priv;
+ struct drm_mock_sched_entity *entity;
+ struct drm_mock_sched_job *job;
+ bool done;
+
+ /*
+ * Submit a single job against a scheduler with the timeout configured
+ * and verify that the timeout handling will run if the backend fails
+ * to complete it in time.
+ */
+
+ entity = drm_mock_sched_entity_new(test,
+ DRM_SCHED_PRIORITY_NORMAL,
+ sched);
+ job = drm_mock_sched_job_new(test, entity);
+
+ drm_mock_sched_job_submit(job);
+
+ done = drm_mock_sched_job_wait_scheduled(job, HZ);
+ KUNIT_ASSERT_TRUE(test, done);
+
+ done = drm_mock_sched_job_wait_finished(job, HZ / 2);
+ KUNIT_ASSERT_FALSE(test, done);
+
+ KUNIT_ASSERT_EQ(test,
+ job->flags & DRM_MOCK_SCHED_JOB_TIMEDOUT,
+ 0);
+
+ done = drm_mock_sched_job_wait_finished(job, HZ);
+ KUNIT_ASSERT_FALSE(test, done);
+
+ KUNIT_ASSERT_EQ(test,
+ job->flags & DRM_MOCK_SCHED_JOB_TIMEDOUT,
+ DRM_MOCK_SCHED_JOB_TIMEDOUT);
+
+ drm_mock_sched_entity_free(entity);
+}
+
+static struct kunit_case drm_sched_timeout_tests[] = {
+ KUNIT_CASE(drm_sched_basic_timeout),
+ {}
+};
+
+static struct kunit_suite drm_sched_timeout = {
+ .name = "drm_sched_basic_timeout_tests",
+ .init = drm_sched_timeout_init,
+ .exit = drm_sched_basic_exit,
+ .test_cases = drm_sched_timeout_tests,
+};
+
+kunit_test_suites(&drm_sched_basic,
+ &drm_sched_timeout);
--
2.48.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v9 4/6] drm/sched: Add basic priority tests
2025-03-18 13:37 [PATCH v9 0/6] DRM scheduler kunit tests Tvrtko Ursulin
` (2 preceding siblings ...)
2025-03-18 13:37 ` [PATCH v9 3/6] drm/sched: Add a simple timeout test Tvrtko Ursulin
@ 2025-03-18 13:38 ` Tvrtko Ursulin
2025-03-18 13:38 ` [PATCH v9 5/6] drm/sched: Add a basic test for modifying entities scheduler list Tvrtko Ursulin
2025-03-18 13:38 ` [PATCH v9 6/6] drm/sched: Add a basic test for checking credit limit Tvrtko Ursulin
5 siblings, 0 replies; 8+ messages in thread
From: Tvrtko Ursulin @ 2025-03-18 13:38 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
Add some basic tests for exercising entity priority handling.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@kernel.org>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <phasta@kernel.org>
Acked-by: Christian König <christian.koenig@amd.com>
---
drivers/gpu/drm/scheduler/tests/tests_basic.c | 95 ++++++++++++++++++-
1 file changed, 94 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/scheduler/tests/tests_basic.c b/drivers/gpu/drm/scheduler/tests/tests_basic.c
index 0e1fa4767b0d..10378b7ca457 100644
--- a/drivers/gpu/drm/scheduler/tests/tests_basic.c
+++ b/drivers/gpu/drm/scheduler/tests/tests_basic.c
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2025 Valve Corporation */
+#include <linux/delay.h>
+
#include "sched_tests.h"
/*
@@ -254,5 +256,96 @@ static struct kunit_suite drm_sched_timeout = {
.test_cases = drm_sched_timeout_tests,
};
+static void drm_sched_priorities(struct kunit *test)
+{
+ struct drm_mock_sched_entity *entity[DRM_SCHED_PRIORITY_COUNT];
+ struct drm_mock_scheduler *sched = test->priv;
+ struct drm_mock_sched_job *job;
+ const unsigned int qd = 100;
+ unsigned int i, cur_ent = 0;
+ enum drm_sched_priority p;
+ bool done;
+
+ /*
+ * Submit a bunch of jobs against entities configured with different
+ * priorities.
+ */
+
+ BUILD_BUG_ON(DRM_SCHED_PRIORITY_KERNEL > DRM_SCHED_PRIORITY_LOW);
+ BUILD_BUG_ON(ARRAY_SIZE(entity) != DRM_SCHED_PRIORITY_COUNT);
+
+ for (p = DRM_SCHED_PRIORITY_KERNEL; p <= DRM_SCHED_PRIORITY_LOW; p++)
+ entity[p] = drm_mock_sched_entity_new(test, p, sched);
+
+ for (i = 0; i < qd; i++) {
+ job = drm_mock_sched_job_new(test, entity[cur_ent++]);
+ cur_ent %= ARRAY_SIZE(entity);
+ drm_mock_sched_job_set_duration_us(job, 1000);
+ drm_mock_sched_job_submit(job);
+ }
+
+ done = drm_mock_sched_job_wait_finished(job, HZ);
+ KUNIT_ASSERT_TRUE(test, done);
+
+ for (i = 0; i < ARRAY_SIZE(entity); i++)
+ drm_mock_sched_entity_free(entity[i]);
+}
+
+static void drm_sched_change_priority(struct kunit *test)
+{
+ struct drm_mock_sched_entity *entity[DRM_SCHED_PRIORITY_COUNT];
+ struct drm_mock_scheduler *sched = test->priv;
+ struct drm_mock_sched_job *job;
+ const unsigned int qd = 1000;
+ unsigned int i, cur_ent = 0;
+ enum drm_sched_priority p;
+
+ /*
+ * Submit a bunch of jobs against entities configured with different
+ * priorities and while waiting for them to complete, periodically keep
+ * changing their priorities.
+ *
+ * We set up the queue-depth (qd) and job duration so the priority
+ * changing loop has some time to interact with submissions to the
+ * backend and job completions as they progress.
+ */
+
+ for (p = DRM_SCHED_PRIORITY_KERNEL; p <= DRM_SCHED_PRIORITY_LOW; p++)
+ entity[p] = drm_mock_sched_entity_new(test, p, sched);
+
+ for (i = 0; i < qd; i++) {
+ job = drm_mock_sched_job_new(test, entity[cur_ent++]);
+ cur_ent %= ARRAY_SIZE(entity);
+ drm_mock_sched_job_set_duration_us(job, 1000);
+ drm_mock_sched_job_submit(job);
+ }
+
+ do {
+ drm_sched_entity_set_priority(&entity[cur_ent]->base,
+ (entity[cur_ent]->base.priority + 1) %
+ DRM_SCHED_PRIORITY_COUNT);
+ cur_ent++;
+ cur_ent %= ARRAY_SIZE(entity);
+ usleep_range(200, 500);
+ } while (!drm_mock_sched_job_is_finished(job));
+
+ for (i = 0; i < ARRAY_SIZE(entity); i++)
+ drm_mock_sched_entity_free(entity[i]);
+}
+
+static struct kunit_case drm_sched_priority_tests[] = {
+ KUNIT_CASE(drm_sched_priorities),
+ KUNIT_CASE(drm_sched_change_priority),
+ {}
+};
+
+static struct kunit_suite drm_sched_priority = {
+ .name = "drm_sched_basic_priority_tests",
+ .init = drm_sched_basic_init,
+ .exit = drm_sched_basic_exit,
+ .test_cases = drm_sched_priority_tests,
+};
+
kunit_test_suites(&drm_sched_basic,
- &drm_sched_timeout);
+ &drm_sched_timeout,
+ &drm_sched_priority);
--
2.48.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v9 5/6] drm/sched: Add a basic test for modifying entities scheduler list
2025-03-18 13:37 [PATCH v9 0/6] DRM scheduler kunit tests Tvrtko Ursulin
` (3 preceding siblings ...)
2025-03-18 13:38 ` [PATCH v9 4/6] drm/sched: Add basic priority tests Tvrtko Ursulin
@ 2025-03-18 13:38 ` Tvrtko Ursulin
2025-03-18 13:38 ` [PATCH v9 6/6] drm/sched: Add a basic test for checking credit limit Tvrtko Ursulin
5 siblings, 0 replies; 8+ messages in thread
From: Tvrtko Ursulin @ 2025-03-18 13:38 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
Add a basic test for exercising modifying the entities scheduler list at
runtime.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@kernel.org>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <phasta@kernel.org>
Acked-by: Christian König <christian.koenig@amd.com>
---
drivers/gpu/drm/scheduler/tests/tests_basic.c | 69 ++++++++++++++++++-
1 file changed, 68 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/scheduler/tests/tests_basic.c b/drivers/gpu/drm/scheduler/tests/tests_basic.c
index 10378b7ca457..996cac00bb52 100644
--- a/drivers/gpu/drm/scheduler/tests/tests_basic.c
+++ b/drivers/gpu/drm/scheduler/tests/tests_basic.c
@@ -346,6 +346,73 @@ static struct kunit_suite drm_sched_priority = {
.test_cases = drm_sched_priority_tests,
};
+static void drm_sched_test_modify_sched(struct kunit *test)
+{
+ unsigned int i, cur_ent = 0, cur_sched = 0;
+ struct drm_mock_sched_entity *entity[13];
+ struct drm_mock_scheduler *sched[3];
+ struct drm_mock_sched_job *job;
+ const unsigned int qd = 1000;
+
+ /*
+ * Submit a bunch of jobs against entities configured with different
+ * schedulers and while waiting for them to complete, periodically keep
+ * changing schedulers associated with each entity.
+ *
+ * We set up the queue-depth (qd) and job duration so the sched modify
+ * loop has some time to interact with submissions to the backend and
+ * job completions as they progress.
+ *
+ * For the number of schedulers and entities we use primes in order to
+ * perturb the entity->sched assignments with less of a regular pattern.
+ */
+
+ for (i = 0; i < ARRAY_SIZE(sched); i++)
+ sched[i] = drm_mock_sched_new(test, MAX_SCHEDULE_TIMEOUT);
+
+ for (i = 0; i < ARRAY_SIZE(entity); i++)
+ entity[i] = drm_mock_sched_entity_new(test,
+ DRM_SCHED_PRIORITY_NORMAL,
+ sched[i % ARRAY_SIZE(sched)]);
+
+ for (i = 0; i < qd; i++) {
+ job = drm_mock_sched_job_new(test, entity[cur_ent++]);
+ cur_ent %= ARRAY_SIZE(entity);
+ drm_mock_sched_job_set_duration_us(job, 1000);
+ drm_mock_sched_job_submit(job);
+ }
+
+ do {
+ struct drm_gpu_scheduler *modify;
+
+ usleep_range(200, 500);
+ cur_ent++;
+ cur_ent %= ARRAY_SIZE(entity);
+ cur_sched++;
+ cur_sched %= ARRAY_SIZE(sched);
+ modify = &sched[cur_sched]->base;
+ drm_sched_entity_modify_sched(&entity[cur_ent]->base, &modify,
+ 1);
+ } while (!drm_mock_sched_job_is_finished(job));
+
+ for (i = 0; i < ARRAY_SIZE(entity); i++)
+ drm_mock_sched_entity_free(entity[i]);
+
+ for (i = 0; i < ARRAY_SIZE(sched); i++)
+ drm_mock_sched_fini(sched[i]);
+}
+
+static struct kunit_case drm_sched_modify_sched_tests[] = {
+ KUNIT_CASE(drm_sched_test_modify_sched),
+ {}
+};
+
+static struct kunit_suite drm_sched_modify_sched = {
+ .name = "drm_sched_basic_modify_sched_tests",
+ .test_cases = drm_sched_modify_sched_tests,
+};
+
kunit_test_suites(&drm_sched_basic,
&drm_sched_timeout,
- &drm_sched_priority);
+ &drm_sched_priority,
+ &drm_sched_modify_sched);
--
2.48.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v9 6/6] drm/sched: Add a basic test for checking credit limit
2025-03-18 13:37 [PATCH v9 0/6] DRM scheduler kunit tests Tvrtko Ursulin
` (4 preceding siblings ...)
2025-03-18 13:38 ` [PATCH v9 5/6] drm/sched: Add a basic test for modifying entities scheduler list Tvrtko Ursulin
@ 2025-03-18 13:38 ` Tvrtko Ursulin
5 siblings, 0 replies; 8+ messages in thread
From: Tvrtko Ursulin @ 2025-03-18 13:38 UTC (permalink / raw)
To: dri-devel
Cc: kernel-dev, Tvrtko Ursulin, Christian König,
Danilo Krummrich, Matthew Brost, Philipp Stanner
Add a basic test for checking whether scheduler respects the configured
credit limit.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@kernel.org>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <phasta@kernel.org>
Acked-by: Christian König <christian.koenig@amd.com>
---
drivers/gpu/drm/scheduler/tests/tests_basic.c | 60 ++++++++++++++++++-
1 file changed, 59 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/scheduler/tests/tests_basic.c b/drivers/gpu/drm/scheduler/tests/tests_basic.c
index 996cac00bb52..7230057e0594 100644
--- a/drivers/gpu/drm/scheduler/tests/tests_basic.c
+++ b/drivers/gpu/drm/scheduler/tests/tests_basic.c
@@ -412,7 +412,65 @@ static struct kunit_suite drm_sched_modify_sched = {
.test_cases = drm_sched_modify_sched_tests,
};
+static void drm_sched_test_credits(struct kunit *test)
+{
+ struct drm_mock_sched_entity *entity;
+ struct drm_mock_scheduler *sched;
+ struct drm_mock_sched_job *job[2];
+ bool done;
+ int i;
+
+ /*
+ * Check that the configured credit limit is respected.
+ */
+
+ sched = drm_mock_sched_new(test, MAX_SCHEDULE_TIMEOUT);
+ sched->base.credit_limit = 1;
+
+ entity = drm_mock_sched_entity_new(test,
+ DRM_SCHED_PRIORITY_NORMAL,
+ sched);
+
+ job[0] = drm_mock_sched_job_new(test, entity);
+ job[1] = drm_mock_sched_job_new(test, entity);
+
+ drm_mock_sched_job_submit(job[0]);
+ drm_mock_sched_job_submit(job[1]);
+
+ done = drm_mock_sched_job_wait_scheduled(job[0], HZ);
+ KUNIT_ASSERT_TRUE(test, done);
+
+ done = drm_mock_sched_job_wait_scheduled(job[1], HZ);
+ KUNIT_ASSERT_FALSE(test, done);
+
+ i = drm_mock_sched_advance(sched, 1);
+ KUNIT_ASSERT_EQ(test, i, 1);
+
+ done = drm_mock_sched_job_wait_scheduled(job[1], HZ);
+ KUNIT_ASSERT_TRUE(test, done);
+
+ i = drm_mock_sched_advance(sched, 1);
+ KUNIT_ASSERT_EQ(test, i, 1);
+
+ done = drm_mock_sched_job_wait_finished(job[1], HZ);
+ KUNIT_ASSERT_TRUE(test, done);
+
+ drm_mock_sched_entity_free(entity);
+ drm_mock_sched_fini(sched);
+}
+
+static struct kunit_case drm_sched_credits_tests[] = {
+ KUNIT_CASE(drm_sched_test_credits),
+ {}
+};
+
+static struct kunit_suite drm_sched_credits = {
+ .name = "drm_sched_basic_credits_tests",
+ .test_cases = drm_sched_credits_tests,
+};
+
kunit_test_suites(&drm_sched_basic,
&drm_sched_timeout,
&drm_sched_priority,
- &drm_sched_modify_sched);
+ &drm_sched_modify_sched,
+ &drm_sched_credits);
--
2.48.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v9 1/6] drm: Move some options to separate new Kconfig
2025-03-18 13:37 ` [PATCH v9 1/6] drm: Move some options to separate new Kconfig Tvrtko Ursulin
@ 2025-03-24 9:03 ` Philipp Stanner
0 siblings, 0 replies; 8+ messages in thread
From: Philipp Stanner @ 2025-03-24 9:03 UTC (permalink / raw)
To: Tvrtko Ursulin, dri-devel
Cc: kernel-dev, Christian König, Danilo Krummrich, Matthew Brost,
Philipp Stanner
On Tue, 2025-03-18 at 13:37 +0000, Tvrtko Ursulin wrote:
> Move some options out into a new debug specific kconfig file in order
> to
> make things a bit cleaner.
>
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: Danilo Krummrich <dakr@kernel.org>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: Philipp Stanner <phasta@kernel.org>
> Acked-by: Christian König <christian.koenig@amd.com>
> ---
> drivers/gpu/drm/Kconfig | 109 ++------------------------------
> --
> drivers/gpu/drm/Kconfig.debug | 103 ++++++++++++++++++++++++++++++++
> 2 files changed, 108 insertions(+), 104 deletions(-)
> create mode 100644 drivers/gpu/drm/Kconfig.debug
>
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index 1be14d8634f4..d32d70c3ddf1 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
I've tested the series on Friday. Looks good. Can go into drm-misc-next
from my POV.
Unfortunately doesn't apply yet due to a merge conflict in Kconfig. If
you could be so kind and rebase to drm-misc-next we could then quickly
pull the series in, avoiding further collisions
Thx
P.
> @@ -26,6 +26,11 @@ menuconfig DRM
> details. You should also select and configure AGP
> (/dev/agpgart) support if it is available for your
> platform.
>
> +menu "DRM debugging options"
> +depends on DRM
> +source "drivers/gpu/drm/Kconfig.debug"
> +endmenu
> +
> if DRM
>
> config DRM_MIPI_DBI
> @@ -37,65 +42,6 @@ config DRM_MIPI_DSI
> bool
> depends on DRM
>
> -config DRM_DEBUG_MM
> - bool "Insert extra checks and debug info into the DRM range
> managers"
> - default n
> - depends on DRM
> - depends on STACKTRACE_SUPPORT
> - select STACKDEPOT
> - help
> - Enable allocation tracking of memory manager and leak
> detection on
> - shutdown.
> -
> - Recommended for driver developers only.
> -
> - If in doubt, say "N".
> -
> -config DRM_USE_DYNAMIC_DEBUG
> - bool "use dynamic debug to implement drm.debug"
> - default n
> - depends on BROKEN
> - depends on DRM
> - depends on DYNAMIC_DEBUG || DYNAMIC_DEBUG_CORE
> - depends on JUMP_LABEL
> - help
> - Use dynamic-debug to avoid drm_debug_enabled() runtime
> overheads.
> - Due to callsite counts in DRM drivers (~4k in amdgpu) and
> 56
> - bytes per callsite, the .data costs can be substantial,
> and
> - are therefore configurable.
> -
> -config DRM_KUNIT_TEST_HELPERS
> - tristate
> - depends on DRM && KUNIT
> - select DRM_KMS_HELPER
> - help
> - KUnit Helpers for KMS drivers.
> -
> -config DRM_KUNIT_TEST
> - tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS
> - depends on DRM && KUNIT && MMU
> - select DRM_BUDDY
> - select DRM_DISPLAY_DP_HELPER
> - select DRM_DISPLAY_HDMI_STATE_HELPER
> - select DRM_DISPLAY_HELPER
> - select DRM_EXEC
> - select DRM_EXPORT_FOR_TESTS if m
> - select DRM_GEM_SHMEM_HELPER
> - select DRM_KUNIT_TEST_HELPERS
> - select DRM_LIB_RANDOM
> - select PRIME_NUMBERS
> - default KUNIT_ALL_TESTS
> - help
> - This builds unit tests for DRM. This option is not useful
> for
> - distributions or general kernels, but only for kernel
> - developers working on DRM and associated drivers.
> -
> - For more information on KUnit and unit tests in general,
> - please refer to the KUnit documentation in
> - Documentation/dev-tools/kunit/.
> -
> - If in doubt, say "N".
> -
> config DRM_KMS_HELPER
> tristate
> depends on DRM
> @@ -247,23 +193,6 @@ config DRM_TTM
> GPU memory types. Will be enabled automatically if a
> device driver
> uses it.
>
> -config DRM_TTM_KUNIT_TEST
> - tristate "KUnit tests for TTM" if !KUNIT_ALL_TESTS
> - default n
> - depends on DRM && KUNIT && MMU && (UML || COMPILE_TEST)
> - select DRM_TTM
> - select DRM_BUDDY
> - select DRM_EXPORT_FOR_TESTS if m
> - select DRM_KUNIT_TEST_HELPERS
> - default KUNIT_ALL_TESTS
> - help
> - Enables unit tests for TTM, a GPU memory manager subsystem
> used
> - to manage memory buffers. This option is mostly useful for
> kernel
> - developers. It depends on (UML || COMPILE_TEST) since no
> other driver
> - which uses TTM can be loaded while running the tests.
> -
> - If in doubt, say "N".
> -
> config DRM_EXEC
> tristate
> depends on DRM
> @@ -474,9 +403,6 @@ config DRM_HYPERV
>
> If M is selected the module will be called hyperv_drm.
>
> -config DRM_EXPORT_FOR_TESTS
> - bool
> -
> # Separate option as not all DRM drivers use it
> config DRM_PANEL_BACKLIGHT_QUIRKS
> tristate
> @@ -489,31 +415,6 @@ config DRM_PRIVACY_SCREEN
> bool
> default n
>
> -config DRM_WERROR
> - bool "Compile the drm subsystem with warnings as errors"
> - depends on DRM && EXPERT
> - depends on !WERROR
> - default n
> - help
> - A kernel build should not cause any compiler warnings, and
> this
> - enables the '-Werror' flag to enforce that rule in the drm
> subsystem.
> -
> - The drm subsystem enables more warnings than the kernel
> default, so
> - this config option is disabled by default.
> -
> - If in doubt, say N.
> -
> -config DRM_HEADER_TEST
> - bool "Ensure DRM headers are self-contained and pass kernel-
> doc"
> - depends on DRM && EXPERT
> - default n
> - help
> - Ensure the DRM subsystem headers both under
> drivers/gpu/drm and
> - include/drm compile, are self-contained, have header
> guards, and have
> - no kernel-doc warnings.
> -
> - If in doubt, say N.
> -
> endif
>
> # Separate option because drm_panel_orientation_quirks.c is shared
> with fbdev
> diff --git a/drivers/gpu/drm/Kconfig.debug
> b/drivers/gpu/drm/Kconfig.debug
> new file mode 100644
> index 000000000000..601d7e07d421
> --- /dev/null
> +++ b/drivers/gpu/drm/Kconfig.debug
> @@ -0,0 +1,103 @@
> +config DRM_USE_DYNAMIC_DEBUG
> + bool "use dynamic debug to implement drm.debug"
> + default n
> + depends on BROKEN
> + depends on DRM
> + depends on DYNAMIC_DEBUG || DYNAMIC_DEBUG_CORE
> + depends on JUMP_LABEL
> + help
> + Use dynamic-debug to avoid drm_debug_enabled() runtime
> overheads.
> + Due to callsite counts in DRM drivers (~4k in amdgpu) and
> 56
> + bytes per callsite, the .data costs can be substantial, and
> + are therefore configurable.
> +
> +config DRM_WERROR
> + bool "Compile the drm subsystem with warnings as errors"
> + depends on DRM && EXPERT
> + depends on !WERROR
> + default n
> + help
> + A kernel build should not cause any compiler warnings, and
> this
> + enables the '-Werror' flag to enforce that rule in the drm
> subsystem.
> +
> + The drm subsystem enables more warnings than the kernel
> default, so
> + this config option is disabled by default.
> +
> + If in doubt, say N.
> +
> +config DRM_HEADER_TEST
> + bool "Ensure DRM headers are self-contained and pass kernel-
> doc"
> + depends on DRM && EXPERT
> + default n
> + help
> + Ensure the DRM subsystem headers both under
> drivers/gpu/drm and
> + include/drm compile, are self-contained, have header
> guards, and have
> + no kernel-doc warnings.
> +
> + If in doubt, say N.
> +
> +config DRM_DEBUG_MM
> + bool "Insert extra checks and debug info into the DRM range
> managers"
> + default n
> + depends on DRM
> + depends on STACKTRACE_SUPPORT
> + select STACKDEPOT
> + help
> + Enable allocation tracking of memory manager and leak
> detection on
> + shutdown.
> +
> + Recommended for driver developers only.
> +
> + If in doubt, say "N".
> +
> +config DRM_KUNIT_TEST_HELPERS
> + tristate
> + depends on DRM && KUNIT
> + select DRM_KMS_HELPER
> + help
> + KUnit Helpers for KMS drivers.
> +
> +config DRM_KUNIT_TEST
> + tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS
> + depends on DRM && KUNIT && MMU
> + select DRM_BUDDY
> + select DRM_DISPLAY_DP_HELPER
> + select DRM_DISPLAY_HDMI_STATE_HELPER
> + select DRM_DISPLAY_HELPER
> + select DRM_EXEC
> + select DRM_EXPORT_FOR_TESTS if m
> + select DRM_GEM_SHMEM_HELPER
> + select DRM_KUNIT_TEST_HELPERS
> + select DRM_LIB_RANDOM
> + select PRIME_NUMBERS
> + default KUNIT_ALL_TESTS
> + help
> + This builds unit tests for DRM. This option is not useful
> for
> + distributions or general kernels, but only for kernel
> + developers working on DRM and associated drivers.
> +
> + For more information on KUnit and unit tests in general,
> + please refer to the KUnit documentation in
> + Documentation/dev-tools/kunit/.
> +
> + If in doubt, say "N".
> +
> +config DRM_TTM_KUNIT_TEST
> + tristate "KUnit tests for TTM" if !KUNIT_ALL_TESTS
> + default n
> + depends on DRM && KUNIT && MMU && (UML || COMPILE_TEST)
> + select DRM_TTM
> + select DRM_BUDDY
> + select DRM_EXPORT_FOR_TESTS if m
> + select DRM_KUNIT_TEST_HELPERS
> + default KUNIT_ALL_TESTS
> + help
> + Enables unit tests for TTM, a GPU memory manager subsystem
> used
> + to manage memory buffers. This option is mostly useful for
> kernel
> + developers. It depends on (UML || COMPILE_TEST) since no
> other driver
> + which uses TTM can be loaded while running the tests.
> +
> + If in doubt, say "N".
> +
> +config DRM_EXPORT_FOR_TESTS
> + bool
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-03-24 9:03 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-18 13:37 [PATCH v9 0/6] DRM scheduler kunit tests Tvrtko Ursulin
2025-03-18 13:37 ` [PATCH v9 1/6] drm: Move some options to separate new Kconfig Tvrtko Ursulin
2025-03-24 9:03 ` Philipp Stanner
2025-03-18 13:37 ` [PATCH v9 2/6] drm/sched: Add scheduler unit testing infrastructure and some basic tests Tvrtko Ursulin
2025-03-18 13:37 ` [PATCH v9 3/6] drm/sched: Add a simple timeout test Tvrtko Ursulin
2025-03-18 13:38 ` [PATCH v9 4/6] drm/sched: Add basic priority tests Tvrtko Ursulin
2025-03-18 13:38 ` [PATCH v9 5/6] drm/sched: Add a basic test for modifying entities scheduler list Tvrtko Ursulin
2025-03-18 13:38 ` [PATCH v9 6/6] drm/sched: Add a basic test for checking credit limit Tvrtko Ursulin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).