aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
diff options
context:
space:
mode:
authorAndres Rodriguez <andresx7@gmail.com>2017-03-06 16:27:55 -0500
committerAlex Deucher <alexander.deucher@amd.com>2017-05-31 16:49:02 -0400
commit795f2813e628bcf57a69f2dfe413360d14a1d7f4 (patch)
treef60bfe602590fde4bd170c263a569cd8147ffdd0 /drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
parenteffd924d2f3b9c52d5bd8137c3803e83f719a290 (diff)
drm/amdgpu: implement lru amdgpu_queue_mgr policy for compute v4
Use an LRU policy to map usermode rings to HW compute queues. Most compute clients use one queue, and usually the first queue available. This results in poor pipe/queue work distribution when multiple compute apps are running. In most cases pipe 0 queue 0 is the only queue that gets used. In order to better distribute work across multiple HW queues, we adopt a policy to map the usermode ring ids to the LRU HW queue. This fixes a large majority of multi-app compute workloads sharing the same HW queue, even though 7 other queues are available. v2: use ring->funcs->type instead of ring->hw_ip v3: remove amdgpu_queue_mapper_funcs v4: change ring_lru_list_lock to spinlock, grab only once in lru_get() Signed-off-by: Andres Rodriguez <andresx7@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
index 7d95435fad16..f1076e3edf53 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
@@ -135,6 +135,8 @@ void amdgpu_ring_commit(struct amdgpu_ring *ring)
135 135
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
139 amdgpu_ring_lru_touch(ring->adev, ring);
138} 140}
139 141
140/** 142/**
@@ -283,6 +285,8 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
283 } 285 }
284 286
285 ring->max_dw = max_dw; 287 ring->max_dw = max_dw;
288 INIT_LIST_HEAD(&ring->lru_list);
289 amdgpu_ring_lru_touch(adev, ring);
286 290
287 if (amdgpu_debugfs_ring_init(adev, ring)) { 291 if (amdgpu_debugfs_ring_init(adev, ring)) {
288 DRM_ERROR("Failed to register debugfs file for rings !\n"); 292 DRM_ERROR("Failed to register debugfs file for rings !\n");
@@ -327,6 +331,65 @@ void amdgpu_ring_fini(struct amdgpu_ring *ring)
327 ring->adev->rings[ring->idx] = NULL; 331 ring->adev->rings[ring->idx] = NULL;
328} 332}
329 333
334static void amdgpu_ring_lru_touch_locked(struct amdgpu_device *adev,
335 struct amdgpu_ring *ring)
336{
337 /* list_move_tail handles the case where ring isn't part of the list */
338 list_move_tail(&ring->lru_list, &adev->ring_lru_list);
339}
340
341/**
342 * amdgpu_ring_lru_get - get the least recently used ring for a HW IP block
343 *
344 * @adev: amdgpu_device pointer
345 * @type: amdgpu_ring_type enum
346 * @ring: output ring
347 *
348 * Retrieve the amdgpu_ring structure for the least recently used ring of
349 * a specific IP block (all asics).
350 * Returns 0 on success, error on failure.
351 */
352int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type,
353 struct amdgpu_ring **ring)
354{
355 struct amdgpu_ring *entry;
356
357 /* List is sorted in LRU order, find first entry corresponding
358 * to the desired HW IP */
359 *ring = NULL;
360 spin_lock(&adev->ring_lru_list_lock);
361 list_for_each_entry(entry, &adev->ring_lru_list, lru_list) {
362 if (entry->funcs->type == type) {
363 *ring = entry;
364 amdgpu_ring_lru_touch_locked(adev, *ring);
365 break;
366 }
367 }
368 spin_unlock(&adev->ring_lru_list_lock);
369
370 if (!*ring) {
371 DRM_ERROR("Ring LRU contains no entries for ring type:%d\n", type);
372 return -EINVAL;
373 }
374
375 return 0;
376}
377
378/**
379 * amdgpu_ring_lru_touch - mark a ring as recently being used
380 *
381 * @adev: amdgpu_device pointer
382 * @ring: ring to touch
383 *
384 * Move @ring to the tail of the lru list
385 */
386void amdgpu_ring_lru_touch(struct amdgpu_device *adev, struct amdgpu_ring *ring)
387{
388 spin_lock(&adev->ring_lru_list_lock);
389 amdgpu_ring_lru_touch_locked(adev, ring);
390 spin_unlock(&adev->ring_lru_list_lock);
391}
392
330/* 393/*
331 * Debugfs info 394 * Debugfs info
332 */ 395 */