summaryrefslogtreecommitdiff
path: root/drivers/gpu/msm/kgsl.c
diff options
context:
space:
mode:
authorJordan Crouse <jcrouse@codeaurora.org>2020-12-31 13:55:39 +0530
committerTiwari, Shubham <shubtiwa@codeaurora.org>2021-03-15 02:38:42 -0700
commit854ef3ce73f55f3ce1a193322796f155cb40717b (patch)
treee45ddcefc5e9ce0cbca2222349728d7e13a35301 /drivers/gpu/msm/kgsl.c
parent79c8161aeac99344506e989af2ca92b13e0d0676 (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.c35
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);