mirror of
https://github.com/torvalds/linux.git
synced 2026-05-01 21:12:29 -04:00
drm/amdgpu: protect ring overrun
Wait for the oldest sequence on the ring to be signaled in order to make sure there will be no command overrun. v2: fix coding stype and remove abs operation v3: remove the initialization of variable r Signed-off-by: Yintian Tao <yttao@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
committed by
Alex Deucher
parent
312a79b6ea
commit
04e4e2e955
@@ -192,14 +192,22 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f,
|
||||
* Used For polling fence.
|
||||
* Returns 0 on success, -ENOMEM on failure.
|
||||
*/
|
||||
int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s)
|
||||
int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s,
|
||||
uint32_t timeout)
|
||||
{
|
||||
uint32_t seq;
|
||||
signed long r;
|
||||
|
||||
if (!s)
|
||||
return -EINVAL;
|
||||
|
||||
seq = ++ring->fence_drv.sync_seq;
|
||||
r = amdgpu_fence_wait_polling(ring,
|
||||
seq - ring->fence_drv.num_fences_mask,
|
||||
timeout);
|
||||
if (r < 1)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr,
|
||||
seq, 0);
|
||||
|
||||
|
||||
@@ -675,13 +675,15 @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg)
|
||||
|
||||
spin_lock_irqsave(&kiq->ring_lock, flags);
|
||||
if (amdgpu_device_wb_get(adev, ®_val_offs)) {
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
pr_err("critical bug! too many kiq readers\n");
|
||||
goto failed_kiq_read;
|
||||
goto failed_unlock;
|
||||
}
|
||||
amdgpu_ring_alloc(ring, 32);
|
||||
amdgpu_ring_emit_rreg(ring, reg, reg_val_offs);
|
||||
amdgpu_fence_emit_polling(ring, &seq);
|
||||
r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
|
||||
if (r)
|
||||
goto failed_undo;
|
||||
|
||||
amdgpu_ring_commit(ring);
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
|
||||
@@ -712,7 +714,13 @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg)
|
||||
amdgpu_device_wb_free(adev, reg_val_offs);
|
||||
return value;
|
||||
|
||||
failed_undo:
|
||||
amdgpu_ring_undo(ring);
|
||||
failed_unlock:
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
failed_kiq_read:
|
||||
if (reg_val_offs)
|
||||
amdgpu_device_wb_free(adev, reg_val_offs);
|
||||
pr_err("failed to read reg:%x\n", reg);
|
||||
return ~0;
|
||||
}
|
||||
@@ -730,7 +738,10 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v)
|
||||
spin_lock_irqsave(&kiq->ring_lock, flags);
|
||||
amdgpu_ring_alloc(ring, 32);
|
||||
amdgpu_ring_emit_wreg(ring, reg, v);
|
||||
amdgpu_fence_emit_polling(ring, &seq);
|
||||
r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
|
||||
if (r)
|
||||
goto failed_undo;
|
||||
|
||||
amdgpu_ring_commit(ring);
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
|
||||
@@ -759,6 +770,9 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v)
|
||||
|
||||
return;
|
||||
|
||||
failed_undo:
|
||||
amdgpu_ring_undo(ring);
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
failed_kiq_write:
|
||||
pr_err("failed to write reg:%x\n", reg);
|
||||
}
|
||||
|
||||
@@ -105,7 +105,8 @@ void amdgpu_fence_driver_suspend(struct amdgpu_device *adev);
|
||||
void amdgpu_fence_driver_resume(struct amdgpu_device *adev);
|
||||
int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **fence,
|
||||
unsigned flags);
|
||||
int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s);
|
||||
int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s,
|
||||
uint32_t timeout);
|
||||
bool amdgpu_fence_process(struct amdgpu_ring *ring);
|
||||
int amdgpu_fence_wait_empty(struct amdgpu_ring *ring);
|
||||
signed long amdgpu_fence_wait_polling(struct amdgpu_ring *ring,
|
||||
|
||||
@@ -60,7 +60,10 @@ void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev,
|
||||
amdgpu_ring_alloc(ring, 32);
|
||||
amdgpu_ring_emit_reg_write_reg_wait(ring, reg0, reg1,
|
||||
ref, mask);
|
||||
amdgpu_fence_emit_polling(ring, &seq);
|
||||
r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
|
||||
if (r)
|
||||
goto failed_undo;
|
||||
|
||||
amdgpu_ring_commit(ring);
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
|
||||
@@ -82,6 +85,9 @@ void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev,
|
||||
|
||||
return;
|
||||
|
||||
failed_undo:
|
||||
amdgpu_ring_undo(ring);
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
failed_kiq:
|
||||
pr_err("failed to write reg %x wait reg %x\n", reg0, reg1);
|
||||
}
|
||||
|
||||
@@ -4054,9 +4054,8 @@ static uint64_t gfx_v9_0_kiq_read_clock(struct amdgpu_device *adev)
|
||||
|
||||
spin_lock_irqsave(&kiq->ring_lock, flags);
|
||||
if (amdgpu_device_wb_get(adev, ®_val_offs)) {
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
pr_err("critical bug! too many kiq readers\n");
|
||||
goto failed_kiq_read;
|
||||
goto failed_unlock;
|
||||
}
|
||||
amdgpu_ring_alloc(ring, 32);
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_COPY_DATA, 4));
|
||||
@@ -4070,7 +4069,10 @@ static uint64_t gfx_v9_0_kiq_read_clock(struct amdgpu_device *adev)
|
||||
reg_val_offs * 4));
|
||||
amdgpu_ring_write(ring, upper_32_bits(adev->wb.gpu_addr +
|
||||
reg_val_offs * 4));
|
||||
amdgpu_fence_emit_polling(ring, &seq);
|
||||
r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
|
||||
if (r)
|
||||
goto failed_undo;
|
||||
|
||||
amdgpu_ring_commit(ring);
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
|
||||
@@ -4102,7 +4104,13 @@ static uint64_t gfx_v9_0_kiq_read_clock(struct amdgpu_device *adev)
|
||||
amdgpu_device_wb_free(adev, reg_val_offs);
|
||||
return value;
|
||||
|
||||
failed_undo:
|
||||
amdgpu_ring_undo(ring);
|
||||
failed_unlock:
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
failed_kiq_read:
|
||||
if (reg_val_offs)
|
||||
amdgpu_device_wb_free(adev, reg_val_offs);
|
||||
pr_err("failed to read gpu clock\n");
|
||||
return ~0;
|
||||
}
|
||||
|
||||
@@ -426,7 +426,13 @@ static int gmc_v10_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
|
||||
amdgpu_ring_alloc(ring, kiq->pmf->invalidate_tlbs_size + 8);
|
||||
kiq->pmf->kiq_invalidate_tlbs(ring,
|
||||
pasid, flush_type, all_hub);
|
||||
amdgpu_fence_emit_polling(ring, &seq);
|
||||
r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
|
||||
if (r) {
|
||||
amdgpu_ring_undo(ring);
|
||||
spin_unlock(&kiq->ring_lock);
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
amdgpu_ring_commit(ring);
|
||||
spin_unlock(&adev->gfx.kiq.ring_lock);
|
||||
r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout);
|
||||
|
||||
@@ -621,7 +621,13 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
|
||||
pasid, 2, all_hub);
|
||||
kiq->pmf->kiq_invalidate_tlbs(ring,
|
||||
pasid, flush_type, all_hub);
|
||||
amdgpu_fence_emit_polling(ring, &seq);
|
||||
r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
|
||||
if (r) {
|
||||
amdgpu_ring_undo(ring);
|
||||
spin_unlock(&kiq->ring_lock);
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
amdgpu_ring_commit(ring);
|
||||
spin_unlock(&adev->gfx.kiq.ring_lock);
|
||||
r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout);
|
||||
|
||||
Reference in New Issue
Block a user