aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2015-08-12 05:46:04 -0400
committerAlex Deucher <alexander.deucher@amd.com>2015-08-17 16:51:22 -0400
commit432a4ff8b7224908a8bbc34b598f48af3f42b827 (patch)
tree06753b59a3710a465f6a1a8b6562dec2ff62cdb7
parentc3b95d4f9e460704e184ded7af60b9c4898f6181 (diff)
drm/amdgpu: cleanup sheduler rq handling v2
Rework run queue implementation, especially remove the odd list handling. v2: cleanup the code only, no algorithem change. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Chunming Zhou <david1.zhou@amd.com>
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c2
-rw-r--r--drivers/gpu/drm/amd/scheduler/gpu_scheduler.c103
-rw-r--r--drivers/gpu/drm/amd/scheduler/gpu_scheduler.h25
3 files changed, 54 insertions, 76 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
index 1833f05c7e0b..08bc7722ddb8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
@@ -41,7 +41,7 @@ int amdgpu_ctx_init(struct amdgpu_device *adev, bool kernel,
41 if (amdgpu_enable_scheduler) { 41 if (amdgpu_enable_scheduler) {
42 /* create context entity for each ring */ 42 /* create context entity for each ring */
43 for (i = 0; i < adev->num_rings; i++) { 43 for (i = 0; i < adev->num_rings; i++) {
44 struct amd_run_queue *rq; 44 struct amd_sched_rq *rq;
45 if (kernel) 45 if (kernel)
46 rq = &adev->rings[i]->scheduler->kernel_rq; 46 rq = &adev->rings[i]->scheduler->kernel_rq;
47 else 47 else
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
index 3d45ff29eaa8..265d3e2f63cc 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
@@ -28,31 +28,29 @@
28#include "gpu_scheduler.h" 28#include "gpu_scheduler.h"
29 29
30/* Initialize a given run queue struct */ 30/* Initialize a given run queue struct */
31static void init_rq(struct amd_run_queue *rq) 31static void amd_sched_rq_init(struct amd_sched_rq *rq)
32{ 32{
33 INIT_LIST_HEAD(&rq->head.list); 33 INIT_LIST_HEAD(&rq->entities);
34 rq->head.belongto_rq = rq;
35 mutex_init(&rq->lock); 34 mutex_init(&rq->lock);
36 atomic_set(&rq->nr_entity, 0); 35 rq->current_entity = NULL;
37 rq->current_entity = &rq->head;
38} 36}
39 37
40/* Note: caller must hold the lock or in a atomic context */ 38static void amd_sched_rq_add_entity(struct amd_sched_rq *rq,
41static void rq_remove_entity(struct amd_run_queue *rq, 39 struct amd_sched_entity *entity)
42 struct amd_sched_entity *entity)
43{ 40{
44 if (rq->current_entity == entity) 41 mutex_lock(&rq->lock);
45 rq->current_entity = list_entry(entity->list.prev, 42 list_add_tail(&entity->list, &rq->entities);
46 typeof(*entity), list); 43 mutex_unlock(&rq->lock);
47 list_del_init(&entity->list);
48 atomic_dec(&rq->nr_entity);
49} 44}
50 45
51static void rq_add_entity(struct amd_run_queue *rq, 46static void amd_sched_rq_remove_entity(struct amd_sched_rq *rq,
52 struct amd_sched_entity *entity) 47 struct amd_sched_entity *entity)
53{ 48{
54 list_add_tail(&entity->list, &rq->head.list); 49 mutex_lock(&rq->lock);
55 atomic_inc(&rq->nr_entity); 50 list_del_init(&entity->list);
51 if (rq->current_entity == entity)
52 rq->current_entity = NULL;
53 mutex_unlock(&rq->lock);
56} 54}
57 55
58/** 56/**
@@ -60,38 +58,32 @@ static void rq_add_entity(struct amd_run_queue *rq,
60 * It could return the same entity as current one if current is the only 58 * It could return the same entity as current one if current is the only
61 * available one in the queue. Return NULL if nothing available. 59 * available one in the queue. Return NULL if nothing available.
62 */ 60 */
63static struct amd_sched_entity *rq_select_entity(struct amd_run_queue *rq) 61static struct amd_sched_entity *
62amd_sched_rq_select_entity(struct amd_sched_rq *rq)
64{ 63{
65 struct amd_sched_entity *p = rq->current_entity; 64 struct amd_sched_entity *entity = rq->current_entity;
66 int i = atomic_read(&rq->nr_entity) + 1; /*real count + dummy head*/ 65
67 66 if (entity) {
68 while (i) { 67 list_for_each_entry_continue(entity, &rq->entities, list) {
69 p = list_entry(p->list.next, typeof(*p), list); 68 if (!kfifo_is_empty(&entity->job_queue)) {
70 if (!rq->check_entity_status(p)) { 69 rq->current_entity = entity;
71 rq->current_entity = p; 70 return rq->current_entity;
72 break; 71 }
73 } 72 }
74 i--;
75 } 73 }
76 return i ? p : NULL;
77}
78 74
79static bool context_entity_is_waiting(struct amd_sched_entity *entity) 75 list_for_each_entry(entity, &rq->entities, list) {
80{
81 /* TODO: sync obj for multi-ring synchronization */
82 return false;
83}
84 76
85static int gpu_entity_check_status(struct amd_sched_entity *entity) 77 if (!kfifo_is_empty(&entity->job_queue)) {
86{ 78 rq->current_entity = entity;
87 if (entity == &entity->belongto_rq->head) 79 return rq->current_entity;
88 return -1; 80 }
89 81
90 if (kfifo_is_empty(&entity->job_queue) || 82 if (entity == rq->current_entity)
91 context_entity_is_waiting(entity)) 83 break;
92 return -1; 84 }
93 85
94 return 0; 86 return NULL;
95} 87}
96 88
97/** 89/**
@@ -124,10 +116,10 @@ static struct amd_sched_entity *
124kernel_rq_select_context(struct amd_gpu_scheduler *sched) 116kernel_rq_select_context(struct amd_gpu_scheduler *sched)
125{ 117{
126 struct amd_sched_entity *sched_entity; 118 struct amd_sched_entity *sched_entity;
127 struct amd_run_queue *rq = &sched->kernel_rq; 119 struct amd_sched_rq *rq = &sched->kernel_rq;
128 120
129 mutex_lock(&rq->lock); 121 mutex_lock(&rq->lock);
130 sched_entity = rq_select_entity(rq); 122 sched_entity = amd_sched_rq_select_entity(rq);
131 mutex_unlock(&rq->lock); 123 mutex_unlock(&rq->lock);
132 return sched_entity; 124 return sched_entity;
133} 125}
@@ -140,7 +132,7 @@ select_context(struct amd_gpu_scheduler *sched)
140{ 132{
141 struct amd_sched_entity *wake_entity = NULL; 133 struct amd_sched_entity *wake_entity = NULL;
142 struct amd_sched_entity *tmp; 134 struct amd_sched_entity *tmp;
143 struct amd_run_queue *rq; 135 struct amd_sched_rq *rq;
144 136
145 if (!is_scheduler_ready(sched)) 137 if (!is_scheduler_ready(sched))
146 return NULL; 138 return NULL;
@@ -152,7 +144,7 @@ select_context(struct amd_gpu_scheduler *sched)
152 144
153 rq = &sched->sched_rq; 145 rq = &sched->sched_rq;
154 mutex_lock(&rq->lock); 146 mutex_lock(&rq->lock);
155 tmp = rq_select_entity(rq); 147 tmp = amd_sched_rq_select_entity(rq);
156 mutex_unlock(&rq->lock); 148 mutex_unlock(&rq->lock);
157exit: 149exit:
158 if (sched->current_entity && (sched->current_entity != tmp)) 150 if (sched->current_entity && (sched->current_entity != tmp))
@@ -176,7 +168,7 @@ exit:
176*/ 168*/
177int amd_sched_entity_init(struct amd_gpu_scheduler *sched, 169int amd_sched_entity_init(struct amd_gpu_scheduler *sched,
178 struct amd_sched_entity *entity, 170 struct amd_sched_entity *entity,
179 struct amd_run_queue *rq, 171 struct amd_sched_rq *rq,
180 uint32_t jobs) 172 uint32_t jobs)
181{ 173{
182 uint64_t seq_ring = 0; 174 uint64_t seq_ring = 0;
@@ -206,9 +198,7 @@ int amd_sched_entity_init(struct amd_gpu_scheduler *sched,
206 atomic64_set(&entity->last_signaled_v_seq, seq_ring); 198 atomic64_set(&entity->last_signaled_v_seq, seq_ring);
207 199
208 /* Add the entity to the run queue */ 200 /* Add the entity to the run queue */
209 mutex_lock(&rq->lock); 201 amd_sched_rq_add_entity(rq, entity);
210 rq_add_entity(rq, entity);
211 mutex_unlock(&rq->lock);
212 return 0; 202 return 0;
213} 203}
214 204
@@ -254,7 +244,7 @@ int amd_sched_entity_fini(struct amd_gpu_scheduler *sched,
254 struct amd_sched_entity *entity) 244 struct amd_sched_entity *entity)
255{ 245{
256 int r = 0; 246 int r = 0;
257 struct amd_run_queue *rq = entity->belongto_rq; 247 struct amd_sched_rq *rq = entity->belongto_rq;
258 248
259 if (!is_context_entity_initialized(sched, entity)) 249 if (!is_context_entity_initialized(sched, entity))
260 return 0; 250 return 0;
@@ -276,9 +266,7 @@ int amd_sched_entity_fini(struct amd_gpu_scheduler *sched,
276 entity); 266 entity);
277 } 267 }
278 268
279 mutex_lock(&rq->lock); 269 amd_sched_rq_remove_entity(rq, entity);
280 rq_remove_entity(rq, entity);
281 mutex_unlock(&rq->lock);
282 kfifo_free(&entity->job_queue); 270 kfifo_free(&entity->job_queue);
283 return r; 271 return r;
284} 272}
@@ -429,11 +417,8 @@ struct amd_gpu_scheduler *amd_sched_create(void *device,
429 snprintf(name, sizeof(name), "gpu_sched[%d]", ring); 417 snprintf(name, sizeof(name), "gpu_sched[%d]", ring);
430 mutex_init(&sched->sched_lock); 418 mutex_init(&sched->sched_lock);
431 spin_lock_init(&sched->queue_lock); 419 spin_lock_init(&sched->queue_lock);
432 init_rq(&sched->sched_rq); 420 amd_sched_rq_init(&sched->sched_rq);
433 sched->sched_rq.check_entity_status = gpu_entity_check_status; 421 amd_sched_rq_init(&sched->kernel_rq);
434
435 init_rq(&sched->kernel_rq);
436 sched->kernel_rq.check_entity_status = gpu_entity_check_status;
437 422
438 init_waitqueue_head(&sched->wait_queue); 423 init_waitqueue_head(&sched->wait_queue);
439 INIT_LIST_HEAD(&sched->active_hw_rq); 424 INIT_LIST_HEAD(&sched->active_hw_rq);
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
index 47823b4a71e0..ceb5918bfbeb 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
@@ -30,7 +30,7 @@
30#define AMD_GPU_WAIT_IDLE_TIMEOUT_IN_MS 3000 30#define AMD_GPU_WAIT_IDLE_TIMEOUT_IN_MS 3000
31 31
32struct amd_gpu_scheduler; 32struct amd_gpu_scheduler;
33struct amd_run_queue; 33struct amd_sched_rq;
34 34
35/** 35/**
36 * A scheduler entity is a wrapper around a job queue or a group 36 * A scheduler entity is a wrapper around a job queue or a group
@@ -40,7 +40,7 @@ struct amd_run_queue;
40*/ 40*/
41struct amd_sched_entity { 41struct amd_sched_entity {
42 struct list_head list; 42 struct list_head list;
43 struct amd_run_queue *belongto_rq; 43 struct amd_sched_rq *belongto_rq;
44 spinlock_t lock; 44 spinlock_t lock;
45 /* the virtual_seq is unique per context per ring */ 45 /* the virtual_seq is unique per context per ring */
46 atomic64_t last_queued_v_seq; 46 atomic64_t last_queued_v_seq;
@@ -62,17 +62,10 @@ struct amd_sched_entity {
62 * one specific ring. It implements the scheduling policy that selects 62 * one specific ring. It implements the scheduling policy that selects
63 * the next entity to emit commands from. 63 * the next entity to emit commands from.
64*/ 64*/
65struct amd_run_queue { 65struct amd_sched_rq {
66 struct mutex lock; 66 struct mutex lock;
67 atomic_t nr_entity; 67 struct list_head entities;
68 struct amd_sched_entity head; 68 struct amd_sched_entity *current_entity;
69 struct amd_sched_entity *current_entity;
70 /**
71 * Return 0 means this entity can be scheduled
72 * Return -1 means this entity cannot be scheduled for reasons,
73 * i.e, it is the head, or these is no job, etc
74 */
75 int (*check_entity_status)(struct amd_sched_entity *entity);
76}; 69};
77 70
78struct amd_sched_fence { 71struct amd_sched_fence {
@@ -124,8 +117,8 @@ struct amd_sched_backend_ops {
124struct amd_gpu_scheduler { 117struct amd_gpu_scheduler {
125 void *device; 118 void *device;
126 struct task_struct *thread; 119 struct task_struct *thread;
127 struct amd_run_queue sched_rq; 120 struct amd_sched_rq sched_rq;
128 struct amd_run_queue kernel_rq; 121 struct amd_sched_rq kernel_rq;
129 struct list_head active_hw_rq; 122 struct list_head active_hw_rq;
130 atomic64_t hw_rq_count; 123 atomic64_t hw_rq_count;
131 struct amd_sched_backend_ops *ops; 124 struct amd_sched_backend_ops *ops;
@@ -154,7 +147,7 @@ int amd_sched_push_job(struct amd_gpu_scheduler *sched,
154 147
155int amd_sched_entity_init(struct amd_gpu_scheduler *sched, 148int amd_sched_entity_init(struct amd_gpu_scheduler *sched,
156 struct amd_sched_entity *entity, 149 struct amd_sched_entity *entity,
157 struct amd_run_queue *rq, 150 struct amd_sched_rq *rq,
158 uint32_t jobs); 151 uint32_t jobs);
159int amd_sched_entity_fini(struct amd_gpu_scheduler *sched, 152int amd_sched_entity_fini(struct amd_gpu_scheduler *sched,
160 struct amd_sched_entity *entity); 153 struct amd_sched_entity *entity);