[PATCH 12/13] drm/amdgpu: add amdgpu_pasid_bind/undbing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Allow us to bind a PASID to the current process and unbind it when the
VM isn't used any more.

Signed-off-by: Christian König <christian.koenig at amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 28 ++++++++++++++++++++++++++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h |  3 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c |  2 +-
 3 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
index c13cf7e79b2e..8cfdb07a4439 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
@@ -24,6 +24,7 @@
 
 #include <linux/idr.h>
 #include <linux/dma-fence-array.h>
+#include <linux/amd-iommu.h>
 #include <drm/drmP.h>
 
 #include "amdgpu.h"
@@ -43,6 +44,7 @@ static DEFINE_IDA(amdgpu_pasid_ida);
 /* Helper to free pasid from a fence callback */
 struct amdgpu_pasid_cb {
 	struct dma_fence_cb cb;
+	struct pci_dev *pdev;
 	unsigned int pasid;
 };
 
@@ -85,12 +87,30 @@ void amdgpu_pasid_free(unsigned int pasid)
 	ida_simple_remove(&amdgpu_pasid_ida, pasid);
 }
 
+int amdgpu_pasid_bind(struct pci_dev *pdev, unsigned int pasid)
+{
+#ifdef CONFIG_DRM_AMDGPU_ATC
+	return amd_iommu_bind_pasid(pdev, pasid, current);
+#else
+	return -ENODEV;
+#endif
+}
+
+void amdgpu_pasid_unbind(struct pci_dev *pdev, unsigned int pasid)
+{
+#ifdef CONFIG_DRM_AMDGPU_ATC
+	if (pdev)
+		amd_iommu_unbind_pasid(pdev, pasid);
+#endif
+}
+
 static void amdgpu_pasid_free_cb(struct dma_fence *fence,
 				 struct dma_fence_cb *_cb)
 {
 	struct amdgpu_pasid_cb *cb =
 		container_of(_cb, struct amdgpu_pasid_cb, cb);
 
+	amdgpu_pasid_unbind(cb->pdev, cb->pasid);
 	amdgpu_pasid_free(cb->pasid);
 	dma_fence_put(fence);
 	kfree(cb);
@@ -100,11 +120,13 @@ static void amdgpu_pasid_free_cb(struct dma_fence *fence,
  * amdgpu_pasid_free_delayed - free pasid when fences signal
  *
  * @resv: reservation object with the fences to wait for
+ * @pdev: optional pci device to unbind the PASID from
  * @pasid: pasid to free
  *
  * Free the pasid only after all the fences in resv are signaled.
  */
 void amdgpu_pasid_free_delayed(struct reservation_object *resv,
+			       struct pci_dev *pdev,
 			       unsigned int pasid)
 {
 	struct dma_fence *fence, **fences;
@@ -117,6 +139,7 @@ void amdgpu_pasid_free_delayed(struct reservation_object *resv,
 		goto fallback;
 
 	if (count == 0) {
+		amdgpu_pasid_unbind(pdev, pasid);
 		amdgpu_pasid_free(pasid);
 		return;
 	}
@@ -140,10 +163,10 @@ void amdgpu_pasid_free_delayed(struct reservation_object *resv,
 	cb = kmalloc(sizeof(*cb), GFP_KERNEL);
 	if (!cb) {
 		/* Last resort when we are OOM */
-		dma_fence_wait(fence, false);
 		dma_fence_put(fence);
-		amdgpu_pasid_free(pasid);
+		goto fallback;
 	} else {
+		cb->pdev = pdev;
 		cb->pasid = pasid;
 		if (dma_fence_add_callback(fence, &cb->cb,
 					   amdgpu_pasid_free_cb))
@@ -158,6 +181,7 @@ void amdgpu_pasid_free_delayed(struct reservation_object *resv,
 	 */
 	reservation_object_wait_timeout_rcu(resv, true, false,
 					    MAX_SCHEDULE_TIMEOUT);
+	amdgpu_pasid_unbind(pdev, pasid);
 	amdgpu_pasid_free(pasid);
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
index 38f37c16fc5e..ef88fc4f21fb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
@@ -69,7 +69,10 @@ struct amdgpu_vmid_mgr {
 
 int amdgpu_pasid_alloc(unsigned int bits);
 void amdgpu_pasid_free(unsigned int pasid);
+int amdgpu_pasid_bind(struct pci_dev *pdev, unsigned int pasid);
+void amdgpu_pasid_unbind(struct pci_dev *pdev, unsigned int pasid);
 void amdgpu_pasid_free_delayed(struct reservation_object *resv,
+			       struct pci_dev *pdev,
 			       unsigned int pasid);
 
 bool amdgpu_vmid_had_gpu_reset(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 431038885778..b18920007624 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -927,7 +927,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
 
 	amdgpu_vm_fini(adev, &fpriv->vm);
 	if (pasid)
-		amdgpu_pasid_free_delayed(pd->tbo.resv, pasid);
+		amdgpu_pasid_free_delayed(pd->tbo.resv, NULL, pasid);
 	amdgpu_bo_unref(&pd);
 
 	idr_for_each_entry(&fpriv->bo_list_handles, list, handle)
-- 
2.14.1



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux