diff options
author | Jordan Crouse <jcrouse@codeaurora.org> | 2020-12-31 13:55:39 +0530 |
---|---|---|
committer | Tiwari, Shubham <shubtiwa@codeaurora.org> | 2021-03-15 02:38:42 -0700 |
commit | 854ef3ce73f55f3ce1a193322796f155cb40717b (patch) | |
tree | e45ddcefc5e9ce0cbca2222349728d7e13a35301 /drivers/gpu/msm/kgsl.c | |
parent | 79c8161aeac99344506e989af2ca92b13e0d0676 (diff) |
msm: kgsl: Protect the memdesc->gpuaddr in SVM use cases.
When SVM is being used there can only be one GPU address assigned
to the memory descriptor. Don't allow the GPU address to be changed
after it has been negotiated the first time by a process.
Change-Id: Ic0dedbad2a1b3ccdc2c1598a6c501b2be288d64e
Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Harshitha Sai Neelati <hsaine@codeaurora.org>
Signed-off-by: Kamal Agrawal <kamaagra@codeaurora.org>
Diffstat (limited to 'drivers/gpu/msm/kgsl.c')
-rw-r--r-- | drivers/gpu/msm/kgsl.c | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 1f6e562bad67..a9b6e24728c7 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -2428,6 +2428,8 @@ long kgsl_ioctl_gpuobj_import(struct kgsl_device_private *dev_priv, if (entry == NULL) return -ENOMEM; + spin_lock_init(&entry->memdesc.lock); + param->flags &= KGSL_MEMFLAGS_GPUREADONLY | KGSL_MEMTYPE_MASK | KGSL_MEMALIGN_MASK @@ -2701,6 +2703,8 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, if (entry == NULL) return -ENOMEM; + spin_lock_init(&entry->memdesc.lock); + /* * Convert from enum value to KGSL_MEM_ENTRY value, so that * we can use the latter consistently everywhere. @@ -3481,6 +3485,8 @@ long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv, if (entry == NULL) return -ENOMEM; + spin_lock_init(&entry->memdesc.lock); + entry->memdesc.flags = KGSL_MEMFLAGS_SPARSE_VIRT; entry->memdesc.size = param->size; entry->memdesc.cur_bindings = 0; @@ -4334,19 +4340,34 @@ static unsigned long _gpu_set_svm_region(struct kgsl_process_private *private, { int ret; + /* + * Protect access to the gpuaddr here to prevent multiple vmas from + * trying to map a SVM region at the same time + */ + spin_lock(&entry->memdesc.lock); + + if (entry->memdesc.gpuaddr) { + spin_unlock(&entry->memdesc.lock); + return (unsigned long) -EBUSY; + } + ret = kgsl_mmu_set_svm_region(private->pagetable, (uint64_t) addr, (uint64_t) size); - if (ret != 0) - return ret; + if (ret != 0) { + spin_unlock(&entry->memdesc.lock); + return (unsigned long) ret; + } entry->memdesc.gpuaddr = (uint64_t) addr; + spin_unlock(&entry->memdesc.lock); + entry->memdesc.pagetable = private->pagetable; ret = kgsl_mmu_map(private->pagetable, &entry->memdesc); if (ret) { kgsl_mmu_put_gpuaddr(&entry->memdesc); - return ret; + return (unsigned long) ret; } kgsl_memfree_purge(private->pagetable, entry->memdesc.gpuaddr, @@ -4409,6 +4430,14 @@ static unsigned long _search_range(struct kgsl_process_private *private, result = _gpu_set_svm_region(private, entry, cpu, len); if (!IS_ERR_VALUE(result)) break; + /* + * _gpu_set_svm_region will return -EBUSY if we tried to set up + * SVM on an object that already has a GPU address. If + * that happens don't bother walking the rest of the + * region + */ + if ((long) result == -EBUSY) + return -EBUSY; trace_kgsl_mem_unmapped_area_collision(entry, cpu, len); |