diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 40 | 
1 files changed, 33 insertions, 7 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 4dc75eda1d91..d16231d6a790 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -83,6 +83,32 @@ struct amdgpu_prt_cb {  };  /** + * vm eviction_lock can be taken in MMU notifiers. Make sure no reclaim-FS + * happens while holding this lock anywhere to prevent deadlocks when + * an MMU notifier runs in reclaim-FS context. + */ +static inline void amdgpu_vm_eviction_lock(struct amdgpu_vm *vm) +{ +	mutex_lock(&vm->eviction_lock); +	vm->saved_flags = memalloc_nofs_save(); +} + +static inline int amdgpu_vm_eviction_trylock(struct amdgpu_vm *vm) +{ +	if (mutex_trylock(&vm->eviction_lock)) { +		vm->saved_flags = memalloc_nofs_save(); +		return 1; +	} +	return 0; +} + +static inline void amdgpu_vm_eviction_unlock(struct amdgpu_vm *vm) +{ +	memalloc_nofs_restore(vm->saved_flags); +	mutex_unlock(&vm->eviction_lock); +} + +/**   * amdgpu_vm_level_shift - return the addr shift for each level   *   * @adev: amdgpu_device pointer @@ -678,9 +704,9 @@ int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,  		}  	} -	mutex_lock(&vm->eviction_lock); +	amdgpu_vm_eviction_lock(vm);  	vm->evicting = false; -	mutex_unlock(&vm->eviction_lock); +	amdgpu_vm_eviction_unlock(vm);  	return 0;  } @@ -1559,7 +1585,7 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,  	if (!(flags & AMDGPU_PTE_VALID))  		owner = AMDGPU_FENCE_OWNER_KFD; -	mutex_lock(&vm->eviction_lock); +	amdgpu_vm_eviction_lock(vm);  	if (vm->evicting) {  		r = -EBUSY;  		goto error_unlock; @@ -1576,7 +1602,7 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,  	r = vm->update_funcs->commit(¶ms, fence);  error_unlock: -	mutex_unlock(&vm->eviction_lock); +	amdgpu_vm_eviction_unlock(vm);  	return r;  } @@ -2533,18 +2559,18 @@ bool amdgpu_vm_evictable(struct amdgpu_bo *bo)  		return false;  	/* Try to block ongoing updates */ -	if (!mutex_trylock(&bo_base->vm->eviction_lock)) +	if (!amdgpu_vm_eviction_trylock(bo_base->vm))  		return false;  	/* Don't evict VM page tables while they are updated */  	if (!dma_fence_is_signaled(bo_base->vm->last_direct) ||  	    !dma_fence_is_signaled(bo_base->vm->last_delayed)) { -		mutex_unlock(&bo_base->vm->eviction_lock); +		amdgpu_vm_eviction_unlock(bo_base->vm);  		return false;  	}  	bo_base->vm->evicting = true; -	mutex_unlock(&bo_base->vm->eviction_lock); +	amdgpu_vm_eviction_unlock(bo_base->vm);  	return true;  }  | 
