aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0464-drm-amdgpu-cleanup-sheduler-rq-handling-v2.patch
blob: aac74c54c8180127815156814927ffbac2c5d6ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
From 432a4ff8b7224908a8bbc34b598f48af3f42b827 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
Date: Wed, 12 Aug 2015 11:46:04 +0200
Subject: [PATCH 0464/1050] drm/amdgpu: cleanup sheduler rq handling v2
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

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>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c       |   2 +-
 drivers/gpu/drm/amd/scheduler/gpu_scheduler.c | 103 +++++++++++---------------
 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 1833f05..08bc772 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,
 	if (amdgpu_enable_scheduler) {
 		/* create context entity for each ring */
 		for (i = 0; i < adev->num_rings; i++) {
-			struct amd_run_queue *rq;
+			struct amd_sched_rq *rq;
 			if (kernel)
 				rq = &adev->rings[i]->scheduler->kernel_rq;
 			else
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
index 3d45ff2..265d3e2 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
@@ -28,31 +28,29 @@
 #include "gpu_scheduler.h"
 
 /* Initialize a given run queue struct */
-static void init_rq(struct amd_run_queue *rq)
+static void amd_sched_rq_init(struct amd_sched_rq *rq)
 {
-	INIT_LIST_HEAD(&rq->head.list);
-	rq->head.belongto_rq = rq;
+	INIT_LIST_HEAD(&rq->entities);
 	mutex_init(&rq->lock);
-	atomic_set(&rq->nr_entity, 0);
-	rq->current_entity = &rq->head;
+	rq->current_entity = NULL;
 }
 
-/* Note: caller must hold the lock or in a atomic context */
-static void rq_remove_entity(struct amd_run_queue *rq,
-			     struct amd_sched_entity *entity)
+static void amd_sched_rq_add_entity(struct amd_sched_rq *rq,
+				    struct amd_sched_entity *entity)
 {
-	if (rq->current_entity == entity)
-		rq->current_entity = list_entry(entity->list.prev,
-						typeof(*entity), list);
-	list_del_init(&entity->list);
-	atomic_dec(&rq->nr_entity);
+	mutex_lock(&rq->lock);
+	list_add_tail(&entity->list, &rq->entities);
+	mutex_unlock(&rq->lock);
 }
 
-static void rq_add_entity(struct amd_run_queue *rq,
-			  struct amd_sched_entity *entity)
+static void amd_sched_rq_remove_entity(struct amd_sched_rq *rq,
+				       struct amd_sched_entity *entity)
 {
-	list_add_tail(&entity->list, &rq->head.list);
-	atomic_inc(&rq->nr_entity);
+	mutex_lock(&rq->lock);
+	list_del_init(&entity->list);
+	if (rq->current_entity == entity)
+		rq->current_entity = NULL;
+	mutex_unlock(&rq->lock);
 }
 
 /**
@@ -60,38 +58,32 @@ static void rq_add_entity(struct amd_run_queue *rq,
  * It could return the same entity as current one if current is the only
  * available one in the queue. Return NULL if nothing available.
  */
-static struct amd_sched_entity *rq_select_entity(struct amd_run_queue *rq)
+static struct amd_sched_entity *
+amd_sched_rq_select_entity(struct amd_sched_rq *rq)
 {
-	struct amd_sched_entity *p = rq->current_entity;
-	int i = atomic_read(&rq->nr_entity) + 1; /*real count + dummy head*/
-
-	while (i) {
-		p = list_entry(p->list.next, typeof(*p), list);
-		if (!rq->check_entity_status(p)) {
-			rq->current_entity = p;
-			break;
+	struct amd_sched_entity *entity = rq->current_entity;
+
+	if (entity) {
+		list_for_each_entry_continue(entity, &rq->entities, list) {
+			if (!kfifo_is_empty(&entity->job_queue)) {
+				rq->current_entity = entity;
+				return rq->current_entity;
+			}
 		}
-		i--;
 	}
-	return i ? p : NULL;
-}
 
-static bool context_entity_is_waiting(struct amd_sched_entity *entity)
-{
-	/* TODO: sync obj for multi-ring synchronization */
-	return false;
-}
+	list_for_each_entry(entity, &rq->entities, list) {
 
-static int gpu_entity_check_status(struct amd_sched_entity *entity)
-{
-	if (entity == &entity->belongto_rq->head)
-		return -1;
+		if (!kfifo_is_empty(&entity->job_queue)) {
+			rq->current_entity = entity;
+			return rq->current_entity;
+		}
 
-	if (kfifo_is_empty(&entity->job_queue) ||
-	    context_entity_is_waiting(entity))
-		return -1;
+		if (entity == rq->current_entity)
+			break;
+	}
 
-	return 0;
+	return NULL;
 }
 
 /**
@@ -124,10 +116,10 @@ static struct amd_sched_entity *
 kernel_rq_select_context(struct amd_gpu_scheduler *sched)
 {
 	struct amd_sched_entity *sched_entity;
-	struct amd_run_queue *rq = &sched->kernel_rq;
+	struct amd_sched_rq *rq = &sched->kernel_rq;
 
 	mutex_lock(&rq->lock);
-	sched_entity = rq_select_entity(rq);
+	sched_entity = amd_sched_rq_select_entity(rq);
 	mutex_unlock(&rq->lock);
 	return sched_entity;
 }
@@ -140,7 +132,7 @@ select_context(struct amd_gpu_scheduler *sched)
 {
 	struct amd_sched_entity *wake_entity = NULL;
 	struct amd_sched_entity *tmp;
-	struct amd_run_queue *rq;
+	struct amd_sched_rq *rq;
 
 	if (!is_scheduler_ready(sched))
 		return NULL;
@@ -152,7 +144,7 @@ select_context(struct amd_gpu_scheduler *sched)
 
 	rq = &sched->sched_rq;
 	mutex_lock(&rq->lock);
-	tmp = rq_select_entity(rq);
+	tmp = amd_sched_rq_select_entity(rq);
 	mutex_unlock(&rq->lock);
 exit:
 	if (sched->current_entity && (sched->current_entity != tmp))
@@ -176,7 +168,7 @@ exit:
 */
 int amd_sched_entity_init(struct amd_gpu_scheduler *sched,
 			  struct amd_sched_entity *entity,
-			  struct amd_run_queue *rq,
+			  struct amd_sched_rq *rq,
 			  uint32_t jobs)
 {
 	uint64_t seq_ring = 0;
@@ -206,9 +198,7 @@ int amd_sched_entity_init(struct amd_gpu_scheduler *sched,
 	atomic64_set(&entity->last_signaled_v_seq, seq_ring);
 
 	/* Add the entity to the run queue */
-	mutex_lock(&rq->lock);
-	rq_add_entity(rq, entity);
-	mutex_unlock(&rq->lock);
+	amd_sched_rq_add_entity(rq, entity);
 	return 0;
 }
 
@@ -254,7 +244,7 @@ int amd_sched_entity_fini(struct amd_gpu_scheduler *sched,
 			    struct amd_sched_entity *entity)
 {
 	int r = 0;
-	struct amd_run_queue *rq = entity->belongto_rq;
+	struct amd_sched_rq *rq = entity->belongto_rq;
 
 	if (!is_context_entity_initialized(sched, entity))
 		return 0;
@@ -276,9 +266,7 @@ int amd_sched_entity_fini(struct amd_gpu_scheduler *sched,
 				 entity);
 	}
 
-	mutex_lock(&rq->lock);
-	rq_remove_entity(rq, entity);
-	mutex_unlock(&rq->lock);
+	amd_sched_rq_remove_entity(rq, entity);
 	kfifo_free(&entity->job_queue);
 	return r;
 }
@@ -429,11 +417,8 @@ struct amd_gpu_scheduler *amd_sched_create(void *device,
 	snprintf(name, sizeof(name), "gpu_sched[%d]", ring);
 	mutex_init(&sched->sched_lock);
 	spin_lock_init(&sched->queue_lock);
-	init_rq(&sched->sched_rq);
-	sched->sched_rq.check_entity_status = gpu_entity_check_status;
-
-	init_rq(&sched->kernel_rq);
-	sched->kernel_rq.check_entity_status = gpu_entity_check_status;
+	amd_sched_rq_init(&sched->sched_rq);
+	amd_sched_rq_init(&sched->kernel_rq);
 
 	init_waitqueue_head(&sched->wait_queue);
 	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 47823b4..ceb5918 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
@@ -30,7 +30,7 @@
 #define AMD_GPU_WAIT_IDLE_TIMEOUT_IN_MS		3000
 
 struct amd_gpu_scheduler;
-struct amd_run_queue;
+struct amd_sched_rq;
 
 /**
  * A scheduler entity is a wrapper around a job queue or a group
@@ -40,7 +40,7 @@ struct amd_run_queue;
 */
 struct amd_sched_entity {
 	struct list_head		list;
-	struct amd_run_queue		*belongto_rq;
+	struct amd_sched_rq		*belongto_rq;
 	spinlock_t			lock;
 	/* the virtual_seq is unique per context per ring */
 	atomic64_t			last_queued_v_seq;
@@ -62,17 +62,10 @@ struct amd_sched_entity {
  * one specific ring. It implements the scheduling policy that selects
  * the next entity to emit commands from.
 */
-struct amd_run_queue {
-	struct mutex			lock;
-	atomic_t			nr_entity;
-	struct amd_sched_entity	        head;
-	struct amd_sched_entity	        *current_entity;
-	/**
-	 * Return 0 means this entity can be scheduled
-	 * Return -1 means this entity cannot be scheduled for reasons,
-	 * i.e, it is the head, or these is no job, etc
-	*/
-	int (*check_entity_status)(struct amd_sched_entity *entity);
+struct amd_sched_rq {
+	struct mutex		lock;
+	struct list_head	entities;
+	struct amd_sched_entity	*current_entity;
 };
 
 struct amd_sched_fence {
@@ -124,8 +117,8 @@ struct amd_sched_backend_ops {
 struct amd_gpu_scheduler {
 	void			        *device;
 	struct task_struct		*thread;
-	struct amd_run_queue		sched_rq;
-	struct amd_run_queue		kernel_rq;
+	struct amd_sched_rq		sched_rq;
+	struct amd_sched_rq		kernel_rq;
 	struct list_head		active_hw_rq;
 	atomic64_t			hw_rq_count;
 	struct amd_sched_backend_ops	*ops;
@@ -154,7 +147,7 @@ int amd_sched_push_job(struct amd_gpu_scheduler *sched,
 
 int amd_sched_entity_init(struct amd_gpu_scheduler *sched,
 			  struct amd_sched_entity *entity,
-			  struct amd_run_queue *rq,
+			  struct amd_sched_rq *rq,
 			  uint32_t jobs);
 int amd_sched_entity_fini(struct amd_gpu_scheduler *sched,
 			  struct amd_sched_entity *entity);
-- 
1.9.1