aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2015-08-26 05:31:23 -0400
committerAlex Deucher <alexander.deucher@amd.com>2015-08-28 15:04:17 -0400
commit69bd5bf13a8eccb4db5f26de608556416a56d973 (patch)
treeeb0c78ec8b8746566b04a82709116f1d843ac6f9 /drivers/gpu/drm/amd
parent86b7709d48f0df8796bddd7e1ce45c6fb7a7c6ec (diff)
drm/amdgpu: let the scheduler work more with jobs v2
v2: fix another race condition Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Chunming Zhou <david1.zhou@amd.com> Reviewed-by: Jammy Zhou <Jammy.Zhou@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd')
-rw-r--r--drivers/gpu/drm/amd/scheduler/gpu_scheduler.c61
1 files changed, 37 insertions, 24 deletions
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
index d99fe90991dc..205cb887d023 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
@@ -27,6 +27,8 @@
27#include <drm/drmP.h> 27#include <drm/drmP.h>
28#include "gpu_scheduler.h" 28#include "gpu_scheduler.h"
29 29
30static struct amd_sched_job *
31amd_sched_entity_pop_job(struct amd_sched_entity *entity);
30static void amd_sched_wakeup(struct amd_gpu_scheduler *sched); 32static void amd_sched_wakeup(struct amd_gpu_scheduler *sched);
31 33
32/* Initialize a given run queue struct */ 34/* Initialize a given run queue struct */
@@ -56,34 +58,36 @@ static void amd_sched_rq_remove_entity(struct amd_sched_rq *rq,
56} 58}
57 59
58/** 60/**
59 * Select next entity from a specified run queue with round robin policy. 61 * Select next job from a specified run queue with round robin policy.
60 * It could return the same entity as current one if current is the only 62 * Return NULL if nothing available.
61 * available one in the queue. Return NULL if nothing available.
62 */ 63 */
63static struct amd_sched_entity * 64static struct amd_sched_job *
64amd_sched_rq_select_entity(struct amd_sched_rq *rq) 65amd_sched_rq_select_job(struct amd_sched_rq *rq)
65{ 66{
66 struct amd_sched_entity *entity; 67 struct amd_sched_entity *entity;
68 struct amd_sched_job *job;
67 69
68 spin_lock(&rq->lock); 70 spin_lock(&rq->lock);
69 71
70 entity = rq->current_entity; 72 entity = rq->current_entity;
71 if (entity) { 73 if (entity) {
72 list_for_each_entry_continue(entity, &rq->entities, list) { 74 list_for_each_entry_continue(entity, &rq->entities, list) {
73 if (!kfifo_is_empty(&entity->job_queue)) { 75 job = amd_sched_entity_pop_job(entity);
76 if (job) {
74 rq->current_entity = entity; 77 rq->current_entity = entity;
75 spin_unlock(&rq->lock); 78 spin_unlock(&rq->lock);
76 return rq->current_entity; 79 return job;
77 } 80 }
78 } 81 }
79 } 82 }
80 83
81 list_for_each_entry(entity, &rq->entities, list) { 84 list_for_each_entry(entity, &rq->entities, list) {
82 85
83 if (!kfifo_is_empty(&entity->job_queue)) { 86 job = amd_sched_entity_pop_job(entity);
87 if (job) {
84 rq->current_entity = entity; 88 rq->current_entity = entity;
85 spin_unlock(&rq->lock); 89 spin_unlock(&rq->lock);
86 return rq->current_entity; 90 return job;
87 } 91 }
88 92
89 if (entity == rq->current_entity) 93 if (entity == rq->current_entity)
@@ -188,6 +192,17 @@ void amd_sched_entity_fini(struct amd_gpu_scheduler *sched,
188 kfifo_free(&entity->job_queue); 192 kfifo_free(&entity->job_queue);
189} 193}
190 194
195static struct amd_sched_job *
196amd_sched_entity_pop_job(struct amd_sched_entity *entity)
197{
198 struct amd_sched_job *job;
199
200 if (!kfifo_out_peek(&entity->job_queue, &job, sizeof(job)))
201 return NULL;
202
203 return job;
204}
205
191/** 206/**
192 * Helper to submit a job to the job queue 207 * Helper to submit a job to the job queue
193 * 208 *
@@ -260,22 +275,22 @@ static void amd_sched_wakeup(struct amd_gpu_scheduler *sched)
260} 275}
261 276
262/** 277/**
263 * Select next entity containing real IB submissions 278 * Select next to run
264*/ 279*/
265static struct amd_sched_entity * 280static struct amd_sched_job *
266amd_sched_select_context(struct amd_gpu_scheduler *sched) 281amd_sched_select_job(struct amd_gpu_scheduler *sched)
267{ 282{
268 struct amd_sched_entity *tmp; 283 struct amd_sched_job *job;
269 284
270 if (!amd_sched_ready(sched)) 285 if (!amd_sched_ready(sched))
271 return NULL; 286 return NULL;
272 287
273 /* Kernel run queue has higher priority than normal run queue*/ 288 /* Kernel run queue has higher priority than normal run queue*/
274 tmp = amd_sched_rq_select_entity(&sched->kernel_rq); 289 job = amd_sched_rq_select_job(&sched->kernel_rq);
275 if (tmp == NULL) 290 if (job == NULL)
276 tmp = amd_sched_rq_select_entity(&sched->sched_rq); 291 job = amd_sched_rq_select_job(&sched->sched_rq);
277 292
278 return tmp; 293 return job;
279} 294}
280 295
281static void amd_sched_process_job(struct fence *f, struct fence_cb *cb) 296static void amd_sched_process_job(struct fence *f, struct fence_cb *cb)
@@ -301,22 +316,19 @@ static int amd_sched_main(void *param)
301 sched_setscheduler(current, SCHED_FIFO, &sparam); 316 sched_setscheduler(current, SCHED_FIFO, &sparam);
302 317
303 while (!kthread_should_stop()) { 318 while (!kthread_should_stop()) {
304 struct amd_sched_entity *c_entity = NULL; 319 struct amd_sched_entity *entity;
305 struct amd_sched_job *job; 320 struct amd_sched_job *job;
306 struct fence *fence; 321 struct fence *fence;
307 322
308 wait_event_interruptible(sched->wake_up_worker, 323 wait_event_interruptible(sched->wake_up_worker,
309 kthread_should_stop() || 324 kthread_should_stop() ||
310 (c_entity = amd_sched_select_context(sched))); 325 (job = amd_sched_select_job(sched)));
311 326
312 if (!c_entity) 327 if (!job)
313 continue; 328 continue;
314 329
315 r = kfifo_out(&c_entity->job_queue, &job, sizeof(void *)); 330 entity = job->s_entity;
316 if (r != sizeof(void *))
317 continue;
318 atomic_inc(&sched->hw_rq_count); 331 atomic_inc(&sched->hw_rq_count);
319
320 fence = sched->ops->run_job(job); 332 fence = sched->ops->run_job(job);
321 if (fence) { 333 if (fence) {
322 r = fence_add_callback(fence, &job->cb, 334 r = fence_add_callback(fence, &job->cb,
@@ -328,6 +340,7 @@ static int amd_sched_main(void *param)
328 fence_put(fence); 340 fence_put(fence);
329 } 341 }
330 342
343 kfifo_out(&entity->job_queue, &job, sizeof(job));
331 wake_up(&sched->job_scheduled); 344 wake_up(&sched->job_scheduled);
332 } 345 }
333 return 0; 346 return 0;