diff options
| author | Harshdeep Dhatt <hdhatt@codeaurora.org> | 2016-09-16 11:02:37 -0600 |
|---|---|---|
| committer | Harshdeep Dhatt <hdhatt@codeaurora.org> | 2016-09-29 14:40:50 -0600 |
| commit | 3f25aa2b782aef42da07fd54a89b9c3e729cc6bf (patch) | |
| tree | c0c1a7028f8b60f68aa6b30a62ad2fe4364bb670 /drivers/gpu/msm | |
| parent | 626caf4e54864d90e8d104277f9a1446e487c7e1 (diff) | |
msm: kgsl: Do not free gpuaddr range if unmap fails
Currently, we free up the gpuaddr range whether unmap
succeeds or fails. If it fails and we free up the gpuaddr
range, there is a possibility that a later allocation will
overlap with this range. Mapping this new range leads to a
BUG_ON() in the iommu driver which thinks that we are
overwriting an existing mapping. To avoid this, we never
free the failing gpuaddr range, effectively removing it
from being re-used for any future mappings.
CRs-Fixed: 1072834
Change-Id: I57dfd6abe6c928dbe4df1bcc682d4093040ccb9f
Signed-off-by: Harshdeep Dhatt <hdhatt@codeaurora.org>
Diffstat (limited to 'drivers/gpu/msm')
| -rw-r--r-- | drivers/gpu/msm/kgsl.c | 12 | ||||
| -rw-r--r-- | drivers/gpu/msm/kgsl_mmu.c | 7 | ||||
| -rw-r--r-- | drivers/gpu/msm/kgsl_sharedmem.c | 12 |
3 files changed, 22 insertions, 9 deletions
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 6e9abc99bcc4..88581b079246 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -485,6 +485,7 @@ err_put_proc_priv: static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry) { unsigned int type; + int ret; if (entry == NULL) return; @@ -501,9 +502,14 @@ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry) 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); + ret = kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc); + /* + * Do not free the gpuaddr/size if unmap fails. Because if we try + * to map this range in future, the iommu driver will throw + * a BUG_ON() because it feels we are overwriting a mapping. + */ + if (ret == 0) + kgsl_mem_entry_untrack_gpuaddr(entry->priv, entry); kgsl_process_private_put(entry->priv); diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c index 4371c9a1b87e..ba564b2851f9 100644 --- a/drivers/gpu/msm/kgsl_mmu.c +++ b/drivers/gpu/msm/kgsl_mmu.c @@ -450,24 +450,23 @@ int kgsl_mmu_unmap(struct kgsl_pagetable *pagetable, struct kgsl_memdesc *memdesc) { + int ret = 0; + if (memdesc->size == 0) return -EINVAL; if (PT_OP_VALID(pagetable, mmu_unmap)) { - int ret; uint64_t size; size = kgsl_memdesc_footprint(memdesc); ret = pagetable->pt_ops->mmu_unmap(pagetable, memdesc); - if (ret) - return ret; atomic_dec(&pagetable->stats.entries); atomic_long_sub(size, &pagetable->stats.mapped); } - return 0; + return ret; } EXPORT_SYMBOL(kgsl_mmu_unmap); diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index 73edc3f7e146..72895c18119f 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -807,8 +807,16 @@ void kgsl_sharedmem_free(struct kgsl_memdesc *memdesc) return; if (memdesc->gpuaddr) { - kgsl_mmu_unmap(memdesc->pagetable, memdesc); - kgsl_mmu_put_gpuaddr(memdesc->pagetable, memdesc); + int ret = 0; + + ret = kgsl_mmu_unmap(memdesc->pagetable, memdesc); + /* + * Do not free the gpuaddr/size if unmap fails. Because if we + * try to map this range in future, the iommu driver will throw + * a BUG_ON() because it feels we are overwriting a mapping. + */ + if (ret == 0) + kgsl_mmu_put_gpuaddr(memdesc->pagetable, memdesc); } if (memdesc->ops && memdesc->ops->free) |
