]> Git Repo - linux.git/blobdiff - drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
Merge tag 'platform-drivers-x86-v4.13-2' of git://git.infradead.org/linux-platform...
[linux.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_ring.c
index 6a85db0c0bc3b82082f4ad5ff392e2b633ea3f78..75165e07b1cd8807831d4dd602a9c1a2037d8ad6 100644 (file)
@@ -135,6 +135,8 @@ void amdgpu_ring_commit(struct amdgpu_ring *ring)
 
        if (ring->funcs->end_use)
                ring->funcs->end_use(ring);
 
        if (ring->funcs->end_use)
                ring->funcs->end_use(ring);
+
+       amdgpu_ring_lru_touch(ring->adev, ring);
 }
 
 /**
 }
 
 /**
@@ -253,10 +255,13 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
        }
 
        ring->max_dw = max_dw;
        }
 
        ring->max_dw = max_dw;
+       INIT_LIST_HEAD(&ring->lru_list);
+       amdgpu_ring_lru_touch(adev, ring);
 
        if (amdgpu_debugfs_ring_init(adev, ring)) {
                DRM_ERROR("Failed to register debugfs file for rings !\n");
        }
 
        if (amdgpu_debugfs_ring_init(adev, ring)) {
                DRM_ERROR("Failed to register debugfs file for rings !\n");
        }
+
        return 0;
 }
 
        return 0;
 }
 
@@ -294,6 +299,84 @@ void amdgpu_ring_fini(struct amdgpu_ring *ring)
        ring->adev->rings[ring->idx] = NULL;
 }
 
        ring->adev->rings[ring->idx] = NULL;
 }
 
+static void amdgpu_ring_lru_touch_locked(struct amdgpu_device *adev,
+                                        struct amdgpu_ring *ring)
+{
+       /* list_move_tail handles the case where ring isn't part of the list */
+       list_move_tail(&ring->lru_list, &adev->ring_lru_list);
+}
+
+static bool amdgpu_ring_is_blacklisted(struct amdgpu_ring *ring,
+                                      int *blacklist, int num_blacklist)
+{
+       int i;
+
+       for (i = 0; i < num_blacklist; i++) {
+               if (ring->idx == blacklist[i])
+                       return true;
+       }
+
+       return false;
+}
+
+/**
+ * amdgpu_ring_lru_get - get the least recently used ring for a HW IP block
+ *
+ * @adev: amdgpu_device pointer
+ * @type: amdgpu_ring_type enum
+ * @blacklist: blacklisted ring ids array
+ * @num_blacklist: number of entries in @blacklist
+ * @ring: output ring
+ *
+ * Retrieve the amdgpu_ring structure for the least recently used ring of
+ * a specific IP block (all asics).
+ * Returns 0 on success, error on failure.
+ */
+int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type, int *blacklist,
+                       int num_blacklist, struct amdgpu_ring **ring)
+{
+       struct amdgpu_ring *entry;
+
+       /* List is sorted in LRU order, find first entry corresponding
+        * to the desired HW IP */
+       *ring = NULL;
+       spin_lock(&adev->ring_lru_list_lock);
+       list_for_each_entry(entry, &adev->ring_lru_list, lru_list) {
+               if (entry->funcs->type != type)
+                       continue;
+
+               if (amdgpu_ring_is_blacklisted(entry, blacklist, num_blacklist))
+                       continue;
+
+               *ring = entry;
+               amdgpu_ring_lru_touch_locked(adev, *ring);
+               break;
+       }
+       spin_unlock(&adev->ring_lru_list_lock);
+
+       if (!*ring) {
+               DRM_ERROR("Ring LRU contains no entries for ring type:%d\n", type);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/**
+ * amdgpu_ring_lru_touch - mark a ring as recently being used
+ *
+ * @adev: amdgpu_device pointer
+ * @ring: ring to touch
+ *
+ * Move @ring to the tail of the lru list
+ */
+void amdgpu_ring_lru_touch(struct amdgpu_device *adev, struct amdgpu_ring *ring)
+{
+       spin_lock(&adev->ring_lru_list_lock);
+       amdgpu_ring_lru_touch_locked(adev, ring);
+       spin_unlock(&adev->ring_lru_list_lock);
+}
+
 /*
  * Debugfs info
  */
 /*
  * Debugfs info
  */
This page took 0.035675 seconds and 4 git commands to generate.