xref: /linux/drivers/gpu/drm/scheduler/sched_internal.h (revision c06b6cde2a1c3bcbb561bd57bb6f34eae9030921)
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 bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
35 			 struct drm_sched_entity *entity);
36 void drm_sched_wakeup(struct drm_gpu_scheduler *sched);
37 
38 void drm_sched_rq_init(struct drm_sched_rq *rq);
39 
40 struct drm_gpu_scheduler *
41 drm_sched_rq_add_entity(struct drm_sched_entity *entity);
42 void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
43 				struct drm_sched_entity *entity);
44 void drm_sched_rq_pop_entity(struct drm_sched_entity *entity);
45 
46 struct drm_sched_entity *
47 drm_sched_select_entity(struct drm_gpu_scheduler *sched);
48 
49 void drm_sched_entity_select_rq(struct drm_sched_entity *entity);
50 struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity);
51 
52 struct drm_sched_fence *drm_sched_fence_alloc(struct drm_sched_entity *s_entity,
53 					      void *owner, u64 drm_client_id);
54 void drm_sched_fence_init(struct drm_sched_fence *fence,
55 			  struct drm_sched_entity *entity);
56 void drm_sched_fence_free(struct drm_sched_fence *fence);
57 
58 void drm_sched_fence_scheduled(struct drm_sched_fence *fence,
59 			       struct dma_fence *parent);
60 void drm_sched_fence_finished(struct drm_sched_fence *fence, int result);
61 
62 /**
63  * drm_sched_entity_queue_pop - Low level helper for popping queued jobs
64  *
65  * @entity: scheduler entity
66  *
67  * Low level helper for popping queued jobs.
68  *
69  * Returns: The job dequeued or NULL.
70  */
71 static inline struct drm_sched_job *
72 drm_sched_entity_queue_pop(struct drm_sched_entity *entity)
73 {
74 	struct spsc_node *node;
75 
76 	node = spsc_queue_pop(&entity->job_queue);
77 	if (!node)
78 		return NULL;
79 
80 	return container_of(node, struct drm_sched_job, queue_node);
81 }
82 
83 /**
84  * drm_sched_entity_queue_peek - Low level helper for peeking at the job queue
85  *
86  * @entity: scheduler entity
87  *
88  * Low level helper for peeking at the job queue
89  *
90  * Returns: The job at the head of the queue or NULL.
91  */
92 static inline struct drm_sched_job *
93 drm_sched_entity_queue_peek(struct drm_sched_entity *entity)
94 {
95 	struct spsc_node *node;
96 
97 	node = spsc_queue_peek(&entity->job_queue);
98 	if (!node)
99 		return NULL;
100 
101 	return container_of(node, struct drm_sched_job, queue_node);
102 }
103 
104 /* Return true if entity could provide a job. */
105 static inline bool
106 drm_sched_entity_is_ready(struct drm_sched_entity *entity)
107 {
108 	if (!spsc_queue_count(&entity->job_queue))
109 		return false;
110 
111 	if (READ_ONCE(entity->dependency))
112 		return false;
113 
114 	return true;
115 }
116 
117 void drm_sched_entity_stats_release(struct kref *kref);
118 
119 /**
120  * drm_sched_entity_stats_get - Obtain a reference count on &struct drm_sched_entity_stats object
121  * @stats: struct drm_sched_entity_stats pointer
122  *
123  * Return: struct drm_sched_entity_stats pointer
124  */
125 static inline struct drm_sched_entity_stats *
126 drm_sched_entity_stats_get(struct drm_sched_entity_stats *stats)
127 {
128 	kref_get(&stats->kref);
129 
130 	return stats;
131 }
132 
133 /**
134  * drm_sched_entity_stats_put - Release a reference count on &struct drm_sched_entity_stats object
135  * @stats: struct drm_sched_entity_stats pointer
136  */
137 static inline void
138 drm_sched_entity_stats_put(struct drm_sched_entity_stats *stats)
139 {
140 	kref_put(&stats->kref, drm_sched_entity_stats_release);
141 }
142 
143 ktime_t drm_sched_entity_stats_job_add_gpu_time(struct drm_sched_job *job);
144 
145 #endif
146