msm: kgsl: Detach memory objects from a process ahead of destroy time
Previously, memory objects assumed that they remained attached to a
process until they are destroyed. In the past this was mostly true,
but worked by luck because a process could technically map the memory
and then close the file descriptor which would eventually explode. Now we
do the process related cleanup (MMU unmap, fixup statistics) when the
object is released from the process so the process can go away without
affecting the other holders of the mem object refcount.
Change-Id: Ic0dedbadde0db62b5f3eb02716d6bb8f65f2562d
Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 50a6fab..67efdb9 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -156,8 +156,6 @@
struct kgsl_mem_entry,
refcount);
- entry->priv->stats[entry->memtype].cur -= entry->memdesc.size;
-
if (entry->memtype != KGSL_MEM_ENTRY_KERNEL)
kgsl_driver.stats.mapped -= entry->memdesc.size;
@@ -200,6 +198,21 @@
entry->priv = process;
}
+/* Detach a memory entry from a process and unmap it from the MMU */
+
+static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry)
+{
+ if (entry == NULL)
+ return;
+
+ entry->priv->stats[entry->memtype].cur -= entry->memdesc.size;
+ entry->priv = NULL;
+
+ kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc);
+
+ kgsl_mem_entry_put(entry);
+}
+
/* Allocate a new context id */
static struct kgsl_context *
@@ -593,7 +606,7 @@
list_for_each_entry_safe(entry, entry_tmp, &private->mem_list, list) {
list_del(&entry->list);
- kgsl_mem_entry_put(entry);
+ kgsl_mem_entry_detach_process(entry);
}
kgsl_mmu_putpagetable(private->pagetable);
@@ -1016,7 +1029,7 @@
list_del(&entry->list);
spin_unlock(&entry->priv->mem_lock);
trace_kgsl_mem_timestamp_free(entry, timestamp);
- kgsl_mem_entry_put(entry);
+ kgsl_mem_entry_detach_process(entry);
}
static long kgsl_ioctl_cmdstream_freememontimestamp(struct kgsl_device_private
@@ -1117,7 +1130,7 @@
if (entry) {
trace_kgsl_mem_free(entry);
- kgsl_mem_entry_put(entry);
+ kgsl_mem_entry_detach_process(entry);
} else {
KGSL_CORE_ERR("invalid gpuaddr %08x\n", param->gpuaddr);
result = -EINVAL;