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