summaryrefslogtreecommitdiff
path: root/drivers/gpu/msm/kgsl_mmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/msm/kgsl_mmu.c')
-rw-r--r--drivers/gpu/msm/kgsl_mmu.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index ba564b2851f9..0df1ad02f16e 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -414,17 +414,29 @@ EXPORT_SYMBOL(kgsl_mmu_map);
* @pagetable: Pagetable to release the memory from
* @memdesc: Memory descriptor containing the GPU address to free
*/
-void kgsl_mmu_put_gpuaddr(struct kgsl_pagetable *pagetable,
- struct kgsl_memdesc *memdesc)
+void kgsl_mmu_put_gpuaddr(struct kgsl_memdesc *memdesc)
{
+ struct kgsl_pagetable *pagetable = memdesc->pagetable;
+ int unmap_fail = 0;
+
if (memdesc->size == 0 || memdesc->gpuaddr == 0)
return;
- if (PT_OP_VALID(pagetable, put_gpuaddr))
- pagetable->pt_ops->put_gpuaddr(pagetable, memdesc);
+ if (!kgsl_memdesc_is_global(memdesc))
+ unmap_fail = kgsl_mmu_unmap(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 (PT_OP_VALID(pagetable, put_gpuaddr) && (unmap_fail == 0))
+ pagetable->pt_ops->put_gpuaddr(memdesc);
if (!kgsl_memdesc_is_global(memdesc))
memdesc->gpuaddr = 0;
+
+ memdesc->pagetable = NULL;
}
EXPORT_SYMBOL(kgsl_mmu_put_gpuaddr);
@@ -610,7 +622,12 @@ static int nommu_get_gpuaddr(struct kgsl_pagetable *pagetable,
memdesc->gpuaddr = (uint64_t) sg_phys(memdesc->sgt->sgl);
- return memdesc->gpuaddr != 0 ? 0 : -ENOMEM;
+ if (memdesc->gpuaddr) {
+ memdesc->pagetable = pagetable;
+ return 0;
+ }
+
+ return -ENOMEM;
}
static struct kgsl_mmu_pt_ops nommu_pt_ops = {