summaryrefslogtreecommitdiff
path: root/drivers/gpu/msm
diff options
context:
space:
mode:
authorHarshdeep Dhatt <hdhatt@codeaurora.org>2016-09-16 11:02:37 -0600
committerHarshdeep Dhatt <hdhatt@codeaurora.org>2016-09-29 14:40:50 -0600
commit3f25aa2b782aef42da07fd54a89b9c3e729cc6bf (patch)
treec0c1a7028f8b60f68aa6b30a62ad2fe4364bb670 /drivers/gpu/msm
parent626caf4e54864d90e8d104277f9a1446e487c7e1 (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.c12
-rw-r--r--drivers/gpu/msm/kgsl_mmu.c7
-rw-r--r--drivers/gpu/msm/kgsl_sharedmem.c12
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)