drm/amdgpu: invalidate mmhub semaphore workaround in gmc9/gmc10
It may lose gpuvm invalidate acknowldege state across power-gating off cycle. To avoid this issue in gmc9/gmc10 invalidation, add semaphore acquire before invalidation and semaphore release after invalidation. After adding semaphore acquire before invalidation, the semaphore register become read-only if another process try to acquire semaphore. Then it will not be able to release this semaphore. Then it may cause deadlock problem. If this deadlock problem happens, it needs a semaphore firmware fix. Signed-off-by: changzhu <Changfeng.Zhu@amd.com> Acked-by: Huang Rui <ray.huang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org
This commit is contained in:
parent
6c2c897237
commit
f920d1bb9c
|
@ -235,6 +235,29 @@ static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
|
||||||
const unsigned eng = 17;
|
const unsigned eng = 17;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
spin_lock(&adev->gmc.invalidate_lock);
|
||||||
|
/*
|
||||||
|
* It may lose gpuvm invalidate acknowldege state across power-gating
|
||||||
|
* off cycle, add semaphore acquire before invalidation and semaphore
|
||||||
|
* release after invalidation to avoid entering power gated state
|
||||||
|
* to WA the Issue
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
||||||
|
if (vmhub == AMDGPU_MMHUB_0 ||
|
||||||
|
vmhub == AMDGPU_MMHUB_1) {
|
||||||
|
for (i = 0; i < adev->usec_timeout; i++) {
|
||||||
|
/* a read return value of 1 means semaphore acuqire */
|
||||||
|
tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng);
|
||||||
|
if (tmp & 0x1)
|
||||||
|
break;
|
||||||
|
udelay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= adev->usec_timeout)
|
||||||
|
DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n");
|
||||||
|
}
|
||||||
|
|
||||||
WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, tmp);
|
WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, tmp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -254,6 +277,17 @@ static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
|
||||||
udelay(1);
|
udelay(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
||||||
|
if (vmhub == AMDGPU_MMHUB_0 ||
|
||||||
|
vmhub == AMDGPU_MMHUB_1)
|
||||||
|
/*
|
||||||
|
* add semaphore release after invalidation,
|
||||||
|
* write with 0 means semaphore release
|
||||||
|
*/
|
||||||
|
WREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng, 0);
|
||||||
|
|
||||||
|
spin_unlock(&adev->gmc.invalidate_lock);
|
||||||
|
|
||||||
if (i < adev->usec_timeout)
|
if (i < adev->usec_timeout)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -338,6 +372,20 @@ static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
|
||||||
uint32_t req = gmc_v10_0_get_invalidate_req(vmid, 0);
|
uint32_t req = gmc_v10_0_get_invalidate_req(vmid, 0);
|
||||||
unsigned eng = ring->vm_inv_eng;
|
unsigned eng = ring->vm_inv_eng;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It may lose gpuvm invalidate acknowldege state across power-gating
|
||||||
|
* off cycle, add semaphore acquire before invalidation and semaphore
|
||||||
|
* release after invalidation to avoid entering power gated state
|
||||||
|
* to WA the Issue
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
||||||
|
if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
|
||||||
|
ring->funcs->vmhub == AMDGPU_MMHUB_1)
|
||||||
|
/* a read return value of 1 means semaphore acuqire */
|
||||||
|
amdgpu_ring_emit_reg_wait(ring,
|
||||||
|
hub->vm_inv_eng0_sem + eng, 0x1, 0x1);
|
||||||
|
|
||||||
amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_lo32 + (2 * vmid),
|
amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_lo32 + (2 * vmid),
|
||||||
lower_32_bits(pd_addr));
|
lower_32_bits(pd_addr));
|
||||||
|
|
||||||
|
@ -348,6 +396,15 @@ static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
|
||||||
hub->vm_inv_eng0_ack + eng,
|
hub->vm_inv_eng0_ack + eng,
|
||||||
req, 1 << vmid);
|
req, 1 << vmid);
|
||||||
|
|
||||||
|
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
||||||
|
if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
|
||||||
|
ring->funcs->vmhub == AMDGPU_MMHUB_1)
|
||||||
|
/*
|
||||||
|
* add semaphore release after invalidation,
|
||||||
|
* write with 0 means semaphore release
|
||||||
|
*/
|
||||||
|
amdgpu_ring_emit_wreg(ring, hub->vm_inv_eng0_sem + eng, 0);
|
||||||
|
|
||||||
return pd_addr;
|
return pd_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -459,6 +459,29 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&adev->gmc.invalidate_lock);
|
spin_lock(&adev->gmc.invalidate_lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It may lose gpuvm invalidate acknowldege state across power-gating
|
||||||
|
* off cycle, add semaphore acquire before invalidation and semaphore
|
||||||
|
* release after invalidation to avoid entering power gated state
|
||||||
|
* to WA the Issue
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
||||||
|
if (vmhub == AMDGPU_MMHUB_0 ||
|
||||||
|
vmhub == AMDGPU_MMHUB_1) {
|
||||||
|
for (j = 0; j < adev->usec_timeout; j++) {
|
||||||
|
/* a read return value of 1 means semaphore acuqire */
|
||||||
|
tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng);
|
||||||
|
if (tmp & 0x1)
|
||||||
|
break;
|
||||||
|
udelay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j >= adev->usec_timeout)
|
||||||
|
DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n");
|
||||||
|
}
|
||||||
|
|
||||||
WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, tmp);
|
WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, tmp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -474,7 +497,18 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
||||||
break;
|
break;
|
||||||
udelay(1);
|
udelay(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
||||||
|
if (vmhub == AMDGPU_MMHUB_0 ||
|
||||||
|
vmhub == AMDGPU_MMHUB_1)
|
||||||
|
/*
|
||||||
|
* add semaphore release after invalidation,
|
||||||
|
* write with 0 means semaphore release
|
||||||
|
*/
|
||||||
|
WREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng, 0);
|
||||||
|
|
||||||
spin_unlock(&adev->gmc.invalidate_lock);
|
spin_unlock(&adev->gmc.invalidate_lock);
|
||||||
|
|
||||||
if (j < adev->usec_timeout)
|
if (j < adev->usec_timeout)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -489,6 +523,20 @@ static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
|
||||||
uint32_t req = gmc_v9_0_get_invalidate_req(vmid, 0);
|
uint32_t req = gmc_v9_0_get_invalidate_req(vmid, 0);
|
||||||
unsigned eng = ring->vm_inv_eng;
|
unsigned eng = ring->vm_inv_eng;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It may lose gpuvm invalidate acknowldege state across power-gating
|
||||||
|
* off cycle, add semaphore acquire before invalidation and semaphore
|
||||||
|
* release after invalidation to avoid entering power gated state
|
||||||
|
* to WA the Issue
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
||||||
|
if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
|
||||||
|
ring->funcs->vmhub == AMDGPU_MMHUB_1)
|
||||||
|
/* a read return value of 1 means semaphore acuqire */
|
||||||
|
amdgpu_ring_emit_reg_wait(ring,
|
||||||
|
hub->vm_inv_eng0_sem + eng, 0x1, 0x1);
|
||||||
|
|
||||||
amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_lo32 + (2 * vmid),
|
amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_lo32 + (2 * vmid),
|
||||||
lower_32_bits(pd_addr));
|
lower_32_bits(pd_addr));
|
||||||
|
|
||||||
|
@ -499,6 +547,15 @@ static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
|
||||||
hub->vm_inv_eng0_ack + eng,
|
hub->vm_inv_eng0_ack + eng,
|
||||||
req, 1 << vmid);
|
req, 1 << vmid);
|
||||||
|
|
||||||
|
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
||||||
|
if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
|
||||||
|
ring->funcs->vmhub == AMDGPU_MMHUB_1)
|
||||||
|
/*
|
||||||
|
* add semaphore release after invalidation,
|
||||||
|
* write with 0 means semaphore release
|
||||||
|
*/
|
||||||
|
amdgpu_ring_emit_wreg(ring, hub->vm_inv_eng0_sem + eng, 0);
|
||||||
|
|
||||||
return pd_addr;
|
return pd_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,8 @@
|
||||||
#include "nbio_v7_0.h"
|
#include "nbio_v7_0.h"
|
||||||
#include "nbio_v7_4.h"
|
#include "nbio_v7_4.h"
|
||||||
|
|
||||||
#define SOC15_FLUSH_GPU_TLB_NUM_WREG 4
|
#define SOC15_FLUSH_GPU_TLB_NUM_WREG 6
|
||||||
#define SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT 1
|
#define SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT 3
|
||||||
|
|
||||||
extern const struct amd_ip_funcs soc15_common_ip_funcs;
|
extern const struct amd_ip_funcs soc15_common_ip_funcs;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue