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().

v4:
- Allocate DRM PASIDs with fpriv directly.
- Squash ownership registration and PASID lookup conversion.

Cc: Alex Deucher <[email protected]>
Suggested-by: Christian König <[email protected]>
Signed-off-by: Srinivasan Shanmugam <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 16 +++++-----
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c  | 40 ++++++++++++++++---------
 2 files changed, 34 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 4610d6889e9b..087ca7783d1b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -1375,11 +1375,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;
@@ -1464,7 +1464,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);
@@ -1487,16 +1487,16 @@ int amdgpu_driver_open_kms(struct drm_device *dev, 
struct drm_file *file_priv)
                goto out_suspend;
        }
 
-       pasid = amdgpu_pasid_alloc(16, NULL);
+       r = amdgpu_xcp_open_device(adev, fpriv, file_priv);
+       if (r)
+               goto error_pasid;
+
+       pasid = amdgpu_pasid_alloc(16, fpriv);
        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);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 32719f31b6c9..9092ff227a55 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -2463,12 +2463,14 @@ static void amdgpu_vm_destroy_task_info(struct kref 
*kref)
 static inline struct amdgpu_vm *
 amdgpu_vm_get_vm_from_pasid(struct amdgpu_device *adev, u32 pasid)
 {
+       struct amdgpu_fpriv *fpriv;
        struct amdgpu_vm *vm;
        unsigned long flags;
 
-       xa_lock_irqsave(&adev->vm_manager.pasids, flags);
-       vm = xa_load(&adev->vm_manager.pasids, pasid);
-       xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
+       amdgpu_pasid_lock(&flags);
+       fpriv = amdgpu_pasid_get_fpriv_locked(pasid);
+       vm = fpriv ? &fpriv->vm : NULL;
+       amdgpu_pasid_unlock(flags);
 
        return vm;
 }
@@ -2943,14 +2945,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;
@@ -2962,11 +2966,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);
@@ -3163,12 +3173,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
@@ -3201,7 +3213,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,
-- 
2.34.1

Reply via email to