diff options
author | Christian König <christian.koenig@amd.com> | 2015-08-12 05:46:04 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2015-08-17 16:51:22 -0400 |
commit | 432a4ff8b7224908a8bbc34b598f48af3f42b827 (patch) | |
tree | 06753b59a3710a465f6a1a8b6562dec2ff62cdb7 | |
parent | c3b95d4f9e460704e184ded7af60b9c4898f6181 (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.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/scheduler/gpu_scheduler.c | 103 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/scheduler/gpu_scheduler.h | 25 |
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 */ |
31 | static void init_rq(struct amd_run_queue *rq) | 31 | static 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 */ | 38 | static void amd_sched_rq_add_entity(struct amd_sched_rq *rq, |
41 | static 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 | ||
51 | static void rq_add_entity(struct amd_run_queue *rq, | 46 | static 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 | */ |
63 | static struct amd_sched_entity *rq_select_entity(struct amd_run_queue *rq) | 61 | static struct amd_sched_entity * |
62 | amd_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 | ||
79 | static 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 | ||
85 | static 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 * | |||
124 | kernel_rq_select_context(struct amd_gpu_scheduler *sched) | 116 | kernel_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); |
157 | exit: | 149 | exit: |
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 | */ |
177 | int amd_sched_entity_init(struct amd_gpu_scheduler *sched, | 169 | int 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 | ||
32 | struct amd_gpu_scheduler; | 32 | struct amd_gpu_scheduler; |
33 | struct amd_run_queue; | 33 | struct 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 | */ |
41 | struct amd_sched_entity { | 41 | struct 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 | */ |
65 | struct amd_run_queue { | 65 | struct 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 | ||
78 | struct amd_sched_fence { | 71 | struct amd_sched_fence { |
@@ -124,8 +117,8 @@ struct amd_sched_backend_ops { | |||
124 | struct amd_gpu_scheduler { | 117 | struct 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 | ||
155 | int amd_sched_entity_init(struct amd_gpu_scheduler *sched, | 148 | int 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); |
159 | int amd_sched_entity_fini(struct amd_gpu_scheduler *sched, | 152 | int amd_sched_entity_fini(struct amd_gpu_scheduler *sched, |
160 | struct amd_sched_entity *entity); | 153 | struct amd_sched_entity *entity); |