Commit 34e087e8 authored by Jack Xiao's avatar Jack Xiao Committed by Alex Deucher

drm/amdgpu/mes: fix mes ring buffer overflow

wait memory room until enough before writing mes packets
to avoid ring buffer overflow.

v2: squash in sched_hw_submission fix

Fixes: de324625 ("drm/amdgpu: cleanup MES11 command submission")
Fixes: fffe347e ("drm/amdgpu: cleanup MES12 command submission")
Signed-off-by: default avatarJack Xiao <Jack.Xiao@amd.com>
Acked-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 46142cc1
...@@ -214,6 +214,8 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, ...@@ -214,6 +214,8 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
*/ */
if (ring->funcs->type == AMDGPU_RING_TYPE_KIQ) if (ring->funcs->type == AMDGPU_RING_TYPE_KIQ)
sched_hw_submission = max(sched_hw_submission, 256); sched_hw_submission = max(sched_hw_submission, 256);
if (ring->funcs->type == AMDGPU_RING_TYPE_MES)
sched_hw_submission = 8;
else if (ring == &adev->sdma.instance[0].page) else if (ring == &adev->sdma.instance[0].page)
sched_hw_submission = 256; sched_hw_submission = 256;
......
...@@ -168,7 +168,7 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, ...@@ -168,7 +168,7 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
const char *op_str, *misc_op_str; const char *op_str, *misc_op_str;
unsigned long flags; unsigned long flags;
u64 status_gpu_addr; u64 status_gpu_addr;
u32 status_offset; u32 seq, status_offset;
u64 *status_ptr; u64 *status_ptr;
signed long r; signed long r;
int ret; int ret;
...@@ -196,6 +196,13 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, ...@@ -196,6 +196,13 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
if (r) if (r)
goto error_unlock_free; goto error_unlock_free;
seq = ++ring->fence_drv.sync_seq;
r = amdgpu_fence_wait_polling(ring,
seq - ring->fence_drv.num_fences_mask,
timeout);
if (r < 1)
goto error_undo;
api_status = (struct MES_API_STATUS *)((char *)pkt + api_status_off); api_status = (struct MES_API_STATUS *)((char *)pkt + api_status_off);
api_status->api_completion_fence_addr = status_gpu_addr; api_status->api_completion_fence_addr = status_gpu_addr;
api_status->api_completion_fence_value = 1; api_status->api_completion_fence_value = 1;
...@@ -208,8 +215,7 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, ...@@ -208,8 +215,7 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
mes_status_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS; mes_status_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS;
mes_status_pkt.api_status.api_completion_fence_addr = mes_status_pkt.api_status.api_completion_fence_addr =
ring->fence_drv.gpu_addr; ring->fence_drv.gpu_addr;
mes_status_pkt.api_status.api_completion_fence_value = mes_status_pkt.api_status.api_completion_fence_value = seq;
++ring->fence_drv.sync_seq;
amdgpu_ring_write_multiple(ring, &mes_status_pkt, amdgpu_ring_write_multiple(ring, &mes_status_pkt,
sizeof(mes_status_pkt) / 4); sizeof(mes_status_pkt) / 4);
...@@ -229,7 +235,7 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, ...@@ -229,7 +235,7 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
dev_dbg(adev->dev, "MES msg=%d was emitted\n", dev_dbg(adev->dev, "MES msg=%d was emitted\n",
x_pkt->header.opcode); x_pkt->header.opcode);
r = amdgpu_fence_wait_polling(ring, ring->fence_drv.sync_seq, timeout); r = amdgpu_fence_wait_polling(ring, seq, timeout);
if (r < 1 || !*status_ptr) { if (r < 1 || !*status_ptr) {
if (misc_op_str) if (misc_op_str)
...@@ -252,6 +258,10 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, ...@@ -252,6 +258,10 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
amdgpu_device_wb_free(adev, status_offset); amdgpu_device_wb_free(adev, status_offset);
return 0; return 0;
error_undo:
dev_err(adev->dev, "MES ring buffer is full.\n");
amdgpu_ring_undo(ring);
error_unlock_free: error_unlock_free:
spin_unlock_irqrestore(&mes->ring_lock, flags); spin_unlock_irqrestore(&mes->ring_lock, flags);
......
...@@ -154,7 +154,7 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, ...@@ -154,7 +154,7 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
const char *op_str, *misc_op_str; const char *op_str, *misc_op_str;
unsigned long flags; unsigned long flags;
u64 status_gpu_addr; u64 status_gpu_addr;
u32 status_offset; u32 seq, status_offset;
u64 *status_ptr; u64 *status_ptr;
signed long r; signed long r;
int ret; int ret;
...@@ -182,6 +182,13 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, ...@@ -182,6 +182,13 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
if (r) if (r)
goto error_unlock_free; goto error_unlock_free;
seq = ++ring->fence_drv.sync_seq;
r = amdgpu_fence_wait_polling(ring,
seq - ring->fence_drv.num_fences_mask,
timeout);
if (r < 1)
goto error_undo;
api_status = (struct MES_API_STATUS *)((char *)pkt + api_status_off); api_status = (struct MES_API_STATUS *)((char *)pkt + api_status_off);
api_status->api_completion_fence_addr = status_gpu_addr; api_status->api_completion_fence_addr = status_gpu_addr;
api_status->api_completion_fence_value = 1; api_status->api_completion_fence_value = 1;
...@@ -194,8 +201,7 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, ...@@ -194,8 +201,7 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
mes_status_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS; mes_status_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS;
mes_status_pkt.api_status.api_completion_fence_addr = mes_status_pkt.api_status.api_completion_fence_addr =
ring->fence_drv.gpu_addr; ring->fence_drv.gpu_addr;
mes_status_pkt.api_status.api_completion_fence_value = mes_status_pkt.api_status.api_completion_fence_value = seq;
++ring->fence_drv.sync_seq;
amdgpu_ring_write_multiple(ring, &mes_status_pkt, amdgpu_ring_write_multiple(ring, &mes_status_pkt,
sizeof(mes_status_pkt) / 4); sizeof(mes_status_pkt) / 4);
...@@ -215,7 +221,7 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, ...@@ -215,7 +221,7 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
dev_dbg(adev->dev, "MES msg=%d was emitted\n", dev_dbg(adev->dev, "MES msg=%d was emitted\n",
x_pkt->header.opcode); x_pkt->header.opcode);
r = amdgpu_fence_wait_polling(ring, ring->fence_drv.sync_seq, timeout); r = amdgpu_fence_wait_polling(ring, seq, timeout);
if (r < 1 || !*status_ptr) { if (r < 1 || !*status_ptr) {
if (misc_op_str) if (misc_op_str)
...@@ -238,6 +244,10 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, ...@@ -238,6 +244,10 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
amdgpu_device_wb_free(adev, status_offset); amdgpu_device_wb_free(adev, status_offset);
return 0; return 0;
error_undo:
dev_err(adev->dev, "MES ring buffer is full.\n");
amdgpu_ring_undo(ring);
error_unlock_free: error_unlock_free:
spin_unlock_irqrestore(&mes->ring_lock, flags); spin_unlock_irqrestore(&mes->ring_lock, flags);
......
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