diff options
| author | Rajesh Kemisetti <rajeshk@codeaurora.org> | 2016-03-08 14:12:37 +0530 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-25 16:03:36 -0700 |
| commit | 6eea801d0bf14513eabd9f6c7fbb2bea046774a5 (patch) | |
| tree | 54f7912858bd5dc5c02027ced6a88481657a2228 /drivers | |
| parent | 2e21911abee5189cb1ccb2bb8bd9d093e6cc3c3d (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.c | 14 |
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; |
