mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 09:20:13 -04:00
drm/amdgpu: Resolve VM through DRM PASID ownership
Allocate DRM PASIDs with fpriv and resolve VM lookup users through: PASID -> fpriv -> VM This preserves the root BO reference and revalidation flow in amdgpu_vm_lock_by_pasid(). The obsolete per-device vm_manager.pasids mapping is removed by the following patch in this series. v6: - Allocate and publish the DRM PASID after amdgpu_vm_init() completes. - Assign the allocated PASID to vm->pasid in the DRM open path. - Unpublish PASID ownership before tearing down the VM in both the open-failure and normal file-close paths. v5: - Delay DRM PASID allocation until after amdgpu_vm_init() completes. v4: - Allocate DRM PASIDs with fpriv directly. - Squash ownership registration and PASID lookup conversion. Cc: Alex Deucher <alexander.deucher@amd.com> Suggested-by: Christian König <christian.koenig@amd.com> Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
committed by
Alex Deucher
parent
636df65409
commit
b0ae60ea3f
@@ -1376,11 +1376,11 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
|
||||
memset(&gpuvm_fault, 0, sizeof(gpuvm_fault));
|
||||
|
||||
xa_lock_irqsave(&adev->vm_manager.pasids, flags);
|
||||
amdgpu_pasid_lock(&flags);
|
||||
gpuvm_fault.addr = vm->fault_info.addr;
|
||||
gpuvm_fault.status = vm->fault_info.status;
|
||||
gpuvm_fault.vmhub = vm->fault_info.vmhub;
|
||||
xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
|
||||
amdgpu_pasid_unlock(flags);
|
||||
|
||||
return copy_to_user(out, &gpuvm_fault,
|
||||
min((size_t)size, sizeof(gpuvm_fault))) ? -EFAULT : 0;
|
||||
@@ -1465,7 +1465,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
struct amdgpu_fpriv *fpriv;
|
||||
struct drm_exec exec;
|
||||
int r, pasid;
|
||||
int r, pasid = 0;
|
||||
|
||||
/* Ensure IB tests are run on ring */
|
||||
flush_delayed_work(&adev->delayed_init_work);
|
||||
@@ -1488,22 +1488,23 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
|
||||
goto out_suspend;
|
||||
}
|
||||
|
||||
pasid = amdgpu_pasid_alloc(16, NULL);
|
||||
if (pasid < 0) {
|
||||
dev_warn(adev->dev, "No more PASIDs available!");
|
||||
pasid = 0;
|
||||
}
|
||||
|
||||
r = amdgpu_xcp_open_device(adev, fpriv, file_priv);
|
||||
if (r)
|
||||
goto error_pasid;
|
||||
|
||||
amdgpu_debugfs_vm_init(file_priv);
|
||||
|
||||
r = amdgpu_vm_init(adev, &fpriv->vm, fpriv->xcp_id, pasid);
|
||||
r = amdgpu_vm_init(adev, &fpriv->vm, fpriv->xcp_id, 0);
|
||||
if (r)
|
||||
goto error_pasid;
|
||||
|
||||
pasid = amdgpu_pasid_alloc(16, fpriv);
|
||||
if (pasid < 0) {
|
||||
dev_warn(adev->dev, "No more PASIDs available!");
|
||||
pasid = 0;
|
||||
}
|
||||
fpriv->vm.pasid = pasid;
|
||||
|
||||
drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 0);
|
||||
drm_exec_until_all_locked(&exec) {
|
||||
r = amdgpu_vm_lock_pd(&fpriv->vm, &exec, 0);
|
||||
@@ -1547,12 +1548,14 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
|
||||
goto out_suspend;
|
||||
|
||||
error_vm:
|
||||
if (pasid) {
|
||||
amdgpu_pasid_free(pasid);
|
||||
pasid = 0;
|
||||
}
|
||||
|
||||
amdgpu_vm_fini(adev, &fpriv->vm);
|
||||
|
||||
error_pasid:
|
||||
if (pasid)
|
||||
amdgpu_pasid_free(pasid);
|
||||
|
||||
kfree(fpriv);
|
||||
|
||||
out_suspend:
|
||||
@@ -1608,10 +1611,11 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
|
||||
}
|
||||
|
||||
amdgpu_ctx_mgr_fini(&fpriv->ctx_mgr);
|
||||
amdgpu_vm_fini(adev, &fpriv->vm);
|
||||
|
||||
if (pasid)
|
||||
amdgpu_pasid_free_delayed(pd->tbo.base.resv, pasid);
|
||||
|
||||
amdgpu_vm_fini(adev, &fpriv->vm);
|
||||
amdgpu_bo_unref(&pd);
|
||||
|
||||
xa_for_each(&fpriv->bo_list_handles, handle, list)
|
||||
|
||||
@@ -2506,14 +2506,16 @@ amdgpu_vm_get_task_info_vm(struct amdgpu_vm *vm)
|
||||
struct amdgpu_task_info *
|
||||
amdgpu_vm_get_task_info_pasid(struct amdgpu_device *adev, u32 pasid)
|
||||
{
|
||||
struct amdgpu_fpriv *fpriv;
|
||||
struct amdgpu_task_info *ti;
|
||||
struct amdgpu_vm *vm;
|
||||
unsigned long flags;
|
||||
|
||||
xa_lock_irqsave(&adev->vm_manager.pasids, flags);
|
||||
vm = xa_load(&adev->vm_manager.pasids, pasid);
|
||||
amdgpu_pasid_lock(&flags);
|
||||
fpriv = amdgpu_pasid_get_fpriv_locked(pasid);
|
||||
vm = fpriv ? &fpriv->vm : NULL;
|
||||
ti = amdgpu_vm_get_task_info_vm(vm);
|
||||
xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
|
||||
amdgpu_pasid_unlock(flags);
|
||||
|
||||
return ti;
|
||||
}
|
||||
@@ -2935,14 +2937,16 @@ struct amdgpu_vm *amdgpu_vm_lock_by_pasid(struct amdgpu_device *adev,
|
||||
u32 pasid, struct drm_exec *exec)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
struct amdgpu_fpriv *fpriv;
|
||||
struct amdgpu_bo *root;
|
||||
struct amdgpu_vm *vm;
|
||||
int r;
|
||||
|
||||
xa_lock_irqsave(&adev->vm_manager.pasids, irqflags);
|
||||
vm = xa_load(&adev->vm_manager.pasids, pasid);
|
||||
root = vm ? amdgpu_bo_ref(vm->root.bo) : NULL;
|
||||
xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);
|
||||
amdgpu_pasid_lock(&irqflags);
|
||||
fpriv = amdgpu_pasid_get_fpriv_locked(pasid);
|
||||
vm = fpriv ? &fpriv->vm : NULL;
|
||||
root = vm && vm->root.bo ? amdgpu_bo_ref(vm->root.bo) : NULL;
|
||||
amdgpu_pasid_unlock(irqflags);
|
||||
|
||||
if (!root)
|
||||
return NULL;
|
||||
@@ -2954,11 +2958,17 @@ struct amdgpu_vm *amdgpu_vm_lock_by_pasid(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
/* Double check that the VM still exists */
|
||||
xa_lock_irqsave(&adev->vm_manager.pasids, irqflags);
|
||||
vm = xa_load(&adev->vm_manager.pasids, pasid);
|
||||
if (vm && vm->root.bo != root)
|
||||
amdgpu_pasid_lock(&irqflags);
|
||||
fpriv = amdgpu_pasid_get_fpriv_locked(pasid);
|
||||
if (!fpriv) {
|
||||
vm = NULL;
|
||||
xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);
|
||||
} else {
|
||||
vm = &fpriv->vm;
|
||||
if (vm->root.bo != root)
|
||||
vm = NULL;
|
||||
}
|
||||
amdgpu_pasid_unlock(irqflags);
|
||||
|
||||
if (!vm) {
|
||||
drm_exec_unlock_obj(exec, &root->tbo.base);
|
||||
amdgpu_bo_unref(&root);
|
||||
@@ -3155,12 +3165,14 @@ void amdgpu_vm_update_fault_cache(struct amdgpu_device *adev,
|
||||
uint32_t status,
|
||||
unsigned int vmhub)
|
||||
{
|
||||
struct amdgpu_fpriv *fpriv;
|
||||
struct amdgpu_vm *vm;
|
||||
unsigned long flags;
|
||||
|
||||
xa_lock_irqsave(&adev->vm_manager.pasids, flags);
|
||||
amdgpu_pasid_lock(&flags);
|
||||
|
||||
vm = xa_load(&adev->vm_manager.pasids, pasid);
|
||||
fpriv = amdgpu_pasid_get_fpriv_locked(pasid);
|
||||
vm = fpriv ? &fpriv->vm : NULL;
|
||||
/* Don't update the fault cache if status is 0. In the multiple
|
||||
* fault case, subsequent faults will return a 0 status which is
|
||||
* useless for userspace and replaces the useful fault status, so
|
||||
@@ -3193,7 +3205,7 @@ void amdgpu_vm_update_fault_cache(struct amdgpu_device *adev,
|
||||
WARN_ONCE(1, "Invalid vmhub %u\n", vmhub);
|
||||
}
|
||||
}
|
||||
xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
|
||||
amdgpu_pasid_unlock(flags);
|
||||
}
|
||||
|
||||
void amdgpu_vm_print_task_info(struct amdgpu_device *adev,
|
||||
|
||||
Reference in New Issue
Block a user