Commit 35161bbc authored by Andres Rodriguez's avatar Andres Rodriguez Committed by Alex Deucher

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.
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAndres Rodriguez <andresx7@gmail.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 4a75aefe
...@@ -121,7 +121,7 @@ static enum amdgpu_ring_type amdgpu_hw_ip_to_ring_type(int hw_ip) ...@@ -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, static int amdgpu_lru_map(struct amdgpu_device *adev,
struct amdgpu_queue_mapper *mapper, struct amdgpu_queue_mapper *mapper,
int user_ring, int user_ring, bool lru_pipe_order,
struct amdgpu_ring **out_ring) struct amdgpu_ring **out_ring)
{ {
int r, i, j; int r, i, j;
...@@ -139,7 +139,7 @@ static int amdgpu_lru_map(struct amdgpu_device *adev, ...@@ -139,7 +139,7 @@ static int amdgpu_lru_map(struct amdgpu_device *adev,
} }
r = amdgpu_ring_lru_get(adev, ring_type, ring_blacklist, r = amdgpu_ring_lru_get(adev, ring_type, ring_blacklist,
j, out_ring); j, lru_pipe_order, out_ring);
if (r) if (r)
return r; return r;
...@@ -284,8 +284,10 @@ int amdgpu_queue_mgr_map(struct amdgpu_device *adev, ...@@ -284,8 +284,10 @@ int amdgpu_queue_mgr_map(struct amdgpu_device *adev,
r = amdgpu_identity_map(adev, mapper, ring, out_ring); r = amdgpu_identity_map(adev, mapper, ring, out_ring);
break; break;
case AMDGPU_HW_IP_DMA: case AMDGPU_HW_IP_DMA:
r = amdgpu_lru_map(adev, mapper, ring, false, out_ring);
break;
case AMDGPU_HW_IP_COMPUTE: 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; break;
default: default:
*out_ring = NULL; *out_ring = NULL;
......
...@@ -315,14 +315,16 @@ static bool amdgpu_ring_is_blacklisted(struct amdgpu_ring *ring, ...@@ -315,14 +315,16 @@ static bool amdgpu_ring_is_blacklisted(struct amdgpu_ring *ring,
* @type: amdgpu_ring_type enum * @type: amdgpu_ring_type enum
* @blacklist: blacklisted ring ids array * @blacklist: blacklisted ring ids array
* @num_blacklist: number of entries in @blacklist * @num_blacklist: number of entries in @blacklist
* @lru_pipe_order: find a ring from the least recently used pipe
* @ring: output ring * @ring: output ring
* *
* Retrieve the amdgpu_ring structure for the least recently used ring of * Retrieve the amdgpu_ring structure for the least recently used ring of
* a specific IP block (all asics). * a specific IP block (all asics).
* Returns 0 on success, error on failure. * Returns 0 on success, error on failure.
*/ */
int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type, int *blacklist, int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type,
int num_blacklist, struct amdgpu_ring **ring) int *blacklist, int num_blacklist,
bool lru_pipe_order, struct amdgpu_ring **ring)
{ {
struct amdgpu_ring *entry; struct amdgpu_ring *entry;
...@@ -337,10 +339,23 @@ int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type, int *blacklist, ...@@ -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)) if (amdgpu_ring_is_blacklisted(entry, blacklist, num_blacklist))
continue; continue;
*ring = entry; if (!*ring) {
amdgpu_ring_lru_touch_locked(adev, *ring); *ring = entry;
break;
/* 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); spin_unlock(&adev->ring_lru_list_lock);
if (!*ring) { if (!*ring) {
......
...@@ -201,8 +201,9 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, ...@@ -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 ring_size, struct amdgpu_irq_src *irq_src,
unsigned irq_type); unsigned irq_type);
void amdgpu_ring_fini(struct amdgpu_ring *ring); void amdgpu_ring_fini(struct amdgpu_ring *ring);
int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type, int *blacklist, int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type,
int num_blacklist, struct amdgpu_ring **ring); 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); void amdgpu_ring_lru_touch(struct amdgpu_device *adev, struct amdgpu_ring *ring);
static inline void amdgpu_ring_clear_ring(struct amdgpu_ring *ring) static inline void amdgpu_ring_clear_ring(struct amdgpu_ring *ring)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment