aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0507-drm-amdgpu-let-the-scheduler-work-more-with-jobs-v2.patch
blob: 6cb65898653d0c7827dd1d5f01f727174238750f (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
From 69bd5bf13a8eccb4db5f26de608556416a56d973 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
Date: Wed, 26 Aug 2015 11:31:23 +0200
Subject: [PATCH 0507/1050] drm/amdgpu: let the scheduler work more with jobs
 v2
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

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>
---
 drivers/gpu/drm/amd/scheduler/gpu_scheduler.c | 61 ++++++++++++++++-----------
 1 file 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 d99fe90..205cb88 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
@@ -27,6 +27,8 @@
 #include <drm/drmP.h>
 #include "gpu_scheduler.h"
 
+static struct amd_sched_job *
+amd_sched_entity_pop_job(struct amd_sched_entity *entity);
 static void amd_sched_wakeup(struct amd_gpu_scheduler *sched);
 
 /* Initialize a given run queue struct */
@@ -56,34 +58,36 @@ static void amd_sched_rq_remove_entity(struct amd_sched_rq *rq,
 }
 
 /**
- * Select next entity from a specified run queue with round robin policy.
- * It could return the same entity as current one if current is the only
- * available one in the queue. Return NULL if nothing available.
+ * Select next job from a specified run queue with round robin policy.
+ * Return NULL if nothing available.
  */
-static struct amd_sched_entity *
-amd_sched_rq_select_entity(struct amd_sched_rq *rq)
+static struct amd_sched_job *
+amd_sched_rq_select_job(struct amd_sched_rq *rq)
 {
 	struct amd_sched_entity *entity;
+	struct amd_sched_job *job;
 
 	spin_lock(&rq->lock);
 
 	entity = rq->current_entity;
 	if (entity) {
 		list_for_each_entry_continue(entity, &rq->entities, list) {
-			if (!kfifo_is_empty(&entity->job_queue)) {
+			job = amd_sched_entity_pop_job(entity);
+			if (job) {
 				rq->current_entity = entity;
 				spin_unlock(&rq->lock);
-				return rq->current_entity;
+				return job;
 			}
 		}
 	}
 
 	list_for_each_entry(entity, &rq->entities, list) {
 
-		if (!kfifo_is_empty(&entity->job_queue)) {
+		job = amd_sched_entity_pop_job(entity);
+		if (job) {
 			rq->current_entity = entity;
 			spin_unlock(&rq->lock);
-			return rq->current_entity;
+			return job;
 		}
 
 		if (entity == rq->current_entity)
@@ -188,6 +192,17 @@ void amd_sched_entity_fini(struct amd_gpu_scheduler *sched,
 	kfifo_free(&entity->job_queue);
 }
 
+static struct amd_sched_job *
+amd_sched_entity_pop_job(struct amd_sched_entity *entity)
+{
+	struct amd_sched_job *job;
+
+	if (!kfifo_out_peek(&entity->job_queue, &job, sizeof(job)))
+		return NULL;
+
+	return job;
+}
+
 /**
  * Helper to submit a job to the job queue
  *
@@ -260,22 +275,22 @@ static void amd_sched_wakeup(struct amd_gpu_scheduler *sched)
 }
 
 /**
- * Select next entity containing real IB submissions
+ * Select next to run
 */
-static struct amd_sched_entity *
-amd_sched_select_context(struct amd_gpu_scheduler *sched)
+static struct amd_sched_job *
+amd_sched_select_job(struct amd_gpu_scheduler *sched)
 {
-	struct amd_sched_entity *tmp;
+	struct amd_sched_job *job;
 
 	if (!amd_sched_ready(sched))
 		return NULL;
 
 	/* Kernel run queue has higher priority than normal run queue*/
-	tmp = amd_sched_rq_select_entity(&sched->kernel_rq);
-	if (tmp == NULL)
-		tmp = amd_sched_rq_select_entity(&sched->sched_rq);
+	job = amd_sched_rq_select_job(&sched->kernel_rq);
+	if (job == NULL)
+		job = amd_sched_rq_select_job(&sched->sched_rq);
 
-	return tmp;
+	return job;
 }
 
 static void amd_sched_process_job(struct fence *f, struct fence_cb *cb)
@@ -301,22 +316,19 @@ static int amd_sched_main(void *param)
 	sched_setscheduler(current, SCHED_FIFO, &sparam);
 
 	while (!kthread_should_stop()) {
-		struct amd_sched_entity *c_entity = NULL;
+		struct amd_sched_entity *entity;
 		struct amd_sched_job *job;
 		struct fence *fence;
 
 		wait_event_interruptible(sched->wake_up_worker,
 			kthread_should_stop() ||
-			(c_entity = amd_sched_select_context(sched)));
+			(job = amd_sched_select_job(sched)));
 
-		if (!c_entity)
+		if (!job)
 			continue;
 
-		r = kfifo_out(&c_entity->job_queue, &job, sizeof(void *));
-		if (r != sizeof(void *))
-			continue;
+		entity = job->s_entity;
 		atomic_inc(&sched->hw_rq_count);
-
 		fence = sched->ops->run_job(job);
 		if (fence) {
 			r = fence_add_callback(fence, &job->cb,
@@ -328,6 +340,7 @@ static int amd_sched_main(void *param)
 			fence_put(fence);
 		}
 
+		kfifo_out(&entity->job_queue, &job, sizeof(job));
 		wake_up(&sched->job_scheduled);
 	}
 	return 0;
-- 
1.9.1