diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2028-drm-amdgpu-busywait-KIQ-register-accessing-v4.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2028-drm-amdgpu-busywait-KIQ-register-accessing-v4.patch | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2028-drm-amdgpu-busywait-KIQ-register-accessing-v4.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2028-drm-amdgpu-busywait-KIQ-register-accessing-v4.patch new file mode 100644 index 00000000..a6ac1e03 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2028-drm-amdgpu-busywait-KIQ-register-accessing-v4.patch @@ -0,0 +1,254 @@ +From 437b7a31501b7a096e3cd9ea19d830895b2766a4 Mon Sep 17 00:00:00 2001 +From: pding <Pixel.Ding@amd.com> +Date: Fri, 13 Oct 2017 15:38:35 +0800 +Subject: [PATCH 2028/4131] drm/amdgpu: busywait KIQ register accessing (v4) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Register accessing is performed when IRQ is disabled. Never sleep in +this function. + +Known issue: dead sleep in many use cases of index/data registers. + +v2: + - wrap polling fence functions. + - don't trigger IRQ for polling in case of wrongly fence signal. + +v3: + - handle wrap round gracefully. + - add comments for polling function + +v4: + - don't return negative timeout confused with error code + +Signed-off-by: pding <Pixel.Ding@amd.com> +Reviewed-by: Christian König <christian.koenig@amd.com> +--- + drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 8 ++--- + drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 50 ++++++++++++++++++++++++++++++ + drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 2 +- + drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 4 +++ + drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 30 ++++++++---------- + 6 files changed, 71 insertions(+), 25 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +index b13c94f..65860f7 100755 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +@@ -905,7 +905,7 @@ struct amdgpu_mec { + struct amdgpu_kiq { + u64 eop_gpu_addr; + struct amdgpu_bo *eop_obj; +- struct mutex ring_mutex; ++ spinlock_t ring_lock; + struct amdgpu_ring ring; + struct amdgpu_irq_src irq; + }; +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index 74a63c2..05f4be0 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -110,10 +110,8 @@ uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg, + { + uint32_t ret; + +- if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev)) { +- BUG_ON(in_interrupt()); ++ if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev)) + return amdgpu_virt_kiq_rreg(adev, reg); +- } + + if ((reg * 4) < adev->rmmio_size && !(acc_flags & AMDGPU_REGS_IDX)) + ret = readl(((void __iomem *)adev->rmmio) + (reg * 4)); +@@ -138,10 +136,8 @@ void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, + adev->last_mm_index = v; + } + +- if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev)) { +- BUG_ON(in_interrupt()); ++ if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev)) + return amdgpu_virt_kiq_wreg(adev, reg, v); +- } + + if ((reg * 4) < adev->rmmio_size && !(acc_flags & AMDGPU_REGS_IDX)) + writel(v, ((void __iomem *)adev->rmmio) + (reg * 4)); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +index 7bdedd7..fb9f88ef 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +@@ -169,6 +169,32 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f) + } + + /** ++ * amdgpu_fence_emit_polling - emit a fence on the requeste ring ++ * ++ * @ring: ring the fence is associated with ++ * @s: resulting sequence number ++ * ++ * Emits a fence command on the requested ring (all asics). ++ * Used For polling fence. ++ * Returns 0 on success, -ENOMEM on failure. ++ */ ++int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s) ++{ ++ uint32_t seq; ++ ++ if (!s) ++ return -EINVAL; ++ ++ seq = ++ring->fence_drv.sync_seq; ++ amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, ++ seq, AMDGPU_FENCE_FLAG_INT); ++ ++ *s = seq; ++ ++ return 0; ++} ++ ++/** + * amdgpu_fence_schedule_fallback - schedule fallback check + * + * @ring: pointer to struct amdgpu_ring +@@ -282,6 +308,30 @@ int amdgpu_fence_wait_empty(struct amdgpu_ring *ring) + } + + /** ++ * amdgpu_fence_wait_polling - busy wait for givn sequence number ++ * ++ * @ring: ring index the fence is associated with ++ * @wait_seq: sequence number to wait ++ * @timeout: the timeout for waiting in usecs ++ * ++ * Wait for all fences on the requested ring to signal (all asics). ++ * Returns left time if no timeout, 0 or minus if timeout. ++ */ ++signed long amdgpu_fence_wait_polling(struct amdgpu_ring *ring, ++ uint32_t wait_seq, ++ signed long timeout) ++{ ++ uint32_t seq; ++ ++ do { ++ seq = amdgpu_fence_read(ring); ++ udelay(5); ++ timeout -= 5; ++ } while ((int32_t)(wait_seq - seq) > 0 && timeout > 0); ++ ++ return timeout > 0 ? timeout : 0; ++} ++/** + * amdgpu_fence_count_emitted - get the count of emitted fences + * + * @ring: ring the fence is associated with +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +index 9391db0..95f46b8 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +@@ -201,7 +201,7 @@ int amdgpu_gfx_kiq_init_ring(struct amdgpu_device *adev, + struct amdgpu_kiq *kiq = &adev->gfx.kiq; + int r = 0; + +- mutex_init(&kiq->ring_mutex); ++ spin_lock_init(&kiq->ring_lock); + + r = amdgpu_wb_get(adev, &adev->virt.reg_val_offs); + if (r) +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +index 494ff48..9fef7c7 100755 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +@@ -91,8 +91,12 @@ int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring, + 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); ++int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s); + void 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, ++ uint32_t wait_seq, ++ signed long timeout); + unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring); + + /* +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +index ed7be2e..e97f80f 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +@@ -22,7 +22,7 @@ + */ + + #include "amdgpu.h" +-#define MAX_KIQ_REG_WAIT 100000 ++#define MAX_KIQ_REG_WAIT 100000000 /* in usecs */ + + int amdgpu_allocate_static_csa(struct amdgpu_device *adev) + { +@@ -114,27 +114,24 @@ void amdgpu_virt_init_setting(struct amdgpu_device *adev) + uint32_t amdgpu_virt_kiq_rreg(struct amdgpu_device *adev, uint32_t reg) + { + signed long r; +- uint32_t val; +- struct dma_fence *f; ++ uint32_t val, seq; + struct amdgpu_kiq *kiq = &adev->gfx.kiq; + struct amdgpu_ring *ring = &kiq->ring; + + BUG_ON(!ring->funcs->emit_rreg); + +- mutex_lock(&kiq->ring_mutex); ++ spin_lock(&kiq->ring_lock); + amdgpu_ring_alloc(ring, 32); + amdgpu_ring_emit_rreg(ring, reg); +- amdgpu_fence_emit(ring, &f); ++ amdgpu_fence_emit_polling(ring, &seq); + amdgpu_ring_commit(ring); +- mutex_unlock(&kiq->ring_mutex); ++ spin_unlock(&kiq->ring_lock); + +- r = dma_fence_wait_timeout(f, false, msecs_to_jiffies(MAX_KIQ_REG_WAIT)); +- dma_fence_put(f); ++ r = amdgpu_fence_wait_polling(ring, seq, MAX_KIQ_REG_WAIT); + if (r < 1) { +- DRM_ERROR("wait for kiq fence error: %ld.\n", r); ++ DRM_ERROR("wait for kiq fence error: %ld\n", r); + return ~0; + } +- + val = adev->wb.wb[adev->virt.reg_val_offs]; + + return val; +@@ -143,23 +140,22 @@ uint32_t amdgpu_virt_kiq_rreg(struct amdgpu_device *adev, uint32_t reg) + void amdgpu_virt_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v) + { + signed long r; +- struct dma_fence *f; ++ uint32_t seq; + struct amdgpu_kiq *kiq = &adev->gfx.kiq; + struct amdgpu_ring *ring = &kiq->ring; + + BUG_ON(!ring->funcs->emit_wreg); + +- mutex_lock(&kiq->ring_mutex); ++ spin_lock(&kiq->ring_lock); + amdgpu_ring_alloc(ring, 32); + amdgpu_ring_emit_wreg(ring, reg, v); +- amdgpu_fence_emit(ring, &f); ++ amdgpu_fence_emit_polling(ring, &seq); + amdgpu_ring_commit(ring); +- mutex_unlock(&kiq->ring_mutex); ++ spin_unlock(&kiq->ring_lock); + +- r = dma_fence_wait_timeout(f, false, msecs_to_jiffies(MAX_KIQ_REG_WAIT)); ++ r = amdgpu_fence_wait_polling(ring, seq, MAX_KIQ_REG_WAIT); + if (r < 1) +- DRM_ERROR("wait for kiq fence error: %ld.\n", r); +- dma_fence_put(f); ++ DRM_ERROR("wait for kiq fence error: %ld\n", r); + } + + /** +-- +2.7.4 + |