diff options
author | Andres Rodriguez <andresx7@gmail.com> | 2017-04-28 19:23:13 -0400 |
---|---|---|
committer | Andres Rodriguez <andresx7@gmail.com> | 2017-05-05 11:18:15 -0400 |
commit | 2515846865b341e6c32893272c191088a6e2f204 (patch) | |
tree | 1e86534730435be5f86339c2e98f4db9e0a38bdd | |
parent | ae98c8704a43aec77bd48abc53e017c0bff37709 (diff) |
drm/amdgpu: add macro for asynchronous KIQ register writes
Add WREG32_KIQ_ASYNC() to allow for a caller to perform a register write
without waiting for the result to be commited.
This allows us to queue register writes from a context that cannot
sleep.
It may also be useful for long sequences of register writes performed
through the kiq. Where only the last write actually needs to be
synchronized.
Signed-off-by: Andres Rodriguez <andresx7@gmail.com>
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 26 |
2 files changed, 18 insertions, 13 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index ca040e6d233f..50bfeadba2c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1669,7 +1669,8 @@ void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, u32 amdgpu_io_rreg(struct amdgpu_device *adev, u32 reg); void amdgpu_io_wreg(struct amdgpu_device *adev, u32 reg, u32 v); uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg); -void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v); +void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, + uint32_t acc_flags); u32 amdgpu_mm_rdoorbell(struct amdgpu_device *adev, u32 index); void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v); @@ -1683,11 +1684,13 @@ void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v); #define AMDGPU_REGS_IDX (1<<0) #define AMDGPU_REGS_NO_KIQ (1<<1) #define AMDGPU_REGS_FORCE_KIQ (1<<2) +#define AMDGPU_REGS_KIQ_ASYNC (1<<3) #define RREG32_NO_KIQ(reg) amdgpu_mm_rreg(adev, (reg), AMDGPU_REGS_NO_KIQ) #define WREG32_NO_KIQ(reg, v) amdgpu_mm_wreg(adev, (reg), (v), AMDGPU_REGS_NO_KIQ) #define RREG32_KIQ(reg) amdgpu_mm_rreg(adev, (reg), AMDGPU_REGS_FORCE_KIQ) #define WREG32_KIQ(reg, v) amdgpu_mm_wreg(adev, (reg), (v), AMDGPU_REGS_FORCE_KIQ) +#define WREG32_KIQ_ASYNC(reg, v) amdgpu_mm_wreg(adev, (reg), (v), AMDGPU_REGS_FORCE_KIQ | AMDGPU_REGS_KIQ_ASYNC) #define RREG32(reg) amdgpu_mm_rreg(adev, (reg), 0) #define RREG32_IDX(reg) amdgpu_mm_rreg(adev, (reg), AMDGPU_REGS_IDX) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 6584d7e0b8f2..3469b9d72678 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -123,10 +123,8 @@ void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, trace_amdgpu_mm_wreg(adev->pdev->device, reg, v); if ((!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev)) - || acc_flags & AMDGPU_REGS_FORCE_KIQ) { - BUG_ON(in_interrupt()); - return amdgpu_kiq_wreg(adev, reg, v); - } + || acc_flags & AMDGPU_REGS_FORCE_KIQ) + return amdgpu_kiq_wreg(adev, reg, v, acc_flags); if ((reg * 4) < adev->rmmio_size && !(acc_flags & AMDGPU_REGS_IDX)) writel(v, ((void __iomem *)adev->rmmio) + (reg * 4)); @@ -188,10 +186,11 @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg) return val; } -void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v) +void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, + uint32_t acc_flags) { signed long r; - struct dma_fence *f; + struct dma_fence *f = NULL; struct amdgpu_kiq *kiq = &adev->gfx.kiq; struct amdgpu_ring *ring = &kiq->ring; @@ -200,17 +199,20 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v) spin_lock(&kiq->ring_lock); amdgpu_ring_alloc(ring, 32); amdgpu_ring_emit_wreg(ring, reg, v); - amdgpu_fence_emit(ring, &f); + if (!(acc_flags & AMDGPU_REGS_KIQ_ASYNC)) + amdgpu_fence_emit(ring, &f); amdgpu_ring_commit(ring); spin_unlock(&kiq->ring_lock); - r = dma_fence_wait(f, false); - if (r) - DRM_ERROR("wait for kiq fence error: %ld.\n", r); - dma_fence_put(f); + if (f) { + BUG_ON(in_interrupt()); + r = dma_fence_wait(f, false); + if (r) + DRM_ERROR("wait for kiq fence error: %ld.\n", r); + dma_fence_put(f); + } } - /** * amdgpu_mm_rdoorbell - read a doorbell dword * |