drm/amdgpu: Set pasid for compute vm (v2)
authorOak Zeng <Oak.Zeng@amd.com>
Wed, 29 Aug 2018 17:33:52 +0000 (12:33 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 29 Aug 2018 17:34:49 +0000 (12:34 -0500)
To make a amdgpu vm to a compute vm, the old pasid will be freed and
replaced with a pasid managed by kfd. Kfd can't reuse original pasid
allocated by amdgpu because kfd uses different pasid policy with amdgpu.
For example, all graphic devices share one same pasid in a process.

v2: rebase (Alex)

Signed-off-by: Oak Zeng <Oak.Zeng@amd.com>
Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
drivers/gpu/drm/amd/amdkfd/kfd_process.c
drivers/gpu/drm/amd/include/kgd_kfd_interface.h

index 2f379c183ed20be8af61e839ebbd75b9890a8593..ba0057e94d5eccee0416de2f4f99da9f9e17f7b1 100644 (file)
@@ -162,11 +162,11 @@ uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd);
        })
 
 /* GPUVM API */
-int amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, void **vm,
-                                       void **process_info,
+int amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, unsigned int pasid,
+                                       void **vm, void **process_info,
                                        struct dma_fence **ef);
 int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct kgd_dev *kgd,
-                                       struct file *filp,
+                                       struct file *filp, unsigned int pasid,
                                        void **vm, void **process_info,
                                        struct dma_fence **ef);
 void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev,
index 2ef6e8557b657f1fccabecae9941eaa782e7dc63..1cbdd9a7538eae8d5617d0e867d34ce4a92d2eff 100644 (file)
@@ -1000,8 +1000,8 @@ create_evict_fence_fail:
        return ret;
 }
 
-int amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, void **vm,
-                                         void **process_info,
+int amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, unsigned int pasid,
+                                         void **vm, void **process_info,
                                          struct dma_fence **ef)
 {
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
@@ -1013,7 +1013,7 @@ int amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, void **vm,
                return -ENOMEM;
 
        /* Initialize AMDGPU part of the VM */
-       ret = amdgpu_vm_init(adev, new_vm, AMDGPU_VM_CONTEXT_COMPUTE, 0);
+       ret = amdgpu_vm_init(adev, new_vm, AMDGPU_VM_CONTEXT_COMPUTE, pasid);
        if (ret) {
                pr_err("Failed init vm ret %d\n", ret);
                goto amdgpu_vm_init_fail;
@@ -1036,7 +1036,7 @@ amdgpu_vm_init_fail:
 }
 
 int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct kgd_dev *kgd,
-                                          struct file *filp,
+                                          struct file *filp, unsigned int pasid,
                                           void **vm, void **process_info,
                                           struct dma_fence **ef)
 {
@@ -1051,7 +1051,7 @@ int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct kgd_dev *kgd,
                return -EINVAL;
 
        /* Convert VM into a compute VM */
-       ret = amdgpu_vm_make_compute(adev, avm);
+       ret = amdgpu_vm_make_compute(adev, avm, pasid);
        if (ret)
                return ret;
 
index 60c0609b78a43a664609d022a8156eccb81a625c..272b7902a25c704f7a6543bfe721d0c855cdc1a8 100644 (file)
@@ -2740,7 +2740,7 @@ error_free_sched_entity:
  * Returns:
  * 0 for success, -errno for errors.
  */
-int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm)
+int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, unsigned int pasid)
 {
        bool pte_support_ats = (adev->asic_type == CHIP_RAVEN);
        int r;
@@ -2752,7 +2752,20 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm)
        /* Sanity checks */
        if (!RB_EMPTY_ROOT(&vm->va.rb_root) || vm->root.entries) {
                r = -EINVAL;
-               goto error;
+               goto unreserve_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);
+
+               if (r == -ENOSPC)
+                       goto unreserve_bo;
+               r = 0;
        }
 
        /* Check if PD needs to be reinitialized and do it before
@@ -2763,7 +2776,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm)
                               adev->vm_manager.root_level,
                               pte_support_ats);
                if (r)
-                       goto error;
+                       goto free_idr;
        }
 
        /* Update VM state */
@@ -2782,13 +2795,30 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm)
                idr_remove(&adev->vm_manager.pasid_idr, vm->pasid);
                spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
 
+               /* Free the original amdgpu allocated pasid
+                * Will be replaced with kfd allocated pasid
+                */
+               amdgpu_pasid_free(vm->pasid);
                vm->pasid = 0;
        }
 
        /* Free the shadow bo for compute VM */
        amdgpu_bo_unref(&vm->root.base.bo->shadow);
 
-error:
+       if (pasid)
+               vm->pasid = pasid;
+
+       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);
+       }
+unreserve_bo:
        amdgpu_bo_unreserve(vm->root.base.bo);
        return r;
 }
index 94fe47890adfc89c0c92dd4831b3c98e6cb69fc8..24b02c91ce0cef468807cff5c1f671041d7bc916 100644 (file)
@@ -297,7 +297,7 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev);
 void amdgpu_vm_manager_fini(struct amdgpu_device *adev);
 int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
                   int vm_context, unsigned int pasid);
-int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm);
+int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, unsigned int pasid);
 void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
 bool amdgpu_vm_pasid_fault_credit(struct amdgpu_device *adev,
                                  unsigned int pasid);
index 4694386cc6236238df2230be18a7173ab1bd86af..a246b8d76c868c34044f6166724b2487c127fee4 100644 (file)
@@ -687,11 +687,11 @@ int kfd_process_device_init_vm(struct kfd_process_device *pdd,
 
        if (drm_file)
                ret = dev->kfd2kgd->acquire_process_vm(
-                       dev->kgd, drm_file,
+                       dev->kgd, drm_file, p->pasid,
                        &pdd->vm, &p->kgd_process_info, &p->ef);
        else
                ret = dev->kfd2kgd->create_process_vm(
-                       dev->kgd, &pdd->vm, &p->kgd_process_info, &p->ef);
+                       dev->kgd, p->pasid, &pdd->vm, &p->kgd_process_info, &p->ef);
        if (ret) {
                pr_err("Failed to create process VM object\n");
                return ret;
index 14391b06080ce4566ebbae1d8fd1a8313ac36bc8..4b9981351bb3d2a3c66e078a3eea11cbdf8d9e47 100644 (file)
@@ -372,10 +372,11 @@ struct kfd2kgd_calls {
                        struct kfd_cu_info *cu_info);
        uint64_t (*get_vram_usage)(struct kgd_dev *kgd);
 
-       int (*create_process_vm)(struct kgd_dev *kgd, void **vm,
+       int (*create_process_vm)(struct kgd_dev *kgd, unsigned int pasid, void **vm,
                        void **process_info, struct dma_fence **ef);
        int (*acquire_process_vm)(struct kgd_dev *kgd, struct file *filp,
-                       void **vm, void **process_info, struct dma_fence **ef);
+                       unsigned int pasid, void **vm, void **process_info,
+                       struct dma_fence **ef);
        void (*destroy_process_vm)(struct kgd_dev *kgd, void *vm);
        uint32_t (*get_process_page_dir)(void *vm);
        void (*set_vm_context_page_table_base)(struct kgd_dev *kgd,