[PATCH 12/13] drm/amdgpu: add amdgpu_pasid_bind/undbing
Christian König
ckoenig.leichtzumerken at gmail.com
Fri Jan 26 20:13:25 UTC 2018
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
More information about the amd-gfx
mailing list