Skip to content

Commit

Permalink
drm/amdgpu/mes11: Use a separate fence per transaction
Browse files Browse the repository at this point in the history
We can't use a shared fence location because each transaction
should be considered independently.

Reviewed-by: Shaoyun.liu <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
  • Loading branch information
alexdeucher authored and kentrussell committed May 9, 2024
1 parent d8e641a commit 96a4c00
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 4 deletions.
12 changes: 12 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@
#define AMDGPU_MES_MAX_NUM_OF_QUEUES_PER_PROCESS 1024
#define AMDGPU_ONE_DOORBELL_SIZE 8

signed long amdgpu_mes_fence_wait_polling(u64 *fence,
u64 wait_seq,
signed long timeout)
{

while ((s64)(wait_seq - *fence) > 0 && timeout > 0) {
udelay(2);
timeout -= 2;
}
return timeout > 0 ? timeout : 0;
}

int amdgpu_mes_doorbell_process_slice(struct amdgpu_device *adev)
{
return roundup(AMDGPU_ONE_DOORBELL_SIZE *
Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,10 @@ struct amdgpu_mes_funcs {
#define amdgpu_mes_kiq_hw_init(adev) (adev)->mes.kiq_hw_init((adev))
#define amdgpu_mes_kiq_hw_fini(adev) (adev)->mes.kiq_hw_fini((adev))

signed long amdgpu_mes_fence_wait_polling(u64 *fence,
u64 wait_seq,
signed long timeout);

int amdgpu_mes_ctx_get_offs(struct amdgpu_ring *ring, unsigned int id_offs);

int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe);
Expand Down
21 changes: 17 additions & 4 deletions drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
struct amdgpu_ring *ring = &mes->ring;
unsigned long flags;
signed long timeout = adev->usec_timeout;
u32 fence_offset;
u64 fence_gpu_addr;
u64 *fence_ptr;
int ret;

if (amdgpu_emu_mode) {
timeout *= 100;
Expand All @@ -118,24 +122,33 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
}
BUG_ON(size % 4 != 0);

ret = amdgpu_device_wb_get(adev, &fence_offset);
if (ret)
return ret;
fence_gpu_addr =
adev->wb.gpu_addr + (fence_offset * 4);
fence_ptr = (u64 *)&adev->wb.wb[fence_offset];
*fence_ptr = 0;

spin_lock_irqsave(&mes->ring_lock, flags);
if (amdgpu_ring_alloc(ring, ndw)) {
spin_unlock_irqrestore(&mes->ring_lock, flags);
amdgpu_device_wb_free(adev, fence_offset);
return -ENOMEM;
}

api_status = (struct MES_API_STATUS *)((char *)pkt + api_status_off);
api_status->api_completion_fence_addr = mes->ring.fence_drv.gpu_addr;
api_status->api_completion_fence_value = ++mes->ring.fence_drv.sync_seq;
api_status->api_completion_fence_addr = fence_gpu_addr;
api_status->api_completion_fence_value = 1;

amdgpu_ring_write_multiple(ring, pkt, ndw);
amdgpu_ring_commit(ring);
spin_unlock_irqrestore(&mes->ring_lock, flags);

DRM_DEBUG("MES msg=%d was emitted\n", x_pkt->header.opcode);

r = amdgpu_fence_wait_polling(ring, ring->fence_drv.sync_seq,
timeout);
r = amdgpu_mes_fence_wait_polling(fence_ptr, (u64)1, timeout);
amdgpu_device_wb_free(adev, fence_offset);
if (r < 1) {
DRM_ERROR("MES failed to response msg=%d\n",
x_pkt->header.opcode);
Expand Down

0 comments on commit 96a4c00

Please sign in to comment.