diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 147 | 
1 files changed, 58 insertions, 89 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 078c068937fe..6362e861a3f5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -88,6 +88,46 @@ struct amdgpu_prt_cb {  	struct dma_fence_cb cb;  }; +/** + * amdgpu_vm_set_pasid - manage pasid and vm ptr mapping + * + * @adev: amdgpu_device pointer + * @vm: amdgpu_vm pointer + * @pasid: the pasid the VM is using on this GPU + * + * Set the pasid this VM is using on this GPU, can also be used to remove the + * pasid by passing in zero. + * + */ +int amdgpu_vm_set_pasid(struct amdgpu_device *adev, struct amdgpu_vm *vm, +			u32 pasid) +{ +	int r; + +	if (vm->pasid == pasid) +		return 0; + +	if (vm->pasid) { +		r = xa_err(xa_erase_irq(&adev->vm_manager.pasids, vm->pasid)); +		if (r < 0) +			return r; + +		vm->pasid = 0; +	} + +	if (pasid) { +		r = xa_err(xa_store_irq(&adev->vm_manager.pasids, pasid, vm, +					GFP_KERNEL)); +		if (r < 0) +			return r; + +		vm->pasid = pasid; +	} + + +	return 0; +} +  /*   * vm eviction_lock can be taken in MMU notifiers. Make sure no reclaim-FS   * happens while holding this lock anywhere to prevent deadlocks when @@ -2863,14 +2903,13 @@ long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout)   *   * @adev: amdgpu_device pointer   * @vm: requested vm - * @pasid: Process address space identifier   *   * Init @vm fields.   *   * Returns:   * 0 for success, error for failure.   */ -int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid) +int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)  {  	struct amdgpu_bo *root_bo;  	struct amdgpu_bo_vm *root; @@ -2944,19 +2983,6 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid)  	amdgpu_bo_unreserve(vm->root.bo); -	if (pasid) { -		unsigned long flags; - -		spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); -		r = idr_alloc(&adev->vm_manager.pasid_idr, vm, pasid, pasid + 1, -			      GFP_ATOMIC); -		spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); -		if (r < 0) -			goto error_free_root; - -		vm->pasid = pasid; -	} -  	INIT_KFIFO(vm->faults);  	return 0; @@ -3012,7 +3038,6 @@ static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev,   *   * @adev: amdgpu_device pointer   * @vm: requested vm - * @pasid: pasid to use   *   * This only works on GFX VMs that don't have any BOs added and no   * page tables allocated yet. @@ -3020,7 +3045,6 @@ static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev,   * Changes the following VM parameters:   * - use_cpu_for_update   * - pte_supports_ats - * - pasid (old PASID is released, because compute manages its own PASIDs)   *   * Reinitializes the page directory to reflect the changed ATS   * setting. @@ -3028,8 +3052,7 @@ static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev,   * Returns:   * 0 for success, -errno for errors.   */ -int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, -			   u32 pasid) +int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm)  {  	bool pte_support_ats = (adev->asic_type == CHIP_RAVEN);  	int r; @@ -3043,19 +3066,6 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm,  	if (r)  		goto unreserve_bo; -	if (pasid) { -		unsigned long flags; - -		spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); -		r = idr_alloc(&adev->vm_manager.pasid_idr, vm, pasid, pasid + 1, -			      GFP_ATOMIC); -		spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); - -		if (r == -ENOSPC) -			goto unreserve_bo; -		r = 0; -	} -  	/* Check if PD needs to be reinitialized and do it before  	 * changing any other state, in case it fails.  	 */ @@ -3065,7 +3075,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm,  				       to_amdgpu_bo_vm(vm->root.bo),  				       false);  		if (r) -			goto free_idr; +			goto unreserve_bo;  	}  	/* Update VM state */ @@ -3082,7 +3092,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm,  		r = amdgpu_bo_sync_wait(vm->root.bo,  					AMDGPU_FENCE_OWNER_UNDEFINED, true);  		if (r) -			goto free_idr; +			goto unreserve_bo;  		vm->update_funcs = &amdgpu_vm_cpu_funcs;  	} else { @@ -3092,36 +3102,11 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm,  	vm->last_update = NULL;  	vm->is_compute_context = true; -	if (vm->pasid) { -		unsigned long flags; - -		spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); -		idr_remove(&adev->vm_manager.pasid_idr, vm->pasid); -		spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); - -		/* Free the original amdgpu allocated pasid -		 * Will be replaced with kfd allocated pasid -		 */ -		amdgpu_pasid_free(vm->pasid); -		vm->pasid = 0; -	} -  	/* Free the shadow bo for compute VM */  	amdgpu_bo_unref(&to_amdgpu_bo_vm(vm->root.bo)->shadow); -	if (pasid) -		vm->pasid = pasid; -  	goto unreserve_bo; -free_idr: -	if (pasid) { -		unsigned long flags; - -		spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); -		idr_remove(&adev->vm_manager.pasid_idr, pasid); -		spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); -	}  unreserve_bo:  	amdgpu_bo_unreserve(vm->root.bo);  	return r; @@ -3137,14 +3122,7 @@ unreserve_bo:   */  void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm)  { -	if (vm->pasid) { -		unsigned long flags; - -		spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); -		idr_remove(&adev->vm_manager.pasid_idr, vm->pasid); -		spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); -	} -	vm->pasid = 0; +	amdgpu_vm_set_pasid(adev, vm, 0);  	vm->is_compute_context = false;  } @@ -3168,15 +3146,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)  	root = amdgpu_bo_ref(vm->root.bo);  	amdgpu_bo_reserve(root, true); -	if (vm->pasid) { -		unsigned long flags; - -		spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); -		idr_remove(&adev->vm_manager.pasid_idr, vm->pasid); -		spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); -		vm->pasid = 0; -	} - +	amdgpu_vm_set_pasid(adev, vm, 0);  	dma_fence_wait(vm->last_unlocked, false);  	dma_fence_put(vm->last_unlocked); @@ -3258,8 +3228,7 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev)  	adev->vm_manager.vm_update_mode = 0;  #endif -	idr_init(&adev->vm_manager.pasid_idr); -	spin_lock_init(&adev->vm_manager.pasid_lock); +	xa_init_flags(&adev->vm_manager.pasids, XA_FLAGS_LOCK_IRQ);  }  /** @@ -3271,8 +3240,8 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev)   */  void amdgpu_vm_manager_fini(struct amdgpu_device *adev)  { -	WARN_ON(!idr_is_empty(&adev->vm_manager.pasid_idr)); -	idr_destroy(&adev->vm_manager.pasid_idr); +	WARN_ON(!xa_empty(&adev->vm_manager.pasids)); +	xa_destroy(&adev->vm_manager.pasids);  	amdgpu_vmid_mgr_fini(adev);  } @@ -3341,13 +3310,13 @@ void amdgpu_vm_get_task_info(struct amdgpu_device *adev, u32 pasid,  	struct amdgpu_vm *vm;  	unsigned long flags; -	spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); +	xa_lock_irqsave(&adev->vm_manager.pasids, flags); -	vm = idr_find(&adev->vm_manager.pasid_idr, pasid); +	vm = xa_load(&adev->vm_manager.pasids, pasid);  	if (vm)  		*task_info = vm->task_info; -	spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); +	xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);  }  /** @@ -3389,15 +3358,15 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,  	struct amdgpu_vm *vm;  	int r; -	spin_lock_irqsave(&adev->vm_manager.pasid_lock, irqflags); -	vm = idr_find(&adev->vm_manager.pasid_idr, pasid); +	xa_lock_irqsave(&adev->vm_manager.pasids, irqflags); +	vm = xa_load(&adev->vm_manager.pasids, pasid);  	if (vm) {  		root = amdgpu_bo_ref(vm->root.bo);  		is_compute_context = vm->is_compute_context;  	} else {  		root = NULL;  	} -	spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, irqflags); +	xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);  	if (!root)  		return false; @@ -3415,11 +3384,11 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,  		goto error_unref;  	/* Double check that the VM still exists */ -	spin_lock_irqsave(&adev->vm_manager.pasid_lock, irqflags); -	vm = idr_find(&adev->vm_manager.pasid_idr, pasid); +	xa_lock_irqsave(&adev->vm_manager.pasids, irqflags); +	vm = xa_load(&adev->vm_manager.pasids, pasid);  	if (vm && vm->root.bo != root)  		vm = NULL; -	spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, irqflags); +	xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);  	if (!vm)  		goto error_unlock; |