aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c104
1 files changed, 97 insertions, 7 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
index 5ce65280b396..a98fbbb4739f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
@@ -136,7 +136,8 @@ void amdgpu_ring_commit(struct amdgpu_ring *ring)
136 if (ring->funcs->end_use) 136 if (ring->funcs->end_use)
137 ring->funcs->end_use(ring); 137 ring->funcs->end_use(ring);
138 138
139 amdgpu_ring_lru_touch(ring->adev, ring); 139 if (ring->funcs->type != AMDGPU_RING_TYPE_KIQ)
140 amdgpu_ring_lru_touch(ring->adev, ring);
140} 141}
141 142
142/** 143/**
@@ -155,6 +156,75 @@ void amdgpu_ring_undo(struct amdgpu_ring *ring)
155} 156}
156 157
157/** 158/**
159 * amdgpu_ring_priority_put - restore a ring's priority
160 *
161 * @ring: amdgpu_ring structure holding the information
162 * @priority: target priority
163 *
164 * Release a request for executing at @priority
165 */
166void amdgpu_ring_priority_put(struct amdgpu_ring *ring,
167 enum amd_sched_priority priority)
168{
169 int i;
170
171 if (!ring->funcs->set_priority)
172 return;
173
174 if (atomic_dec_return(&ring->num_jobs[priority]) > 0)
175 return;
176
177 /* no need to restore if the job is already at the lowest priority */
178 if (priority == AMD_SCHED_PRIORITY_NORMAL)
179 return;
180
181 mutex_lock(&ring->priority_mutex);
182 /* something higher prio is executing, no need to decay */
183 if (ring->priority > priority)
184 goto out_unlock;
185
186 /* decay priority to the next level with a job available */
187 for (i = priority; i >= AMD_SCHED_PRIORITY_MIN; i--) {
188 if (i == AMD_SCHED_PRIORITY_NORMAL
189 || atomic_read(&ring->num_jobs[i])) {
190 ring->priority = i;
191 ring->funcs->set_priority(ring, i);
192 break;
193 }
194 }
195
196out_unlock:
197 mutex_unlock(&ring->priority_mutex);
198}
199
200/**
201 * amdgpu_ring_priority_get - change the ring's priority
202 *
203 * @ring: amdgpu_ring structure holding the information
204 * @priority: target priority
205 *
206 * Request a ring's priority to be raised to @priority (refcounted).
207 */
208void amdgpu_ring_priority_get(struct amdgpu_ring *ring,
209 enum amd_sched_priority priority)
210{
211 if (!ring->funcs->set_priority)
212 return;
213
214 atomic_inc(&ring->num_jobs[priority]);
215
216 mutex_lock(&ring->priority_mutex);
217 if (priority <= ring->priority)
218 goto out_unlock;
219
220 ring->priority = priority;
221 ring->funcs->set_priority(ring, priority);
222
223out_unlock:
224 mutex_unlock(&ring->priority_mutex);
225}
226
227/**
158 * amdgpu_ring_init - init driver ring struct. 228 * amdgpu_ring_init - init driver ring struct.
159 * 229 *
160 * @adev: amdgpu_device pointer 230 * @adev: amdgpu_device pointer
@@ -169,7 +239,7 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
169 unsigned max_dw, struct amdgpu_irq_src *irq_src, 239 unsigned max_dw, struct amdgpu_irq_src *irq_src,
170 unsigned irq_type) 240 unsigned irq_type)
171{ 241{
172 int r; 242 int r, i;
173 int sched_hw_submission = amdgpu_sched_hw_submission; 243 int sched_hw_submission = amdgpu_sched_hw_submission;
174 244
175 /* Set the hw submission limit higher for KIQ because 245 /* Set the hw submission limit higher for KIQ because
@@ -247,9 +317,14 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
247 } 317 }
248 318
249 ring->max_dw = max_dw; 319 ring->max_dw = max_dw;
320 ring->priority = AMD_SCHED_PRIORITY_NORMAL;
321 mutex_init(&ring->priority_mutex);
250 INIT_LIST_HEAD(&ring->lru_list); 322 INIT_LIST_HEAD(&ring->lru_list);
251 amdgpu_ring_lru_touch(adev, ring); 323 amdgpu_ring_lru_touch(adev, ring);
252 324
325 for (i = 0; i < AMD_SCHED_PRIORITY_MAX; ++i)
326 atomic_set(&ring->num_jobs[i], 0);
327
253 if (amdgpu_debugfs_ring_init(adev, ring)) { 328 if (amdgpu_debugfs_ring_init(adev, ring)) {
254 DRM_ERROR("Failed to register debugfs file for rings !\n"); 329 DRM_ERROR("Failed to register debugfs file for rings !\n");
255 } 330 }
@@ -315,14 +390,16 @@ static bool amdgpu_ring_is_blacklisted(struct amdgpu_ring *ring,
315 * @type: amdgpu_ring_type enum 390 * @type: amdgpu_ring_type enum
316 * @blacklist: blacklisted ring ids array 391 * @blacklist: blacklisted ring ids array
317 * @num_blacklist: number of entries in @blacklist 392 * @num_blacklist: number of entries in @blacklist
393 * @lru_pipe_order: find a ring from the least recently used pipe
318 * @ring: output ring 394 * @ring: output ring
319 * 395 *
320 * Retrieve the amdgpu_ring structure for the least recently used ring of 396 * Retrieve the amdgpu_ring structure for the least recently used ring of
321 * a specific IP block (all asics). 397 * a specific IP block (all asics).
322 * Returns 0 on success, error on failure. 398 * Returns 0 on success, error on failure.
323 */ 399 */
324int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type, int *blacklist, 400int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type,
325 int num_blacklist, struct amdgpu_ring **ring) 401 int *blacklist, int num_blacklist,
402 bool lru_pipe_order, struct amdgpu_ring **ring)
326{ 403{
327 struct amdgpu_ring *entry; 404 struct amdgpu_ring *entry;
328 405
@@ -337,10 +414,23 @@ int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type, int *blacklist,
337 if (amdgpu_ring_is_blacklisted(entry, blacklist, num_blacklist)) 414 if (amdgpu_ring_is_blacklisted(entry, blacklist, num_blacklist))
338 continue; 415 continue;
339 416
340 *ring = entry; 417 if (!*ring) {
341 amdgpu_ring_lru_touch_locked(adev, *ring); 418 *ring = entry;
342 break; 419
420 /* We are done for ring LRU */
421 if (!lru_pipe_order)
422 break;
423 }
424
425 /* Move all rings on the same pipe to the end of the list */
426 if (entry->pipe == (*ring)->pipe)
427 amdgpu_ring_lru_touch_locked(adev, entry);
343 } 428 }
429
430 /* Move the ring we found to the end of the list */
431 if (*ring)
432 amdgpu_ring_lru_touch_locked(adev, *ring);
433
344 spin_unlock(&adev->ring_lru_list_lock); 434 spin_unlock(&adev->ring_lru_list_lock);
345 435
346 if (!*ring) { 436 if (!*ring) {