Signed-off-by: Matthew Wilcox <wi...@infradead.org>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 66 +++++++++-----------------
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h |  3 +-
 drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c  | 12 ++---
 3 files changed, 29 insertions(+), 52 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index d2ea5ce2cefb..d094ec7433f9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -3032,12 +3032,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct 
amdgpu_vm *vm,
        amdgpu_bo_unreserve(vm->root.base.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);
+               r = xa_insert_irq(&adev->vm_manager.vms, pasid, vm, GFP_KERNEL);
                if (r < 0)
                        goto error_free_root;
 
@@ -3047,6 +3042,8 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct 
amdgpu_vm *vm,
        vm->fault_hash = init_fault_hash();
        if (!vm->fault_hash) {
                r = -ENOMEM;
+               if (pasid)
+                       xa_erase_irq(&adev->vm_manager.vms, pasid);
                goto error_free_root;
        }
 
@@ -3104,16 +3101,9 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, 
struct amdgpu_vm *vm, uns
        }
 
        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)
+               r = xa_insert_irq(&adev->vm_manager.vms, pasid, vm, GFP_KERNEL);
+               if (r < 0)
                        goto unreserve_bo;
-               r = 0;
        }
 
        /* Check if PD needs to be reinitialized and do it before
@@ -3124,7 +3114,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, 
struct amdgpu_vm *vm, uns
                               adev->vm_manager.root_level,
                               pte_support_ats);
                if (r)
-                       goto free_idr;
+                       goto erase;
        }
 
        /* Update VM state */
@@ -3137,11 +3127,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, 
struct amdgpu_vm *vm, uns
                  "CPU update of VM recommended only for large BAR system\n");
 
        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);
+               xa_erase_irq(&adev->vm_manager.vms, vm->pasid);
 
                /* Free the original amdgpu allocated pasid
                 * Will be replaced with kfd allocated pasid
@@ -3158,14 +3144,9 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, 
struct amdgpu_vm *vm, uns
 
        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);
-       }
+erase:
+       if (pasid)
+               xa_erase_irq(&adev->vm_manager.vms, pasid);
 unreserve_bo:
        amdgpu_bo_unreserve(vm->root.base.bo);
        return r;
@@ -3184,9 +3165,9 @@ 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);
+               xa_lock_irqsave(&adev->vm_manager.vms, flags);
+               __xa_erase(&adev->vm_manager.vms, vm->pasid);
+               xa_unlock_irqrestore(&adev->vm_manager.vms, flags);
        }
        vm->pasid = 0;
 }
@@ -3217,9 +3198,9 @@ void amdgpu_vm_fini(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);
+               xa_lock_irqsave(&adev->vm_manager.vms, flags);
+               __xa_erase(&adev->vm_manager.vms, vm->pasid);
+               xa_unlock_irqrestore(&adev->vm_manager.vms, flags);
        }
 
        kfree(vm->fault_hash);
@@ -3299,8 +3280,8 @@ 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.vms,
+                       XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ);
 }
 
 /**
@@ -3312,8 +3293,7 @@ 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.vms));
 
        amdgpu_vmid_mgr_fini(adev);
 }
@@ -3364,13 +3344,11 @@ void amdgpu_vm_get_task_info(struct amdgpu_device 
*adev, unsigned int pasid,
 {
        struct amdgpu_vm *vm;
 
-       spin_lock(&adev->vm_manager.pasid_lock);
-
-       vm = idr_find(&adev->vm_manager.pasid_idr, pasid);
+       xa_lock(&adev->vm_manager.vms);
+       vm = xa_load(&adev->vm_manager.vms, pasid);
        if (vm)
                *task_info = vm->task_info;
-
-       spin_unlock(&adev->vm_manager.pasid_lock);
+       xa_unlock(&adev->vm_manager.vms);
 }
 
 /**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index e8dcfd59fc93..84b466eee449 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -281,8 +281,7 @@ struct amdgpu_vm_manager {
        /* PASID to VM mapping, will be used in interrupt context to
         * look up VM of a page fault
         */
-       struct idr                              pasid_idr;
-       spinlock_t                              pasid_lock;
+       struct xarray                           vms;
 };
 
 #define amdgpu_vm_copy_pte(adev, ib, pe, src, count) 
((adev)->vm_manager.vm_pte_funcs->copy_pte((ib), (pe), (src), (count)))
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index bacdaef77b6c..c0e6503b7965 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -268,11 +268,11 @@ static bool gmc_v9_0_prescreen_iv(struct amdgpu_device 
*adev,
                return true;
 
        /* Track retry faults in per-VM fault FIFO. */
-       spin_lock(&adev->vm_manager.pasid_lock);
-       vm = idr_find(&adev->vm_manager.pasid_idr, entry->pasid);
+       xa_lock(&adev->vm_manager.vms);
+       vm = xa_load(&adev->vm_manager.vms, entry->pasid);
        if (!vm) {
                /* VM not found, process it normally */
-               spin_unlock(&adev->vm_manager.pasid_lock);
+               xa_unlock(&adev->vm_manager.vms);
                return true;
        }
 
@@ -283,7 +283,7 @@ static bool gmc_v9_0_prescreen_iv(struct amdgpu_device 
*adev,
         * ignore further page faults
         */
        if (r != 0) {
-               spin_unlock(&adev->vm_manager.pasid_lock);
+               xa_unlock(&adev->vm_manager.vms);
                return false;
        }
        /* No locking required with single writer and single reader */
@@ -291,11 +291,11 @@ static bool gmc_v9_0_prescreen_iv(struct amdgpu_device 
*adev,
        if (!r) {
                /* FIFO is full. Ignore it until there is space */
                amdgpu_vm_clear_fault(vm->fault_hash, key);
-               spin_unlock(&adev->vm_manager.pasid_lock);
+               xa_unlock(&adev->vm_manager.vms);
                return false;
        }
 
-       spin_unlock(&adev->vm_manager.pasid_lock);
+       xa_unlock(&adev->vm_manager.vms);
        /* It's the first fault for this address, process it normally */
        return true;
 }
-- 
2.20.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to