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