[PATCH 14/34] drm/amdgpu: Convert pasid_idr to XArray

Matthew Wilcox willy at infradead.org
Thu Feb 21 18:41:48 UTC 2019


Signed-off-by: Matthew Wilcox <willy at 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



More information about the dri-devel mailing list