Commit 84801d4f authored by Yunxiang Li's avatar Yunxiang Li Committed by Alex Deucher
Browse files

drm/amdgpu: fix locking scope when flushing tlb



Which method is used to flush tlb does not depend on whether a reset is
in progress or not. We should skip flush altogether if the GPU will get
reset. So put both path under reset_domain read lock.

Signed-off-by: default avatarYunxiang Li <Yunxiang.Li@amd.com>
Reviewed-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
CC: stable@vger.kernel.org
parent e2654a44
Loading
Loading
Loading
Loading
+34 −32
Original line number Diff line number Diff line
@@ -684,12 +684,17 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
	struct amdgpu_ring *ring = &adev->gfx.kiq[inst].ring;
	struct amdgpu_kiq *kiq = &adev->gfx.kiq[inst];
	unsigned int ndw;
	signed long r;
	int r;
	uint32_t seq;

	if (!adev->gmc.flush_pasid_uses_kiq || !ring->sched.ready ||
	    !down_read_trylock(&adev->reset_domain->sem)) {
	/*
	 * A GPU reset should flush all TLBs anyway, so no need to do
	 * this while one is ongoing.
	 */
	if (!down_read_trylock(&adev->reset_domain->sem))
		return 0;

	if (!adev->gmc.flush_pasid_uses_kiq || !ring->sched.ready) {
		if (adev->gmc.flush_tlb_needs_extra_type_2)
			adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid,
								 2, all_hub,
@@ -703,9 +708,8 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
		adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid,
							 flush_type, all_hub,
							 inst);
		return 0;
	}

		r = 0;
	} else {
		/* 2 dwords flush + 8 dwords fence */
		ndw = kiq->pmf->invalidate_tlbs_size + 8;

@@ -733,13 +737,11 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,

		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);
		if (amdgpu_fence_wait_polling(ring, seq, usec_timeout) < 1) {
			dev_err(adev->dev, "timeout waiting for kiq fence\n");
			r = -ETIME;
		goto error_unlock_reset;
		}
	r = 0;
	}

error_unlock_reset:
	up_read(&adev->reset_domain->sem);