diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/scheduler/gpu_scheduler.c | 68 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/scheduler/gpu_scheduler.h | 4 |
3 files changed, 29 insertions, 47 deletions
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h b/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h index 283a0dc25e84..705380eb693c 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h +++ b/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h | |||
@@ -29,8 +29,8 @@ TRACE_EVENT(amd_sched_job, | |||
29 | __entry->id = sched_job->id; | 29 | __entry->id = sched_job->id; |
30 | __entry->fence = &sched_job->s_fence->finished; | 30 | __entry->fence = &sched_job->s_fence->finished; |
31 | __entry->name = sched_job->sched->name; | 31 | __entry->name = sched_job->sched->name; |
32 | __entry->job_count = kfifo_len( | 32 | __entry->job_count = spsc_queue_count( |
33 | &sched_job->s_entity->job_queue) / sizeof(sched_job); | 33 | &sched_job->s_entity->job_queue); |
34 | __entry->hw_job_count = atomic_read( | 34 | __entry->hw_job_count = atomic_read( |
35 | &sched_job->sched->hw_rq_count); | 35 | &sched_job->sched->hw_rq_count); |
36 | ), | 36 | ), |
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c index 1474866d9048..1a2267ce62a8 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c | |||
@@ -28,9 +28,14 @@ | |||
28 | #include <drm/drmP.h> | 28 | #include <drm/drmP.h> |
29 | #include "gpu_scheduler.h" | 29 | #include "gpu_scheduler.h" |
30 | 30 | ||
31 | #include "spsc_queue.h" | ||
32 | |||
31 | #define CREATE_TRACE_POINTS | 33 | #define CREATE_TRACE_POINTS |
32 | #include "gpu_sched_trace.h" | 34 | #include "gpu_sched_trace.h" |
33 | 35 | ||
36 | #define to_amd_sched_job(sched_job) \ | ||
37 | container_of((sched_job), struct amd_sched_job, queue_node) | ||
38 | |||
34 | static bool amd_sched_entity_is_ready(struct amd_sched_entity *entity); | 39 | static bool amd_sched_entity_is_ready(struct amd_sched_entity *entity); |
35 | static void amd_sched_wakeup(struct amd_gpu_scheduler *sched); | 40 | static void amd_sched_wakeup(struct amd_gpu_scheduler *sched); |
36 | static void amd_sched_process_job(struct dma_fence *f, struct dma_fence_cb *cb); | 41 | static void amd_sched_process_job(struct dma_fence *f, struct dma_fence_cb *cb); |
@@ -123,8 +128,6 @@ int amd_sched_entity_init(struct amd_gpu_scheduler *sched, | |||
123 | struct amd_sched_rq *rq, | 128 | struct amd_sched_rq *rq, |
124 | uint32_t jobs, atomic_t *guilty) | 129 | uint32_t jobs, atomic_t *guilty) |
125 | { | 130 | { |
126 | int r; | ||
127 | |||
128 | if (!(sched && entity && rq)) | 131 | if (!(sched && entity && rq)) |
129 | return -EINVAL; | 132 | return -EINVAL; |
130 | 133 | ||
@@ -136,9 +139,7 @@ int amd_sched_entity_init(struct amd_gpu_scheduler *sched, | |||
136 | 139 | ||
137 | spin_lock_init(&entity->rq_lock); | 140 | spin_lock_init(&entity->rq_lock); |
138 | spin_lock_init(&entity->queue_lock); | 141 | spin_lock_init(&entity->queue_lock); |
139 | r = kfifo_alloc(&entity->job_queue, jobs * sizeof(void *), GFP_KERNEL); | 142 | spsc_queue_init(&entity->job_queue); |
140 | if (r) | ||
141 | return r; | ||
142 | 143 | ||
143 | atomic_set(&entity->fence_seq, 0); | 144 | atomic_set(&entity->fence_seq, 0); |
144 | entity->fence_context = dma_fence_context_alloc(2); | 145 | entity->fence_context = dma_fence_context_alloc(2); |
@@ -171,7 +172,7 @@ static bool amd_sched_entity_is_initialized(struct amd_gpu_scheduler *sched, | |||
171 | static bool amd_sched_entity_is_idle(struct amd_sched_entity *entity) | 172 | static bool amd_sched_entity_is_idle(struct amd_sched_entity *entity) |
172 | { | 173 | { |
173 | rmb(); | 174 | rmb(); |
174 | if (kfifo_is_empty(&entity->job_queue)) | 175 | if (spsc_queue_peek(&entity->job_queue) == NULL) |
175 | return true; | 176 | return true; |
176 | 177 | ||
177 | return false; | 178 | return false; |
@@ -186,7 +187,7 @@ static bool amd_sched_entity_is_idle(struct amd_sched_entity *entity) | |||
186 | */ | 187 | */ |
187 | static bool amd_sched_entity_is_ready(struct amd_sched_entity *entity) | 188 | static bool amd_sched_entity_is_ready(struct amd_sched_entity *entity) |
188 | { | 189 | { |
189 | if (kfifo_is_empty(&entity->job_queue)) | 190 | if (spsc_queue_peek(&entity->job_queue) == NULL) |
190 | return false; | 191 | return false; |
191 | 192 | ||
192 | if (READ_ONCE(entity->dependency)) | 193 | if (READ_ONCE(entity->dependency)) |
@@ -228,7 +229,7 @@ void amd_sched_entity_fini(struct amd_gpu_scheduler *sched, | |||
228 | */ | 229 | */ |
229 | kthread_park(sched->thread); | 230 | kthread_park(sched->thread); |
230 | kthread_unpark(sched->thread); | 231 | kthread_unpark(sched->thread); |
231 | while (kfifo_out(&entity->job_queue, &job, sizeof(job))) { | 232 | while ((job = to_amd_sched_job(spsc_queue_pop(&entity->job_queue)))) { |
232 | struct amd_sched_fence *s_fence = job->s_fence; | 233 | struct amd_sched_fence *s_fence = job->s_fence; |
233 | amd_sched_fence_scheduled(s_fence); | 234 | amd_sched_fence_scheduled(s_fence); |
234 | dma_fence_set_error(&s_fence->finished, -ESRCH); | 235 | dma_fence_set_error(&s_fence->finished, -ESRCH); |
@@ -236,9 +237,7 @@ void amd_sched_entity_fini(struct amd_gpu_scheduler *sched, | |||
236 | dma_fence_put(&s_fence->finished); | 237 | dma_fence_put(&s_fence->finished); |
237 | sched->ops->free_job(job); | 238 | sched->ops->free_job(job); |
238 | } | 239 | } |
239 | |||
240 | } | 240 | } |
241 | kfifo_free(&entity->job_queue); | ||
242 | } | 241 | } |
243 | 242 | ||
244 | static void amd_sched_entity_wakeup(struct dma_fence *f, struct dma_fence_cb *cb) | 243 | static void amd_sched_entity_wakeup(struct dma_fence *f, struct dma_fence_cb *cb) |
@@ -333,40 +332,41 @@ static bool amd_sched_entity_add_dependency_cb(struct amd_sched_entity *entity) | |||
333 | } | 332 | } |
334 | 333 | ||
335 | static struct amd_sched_job * | 334 | static struct amd_sched_job * |
336 | amd_sched_entity_peek_job(struct amd_sched_entity *entity) | 335 | amd_sched_entity_pop_job(struct amd_sched_entity *entity) |
337 | { | 336 | { |
338 | struct amd_gpu_scheduler *sched = entity->sched; | 337 | struct amd_gpu_scheduler *sched = entity->sched; |
339 | struct amd_sched_job *sched_job; | 338 | struct amd_sched_job *sched_job = to_amd_sched_job( |
339 | spsc_queue_peek(&entity->job_queue)); | ||
340 | 340 | ||
341 | if (!kfifo_out_peek(&entity->job_queue, &sched_job, sizeof(sched_job))) | 341 | if (!sched_job) |
342 | return NULL; | 342 | return NULL; |
343 | 343 | ||
344 | while ((entity->dependency = sched->ops->dependency(sched_job))) | 344 | while ((entity->dependency = sched->ops->dependency(sched_job))) |
345 | if (amd_sched_entity_add_dependency_cb(entity)) | 345 | if (amd_sched_entity_add_dependency_cb(entity)) |
346 | return NULL; | 346 | return NULL; |
347 | 347 | ||
348 | sched_job->s_entity = NULL; | ||
349 | spsc_queue_pop(&entity->job_queue); | ||
348 | return sched_job; | 350 | return sched_job; |
349 | } | 351 | } |
350 | 352 | ||
351 | /** | 353 | /** |
352 | * Helper to submit a job to the job queue | 354 | * Submit a job to the job queue |
353 | * | 355 | * |
354 | * @sched_job The pointer to job required to submit | 356 | * @sched_job The pointer to job required to submit |
355 | * | 357 | * |
356 | * Returns true if we could submit the job. | 358 | * Returns 0 for success, negative error code otherwise. |
357 | */ | 359 | */ |
358 | static bool amd_sched_entity_in(struct amd_sched_job *sched_job) | 360 | void amd_sched_entity_push_job(struct amd_sched_job *sched_job) |
359 | { | 361 | { |
360 | struct amd_gpu_scheduler *sched = sched_job->sched; | 362 | struct amd_gpu_scheduler *sched = sched_job->sched; |
361 | struct amd_sched_entity *entity = sched_job->s_entity; | 363 | struct amd_sched_entity *entity = sched_job->s_entity; |
362 | bool added, first = false; | 364 | bool first = false; |
363 | 365 | ||
364 | spin_lock(&entity->queue_lock); | 366 | trace_amd_sched_job(sched_job); |
365 | added = kfifo_in(&entity->job_queue, &sched_job, | ||
366 | sizeof(sched_job)) == sizeof(sched_job); | ||
367 | 367 | ||
368 | if (added && kfifo_len(&entity->job_queue) == sizeof(sched_job)) | 368 | spin_lock(&entity->queue_lock); |
369 | first = true; | 369 | first = spsc_queue_push(&entity->job_queue, &sched_job->queue_node); |
370 | 370 | ||
371 | spin_unlock(&entity->queue_lock); | 371 | spin_unlock(&entity->queue_lock); |
372 | 372 | ||
@@ -378,7 +378,6 @@ static bool amd_sched_entity_in(struct amd_sched_job *sched_job) | |||
378 | spin_unlock(&entity->rq_lock); | 378 | spin_unlock(&entity->rq_lock); |
379 | amd_sched_wakeup(sched); | 379 | amd_sched_wakeup(sched); |
380 | } | 380 | } |
381 | return added; | ||
382 | } | 381 | } |
383 | 382 | ||
384 | /* job_finish is called after hw fence signaled | 383 | /* job_finish is called after hw fence signaled |
@@ -535,22 +534,6 @@ void amd_sched_job_recovery(struct amd_gpu_scheduler *sched) | |||
535 | spin_unlock(&sched->job_list_lock); | 534 | spin_unlock(&sched->job_list_lock); |
536 | } | 535 | } |
537 | 536 | ||
538 | /** | ||
539 | * Submit a job to the job queue | ||
540 | * | ||
541 | * @sched_job The pointer to job required to submit | ||
542 | * | ||
543 | * Returns 0 for success, negative error code otherwise. | ||
544 | */ | ||
545 | void amd_sched_entity_push_job(struct amd_sched_job *sched_job) | ||
546 | { | ||
547 | struct amd_sched_entity *entity = sched_job->s_entity; | ||
548 | |||
549 | trace_amd_sched_job(sched_job); | ||
550 | wait_event(entity->sched->job_scheduled, | ||
551 | amd_sched_entity_in(sched_job)); | ||
552 | } | ||
553 | |||
554 | /* init a sched_job with basic field */ | 537 | /* init a sched_job with basic field */ |
555 | int amd_sched_job_init(struct amd_sched_job *job, | 538 | int amd_sched_job_init(struct amd_sched_job *job, |
556 | struct amd_gpu_scheduler *sched, | 539 | struct amd_gpu_scheduler *sched, |
@@ -641,7 +624,7 @@ static int amd_sched_main(void *param) | |||
641 | { | 624 | { |
642 | struct sched_param sparam = {.sched_priority = 1}; | 625 | struct sched_param sparam = {.sched_priority = 1}; |
643 | struct amd_gpu_scheduler *sched = (struct amd_gpu_scheduler *)param; | 626 | struct amd_gpu_scheduler *sched = (struct amd_gpu_scheduler *)param; |
644 | int r, count; | 627 | int r; |
645 | 628 | ||
646 | sched_setscheduler(current, SCHED_FIFO, &sparam); | 629 | sched_setscheduler(current, SCHED_FIFO, &sparam); |
647 | 630 | ||
@@ -659,7 +642,7 @@ static int amd_sched_main(void *param) | |||
659 | if (!entity) | 642 | if (!entity) |
660 | continue; | 643 | continue; |
661 | 644 | ||
662 | sched_job = amd_sched_entity_peek_job(entity); | 645 | sched_job = amd_sched_entity_pop_job(entity); |
663 | if (!sched_job) | 646 | if (!sched_job) |
664 | continue; | 647 | continue; |
665 | 648 | ||
@@ -686,9 +669,6 @@ static int amd_sched_main(void *param) | |||
686 | amd_sched_process_job(NULL, &s_fence->cb); | 669 | amd_sched_process_job(NULL, &s_fence->cb); |
687 | } | 670 | } |
688 | 671 | ||
689 | count = kfifo_out(&entity->job_queue, &sched_job, | ||
690 | sizeof(sched_job)); | ||
691 | WARN_ON(count != sizeof(sched_job)); | ||
692 | wake_up(&sched->job_scheduled); | 672 | wake_up(&sched->job_scheduled); |
693 | } | 673 | } |
694 | return 0; | 674 | return 0; |
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h index be75172587da..f9e3a83cddc6 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #include <linux/kfifo.h> | 27 | #include <linux/kfifo.h> |
28 | #include <linux/dma-fence.h> | 28 | #include <linux/dma-fence.h> |
29 | #include "spsc_queue.h" | ||
29 | 30 | ||
30 | struct amd_gpu_scheduler; | 31 | struct amd_gpu_scheduler; |
31 | struct amd_sched_rq; | 32 | struct amd_sched_rq; |
@@ -56,7 +57,7 @@ struct amd_sched_entity { | |||
56 | struct amd_gpu_scheduler *sched; | 57 | struct amd_gpu_scheduler *sched; |
57 | 58 | ||
58 | spinlock_t queue_lock; | 59 | spinlock_t queue_lock; |
59 | struct kfifo job_queue; | 60 | struct spsc_queue job_queue; |
60 | 61 | ||
61 | atomic_t fence_seq; | 62 | atomic_t fence_seq; |
62 | uint64_t fence_context; | 63 | uint64_t fence_context; |
@@ -88,6 +89,7 @@ struct amd_sched_fence { | |||
88 | }; | 89 | }; |
89 | 90 | ||
90 | struct amd_sched_job { | 91 | struct amd_sched_job { |
92 | struct spsc_node queue_node; | ||
91 | struct amd_gpu_scheduler *sched; | 93 | struct amd_gpu_scheduler *sched; |
92 | struct amd_sched_entity *s_entity; | 94 | struct amd_sched_entity *s_entity; |
93 | struct amd_sched_fence *s_fence; | 95 | struct amd_sched_fence *s_fence; |