xref: /linux/drivers/gpu/drm/scheduler/sched_internal.h (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 /* SPDX-License-Identifier: MIT */
2 
3 #ifndef _DRM_GPU_SCHEDULER_INTERNAL_H_
4 #define _DRM_GPU_SCHEDULER_INTERNAL_H_
5 
6 #include <linux/ktime.h>
7 #include <linux/kref.h>
8 #include <linux/spinlock.h>
9 
10 /**
11  * struct drm_sched_entity_stats - execution stats for an entity.
12  * @kref: reference count for the object.
13  * @lock: lock guarding the @runtime updates.
14  * @runtime: time entity spent on the GPU.
15  * @prev_runtime: previous @runtime used to get the runtime delta.
16  * @vruntime: virtual runtime as accumulated by the fair algorithm.
17  * @avg_job_us: average job duration.
18  *
19  * Because jobs and entities have decoupled lifetimes, ie. we cannot access the
20  * entity once the job has been de-queued, and we do need know how much GPU time
21  * each entity has spent, we need to track this in a separate object which is
22  * reference counted by both entities and jobs.
23  */
24 struct drm_sched_entity_stats {
25 	struct kref	kref;
26 	spinlock_t	lock; /* Protects the below fields. */
27 	ktime_t		runtime;
28 	ktime_t		prev_runtime;
29 	ktime_t		vruntime;
30 
31 	struct ewma_drm_sched_avgtime   avg_job_us;
32 };
33 
34 /* Used to choose between FIFO and RR job-scheduling */
35 extern int drm_sched_policy;
36 
37 #define DRM_SCHED_POLICY_RR    0
38 #define DRM_SCHED_POLICY_FIFO  1
39 #define DRM_SCHED_POLICY_FAIR  2
40 
41 bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
42 			 struct drm_sched_entity *entity);
43 void drm_sched_wakeup(struct drm_gpu_scheduler *sched);
44 
45 void drm_sched_rq_init(struct drm_gpu_scheduler *sched,
46 		       struct drm_sched_rq *rq);
47 
48 struct drm_gpu_scheduler *
49 drm_sched_rq_add_entity(struct drm_sched_entity *entity, ktime_t ts);
50 void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
51 				struct drm_sched_entity *entity);
52 void drm_sched_rq_pop_entity(struct drm_sched_entity *entity);
53 
54 struct drm_sched_entity *
55 drm_sched_rq_select_entity(struct drm_gpu_scheduler *sched,
56 			   struct drm_sched_rq *rq);
57 
58 void drm_sched_entity_select_rq(struct drm_sched_entity *entity);
59 struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity);
60 
61 struct drm_sched_fence *drm_sched_fence_alloc(struct drm_sched_entity *s_entity,
62 					      void *owner, u64 drm_client_id);
63 void drm_sched_fence_init(struct drm_sched_fence *fence,
64 			  struct drm_sched_entity *entity);
65 void drm_sched_fence_free(struct drm_sched_fence *fence);
66 
67 void drm_sched_fence_scheduled(struct drm_sched_fence *fence,
68 			       struct dma_fence *parent);
69 void drm_sched_fence_finished(struct drm_sched_fence *fence, int result);
70 
71 /**
72  * drm_sched_entity_queue_pop - Low level helper for popping queued jobs
73  *
74  * @entity: scheduler entity
75  *
76  * Low level helper for popping queued jobs.
77  *
78  * Returns: The job dequeued or NULL.
79  */
80 static inline struct drm_sched_job *
81 drm_sched_entity_queue_pop(struct drm_sched_entity *entity)
82 {
83 	struct spsc_node *node;
84 
85 	node = spsc_queue_pop(&entity->job_queue);
86 	if (!node)
87 		return NULL;
88 
89 	return container_of(node, struct drm_sched_job, queue_node);
90 }
91 
92 /**
93  * drm_sched_entity_queue_peek - Low level helper for peeking at the job queue
94  *
95  * @entity: scheduler entity
96  *
97  * Low level helper for peeking at the job queue
98  *
99  * Returns: The job at the head of the queue or NULL.
100  */
101 static inline struct drm_sched_job *
102 drm_sched_entity_queue_peek(struct drm_sched_entity *entity)
103 {
104 	struct spsc_node *node;
105 
106 	node = spsc_queue_peek(&entity->job_queue);
107 	if (!node)
108 		return NULL;
109 
110 	return container_of(node, struct drm_sched_job, queue_node);
111 }
112 
113 /* Return true if entity could provide a job. */
114 static inline bool
115 drm_sched_entity_is_ready(struct drm_sched_entity *entity)
116 {
117 	if (!spsc_queue_count(&entity->job_queue))
118 		return false;
119 
120 	if (READ_ONCE(entity->dependency))
121 		return false;
122 
123 	return true;
124 }
125 
126 void drm_sched_entity_stats_release(struct kref *kref);
127 
128 /**
129  * drm_sched_entity_stats_get - Obtain a reference count on &struct drm_sched_entity_stats object
130  * @stats: struct drm_sched_entity_stats pointer
131  *
132  * Return: struct drm_sched_entity_stats pointer
133  */
134 static inline struct drm_sched_entity_stats *
135 drm_sched_entity_stats_get(struct drm_sched_entity_stats *stats)
136 {
137 	kref_get(&stats->kref);
138 
139 	return stats;
140 }
141 
142 /**
143  * drm_sched_entity_stats_put - Release a reference count on &struct drm_sched_entity_stats object
144  * @stats: struct drm_sched_entity_stats pointer
145  */
146 static inline void
147 drm_sched_entity_stats_put(struct drm_sched_entity_stats *stats)
148 {
149 	kref_put(&stats->kref, drm_sched_entity_stats_release);
150 }
151 
152 ktime_t drm_sched_entity_stats_job_add_gpu_time(struct drm_sched_job *job);
153 
154 #endif
155