mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-12-29 01:16:26 -05:00
181 lines
5.6 KiB
Diff
181 lines
5.6 KiB
Diff
From ec5feea777b07c0e1f9ce45b7f3179a3f6facf75 Mon Sep 17 00:00:00 2001
|
|
From: Sunil Khatri <sunilkh@codeaurora.org>
|
|
Date: Wed, 25 May 2016 15:36:30 +0530
|
|
Subject: msm: kgsl: Defer adding the mem entry to a process
|
|
|
|
If we add the mem entry pointer in the process idr and rb tree
|
|
too early, other threads can do operations on the entry by
|
|
guessing the ID or GPU address before the object gets returned
|
|
by the creating operation.
|
|
|
|
Allocate an ID for the object but don't assign the pointer until
|
|
right before the creating function returns ensuring that another
|
|
operation can't access it until it is ready.
|
|
|
|
CRs-Fixed: 1002974
|
|
Change-Id: Ic0dedbadc0dd2125bd2a7bcc152972c0555e07f8
|
|
Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
|
|
Signed-off-by: Sunil Khatri <sunilkh@codeaurora.org>
|
|
---
|
|
drivers/gpu/msm/kgsl.c | 84 ++++++++++++++++++++++++++++++++------------------
|
|
1 file changed, 54 insertions(+), 30 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
|
|
index 94b09f0..dab99c5 100644
|
|
--- a/drivers/gpu/msm/kgsl.c
|
|
+++ b/drivers/gpu/msm/kgsl.c
|
|
@@ -313,18 +313,13 @@ kgsl_mem_entry_destroy(struct kref *kref)
|
|
EXPORT_SYMBOL(kgsl_mem_entry_destroy);
|
|
|
|
/**
|
|
- * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree and
|
|
- * assign it with a gpu address space before insertion
|
|
+ * kgsl_mem_entry_track_gpuaddr - Get the entry gpu address space before
|
|
+ * insertion to the process
|
|
* @process: the process that owns the memory
|
|
* @entry: the memory entry
|
|
*
|
|
- * @returns - 0 on succcess else error code
|
|
+ * @returns - 0 on success else error code
|
|
*
|
|
- * Insert the kgsl_mem_entry in to the rb_tree for searching by GPU address.
|
|
- * The assignment of gpu address and insertion into list needs to
|
|
- * happen with the memory lock held to avoid race conditions between
|
|
- * gpu address being selected and some other thread looking through the
|
|
- * rb list in search of memory based on gpuaddr
|
|
* This function should be called with processes memory spinlock held
|
|
*/
|
|
static int
|
|
@@ -332,8 +327,6 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process,
|
|
struct kgsl_mem_entry *entry)
|
|
{
|
|
int ret = 0;
|
|
- struct rb_node **node;
|
|
- struct rb_node *parent = NULL;
|
|
struct kgsl_pagetable *pagetable = process->pagetable;
|
|
|
|
assert_spin_locked(&process->mem_lock);
|
|
@@ -354,25 +347,6 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process,
|
|
pagetable = pagetable->mmu->securepagetable;
|
|
|
|
ret = kgsl_mmu_get_gpuaddr(pagetable, &entry->memdesc);
|
|
- if (ret)
|
|
- goto done;
|
|
-
|
|
- node = &process->mem_rb.rb_node;
|
|
-
|
|
- while (*node) {
|
|
- struct kgsl_mem_entry *cur;
|
|
-
|
|
- parent = *node;
|
|
- cur = rb_entry(parent, struct kgsl_mem_entry, node);
|
|
-
|
|
- if (entry->memdesc.gpuaddr < cur->memdesc.gpuaddr)
|
|
- node = &parent->rb_left;
|
|
- else
|
|
- node = &parent->rb_right;
|
|
- }
|
|
-
|
|
- rb_link_node(&entry->node, parent, node);
|
|
- rb_insert_color(&entry->node, &process->mem_rb);
|
|
|
|
done:
|
|
return ret;
|
|
@@ -398,6 +372,47 @@ kgsl_mem_entry_untrack_gpuaddr(struct kgsl_process_private *process,
|
|
}
|
|
}
|
|
|
|
+static void kgsl_mem_entry_commit_mem_list(struct kgsl_process_private *process,
|
|
+ struct kgsl_mem_entry *entry)
|
|
+{
|
|
+ struct rb_node **node;
|
|
+ struct rb_node *parent = NULL;
|
|
+
|
|
+ if (!entry->memdesc.gpuaddr)
|
|
+ return;
|
|
+
|
|
+ /* Insert mem entry in mem_rb tree */
|
|
+ node = &process->mem_rb.rb_node;
|
|
+ while (*node) {
|
|
+ struct kgsl_mem_entry *cur;
|
|
+
|
|
+ parent = *node;
|
|
+ cur = rb_entry(parent, struct kgsl_mem_entry, node);
|
|
+
|
|
+ if (entry->memdesc.gpuaddr < cur->memdesc.gpuaddr)
|
|
+ node = &parent->rb_left;
|
|
+ else
|
|
+ node = &parent->rb_right;
|
|
+ }
|
|
+
|
|
+ rb_link_node(&entry->node, parent, node);
|
|
+ rb_insert_color(&entry->node, &process->mem_rb);
|
|
+}
|
|
+
|
|
+static void kgsl_mem_entry_commit_process(struct kgsl_process_private *process,
|
|
+ struct kgsl_mem_entry *entry)
|
|
+{
|
|
+ if (!entry)
|
|
+ return;
|
|
+
|
|
+ spin_lock(&entry->priv->mem_lock);
|
|
+ /* Insert mem entry in mem_rb tree */
|
|
+ kgsl_mem_entry_commit_mem_list(process, entry);
|
|
+ /* Replace mem entry in mem_idr using id */
|
|
+ idr_replace(&entry->priv->mem_idr, entry, entry->id);
|
|
+ spin_unlock(&entry->priv->mem_lock);
|
|
+}
|
|
+
|
|
/**
|
|
* kgsl_mem_entry_attach_process - Attach a mem_entry to its owner process
|
|
* @entry: the memory entry
|
|
@@ -424,7 +439,8 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry,
|
|
return -EBADF;
|
|
idr_preload(GFP_KERNEL);
|
|
spin_lock(&process->mem_lock);
|
|
- id = idr_alloc(&process->mem_idr, entry, 1, 0, GFP_NOWAIT);
|
|
+ /* Allocate the ID but don't attach the pointer just yet */
|
|
+ id = idr_alloc(&process->mem_idr, NULL, 1, 0, GFP_NOWAIT);
|
|
spin_unlock(&process->mem_lock);
|
|
idr_preload_end();
|
|
|
|
@@ -2400,6 +2416,7 @@ long kgsl_ioctl_gpuobj_import(struct kgsl_device_private *dev_priv,
|
|
|
|
trace_kgsl_mem_map(entry, fd);
|
|
|
|
+ kgsl_mem_entry_commit_process(private, entry);
|
|
return 0;
|
|
|
|
unmap:
|
|
@@ -2671,6 +2688,7 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
|
|
|
|
trace_kgsl_mem_map(entry, param->fd);
|
|
|
|
+ kgsl_mem_entry_commit_process(private, entry);
|
|
return result;
|
|
|
|
error_attach:
|
|
@@ -3084,6 +3102,7 @@ static struct kgsl_mem_entry *gpumem_alloc_entry(
|
|
entry->memdesc.size);
|
|
trace_kgsl_mem_alloc(entry);
|
|
|
|
+ kgsl_mem_entry_commit_process(private, entry);
|
|
return entry;
|
|
err:
|
|
kfree(entry);
|
|
@@ -3579,6 +3598,11 @@ static int kgsl_check_gpu_addr_collision(
|
|
spin_lock(&private->mem_lock);
|
|
kgsl_mem_entry_untrack_gpuaddr(private, entry);
|
|
spin_unlock(&private->mem_lock);
|
|
+ } else {
|
|
+ /* Insert mem entry in mem_rb tree */
|
|
+ spin_lock(&private->mem_lock);
|
|
+ kgsl_mem_entry_commit_mem_list(private, entry);
|
|
+ spin_unlock(&private->mem_lock);
|
|
}
|
|
} else {
|
|
trace_kgsl_mem_unmapped_area_collision(entry, addr, len,
|
|
--
|
|
cgit v1.1
|
|
|