diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/sync_gk20a.c | 25 |
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 | ||
49 | struct gk20a_sync_pt_inst { | 56 | struct 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 | */ | ||
197 | static int gk20a_sync_pt_has_signaled(struct sync_pt *sync_pt) | 212 | static 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 | } |
251 | done: | ||
252 | spin_unlock(&pt->lock); | ||
253 | |||
235 | return signaled; | 254 | return signaled; |
236 | } | 255 | } |
237 | 256 | ||