From f575bc667649ff1a09aac8ecbe626fde8ea5f2f4 Mon Sep 17 00:00:00 2001 From: Lauri Peltonen Date: Wed, 11 Jun 2014 12:56:31 +0300 Subject: gpu: nvgpu: Support semaphore sync when aborting jobs When aborting jobs on channel error situations, we manually set the channel syncpoint's min == max in gk20a_disable_channel_no_update. Nvhost will notice this manual syncpoint increment, and will call back to gk20a_channel_update, which will clean up the job. With semaphore synchronization, we don't have anybody calling back to gk20a_channel_update, so we need to call it ourselves. Release job semaphores (the equivalent of set_min_eq_max) on gk20a_disable_channel_no_update, and if any semaphores were released, call gk20a_channel_update afterwards. Because we are actually calling gk20a_channel_update in some situations, gk20a_disable_channel_no_update is no longer an appropriate name for the function. Rename it to gk20a_channel_abort. Bug 1450122 Change-Id: I1267b099a5778041cbc8e91b7184844812145b93 Signed-off-by: Lauri Peltonen Reviewed-on: http://git-master/r/422161 GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.c') diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index f5d5e467..9492d646 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -406,17 +406,36 @@ static int channel_gk20a_update_runlist(struct channel_gk20a *c, bool add) return gk20a_fifo_update_runlist(c->g, 0, c->hw_chid, add, true); } -void gk20a_disable_channel_no_update(struct channel_gk20a *ch) +void gk20a_channel_abort(struct channel_gk20a *ch) { + struct channel_gk20a_job *job, *n; + bool released_job_semaphore = false; + /* ensure no fences are pending */ if (ch->sync) ch->sync->set_min_eq_max(ch->sync); + /* release all job semaphores (applies only to jobs that use + semaphore synchronization) */ + mutex_lock(&ch->jobs_lock); + list_for_each_entry_safe(job, n, &ch->jobs, list) { + if (job->post_fence.semaphore) { + gk20a_semaphore_release(job->post_fence.semaphore); + released_job_semaphore = true; + } + } + mutex_unlock(&ch->jobs_lock); + /* disable channel */ gk20a_writel(ch->g, ccsr_channel_r(ch->hw_chid), gk20a_readl(ch->g, ccsr_channel_r(ch->hw_chid)) | ccsr_channel_enable_clr_true_f()); + + if (released_job_semaphore) { + wake_up_interruptible_all(&ch->semaphore_wq); + gk20a_channel_update(ch, 0); + } } int gk20a_wait_channel_idle(struct channel_gk20a *ch) @@ -455,7 +474,7 @@ void gk20a_disable_channel(struct channel_gk20a *ch, } /* disable the channel from hw and increment syncpoints */ - gk20a_disable_channel_no_update(ch); + gk20a_channel_abort(ch); gk20a_wait_channel_idle(ch); -- cgit v1.2.2