Skip to contentSkip to conversation

drm/amdgpu: map compute rings by least recently used pipe

PATCH In review Andres Rodriguez 2 participants 2 messages Sep 26, 2017 – Sep 28, 2017 1 message not in the archive

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 drm/amdgpu: map compute rings by least recently used pipe

This patch provides a guarantee that the first n queues allocated by an application will be on different pipes. Where n is the number of pipes available from the hardware.

This helps avoid ring aliasing which can result in work executing in time-sliced mode instead of truly parallel mode.

---
 drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c |  8 +++++---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c      | 25 ++++++++++++++++++++-----
 drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h      |  5 +++--
 3 files changed, 28 insertions(+), 10 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c +5 -3
index befc09b..190e28c 100644
@@ -121,7 +121,7 @@ static enum amdgpu_ring_type amdgpu_hw_ip_to_ring_type(int hw_ip)
 
 static int amdgpu_lru_map(struct amdgpu_device *adev,
 			  struct amdgpu_queue_mapper *mapper,
-			  int user_ring,
+			  int user_ring, bool lru_pipe_order,
 			  struct amdgpu_ring **out_ring)
 {
 	int r, i, j;
@@ -139,7 +139,7 @@ static int amdgpu_lru_map(struct amdgpu_device *adev,
 	}
 
 	r = amdgpu_ring_lru_get(adev, ring_type, ring_blacklist,
-				j, out_ring);
+				j, lru_pipe_order, out_ring);
 	if (r)
 		return r;
 
@@ -284,8 +284,10 @@ int amdgpu_queue_mgr_map(struct amdgpu_device *adev,
 		r = amdgpu_identity_map(adev, mapper, ring, out_ring);
 		break;
 	case AMDGPU_HW_IP_DMA:
+		r = amdgpu_lru_map(adev, mapper, ring, false, out_ring);
+		break;
 	case AMDGPU_HW_IP_COMPUTE:
-		r = amdgpu_lru_map(adev, mapper, ring, out_ring);
+		r = amdgpu_lru_map(adev, mapper, ring, true, out_ring);
 		break;
 	default:
 		*out_ring = NULL;
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +20 -5
index 5ce6528..019932a 100644
@@ -315,14 +315,16 @@ static bool amdgpu_ring_is_blacklisted(struct amdgpu_ring *ring,
  * @type: amdgpu_ring_type enum
  * @blacklist: blacklisted ring ids array
  * @num_blacklist: number of entries in @blacklist
+ * @lru_pipe_order: find a ring from the least recently used pipe
  * @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)
+int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type,
+			int *blacklist,	int num_blacklist,
+			bool lru_pipe_order, struct amdgpu_ring **ring)
 {
 	struct amdgpu_ring *entry;
 
@@ -337,10 +339,23 @@ int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type, int *blacklist,
 		if (amdgpu_ring_is_blacklisted(entry, blacklist, num_blacklist))
 			continue;
 
-		*ring = entry;
-		amdgpu_ring_lru_touch_locked(adev, *ring);
-		break;
+		if (!*ring) {
+			*ring = entry;
+
+			/* We are done for ring LRU */
+			if (!lru_pipe_order)
+				break;
+		}
+
+		/* Move all rings on the same pipe to the end of the list */
+		if (entry->pipe == (*ring)->pipe)
+			amdgpu_ring_lru_touch_locked(adev, entry);
 	}
+
+	/* Move the ring we found to the end of the list */
+	if (*ring)
+		amdgpu_ring_lru_touch_locked(adev, *ring);
+
 	spin_unlock(&adev->ring_lru_list_lock);
 
 	if (!*ring) {
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +3 -2
index 322d2529..491bd55 100644
@@ -201,8 +201,9 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
 		     unsigned ring_size, struct amdgpu_irq_src *irq_src,
 		     unsigned irq_type);
 void amdgpu_ring_fini(struct amdgpu_ring *ring);
-int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type, int *blacklist,
-			int num_blacklist, struct amdgpu_ring **ring);
+int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type,
+			int *blacklist, int num_blacklist,
+			bool lru_pipe_order, struct amdgpu_ring **ring);
 void amdgpu_ring_lru_touch(struct amdgpu_device *adev, struct amdgpu_ring *ring);
 static inline void amdgpu_ring_clear_ring(struct amdgpu_ring *ring)
 {
Signature · 6 lines
2.9.3

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

A message that is not in the archive (sent off-list or not yet received): 20170926214314.3223-1-andresx7-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org

Reviewed-by
#2 lore raw
Quoted 8 lines · Andres Rodriguez

This patch provides a guarantee that the first n queues allocated by an application will be on different pipes. Where n is the number of pipes available from the hardware.

This helps avoid ring aliasing which can result in work executing in time-sliced mode instead of truly parallel mode.

And applied.

Alex

Quoted 109 lines
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c |  8 +++++---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c      | 25 ++++++++++++++++++++-----
 drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h      |  5 +++--
 3 files changed, 28 insertions(+), 10 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c +5 -3
index befc09b..190e28c 100644
@@ -121,7 +121,7 @@ static enum amdgpu_ring_type amdgpu_hw_ip_to_ring_type(int hw_ip)
 
 static int amdgpu_lru_map(struct amdgpu_device *adev,
                          struct amdgpu_queue_mapper *mapper,
-                         int user_ring,
+                         int user_ring, bool lru_pipe_order,
                          struct amdgpu_ring **out_ring)
 {
        int r, i, j;
@@ -139,7 +139,7 @@ static int amdgpu_lru_map(struct amdgpu_device *adev,
        }
 
        r = amdgpu_ring_lru_get(adev, ring_type, ring_blacklist,
-                               j, out_ring);
+                               j, lru_pipe_order, out_ring);
        if (r)
                return r;
 
@@ -284,8 +284,10 @@ int amdgpu_queue_mgr_map(struct amdgpu_device *adev,
                r = amdgpu_identity_map(adev, mapper, ring, out_ring);
                break;
        case AMDGPU_HW_IP_DMA:
+               r = amdgpu_lru_map(adev, mapper, ring, false, out_ring);
+               break;
        case AMDGPU_HW_IP_COMPUTE:
-               r = amdgpu_lru_map(adev, mapper, ring, out_ring);
+               r = amdgpu_lru_map(adev, mapper, ring, true, out_ring);
                break;
        default:
                *out_ring = NULL;
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +20 -5
index 5ce6528..019932a 100644
@@ -315,14 +315,16 @@ static bool amdgpu_ring_is_blacklisted(struct amdgpu_ring *ring,
  * @type: amdgpu_ring_type enum
  * @blacklist: blacklisted ring ids array
  * @num_blacklist: number of entries in @blacklist
+ * @lru_pipe_order: find a ring from the least recently used pipe
  * @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)
+int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type,
+                       int *blacklist, int num_blacklist,
+                       bool lru_pipe_order, struct amdgpu_ring **ring)
 {
        struct amdgpu_ring *entry;
 
@@ -337,10 +339,23 @@ int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type, int *blacklist,
                if (amdgpu_ring_is_blacklisted(entry, blacklist, num_blacklist))
                        continue;
 
-               *ring = entry;
-               amdgpu_ring_lru_touch_locked(adev, *ring);
-               break;
+               if (!*ring) {
+                       *ring = entry;
+
+                       /* We are done for ring LRU */
+                       if (!lru_pipe_order)
+                               break;
+               }
+
+               /* Move all rings on the same pipe to the end of the list */
+               if (entry->pipe == (*ring)->pipe)
+                       amdgpu_ring_lru_touch_locked(adev, entry);
        }
+
+       /* Move the ring we found to the end of the list */
+       if (*ring)
+               amdgpu_ring_lru_touch_locked(adev, *ring);
+
        spin_unlock(&adev->ring_lru_list_lock);
 
        if (!*ring) {
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +3 -3
index 322d2529..491bd55 100644
@@ -201,8 +201,9 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
                     unsigned ring_size, struct amdgpu_irq_src *irq_src,
                     unsigned irq_type);
 void amdgpu_ring_fini(struct amdgpu_ring *ring);
-int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type, int *blacklist,
-                       int num_blacklist, struct amdgpu_ring **ring);
+int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type,
+                       int *blacklist, int num_blacklist,
+                       bool lru_pipe_order, struct amdgpu_ring **ring);
 void amdgpu_ring_lru_touch(struct amdgpu_device *adev, struct amdgpu_ring *ring);
 static inline void amdgpu_ring_clear_ring(struct amdgpu_ring *ring)
 {
--

2.9.3

Quoted 4 lines

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx