diff options
author | Christian König <christian.koenig@amd.com> | 2018-01-26 21:10:45 +0100 |
---|---|---|
committer | Christian König <christian.koenig@amd.com> | 2018-03-06 15:44:44 +0100 |
commit | 342d1f371acf04596422108c4c7f6cf4d8134d55 (patch) | |
tree | 2f27942302b4c9b4f4044f9b51e1f12437bb8748 | |
parent | 58ba752ca96d855081f3bb032f2c2d66e4a04bbf (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.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 94 | ||||
-rw-r--r-- | include/uapi/drm/amdgpu_drm.h | 1 |
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_* */ |