summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndres Rodriguez <andresx7@gmail.com>2017-04-28 19:23:13 -0400
committerAndres Rodriguez <andresx7@gmail.com>2017-05-05 11:18:15 -0400
commit2515846865b341e6c32893272c191088a6e2f204 (patch)
tree1e86534730435be5f86339c2e98f4db9e0a38bdd
parentae98c8704a43aec77bd48abc53e017c0bff37709 (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.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c26
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
*