diff options
author | Konsta Holtta <kholtta@nvidia.com> | 2016-10-06 06:13:36 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2016-10-12 16:02:13 -0400 |
commit | f5069622bb6233e62f8842c5136f2ea5e8c1e0c8 (patch) | |
tree | 00ff6bb17b442d7ddb480d05fcd694766bf365b8 /drivers | |
parent | 1b2529ba68bdd57231b59f2cb6d4f232e3956853 (diff) |
gpu: nvgpu: make sure vidmem is cleared only once
Protect the initial vidmem zeroing performed during the first userspace
alloc with a mutex, so that it blocks next concurrent users and is run
only once. Otherwise, multiple clears could end up running in parallel,
so that the next ones corrupt memory allocated by the thread that has
finished earlier and advanced to allocate and use memory.
Jira DNVGPU-84
Change-Id: If497749abf481b230835250191d011c4a9d1483b
Signed-off-by: Konsta Holtta <kholtta@nvidia.com>
Reviewed-on: http://git-master/r/1232461
(cherry picked from commit 79435a68e6d2713b78acdb0ec6f77cfd78651d7f)
Reviewed-on: http://git-master/r/1234990
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 15 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.h | 1 |
2 files changed, 12 insertions, 4 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c index 570a3708..4c55f8ce 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c | |||
@@ -947,6 +947,8 @@ static int gk20a_init_vidmem(struct mm_gk20a *mm) | |||
947 | mm->vidmem.bootstrap_base = bootstrap_base; | 947 | mm->vidmem.bootstrap_base = bootstrap_base; |
948 | mm->vidmem.bootstrap_size = bootstrap_size; | 948 | mm->vidmem.bootstrap_size = bootstrap_size; |
949 | 949 | ||
950 | mutex_init(&mm->vidmem.first_clear_mutex); | ||
951 | |||
950 | INIT_WORK(&mm->vidmem.clear_mem_worker, gk20a_vidmem_clear_mem_worker); | 952 | INIT_WORK(&mm->vidmem.clear_mem_worker, gk20a_vidmem_clear_mem_worker); |
951 | atomic_set(&mm->vidmem.clears_pending, 0); | 953 | atomic_set(&mm->vidmem.clears_pending, 0); |
952 | INIT_LIST_HEAD(&mm->vidmem.clear_list_head); | 954 | INIT_LIST_HEAD(&mm->vidmem.clear_list_head); |
@@ -2190,11 +2192,16 @@ int gk20a_vidmem_buf_alloc(struct gk20a *g, size_t bytes) | |||
2190 | buf->g = g; | 2192 | buf->g = g; |
2191 | 2193 | ||
2192 | if (!g->mm.vidmem.cleared) { | 2194 | if (!g->mm.vidmem.cleared) { |
2193 | err = gk20a_vidmem_clear_all(g); | 2195 | mutex_lock(&g->mm.vidmem.first_clear_mutex); |
2194 | if (err) { | 2196 | if (!g->mm.vidmem.cleared) { |
2195 | gk20a_err(g->dev, "failed to clear whole vidmem"); | 2197 | err = gk20a_vidmem_clear_all(g); |
2196 | goto err_kfree; | 2198 | if (err) { |
2199 | gk20a_err(g->dev, | ||
2200 | "failed to clear whole vidmem"); | ||
2201 | goto err_kfree; | ||
2202 | } | ||
2197 | } | 2203 | } |
2204 | mutex_unlock(&g->mm.vidmem.first_clear_mutex); | ||
2198 | } | 2205 | } |
2199 | 2206 | ||
2200 | buf->mem = kzalloc(sizeof(struct mem_desc), GFP_KERNEL); | 2207 | buf->mem = kzalloc(sizeof(struct mem_desc), GFP_KERNEL); |
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.h b/drivers/gpu/nvgpu/gk20a/mm_gk20a.h index 8ce110a1..ee2bb61e 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.h | |||
@@ -417,6 +417,7 @@ struct mm_gk20a { | |||
417 | 417 | ||
418 | u32 ce_ctx_id; | 418 | u32 ce_ctx_id; |
419 | bool cleared; | 419 | bool cleared; |
420 | struct mutex first_clear_mutex; | ||
420 | 421 | ||
421 | struct list_head clear_list_head; | 422 | struct list_head clear_list_head; |
422 | struct mutex clear_list_mutex; | 423 | struct mutex clear_list_mutex; |