From 274e1881af2e4c327fda5e28eb804fe304a2f36e Mon Sep 17 00:00:00 2001 From: Alex Waterman Date: Mon, 7 Nov 2016 15:25:34 -0800 Subject: gpu: nvgpu: Allow semaphores to be force released Allow SW to force a semaphore release. Typically SW waits for a semaphore to reach the value right before the semaphore release value before doing a release. For example, assuming a semaphore is to be released by SW by writing a 10 into the semaphore, the code waits for the semaphore to get to 9 before writing 10. The problem with this happens when trying to shutdown the GPU unexpectedly. When aborting a channel after the GPU has terminated the GPU is potantially no longer processing anything. If a SW semaphore release is waiting on the semaphore to reach N-1 before writing N to the semaphore N-1 may never get written by the GPU. This obviously causes a hang in the SW shutdown. The solution is to let SW force a semaphore release in the channel_abort case. Bug 1816516 Bug 1807277 Change-Id: Ib8b4afd86102eacf372362b1748fb6ca04e6fa66 Signed-off-by: Alex Waterman Reviewed-on: http://git-master/r/1250021 (cherry picked from commit 2e9fa40902d2c4d5a1febe0bf2db420ce14bc633) Reviewed-on: http://git-master/r/1261915 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/semaphore_gk20a.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/nvgpu/gk20a/semaphore_gk20a.h') diff --git a/drivers/gpu/nvgpu/gk20a/semaphore_gk20a.h b/drivers/gpu/nvgpu/gk20a/semaphore_gk20a.h index c73d3c05..cf724fdb 100644 --- a/drivers/gpu/nvgpu/gk20a/semaphore_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/semaphore_gk20a.h @@ -249,9 +249,11 @@ static inline u32 gk20a_semaphore_next_value(struct gk20a_semaphore *s) } /* - * Note - if you call this then any prior semaphores will also be released. + * If @force is set then this will not wait for the underlying semaphore to + * catch up to the passed semaphore. */ -static inline void gk20a_semaphore_release(struct gk20a_semaphore *s) +static inline void __gk20a_semaphore_release(struct gk20a_semaphore *s, + bool force) { u32 current_val; u32 val = gk20a_semaphore_get_value(s); @@ -264,6 +266,8 @@ static inline void gk20a_semaphore_release(struct gk20a_semaphore *s) * TODO: tune the wait a little better. */ while ((current_val = gk20a_semaphore_read(s)) < (val - 1)) { + if (force) + break; msleep(100); attempts += 1; if (attempts > 100) { @@ -285,6 +289,11 @@ static inline void gk20a_semaphore_release(struct gk20a_semaphore *s) s->hw_sema->ch->hw_chid, val); } +static inline void gk20a_semaphore_release(struct gk20a_semaphore *s) +{ + __gk20a_semaphore_release(s, false); +} + /* * Configure a software based increment on this semaphore. This is useful for * when we want the GPU to wait on a SW event before processing a channel. -- cgit v1.2.2