aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/5185-drm-amdgpu-use-kiq-to-do-invalidate-tlb.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/5185-drm-amdgpu-use-kiq-to-do-invalidate-tlb.patch')
-rw-r--r--common/recipes-kernel/linux/linux-yocto-4.14.71/5185-drm-amdgpu-use-kiq-to-do-invalidate-tlb.patch171
1 files changed, 171 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/5185-drm-amdgpu-use-kiq-to-do-invalidate-tlb.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/5185-drm-amdgpu-use-kiq-to-do-invalidate-tlb.patch
new file mode 100644
index 00000000..f48fafec
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/5185-drm-amdgpu-use-kiq-to-do-invalidate-tlb.patch
@@ -0,0 +1,171 @@
+From af65449ea823482ec1da97e04e7daf2414842292 Mon Sep 17 00:00:00 2001
+From: Emily Deng <Emily.Deng@amd.com>
+Date: Fri, 17 Aug 2018 18:25:36 +0800
+Subject: [PATCH 5185/5725] drm/amdgpu: use kiq to do invalidate tlb
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+To avoid the tlb flush not interrupted by world switch, use kiq and one
+command to do tlb invalidate.
+
+v2:
+Refine the invalidate lock position.
+
+Signed-off-by: Emily Deng <Emily.Deng@amd.com>
+Reviewed-and-Tested-by: Rex Zhu <Rex.Zhu@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 ++
+ drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 3 --
+ drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 74 +++++++++++++++++++++++++++++---
+ 3 files changed, 71 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+index ece78da..b11832a 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+@@ -216,6 +216,10 @@ enum amdgpu_kiq_irq {
+ AMDGPU_CP_KIQ_IRQ_LAST
+ };
+
++#define MAX_KIQ_REG_WAIT 5000 /* in usecs, 5ms */
++#define MAX_KIQ_REG_BAILOUT_INTERVAL 5 /* in msecs, 5ms */
++#define MAX_KIQ_REG_TRY 20
++
+ int amdgpu_device_ip_set_clockgating_state(void *dev,
+ enum amd_ip_block_type block_type,
+ enum amd_clockgating_state state);
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+index 21adb1b6..3885636 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+@@ -22,9 +22,6 @@
+ */
+
+ #include "amdgpu.h"
+-#define MAX_KIQ_REG_WAIT 5000 /* in usecs, 5ms */
+-#define MAX_KIQ_REG_BAILOUT_INTERVAL 5 /* in msecs, 5ms */
+-#define MAX_KIQ_REG_TRY 20
+
+ uint64_t amdgpu_csa_vaddr(struct amdgpu_device *adev)
+ {
+diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+index 8a5bccc..ff9868a 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+@@ -310,6 +310,58 @@ static uint32_t gmc_v9_0_get_invalidate_req(unsigned int vmid)
+ return req;
+ }
+
++signed long amdgpu_kiq_reg_write_reg_wait(struct amdgpu_device *adev,
++ uint32_t reg0, uint32_t reg1,
++ uint32_t ref, uint32_t mask)
++{
++ signed long r, cnt = 0;
++ unsigned long flags;
++ uint32_t seq;
++ struct amdgpu_kiq *kiq = &adev->gfx.kiq;
++ struct amdgpu_ring *ring = &kiq->ring;
++
++ if (!ring->ready)
++ return -EINVAL;
++
++ spin_lock_irqsave(&kiq->ring_lock, flags);
++
++ amdgpu_ring_alloc(ring, 32);
++ amdgpu_ring_emit_reg_write_reg_wait(ring, reg0, reg1,
++ ref, mask);
++ amdgpu_fence_emit_polling(ring, &seq);
++ amdgpu_ring_commit(ring);
++ spin_unlock_irqrestore(&kiq->ring_lock, flags);
++
++ r = amdgpu_fence_wait_polling(ring, seq, MAX_KIQ_REG_WAIT);
++
++ /* don't wait anymore for gpu reset case because this way may
++ * block gpu_recover() routine forever, e.g. this virt_kiq_rreg
++ * is triggered in TTM and ttm_bo_lock_delayed_workqueue() will
++ * never return if we keep waiting in virt_kiq_rreg, which cause
++ * gpu_recover() hang there.
++ *
++ * also don't wait anymore for IRQ context
++ * */
++ if (r < 1 && (adev->in_gpu_reset || in_interrupt()))
++ goto failed_kiq;
++
++ might_sleep();
++
++ while (r < 1 && cnt++ < MAX_KIQ_REG_TRY) {
++ msleep(MAX_KIQ_REG_BAILOUT_INTERVAL);
++ r = amdgpu_fence_wait_polling(ring, seq, MAX_KIQ_REG_WAIT);
++ }
++
++ if (cnt > MAX_KIQ_REG_TRY)
++ goto failed_kiq;
++
++ return 0;
++
++failed_kiq:
++ pr_err("failed to invalidate tlb with kiq\n");
++ return r;
++}
++
+ /*
+ * GART
+ * VMID 0 is the physical GPU addresses as used by the kernel.
+@@ -331,13 +383,19 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev,
+ /* Use register 17 for GART */
+ const unsigned eng = 17;
+ unsigned i, j;
+-
+- spin_lock(&adev->gmc.invalidate_lock);
++ int r;
+
+ for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) {
+ struct amdgpu_vmhub *hub = &adev->vmhub[i];
+ u32 tmp = gmc_v9_0_get_invalidate_req(vmid);
+
++ r = amdgpu_kiq_reg_write_reg_wait(adev, hub->vm_inv_eng0_req + eng,
++ hub->vm_inv_eng0_ack + eng, tmp, 1 << vmid);
++ if (!r)
++ continue;
++
++ spin_lock(&adev->gmc.invalidate_lock);
++
+ WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, tmp);
+
+ /* Busy wait for ACK.*/
+@@ -348,8 +406,10 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev,
+ break;
+ cpu_relax();
+ }
+- if (j < 100)
++ if (j < 100) {
++ spin_unlock(&adev->gmc.invalidate_lock);
+ continue;
++ }
+
+ /* Wait for ACK with a delay.*/
+ for (j = 0; j < adev->usec_timeout; j++) {
+@@ -359,13 +419,13 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev,
+ break;
+ udelay(1);
+ }
+- if (j < adev->usec_timeout)
++ if (j < adev->usec_timeout) {
++ spin_unlock(&adev->gmc.invalidate_lock);
+ continue;
+-
++ }
++ spin_unlock(&adev->gmc.invalidate_lock);
+ DRM_ERROR("Timeout waiting for VM flush ACK!\n");
+ }
+-
+- spin_unlock(&adev->gmc.invalidate_lock);
+ }
+
+ static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
+--
+2.7.4
+