drm/amdgpu: fix and cleanup gmc_v9_0_flush_gpu_tlb_pasid

Testing for reset is pointless since the reset can start right after the
test.

The same PASID can be used by more than one VMID, invalidate each of them.

Move the KIQ and all the workaround handling into common GMC code.

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Christian König
2023-09-04 13:03:23 +02:00
committed by Alex Deucher
parent 0c525aa406
commit e7b90e99fa
3 changed files with 102 additions and 79 deletions

View File

@@ -32,6 +32,7 @@
#include "amdgpu.h"
#include "amdgpu_gmc.h"
#include "amdgpu_ras.h"
#include "amdgpu_reset.h"
#include "amdgpu_xgmi.h"
#include <drm/drm_drv.h>
@@ -630,6 +631,65 @@ error_alloc:
dev_err(adev->dev, "Error flushing GPU TLB using the SDMA (%d)!\n", r);
}
int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
uint32_t flush_type, bool all_hub,
uint32_t inst)
{
u32 usec_timeout = amdgpu_sriov_vf(adev) ? SRIOV_USEC_TIMEOUT :
adev->usec_timeout;
struct amdgpu_ring *ring = &adev->gfx.kiq[inst].ring;
struct amdgpu_kiq *kiq = &adev->gfx.kiq[inst];
unsigned int ndw;
signed long r;
uint32_t seq;
if (!adev->gmc.flush_pasid_uses_kiq || !ring->sched.ready ||
!down_read_trylock(&adev->reset_domain->sem)) {
return adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid,
flush_type,
all_hub, inst);
}
/* 2 dwords flush + 8 dwords fence */
ndw = kiq->pmf->invalidate_tlbs_size + 8;
if (adev->gmc.flush_tlb_needs_extra_type_2)
ndw += kiq->pmf->invalidate_tlbs_size;
if (adev->gmc.flush_tlb_needs_extra_type_0)
ndw += kiq->pmf->invalidate_tlbs_size;
spin_lock(&adev->gfx.kiq[inst].ring_lock);
amdgpu_ring_alloc(ring, ndw);
if (adev->gmc.flush_tlb_needs_extra_type_2)
kiq->pmf->kiq_invalidate_tlbs(ring, pasid, 2, all_hub);
if (flush_type == 2 && adev->gmc.flush_tlb_needs_extra_type_0)
kiq->pmf->kiq_invalidate_tlbs(ring, pasid, 0, all_hub);
kiq->pmf->kiq_invalidate_tlbs(ring, pasid, flush_type, all_hub);
r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
if (r) {
amdgpu_ring_undo(ring);
spin_unlock(&adev->gfx.kiq[inst].ring_lock);
goto error_unlock_reset;
}
amdgpu_ring_commit(ring);
spin_unlock(&adev->gfx.kiq[inst].ring_lock);
r = amdgpu_fence_wait_polling(ring, seq, usec_timeout);
if (r < 1) {
dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r);
r = -ETIME;
goto error_unlock_reset;
}
r = 0;
error_unlock_reset:
up_read(&adev->reset_domain->sem);
return r;
}
/**
* amdgpu_gmc_tmz_set -- check and set if a device supports TMZ
* @adev: amdgpu_device pointer