xref: /linux/drivers/gpu/drm/scheduler/tests/sched_tests.h (revision 53e65974924ec3e66b2cdf71780f089b338fed33)
15a993507STvrtko Ursulin /* SPDX-License-Identifier: GPL-2.0 */
25a993507STvrtko Ursulin /* Copyright (c) 2025 Valve Corporation */
35a993507STvrtko Ursulin 
45a993507STvrtko Ursulin #ifndef _SCHED_TESTS_H_
55a993507STvrtko Ursulin #define _SCHED_TESTS_H_
65a993507STvrtko Ursulin 
75a993507STvrtko Ursulin #include <kunit/test.h>
85a993507STvrtko Ursulin #include <linux/atomic.h>
95a993507STvrtko Ursulin #include <linux/completion.h>
105a993507STvrtko Ursulin #include <linux/dma-fence.h>
115a993507STvrtko Ursulin #include <linux/hrtimer.h>
125a993507STvrtko Ursulin #include <linux/ktime.h>
135a993507STvrtko Ursulin #include <linux/list.h>
145a993507STvrtko Ursulin #include <linux/atomic.h>
155a993507STvrtko Ursulin #include <linux/mutex.h>
165a993507STvrtko Ursulin #include <linux/types.h>
175a993507STvrtko Ursulin 
185a993507STvrtko Ursulin #include <drm/gpu_scheduler.h>
195a993507STvrtko Ursulin 
205a993507STvrtko Ursulin /*
215a993507STvrtko Ursulin  * DOC: Mock DRM scheduler data structures
225a993507STvrtko Ursulin  *
235a993507STvrtko Ursulin  * drm_mock_* data structures are used to implement a mock "GPU".
245a993507STvrtko Ursulin  *
255a993507STvrtko Ursulin  * They subclass the core DRM scheduler objects and add their data on top, which
265a993507STvrtko Ursulin  * enables tracking the submitted jobs and simulating their execution with the
275a993507STvrtko Ursulin  * attributes as specified by the test case.
285a993507STvrtko Ursulin  */
295a993507STvrtko Ursulin 
305a993507STvrtko Ursulin /**
315a993507STvrtko Ursulin  * struct drm_mock_scheduler - implements a trivial mock GPU execution engine
325a993507STvrtko Ursulin  *
335a993507STvrtko Ursulin  * @base: DRM scheduler base class
345a993507STvrtko Ursulin  * @test: Backpointer to owning the kunit test case
355a993507STvrtko Ursulin  * @lock: Lock to protect the simulated @hw_timeline, @job_list and @done_list
365a993507STvrtko Ursulin  * @job_list: List of jobs submitted to the mock GPU
375a993507STvrtko Ursulin  * @done_list: List of jobs completed by the mock GPU
385a993507STvrtko Ursulin  * @hw_timeline: Simulated hardware timeline has a @context, @next_seqno and
395a993507STvrtko Ursulin  *		 @cur_seqno for implementing a struct dma_fence signaling the
405a993507STvrtko Ursulin  *		 simulated job completion.
415a993507STvrtko Ursulin  *
425a993507STvrtko Ursulin  * Trivial mock GPU execution engine tracks submitted jobs and enables
435a993507STvrtko Ursulin  * completing them strictly in submission order.
445a993507STvrtko Ursulin  */
455a993507STvrtko Ursulin struct drm_mock_scheduler {
465a993507STvrtko Ursulin 	struct drm_gpu_scheduler base;
475a993507STvrtko Ursulin 
485a993507STvrtko Ursulin 	struct kunit		*test;
495a993507STvrtko Ursulin 
505a993507STvrtko Ursulin 	spinlock_t		lock;
515a993507STvrtko Ursulin 	struct list_head	job_list;
525a993507STvrtko Ursulin 	struct list_head	done_list;
535a993507STvrtko Ursulin 
545a993507STvrtko Ursulin 	struct {
555a993507STvrtko Ursulin 		u64		context;
565a993507STvrtko Ursulin 		atomic_t	next_seqno;
575a993507STvrtko Ursulin 		unsigned int	cur_seqno;
585a993507STvrtko Ursulin 	} hw_timeline;
595a993507STvrtko Ursulin };
605a993507STvrtko Ursulin 
615a993507STvrtko Ursulin /**
625a993507STvrtko Ursulin  * struct drm_mock_sched_entity - implements a mock GPU sched entity
635a993507STvrtko Ursulin  *
645a993507STvrtko Ursulin  * @base: DRM scheduler entity base class
655a993507STvrtko Ursulin  * @test: Backpointer to owning the kunit test case
665a993507STvrtko Ursulin  *
675a993507STvrtko Ursulin  * Mock GPU sched entity is used by the test cases to submit jobs to the mock
685a993507STvrtko Ursulin  * scheduler.
695a993507STvrtko Ursulin  */
705a993507STvrtko Ursulin struct drm_mock_sched_entity {
715a993507STvrtko Ursulin 	struct drm_sched_entity base;
725a993507STvrtko Ursulin 
735a993507STvrtko Ursulin 	struct kunit		*test;
745a993507STvrtko Ursulin };
755a993507STvrtko Ursulin 
765a993507STvrtko Ursulin /**
775a993507STvrtko Ursulin  * struct drm_mock_sched_job - implements a mock GPU job
785a993507STvrtko Ursulin  *
795a993507STvrtko Ursulin  * @base: DRM sched job base class
805a993507STvrtko Ursulin  * @done: Completion signaling job completion.
815a993507STvrtko Ursulin  * @flags: Flags designating job state.
825a993507STvrtko Ursulin  * @link: List head element used by job tracking by the drm_mock_scheduler
835a993507STvrtko Ursulin  * @timer: Timer used for simulating job execution duration
845a993507STvrtko Ursulin  * @duration_us: Simulated job duration in micro seconds, or zero if in manual
855a993507STvrtko Ursulin  *		 timeline advance mode
865a993507STvrtko Ursulin  * @finish_at: Absolute time when the jobs with set duration will complete
875a993507STvrtko Ursulin  * @lock: Lock used for @hw_fence
885a993507STvrtko Ursulin  * @hw_fence: Fence returned to DRM scheduler as the hardware fence
895a993507STvrtko Ursulin  * @test: Backpointer to owning the kunit test case
905a993507STvrtko Ursulin  *
915a993507STvrtko Ursulin  * Mock GPU sched job is used by the test cases to submit jobs to the mock
925a993507STvrtko Ursulin  * scheduler.
935a993507STvrtko Ursulin  */
945a993507STvrtko Ursulin struct drm_mock_sched_job {
955a993507STvrtko Ursulin 	struct drm_sched_job	base;
965a993507STvrtko Ursulin 
975a993507STvrtko Ursulin 	struct completion	done;
985a993507STvrtko Ursulin 
995a993507STvrtko Ursulin #define DRM_MOCK_SCHED_JOB_DONE		0x1
100*53e65974STvrtko Ursulin #define DRM_MOCK_SCHED_JOB_TIMEDOUT	0x2
1015a993507STvrtko Ursulin 	unsigned long		flags;
1025a993507STvrtko Ursulin 
1035a993507STvrtko Ursulin 	struct list_head	link;
1045a993507STvrtko Ursulin 	struct hrtimer		timer;
1055a993507STvrtko Ursulin 
1065a993507STvrtko Ursulin 	unsigned int		duration_us;
1075a993507STvrtko Ursulin 	ktime_t			finish_at;
1085a993507STvrtko Ursulin 
1095a993507STvrtko Ursulin 	spinlock_t		lock;
1105a993507STvrtko Ursulin 	struct dma_fence	hw_fence;
1115a993507STvrtko Ursulin 
1125a993507STvrtko Ursulin 	struct kunit		*test;
1135a993507STvrtko Ursulin };
1145a993507STvrtko Ursulin 
1155a993507STvrtko Ursulin static inline struct drm_mock_scheduler *
1165a993507STvrtko Ursulin drm_sched_to_mock_sched(struct drm_gpu_scheduler *sched)
1175a993507STvrtko Ursulin {
1185a993507STvrtko Ursulin 	return container_of(sched, struct drm_mock_scheduler, base);
1195a993507STvrtko Ursulin };
1205a993507STvrtko Ursulin 
1215a993507STvrtko Ursulin static inline struct drm_mock_sched_entity *
1225a993507STvrtko Ursulin drm_sched_entity_to_mock_entity(struct drm_sched_entity *sched_entity)
1235a993507STvrtko Ursulin {
1245a993507STvrtko Ursulin 	return container_of(sched_entity, struct drm_mock_sched_entity, base);
1255a993507STvrtko Ursulin };
1265a993507STvrtko Ursulin 
1275a993507STvrtko Ursulin static inline struct drm_mock_sched_job *
1285a993507STvrtko Ursulin drm_sched_job_to_mock_job(struct drm_sched_job *sched_job)
1295a993507STvrtko Ursulin {
1305a993507STvrtko Ursulin 	return container_of(sched_job, struct drm_mock_sched_job, base);
1315a993507STvrtko Ursulin };
1325a993507STvrtko Ursulin 
133*53e65974STvrtko Ursulin struct drm_mock_scheduler *drm_mock_sched_new(struct kunit *test,
134*53e65974STvrtko Ursulin 					      long timeout);
1355a993507STvrtko Ursulin void drm_mock_sched_fini(struct drm_mock_scheduler *sched);
1365a993507STvrtko Ursulin unsigned int drm_mock_sched_advance(struct drm_mock_scheduler *sched,
1375a993507STvrtko Ursulin 				    unsigned int num);
1385a993507STvrtko Ursulin 
1395a993507STvrtko Ursulin struct drm_mock_sched_entity *
1405a993507STvrtko Ursulin drm_mock_sched_entity_new(struct kunit *test,
1415a993507STvrtko Ursulin 			  enum drm_sched_priority priority,
1425a993507STvrtko Ursulin 			  struct drm_mock_scheduler *sched);
1435a993507STvrtko Ursulin void drm_mock_sched_entity_free(struct drm_mock_sched_entity *entity);
1445a993507STvrtko Ursulin 
1455a993507STvrtko Ursulin struct drm_mock_sched_job *
1465a993507STvrtko Ursulin drm_mock_sched_job_new(struct kunit *test,
1475a993507STvrtko Ursulin 		       struct drm_mock_sched_entity *entity);
1485a993507STvrtko Ursulin 
1495a993507STvrtko Ursulin /**
1505a993507STvrtko Ursulin  * drm_mock_sched_job_submit - Arm and submit a job in one go
1515a993507STvrtko Ursulin  *
1525a993507STvrtko Ursulin  * @job: Job to arm and submit
1535a993507STvrtko Ursulin  */
1545a993507STvrtko Ursulin static inline void drm_mock_sched_job_submit(struct drm_mock_sched_job *job)
1555a993507STvrtko Ursulin {
1565a993507STvrtko Ursulin 	drm_sched_job_arm(&job->base);
1575a993507STvrtko Ursulin 	drm_sched_entity_push_job(&job->base);
1585a993507STvrtko Ursulin }
1595a993507STvrtko Ursulin 
1605a993507STvrtko Ursulin /**
1615a993507STvrtko Ursulin  * drm_mock_sched_job_set_duration_us - Set a job duration
1625a993507STvrtko Ursulin  *
1635a993507STvrtko Ursulin  * @job: Job to set the duration for
1645a993507STvrtko Ursulin  * @duration_us: Duration in micro seconds
1655a993507STvrtko Ursulin  *
1665a993507STvrtko Ursulin  * Jobs with duration set will be automatically completed by the mock scheduler
1675a993507STvrtko Ursulin  * as the timeline progresses, unless a job without a set duration is
1685a993507STvrtko Ursulin  * encountered in the timelime in which case calling drm_mock_sched_advance()
1695a993507STvrtko Ursulin  * will be required to bump the timeline.
1705a993507STvrtko Ursulin  */
1715a993507STvrtko Ursulin static inline void
1725a993507STvrtko Ursulin drm_mock_sched_job_set_duration_us(struct drm_mock_sched_job *job,
1735a993507STvrtko Ursulin 				   unsigned int duration_us)
1745a993507STvrtko Ursulin {
1755a993507STvrtko Ursulin 	job->duration_us = duration_us;
1765a993507STvrtko Ursulin }
1775a993507STvrtko Ursulin 
1785a993507STvrtko Ursulin /**
1795a993507STvrtko Ursulin  * drm_mock_sched_job_is_finished - Check if a job is finished
1805a993507STvrtko Ursulin  *
1815a993507STvrtko Ursulin  * @job: Job to check
1825a993507STvrtko Ursulin  *
1835a993507STvrtko Ursulin  * Returns: true if finished
1845a993507STvrtko Ursulin  */
1855a993507STvrtko Ursulin static inline bool
1865a993507STvrtko Ursulin drm_mock_sched_job_is_finished(struct drm_mock_sched_job *job)
1875a993507STvrtko Ursulin {
1885a993507STvrtko Ursulin 	return job->flags & DRM_MOCK_SCHED_JOB_DONE;
1895a993507STvrtko Ursulin }
1905a993507STvrtko Ursulin 
1915a993507STvrtko Ursulin /**
1925a993507STvrtko Ursulin  * drm_mock_sched_job_wait_finished - Wait until a job is finished
1935a993507STvrtko Ursulin  *
1945a993507STvrtko Ursulin  * @job: Job to wait for
1955a993507STvrtko Ursulin  * @timeout: Wait time in jiffies
1965a993507STvrtko Ursulin  *
1975a993507STvrtko Ursulin  * Returns: true if finished within the timeout provided, otherwise false
1985a993507STvrtko Ursulin  */
1995a993507STvrtko Ursulin static inline bool
2005a993507STvrtko Ursulin drm_mock_sched_job_wait_finished(struct drm_mock_sched_job *job, long timeout)
2015a993507STvrtko Ursulin {
2025a993507STvrtko Ursulin 	if (job->flags & DRM_MOCK_SCHED_JOB_DONE)
2035a993507STvrtko Ursulin 		return true;
2045a993507STvrtko Ursulin 
2055a993507STvrtko Ursulin 	return wait_for_completion_timeout(&job->done, timeout) != 0;
2065a993507STvrtko Ursulin }
2075a993507STvrtko Ursulin 
2085a993507STvrtko Ursulin /**
2095a993507STvrtko Ursulin  * drm_mock_sched_job_wait_scheduled - Wait until a job is scheduled
2105a993507STvrtko Ursulin  *
2115a993507STvrtko Ursulin  * @job: Job to wait for
2125a993507STvrtko Ursulin  * @timeout: Wait time in jiffies
2135a993507STvrtko Ursulin  *
2145a993507STvrtko Ursulin  * Returns: true if scheduled within the timeout provided, otherwise false
2155a993507STvrtko Ursulin  */
2165a993507STvrtko Ursulin static inline bool
2175a993507STvrtko Ursulin drm_mock_sched_job_wait_scheduled(struct drm_mock_sched_job *job, long timeout)
2185a993507STvrtko Ursulin {
2195a993507STvrtko Ursulin 	KUNIT_ASSERT_EQ(job->test, job->flags & DRM_MOCK_SCHED_JOB_DONE, 0);
2205a993507STvrtko Ursulin 
2215a993507STvrtko Ursulin 	return dma_fence_wait_timeout(&job->base.s_fence->scheduled,
2225a993507STvrtko Ursulin 				      false,
2235a993507STvrtko Ursulin 				      timeout) != 0;
2245a993507STvrtko Ursulin }
2255a993507STvrtko Ursulin 
2265a993507STvrtko Ursulin #endif
227