Adds a new helper to do TLB invalidation using SDMA.
Signed-off-by: Alex Deucher <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 36 +++++++++++++++++++++
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 2 ++
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 42 +++++++++++++++++++++++++
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 6 ++++
4 files changed, 86 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
index 3f0b1b7a557b9..5c1237a30b865 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
@@ -928,6 +928,42 @@ void amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device
*adev,
dev_err(adev->dev, "failed to write reg %x wait reg %x\n", reg0, reg1);
}
+int amdgpu_gmc_flush_gpu_tlb_helper(struct amdgpu_device *adev, uint32_t vmid,
+ uint32_t vmhub, uint32_t flush_type)
+{
+ struct dma_fence *fence;
+ /* Use register 17 for GART */
+ u32 inst, eng = 17;
+ int r;
+
+ if (AMDGPU_IS_GFXHUB(vmhub) && !adev->gfx.is_poweron)
+ return 0;
+
+ if (vmhub >= AMDGPU_MMHUB0(0))
+ inst = 0;
+ else
+ inst = vmhub;
+
+ /* flush hdp cache */
+ amdgpu_device_flush_hdp(adev, NULL);
+
+ mutex_lock(&adev->mman.default_entity.lock);
+ r = amdgpu_ttm_tlb_inv(adev, vmid, vmhub, eng, flush_type, inst,
+ &adev->mman.default_entity,
+ NULL, &fence);
+ if (r)
+ goto exit;
+ r = dma_fence_wait(fence, false);
+ dma_fence_put(fence);
+ if (r)
+ goto exit;
+
+exit:
+ mutex_unlock(&adev->mman.default_entity.lock);
+
+ return r;
+}
+
/**
* amdgpu_gmc_tmz_set -- check and set if a device supports TMZ
* @adev: amdgpu_device pointer
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
index 3ca187f5ade85..0135be1418a91 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
@@ -450,6 +450,8 @@ void amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device
*adev,
uint32_t reg0, uint32_t reg1,
uint32_t ref, uint32_t mask,
uint32_t xcc_inst);
+int amdgpu_gmc_flush_gpu_tlb_helper(struct amdgpu_device *adev, uint32_t vmid,
+ uint32_t vmhub, uint32_t flush_type);
extern void amdgpu_gmc_tmz_set(struct amdgpu_device *adev);
extern void amdgpu_gmc_noretry_set(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 74ada995bd8e5..03e74b7ca0003 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -2513,6 +2513,48 @@ int amdgpu_copy_buffer(struct amdgpu_device *adev,
return r;
}
+int amdgpu_ttm_tlb_inv(struct amdgpu_device *adev,
+ unsigned int vmid, u32 vmhub, u32 eng,
+ u32 flush_type, u32 xcc_inst,
+ struct amdgpu_ttm_buffer_entity *entity,
+ struct dma_resv *resv,
+ struct dma_fence **fence)
+{
+ struct amdgpu_ring *ring;
+ struct amdgpu_job *job;
+ int r, num_dw;
+
+ if (!adev->mman.buffer_funcs_enabled)
+ return -EINVAL;
+
+ ring = to_amdgpu_ring(adev->mman.buffer_funcs_scheds[0]);
+
+ if (!ring->sched.ready) {
+ dev_err(adev->dev,
+ "Trying to inv tlbs with ring turned off.\n");
+ return -EINVAL;
+ }
+
+ num_dw = ALIGN(adev->mman.buffer_funcs->tlb_inv_num_dw, 8);
+ r = amdgpu_ttm_prepare_job(adev, entity, num_dw,
+ resv, false, &job,
+ AMDGPU_KERNEL_JOB_ID_VM_UPDATE);
+ if (r)
+ goto error_free;
+
+ amdgpu_emit_tlb_inv(adev, &job->ibs[0], vmid, vmhub, eng,
+ flush_type, xcc_inst);
+
+ *fence = amdgpu_ttm_job_submit(adev, entity, job, num_dw);
+
+ return 0;
+
+error_free:
+ amdgpu_job_free(job);
+ dev_err(adev->dev, "Error scheduling IBs (%d)\n", r);
+ return r;
+}
+
static int amdgpu_ttm_fill_mem(struct amdgpu_device *adev,
struct amdgpu_ttm_buffer_entity *entity,
uint32_t src_data,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
index ff9e2e3466099..f6a69c5a5ee86 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
@@ -195,6 +195,12 @@ int amdgpu_copy_buffer(struct amdgpu_device *adev,
struct dma_resv *resv,
struct dma_fence **fence,
bool vm_needs_flush, uint32_t copy_flags);
+int amdgpu_ttm_tlb_inv(struct amdgpu_device *adev,
+ unsigned int vmid, u32 vmhub, u32 eng,
+ u32 flush_type, u32 xcc_inst,
+ struct amdgpu_ttm_buffer_entity *entity,
+ struct dma_resv *resv,
+ struct dma_fence **fence);
int amdgpu_ttm_clear_buffer(struct amdgpu_ttm_buffer_entity *entity,
struct amdgpu_bo *bo,
struct dma_resv *resv,
--
2.55.0