summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorRajesh Kemisetti <rajeshk@codeaurora.org>2016-03-08 14:12:37 +0530
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-25 16:03:36 -0700
commit6eea801d0bf14513eabd9f6c7fbb2bea046774a5 (patch)
tree54f7912858bd5dc5c02027ced6a88481657a2228 /drivers
parent2e21911abee5189cb1ccb2bb8bd9d093e6cc3c3d (diff)
msm: kgsl: Fix race condition during mem_entry detach
kgsl_mem_entry_detach_process() makes gpuaddr to NULL and then removes the entry from mem_idr list. Sometimes this can cause kgsl_sharedmem_find() to return the same entry for a different gpuaddr/thread if it satisfies GPUADDR_IN_MEMDESC(). To avoid this, first remove the entry from mem_idr list and proceed with unmap/untrack calls. Change-Id: Ib9f2bc0fdaecd394735dd61b18fdc7de57aa3748 Signed-off-by: Rajesh Kemisetti <rajeshk@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/msm/kgsl.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 841e7e450baa..17344a0e9e28 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -464,11 +464,10 @@ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry)
if (entry == NULL)
return;
- /* Unmap here so that below we can call kgsl_mmu_put_gpuaddr */
- kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc);
-
- kgsl_mem_entry_untrack_gpuaddr(entry->priv, entry);
-
+ /*
+ * First remove the entry from mem_idr list
+ * so that no one can operate on obsolete values
+ */
spin_lock(&entry->priv->mem_lock);
if (entry->id != 0)
idr_remove(&entry->priv->mem_idr, entry->id);
@@ -477,6 +476,11 @@ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry)
type = kgsl_memdesc_usermem_type(&entry->memdesc);
entry->priv->stats[type].cur -= entry->memdesc.size;
spin_unlock(&entry->priv->mem_lock);
+
+ kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc);
+
+ kgsl_mem_entry_untrack_gpuaddr(entry->priv, entry);
+
kgsl_process_private_put(entry->priv);
entry->priv = NULL;