diff options
Diffstat (limited to 'drivers/gpu/nvgpu/include')
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/semaphore.h | 65 |
1 files changed, 19 insertions, 46 deletions
diff --git a/drivers/gpu/nvgpu/include/nvgpu/semaphore.h b/drivers/gpu/nvgpu/include/nvgpu/semaphore.h index 771cc7e1..373c5745 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/semaphore.h +++ b/drivers/gpu/nvgpu/include/nvgpu/semaphore.h | |||
@@ -276,37 +276,18 @@ static inline bool nvgpu_semaphore_is_acquired(struct nvgpu_semaphore *s) | |||
276 | } | 276 | } |
277 | 277 | ||
278 | /* | 278 | /* |
279 | * If @force is set then this will not wait for the underlying semaphore to | 279 | * Fast-forward the hw sema to the threshold represented by sema_thresh. |
280 | * catch up to the passed semaphore threshold. | ||
281 | */ | 280 | */ |
282 | static inline void __nvgpu_semaphore_release(struct nvgpu_semaphore *s, | 281 | static inline void nvgpu_semaphore_reset(struct nvgpu_semaphore *sema_thresh, |
283 | bool force, | ||
284 | struct nvgpu_semaphore_int *hw_sema) | 282 | struct nvgpu_semaphore_int *hw_sema) |
285 | { | 283 | { |
286 | u32 current_val; | 284 | u32 current_val; |
287 | u32 threshold = nvgpu_semaphore_get_value(s); | 285 | u32 threshold = nvgpu_semaphore_get_value(sema_thresh); |
288 | int attempts = 0; | ||
289 | 286 | ||
290 | /* | 287 | current_val = nvgpu_semaphore_read(sema_thresh); |
291 | * Wait until the sema value is 1 less than the write value. That | ||
292 | * way this function is essentially an increment. | ||
293 | * | ||
294 | * TODO: tune the wait a little better. | ||
295 | */ | ||
296 | while (!__nvgpu_semaphore_value_released(threshold - 1, | ||
297 | current_val = nvgpu_semaphore_read(s))) { | ||
298 | if (force) | ||
299 | break; | ||
300 | nvgpu_msleep(100); | ||
301 | attempts += 1; | ||
302 | if (attempts > 100) { | ||
303 | WARN(1, "Stall on sema release!"); | ||
304 | return; | ||
305 | } | ||
306 | } | ||
307 | 288 | ||
308 | /* | 289 | /* |
309 | * If the semaphore has already passed the value we would write then | 290 | * If the semaphore has already reached the value we would write then |
310 | * this is really just a NO-OP. | 291 | * this is really just a NO-OP. |
311 | */ | 292 | */ |
312 | if (__nvgpu_semaphore_value_released(threshold, current_val)) | 293 | if (__nvgpu_semaphore_value_released(threshold, current_val)) |
@@ -315,36 +296,28 @@ static inline void __nvgpu_semaphore_release(struct nvgpu_semaphore *s, | |||
315 | nvgpu_mem_wr(hw_sema->ch->g, &hw_sema->location.pool->rw_mem, | 296 | nvgpu_mem_wr(hw_sema->ch->g, &hw_sema->location.pool->rw_mem, |
316 | hw_sema->location.offset, threshold); | 297 | hw_sema->location.offset, threshold); |
317 | 298 | ||
318 | gpu_sema_verbose_dbg(hw_sema->location.pool->sema_sea->gk20a, | 299 | gpu_sema_verbose_dbg(hw_sema->ch->g, "(c=%d) RESET %u -> %u", |
319 | "(c=%d) WRITE %u", hw_sema->ch->chid, threshold); | 300 | hw_sema->ch->chid, current_val, threshold); |
320 | } | ||
321 | |||
322 | static inline void nvgpu_semaphore_release(struct nvgpu_semaphore *s, | ||
323 | struct nvgpu_semaphore_int *hw_sema) | ||
324 | { | ||
325 | __nvgpu_semaphore_release(s, false, hw_sema); | ||
326 | } | 301 | } |
327 | 302 | ||
328 | /* | 303 | /* |
329 | * Configure a software based increment on this semaphore. This is useful for | 304 | * Update nvgpu-tracked shadow of the value in "hw_sema" and mark the threshold |
330 | * when we want the GPU to wait on a SW event before processing a channel. | 305 | * value to "s" which represents the increment that the caller must write in a |
331 | * Another way to describe this is when the GPU needs to wait on a SW pre-fence. | 306 | * pushbuf. The same nvgpu_semaphore will also represent an output fence; when |
332 | * The pre-fence signals SW which in turn calls nvgpu_semaphore_release() which | 307 | * nvgpu_semaphore_is_released(s) == true, the gpu is done with this increment. |
333 | * then allows the GPU to continue. | ||
334 | * | ||
335 | * Also used to prep a semaphore for an INCR by the GPU. | ||
336 | */ | 308 | */ |
337 | static inline void nvgpu_semaphore_incr(struct nvgpu_semaphore *s, | 309 | static inline void nvgpu_semaphore_prepare(struct nvgpu_semaphore *s, |
338 | struct nvgpu_semaphore_int *hw_sema) | 310 | struct nvgpu_semaphore_int *hw_sema) |
339 | { | 311 | { |
340 | BUG_ON(s->incremented); | 312 | int next = nvgpu_atomic_add_return(1, &hw_sema->next_value); |
313 | |||
314 | /* "s" should be an uninitialized sema. */ | ||
315 | WARN_ON(s->incremented); | ||
341 | 316 | ||
342 | nvgpu_atomic_set(&s->value, nvgpu_atomic_add_return(1, &hw_sema->next_value)); | 317 | nvgpu_atomic_set(&s->value, next); |
343 | s->incremented = 1; | 318 | s->incremented = 1; |
344 | 319 | ||
345 | gpu_sema_verbose_dbg(s->g, | 320 | gpu_sema_verbose_dbg(s->g, "INCR sema for c=%d (%u)", |
346 | "INCR sema for c=%d (%u)", | 321 | hw_sema->ch->chid, next); |
347 | hw_sema->ch->chid, | ||
348 | nvgpu_atomic_read(&hw_sema->next_value)); | ||
349 | } | 322 | } |
350 | #endif | 323 | #endif |