summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/sync_gk20a.c
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2016-01-21 17:44:43 -0500
committerAlex Waterman <alexw@nvidia.com>2016-01-27 13:58:57 -0500
commitaa74098f29b3027111baf17c21d6e30a3656e2d0 (patch)
tree298db5833fafb013c05fdc29781a39ec7b89b493 /drivers/gpu/nvgpu/gk20a/sync_gk20a.c
parent04092f74bb473fadfede8955b33807124e642b6c (diff)
gpu: nvgpu: Fix gk20a_sync_pt_has_signaled()
Fix a reentrancy problem in gk20a_sync_pt_has_signaled() where one thread could clear a pointer before another thread tried to access it. A spinlock was added to the gk20a_sync_pt struct which is used to ensure that the underyling gk20a_sync_pt data is accessed in a sane manner. Bug 1604892 Change-Id: I270d89def7b986405a3167285d51ceda950c7b82 Signed-off-by: Alex Waterman <alexw@nvidia.com> Reviewed-on: http://git-master/r/935909 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> GVS: Gerrit_Virtual_Submit
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/sync_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/sync_gk20a.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/sync_gk20a.c b/drivers/gpu/nvgpu/gk20a/sync_gk20a.c
index 74cf5c5a..8740f0e2 100644
--- a/drivers/gpu/nvgpu/gk20a/sync_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/sync_gk20a.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * GK20A Sync Framework Integration 2 * GK20A Sync Framework Integration
3 * 3 *
4 * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. 4 * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License, 7 * under the terms and conditions of the GNU General Public License,
@@ -21,6 +21,7 @@
21#include <linux/hrtimer.h> 21#include <linux/hrtimer.h>
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/spinlock.h>
24#include <uapi/linux/nvgpu.h> 25#include <uapi/linux/nvgpu.h>
25#include "../../../staging/android/sync.h" 26#include "../../../staging/android/sync.h"
26#include "semaphore_gk20a.h" 27#include "semaphore_gk20a.h"
@@ -44,6 +45,12 @@ struct gk20a_sync_pt {
44 struct gk20a_sync_timeline *obj; 45 struct gk20a_sync_timeline *obj;
45 struct sync_fence *dep; 46 struct sync_fence *dep;
46 ktime_t dep_timestamp; 47 ktime_t dep_timestamp;
48
49 /*
50 * A spinlock is necessary since there are times when this lock
51 * will be acquired in interrupt context.
52 */
53 spinlock_t lock;
47}; 54};
48 55
49struct gk20a_sync_pt_inst { 56struct gk20a_sync_pt_inst {
@@ -149,7 +156,10 @@ static struct gk20a_sync_pt *gk20a_sync_pt_create_shared(
149 } 156 }
150 } 157 }
151 158
159 spin_lock_init(&shared->lock);
160
152 gk20a_semaphore_get(sema); 161 gk20a_semaphore_get(sema);
162
153 return shared; 163 return shared;
154} 164}
155 165
@@ -194,14 +204,20 @@ static struct sync_pt *gk20a_sync_pt_dup_inst(struct sync_pt *sync_pt)
194 return &pti->pt; 204 return &pti->pt;
195} 205}
196 206
207/*
208 * This function must be able to run on the same sync_pt concurrently. This
209 * requires a lock to protect access to the sync_pt's internal data structures
210 * which are modified as a side effect of calling this function.
211 */
197static int gk20a_sync_pt_has_signaled(struct sync_pt *sync_pt) 212static int gk20a_sync_pt_has_signaled(struct sync_pt *sync_pt)
198{ 213{
199 struct gk20a_sync_pt *pt = to_gk20a_sync_pt(sync_pt); 214 struct gk20a_sync_pt *pt = to_gk20a_sync_pt(sync_pt);
200 struct gk20a_sync_timeline *obj = pt->obj; 215 struct gk20a_sync_timeline *obj = pt->obj;
201 bool signaled; 216 bool signaled = true;
202 217
218 spin_lock(&pt->lock);
203 if (!pt->sema) 219 if (!pt->sema)
204 return true; 220 goto done;
205 221
206 /* Acquired == not realeased yet == active == not signaled. */ 222 /* Acquired == not realeased yet == active == not signaled. */
207 signaled = !gk20a_semaphore_is_acquired(pt->sema); 223 signaled = !gk20a_semaphore_is_acquired(pt->sema);
@@ -232,6 +248,9 @@ static int gk20a_sync_pt_has_signaled(struct sync_pt *sync_pt)
232 gk20a_semaphore_put(pt->sema); 248 gk20a_semaphore_put(pt->sema);
233 pt->sema = NULL; 249 pt->sema = NULL;
234 } 250 }
251done:
252 spin_unlock(&pt->lock);
253
235 return signaled; 254 return signaled;
236} 255}
237 256