diff options
author | Christian König <christian.koenig@amd.com> | 2015-08-26 05:31:23 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2015-08-28 15:04:17 -0400 |
commit | 69bd5bf13a8eccb4db5f26de608556416a56d973 (patch) | |
tree | eb0c78ec8b8746566b04a82709116f1d843ac6f9 /drivers/gpu/drm/amd | |
parent | 86b7709d48f0df8796bddd7e1ce45c6fb7a7c6ec (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.c | 61 |
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 | ||
30 | static struct amd_sched_job * | ||
31 | amd_sched_entity_pop_job(struct amd_sched_entity *entity); | ||
30 | static void amd_sched_wakeup(struct amd_gpu_scheduler *sched); | 32 | static 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 | */ |
63 | static struct amd_sched_entity * | 64 | static struct amd_sched_job * |
64 | amd_sched_rq_select_entity(struct amd_sched_rq *rq) | 65 | amd_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 | ||
195 | static struct amd_sched_job * | ||
196 | amd_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 | */ |
265 | static struct amd_sched_entity * | 280 | static struct amd_sched_job * |
266 | amd_sched_select_context(struct amd_gpu_scheduler *sched) | 281 | amd_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 | ||
281 | static void amd_sched_process_job(struct fence *f, struct fence_cb *cb) | 296 | static 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; |