diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c | 44 | 
1 files changed, 41 insertions, 3 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c index 88de9f0d4728..358b91243e37 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c @@ -637,10 +637,34 @@ static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base *entry)  	}  	ttm_bo_set_bulk_move(&entry->bo->tbo, NULL);  	entry->bo->vm_bo = NULL; + +	spin_lock(&entry->vm->status_lock);  	list_del(&entry->vm_status); +	spin_unlock(&entry->vm->status_lock);  	amdgpu_bo_unref(&entry->bo);  } +void amdgpu_vm_pt_free_work(struct work_struct *work) +{ +	struct amdgpu_vm_bo_base *entry, *next; +	struct amdgpu_vm *vm; +	LIST_HEAD(pt_freed); + +	vm = container_of(work, struct amdgpu_vm, pt_free_work); + +	spin_lock(&vm->status_lock); +	list_splice_init(&vm->pt_freed, &pt_freed); +	spin_unlock(&vm->status_lock); + +	/* flush_work in amdgpu_vm_fini ensure vm->root.bo is valid. */ +	amdgpu_bo_reserve(vm->root.bo, true); + +	list_for_each_entry_safe(entry, next, &pt_freed, vm_status) +		amdgpu_vm_pt_free(entry); + +	amdgpu_bo_unreserve(vm->root.bo); +} +  /**   * amdgpu_vm_pt_free_dfs - free PD/PT levels   * @@ -652,11 +676,24 @@ static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base *entry)   */  static void amdgpu_vm_pt_free_dfs(struct amdgpu_device *adev,  				  struct amdgpu_vm *vm, -				  struct amdgpu_vm_pt_cursor *start) +				  struct amdgpu_vm_pt_cursor *start, +				  bool unlocked)  {  	struct amdgpu_vm_pt_cursor cursor;  	struct amdgpu_vm_bo_base *entry; +	if (unlocked) { +		spin_lock(&vm->status_lock); +		for_each_amdgpu_vm_pt_dfs_safe(adev, vm, start, cursor, entry) +			list_move(&entry->vm_status, &vm->pt_freed); + +		if (start) +			list_move(&start->entry->vm_status, &vm->pt_freed); +		spin_unlock(&vm->status_lock); +		schedule_work(&vm->pt_free_work); +		return; +	} +  	for_each_amdgpu_vm_pt_dfs_safe(adev, vm, start, cursor, entry)  		amdgpu_vm_pt_free(entry); @@ -673,7 +710,7 @@ static void amdgpu_vm_pt_free_dfs(struct amdgpu_device *adev,   */  void amdgpu_vm_pt_free_root(struct amdgpu_device *adev, struct amdgpu_vm *vm)  { -	amdgpu_vm_pt_free_dfs(adev, vm, NULL); +	amdgpu_vm_pt_free_dfs(adev, vm, NULL, false);  }  /** @@ -966,7 +1003,8 @@ int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params *params,  				if (cursor.entry->bo) {  					params->table_freed = true;  					amdgpu_vm_pt_free_dfs(adev, params->vm, -							      &cursor); +							      &cursor, +							      params->unlocked);  				}  				amdgpu_vm_pt_next(adev, &cursor);  			}  |