xref: /linux/drivers/gpu/drm/xe/xe_dep_scheduler.c (revision bba2c3615bd6cfee7456d1130f2e6b01b3f4e9ba)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2025 Intel Corporation
4  */
5 
6 #include <linux/slab.h>
7 
8 #include <drm/gpu_scheduler.h>
9 
10 #include "xe_dep_job_types.h"
11 #include "xe_dep_scheduler.h"
12 #include "xe_device_types.h"
13 
14 /**
15  * DOC: Xe Dependency Scheduler
16  *
17  * The Xe dependency scheduler is a simple wrapper built around the DRM
18  * scheduler to execute jobs once their dependencies are resolved (i.e., all
19  * input fences specified as dependencies are signaled). The jobs that are
20  * executed contain virtual functions to run (execute) and free the job,
21  * allowing a single dependency scheduler to handle jobs performing different
22  * operations.
23  *
24  * Example use cases include deferred resource freeing, TLB invalidations after
25  * bind jobs, etc.
26  */
27 
28 /** struct xe_dep_scheduler - Generic Xe dependency scheduler */
29 struct xe_dep_scheduler {
30 	/** @sched: DRM GPU scheduler */
31 	struct drm_gpu_scheduler sched;
32 	/** @entity: DRM scheduler entity  */
33 	struct drm_sched_entity entity;
34 	/** @rcu: For safe freeing of exported dma fences */
35 	struct rcu_head rcu;
36 };
37 
38 static struct dma_fence *xe_dep_scheduler_run_job(struct drm_sched_job *drm_job)
39 {
40 	struct xe_dep_job *dep_job =
41 		container_of(drm_job, typeof(*dep_job), drm);
42 
43 	return dep_job->ops->run_job(dep_job);
44 }
45 
46 static void xe_dep_scheduler_free_job(struct drm_sched_job *drm_job)
47 {
48 	struct xe_dep_job *dep_job =
49 		container_of(drm_job, typeof(*dep_job), drm);
50 
51 	dep_job->ops->free_job(dep_job);
52 }
53 
54 static const struct drm_sched_backend_ops sched_ops = {
55 	.run_job = xe_dep_scheduler_run_job,
56 	.free_job = xe_dep_scheduler_free_job,
57 };
58 
59 /**
60  * xe_dep_scheduler_create() - Generic Xe dependency scheduler create
61  * @xe: Xe device
62  * @submit_wq: Submit workqueue struct (can be NULL)
63  * @name: Name of dependency scheduler
64  * @job_limit: Max dependency jobs that can be scheduled
65  *
66  * Create a generic Xe dependency scheduler and initialize internal DRM
67  * scheduler objects.
68  *
69  * Return: Generic Xe dependency scheduler object on success, ERR_PTR failure
70  */
71 struct xe_dep_scheduler *
72 xe_dep_scheduler_create(struct xe_device *xe,
73 			struct workqueue_struct *submit_wq,
74 			const char *name, u32 job_limit)
75 {
76 	struct xe_dep_scheduler *dep_scheduler;
77 	struct drm_gpu_scheduler *sched;
78 	const struct drm_sched_init_args args = {
79 		.ops = &sched_ops,
80 		.submit_wq = submit_wq,
81 		.credit_limit = job_limit,
82 		.timeout = MAX_SCHEDULE_TIMEOUT,
83 		.name = name,
84 		.dev = xe->drm.dev,
85 	};
86 	int err;
87 
88 	dep_scheduler = kzalloc_obj(*dep_scheduler);
89 	if (!dep_scheduler)
90 		return ERR_PTR(-ENOMEM);
91 
92 	err = drm_sched_init(&dep_scheduler->sched, &args);
93 	if (err)
94 		goto err_free;
95 
96 	sched = &dep_scheduler->sched;
97 	err = drm_sched_entity_init(&dep_scheduler->entity, 0, &sched, 1, NULL);
98 	if (err)
99 		goto err_sched;
100 
101 	init_rcu_head(&dep_scheduler->rcu);
102 
103 	return dep_scheduler;
104 
105 err_sched:
106 	drm_sched_fini(&dep_scheduler->sched);
107 err_free:
108 	kfree(dep_scheduler);
109 
110 	return ERR_PTR(err);
111 }
112 
113 /**
114  * xe_dep_scheduler_fini() - Generic Xe dependency scheduler finalize
115  * @dep_scheduler: Generic Xe dependency scheduler object
116  *
117  * Finalize internal DRM scheduler objects and free generic Xe dependency
118  * scheduler object
119  */
120 void xe_dep_scheduler_fini(struct xe_dep_scheduler *dep_scheduler)
121 {
122 	drm_sched_entity_fini(&dep_scheduler->entity);
123 	drm_sched_fini(&dep_scheduler->sched);
124 	/*
125 	 * RCU free due sched being exported via DRM scheduler fences
126 	 * (timeline name).
127 	 */
128 	kfree_rcu(dep_scheduler, rcu);
129 }
130 
131 /**
132  * xe_dep_scheduler_entity() - Retrieve a generic Xe dependency scheduler
133  *                             DRM scheduler entity
134  * @dep_scheduler: Generic Xe dependency scheduler object
135  *
136  * Return: The generic Xe dependency scheduler's DRM scheduler entity
137  */
138 struct drm_sched_entity *
139 xe_dep_scheduler_entity(struct xe_dep_scheduler *dep_scheduler)
140 {
141 	return &dep_scheduler->entity;
142 }
143