diff options
author | Felix Kuehling <Felix.Kuehling@amd.com> | 2021-06-10 18:39:56 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2021-06-15 17:25:41 -0400 |
commit | 5a75ea56e36937d7d01545c53fae91e234ea0de6 (patch) | |
tree | aa961556c6a9070909405505b7b839aa2cef91bb /drivers/gpu/drm/amd/amdkfd/kfd_svm.c | |
parent | d0414a834c0d6c92c9a6db504e196831d118ab54 (diff) |
drm/amdkfd: Disable SVM per GPU, not per process
When some GPUs don't support SVM, don't disabe it for the entire process.
That would be inconsistent with the information the process got from the
topology, which indicates SVM support per GPU.
Instead disable SVM support only for the unsupported GPUs. This is done
by checking any per-device attributes against the bitmap of supported
GPUs. Also use the supported GPU bitmap to initialize access bitmaps for
new SVM address ranges.
Don't handle recoverable page faults from unsupported GPUs. (I don't
think there will be unsupported GPUs that can generate recoverable page
faults. But better safe than sorry.)
Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
Reviewed-by: Philip Yang <philip.yang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdkfd/kfd_svm.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 60 |
1 files changed, 35 insertions, 25 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index da569d417d1d..451e2ff5c062 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -281,7 +281,8 @@ svm_range *svm_range_new(struct svm_range_list *svms, uint64_t start, p = container_of(svms, struct kfd_process, svms); if (p->xnack_enabled) - bitmap_fill(prange->bitmap_access, MAX_GPU_INSTANCE); + bitmap_copy(prange->bitmap_access, svms->bitmap_supported, + MAX_GPU_INSTANCE); svm_range_set_default_attributes(&prange->preferred_loc, &prange->prefetch_loc, @@ -577,36 +578,25 @@ svm_range_check_attr(struct kfd_process *p, uint32_t nattr, struct kfd_ioctl_svm_attribute *attrs) { uint32_t i; - int gpuidx; for (i = 0; i < nattr; i++) { + uint32_t val = attrs[i].value; + int gpuidx = MAX_GPU_INSTANCE; + switch (attrs[i].type) { case KFD_IOCTL_SVM_ATTR_PREFERRED_LOC: - if (attrs[i].value != KFD_IOCTL_SVM_LOCATION_SYSMEM && - attrs[i].value != KFD_IOCTL_SVM_LOCATION_UNDEFINED && - kfd_process_gpuidx_from_gpuid(p, - attrs[i].value) < 0) { - pr_debug("no GPU 0x%x found\n", attrs[i].value); - return -EINVAL; - } + if (val != KFD_IOCTL_SVM_LOCATION_SYSMEM && + val != KFD_IOCTL_SVM_LOCATION_UNDEFINED) + gpuidx = kfd_process_gpuidx_from_gpuid(p, val); break; case KFD_IOCTL_SVM_ATTR_PREFETCH_LOC: - if (attrs[i].value != KFD_IOCTL_SVM_LOCATION_SYSMEM && - kfd_process_gpuidx_from_gpuid(p, - attrs[i].value) < 0) { - pr_debug("no GPU 0x%x found\n", attrs[i].value); - return -EINVAL; - } + if (val != KFD_IOCTL_SVM_LOCATION_SYSMEM) + gpuidx = kfd_process_gpuidx_from_gpuid(p, val); break; case KFD_IOCTL_SVM_ATTR_ACCESS: case KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE: case KFD_IOCTL_SVM_ATTR_NO_ACCESS: - gpuidx = kfd_process_gpuidx_from_gpuid(p, - attrs[i].value); - if (gpuidx < 0) { - pr_debug("no GPU 0x%x found\n", attrs[i].value); - return -EINVAL; - } + gpuidx = kfd_process_gpuidx_from_gpuid(p, val); break; case KFD_IOCTL_SVM_ATTR_SET_FLAGS: break; @@ -618,6 +608,15 @@ svm_range_check_attr(struct kfd_process *p, pr_debug("unknown attr type 0x%x\n", attrs[i].type); return -EINVAL; } + + if (gpuidx < 0) { + pr_debug("no GPU 0x%x found\n", val); + return -EINVAL; + } else if (gpuidx < MAX_GPU_INSTANCE && + !test_bit(gpuidx, p->svms.bitmap_supported)) { + pr_debug("GPU 0x%x not supported\n", val); + return -EINVAL; + } } return 0; @@ -1855,7 +1854,7 @@ static void svm_range_drain_retry_fault(struct svm_range_list *svms) p = container_of(svms, struct kfd_process, svms); - for (i = 0; i < p->n_pdds; i++) { + for_each_set_bit(i, svms->bitmap_supported, p->n_pdds) { pdd = p->pdds[i]; if (!pdd) continue; @@ -2325,6 +2324,11 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid, bool write_locked = false; int r = 0; + if (!KFD_IS_SVM_API_SUPPORTED(adev->kfd.dev)) { + pr_debug("device does not support SVM\n"); + return -EFAULT; + } + p = kfd_lookup_process_by_pasid(pasid); if (!p) { pr_debug("kfd process not founded pasid 0x%x\n", pasid); @@ -2472,6 +2476,7 @@ void svm_range_list_fini(struct kfd_process *p) int svm_range_list_init(struct kfd_process *p) { struct svm_range_list *svms = &p->svms; + int i; svms->objects = RB_ROOT_CACHED; mutex_init(&svms->lock); @@ -2482,6 +2487,10 @@ int svm_range_list_init(struct kfd_process *p) INIT_LIST_HEAD(&svms->deferred_range_list); spin_lock_init(&svms->deferred_list_lock); + for (i = 0; i < p->n_pdds; i++) + if (KFD_IS_SVM_API_SUPPORTED(p->pdds[i]->dev)) + bitmap_set(svms->bitmap_supported, i, 1); + return 0; } @@ -2978,14 +2987,15 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size, svm_range_set_default_attributes(&location, &prefetch_loc, &granularity, &flags); if (p->xnack_enabled) - bitmap_fill(bitmap_access, MAX_GPU_INSTANCE); + bitmap_copy(bitmap_access, svms->bitmap_supported, + MAX_GPU_INSTANCE); else bitmap_zero(bitmap_access, MAX_GPU_INSTANCE); bitmap_zero(bitmap_aip, MAX_GPU_INSTANCE); goto fill_values; } - bitmap_fill(bitmap_access, MAX_GPU_INSTANCE); - bitmap_fill(bitmap_aip, MAX_GPU_INSTANCE); + bitmap_copy(bitmap_access, svms->bitmap_supported, MAX_GPU_INSTANCE); + bitmap_copy(bitmap_aip, svms->bitmap_supported, MAX_GPU_INSTANCE); while (node) { struct interval_tree_node *next; |