summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2018-01-26 21:10:45 +0100
committerChristian König <christian.koenig@amd.com>2018-03-06 15:44:44 +0100
commit342d1f371acf04596422108c4c7f6cf4d8134d55 (patch)
tree2f27942302b4c9b4f4044f9b51e1f12437bb8748
parent58ba752ca96d855081f3bb032f2c2d66e4a04bbf (diff)
drm/amdgpu: add AMDGPU_VM_OP_ENABLE_SVM IOCTLatc_enablement
Add an IOCTL to enable SVM for the current process. One step further towards HMM support. Signed-off-by: Christian König <christian.koenig@amd.com>
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c94
-rw-r--r--include/uapi/drm/amdgpu_drm.h1
3 files changed, 94 insertions, 5 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 074e9ea765df..d69043cf0581 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -902,6 +902,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
struct amdgpu_fpriv *fpriv = file_priv->driver_priv;
struct amdgpu_bo_list *list;
struct amdgpu_bo *pd;
+ struct pci_dev *pdev;
unsigned int pasid;
int handle;
@@ -928,11 +929,12 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
}
pasid = fpriv->vm.pasid;
+ pdev = fpriv->vm.pte_support_ats ? adev->pdev : NULL;
pd = amdgpu_bo_ref(fpriv->vm.root.base.bo);
amdgpu_vm_fini(adev, &fpriv->vm);
if (pasid)
- amdgpu_pasid_free_delayed(pd->tbo.resv, NULL, pasid);
+ amdgpu_pasid_free_delayed(pd->tbo.resv, pdev, pasid);
amdgpu_bo_unref(&pd);
idr_for_each_entry(&fpriv->bo_list_handles, list, handle)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 0b237e027cab..5eee226b5c33 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -258,6 +258,24 @@ bool amdgpu_vm_ready(struct amdgpu_vm *vm)
}
/**
+ * amdgpu_vm_root_ats_entries - number of ATS entries in the root PD
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Returns number of entries in the root PD which should be initialized for ATS
+ * use.
+ */
+static unsigned amdgpu_vm_root_ats_entries(struct amdgpu_device *adev)
+{
+ unsigned level = adev->vm_manager.root_level;
+ unsigned shift;
+
+ shift = amdgpu_vm_level_shift(adev, level);
+ shift += AMDGPU_GPU_PAGE_SHIFT;
+ return AMDGPU_VA_HOLE_START >> shift;
+}
+
+/**
* amdgpu_vm_clear_bo - initially clear the PDs/PTs
*
* @adev: amdgpu_device pointer
@@ -283,9 +301,7 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
if (pte_support_ats) {
if (level == adev->vm_manager.root_level) {
- ats_entries = amdgpu_vm_level_shift(adev, level);
- ats_entries += AMDGPU_GPU_PAGE_SHIFT;
- ats_entries = AMDGPU_VA_HOLE_START >> ats_entries;
+ ats_entries = amdgpu_vm_root_ats_entries(adev);
ats_entries = min(ats_entries, entries);
entries -= ats_entries;
} else {
@@ -328,6 +344,9 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
amdgpu_ring_pad_ib(ring, &job->ibs[0]);
+ amdgpu_sync_resv(adev, &job->sync, bo->tbo.resv,
+ AMDGPU_FENCE_OWNER_VM, false);
+
WARN_ON(job->ibs[0].length_dw > 64);
r = amdgpu_sync_resv(adev, &job->sync, bo->tbo.resv,
AMDGPU_FENCE_OWNER_UNDEFINED, false);
@@ -2591,6 +2610,71 @@ bool amdgpu_vm_pasid_fault_credit(struct amdgpu_device *adev,
}
/**
+ * amdgpu_vm_enable_svm - enable SVM
+ *
+ * @adev: amdgpu_device pointer
+ * @vm: VM to enable SVM
+ *
+ * Initialize SVM.
+ */
+int amdgpu_vm_enable_svm(struct amdgpu_device *adev, struct amdgpu_vm *vm)
+{
+ int r;
+
+ if (!vm->pasid)
+ return -ENODEV;
+
+ r = amdgpu_bo_reserve(vm->root.base.bo, false);
+ if (r)
+ return r;
+
+ if (vm->pte_support_ats) {
+ r = -EALREADY;
+ goto error_unlock;
+ }
+
+ if (vm->root.entries) {
+ unsigned i, entries;
+
+ entries = amdgpu_vm_root_ats_entries(adev);
+ for (i = 0; i < entries; ++i) {
+ if (vm->root.entries[i].base.bo) {
+ r = -EEXIST;
+ goto error_unlock;
+ }
+ }
+
+ entries = amdgpu_bo_size(vm->root.base.bo) / 8;
+ spin_lock(&vm->status_lock);
+ for (; i < entries; ++i) {
+ struct amdgpu_vm_pt *pt = &vm->root.entries[i];
+
+ if (pt->base.bo)
+ list_move(&pt->base.vm_status, &vm->moved);
+ }
+ spin_unlock(&vm->status_lock);
+ }
+
+ r = amdgpu_pasid_bind(adev->pdev, vm->pasid);
+ if (r)
+ goto error_unlock;
+
+ r = amdgpu_vm_clear_bo(adev, vm, vm->root.base.bo,
+ adev->vm_manager.root_level,
+ true);
+ if (r) {
+ amdgpu_pasid_unbind(adev->pdev, vm->pasid);
+ goto error_unlock;
+ }
+
+ vm->pte_support_ats = true;
+
+error_unlock:
+ amdgpu_bo_unreserve(vm->root.base.bo);
+ return r;
+}
+
+/**
* amdgpu_vm_manager_init - init the VM manager
*
* @adev: amdgpu_device pointer
@@ -2649,9 +2733,9 @@ void amdgpu_vm_manager_fini(struct amdgpu_device *adev)
int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
{
- union drm_amdgpu_vm *args = data;
struct amdgpu_device *adev = dev->dev_private;
struct amdgpu_fpriv *fpriv = filp->driver_priv;
+ union drm_amdgpu_vm *args = data;
int r;
switch (args->in.op) {
@@ -2664,6 +2748,8 @@ int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
case AMDGPU_VM_OP_UNRESERVE_VMID:
amdgpu_vmid_free_reserved(adev, &fpriv->vm, AMDGPU_GFXHUB);
break;
+ case AMDGPU_VM_OP_ENABLE_SVM:
+ return amdgpu_vm_enable_svm(adev, &fpriv->vm);
default:
return -EINVAL;
}
diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
index fe17b6785441..c5b13ebe8dfc 100644
--- a/include/uapi/drm/amdgpu_drm.h
+++ b/include/uapi/drm/amdgpu_drm.h
@@ -223,6 +223,7 @@ union drm_amdgpu_ctx {
/* vm ioctl */
#define AMDGPU_VM_OP_RESERVE_VMID 1
#define AMDGPU_VM_OP_UNRESERVE_VMID 2
+#define AMDGPU_VM_OP_ENABLE_SVM 3
struct drm_amdgpu_vm_in {
/** AMDGPU_VM_OP_* */