From 8b05c705fb1cfd3d4f9196f1eadedf0c0b4eff69 Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Wed, 1 Jun 2016 14:23:58 +0530 Subject: gpu: nvgpu: fix TSG abort sequence In gk20a_fifo_abort_tsg(), we loop through channels of TSG and call gk20a_channel_abort() for each channel This is incorrect since we disable and preempt each channel separately, whereas we should disable all channels at once and use TSG specific API to preempt TSG Fix this with below sequence : - gk20a_disable_tsg() to disable all channels - preempt tsg if required - for each channel in TSG - set has_timedout flag - call gk20a_channel_abort_clean_up() to clean up channel state Also, separate out common gk20a_channel_abort_clean_up() API which can be called from both channel and TSG abort routines In gk20a_channel_abort(), call gk20a_fifo_abort_tsg() if the channel is part of TSG Add new argument "preempt" to gk20a_fifo_abort_tsg() and preempt TSG if flag is set Bug 200205041 Change-Id: I4eff5394d26fbb53996f2d30b35140b75450f338 Signed-off-by: Deepak Nibade Reviewed-on: http://git-master/r/1157190 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Alex Waterman Reviewed-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 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 b1d9fa55..3159f026 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -443,21 +443,11 @@ int gk20a_disable_channel_tsg(struct gk20a *g, struct channel_gk20a *ch) return 0; } -void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt) +void gk20a_channel_abort_clean_up(struct channel_gk20a *ch) { struct channel_gk20a_job *job, *n; bool released_job_semaphore = false; - gk20a_dbg_fn(""); - - /* make sure new kickoffs are prevented */ - ch->has_timedout = true; - - ch->g->ops.fifo.disable_channel(ch); - - if (channel_preempt) - gk20a_fifo_preempt(ch->g, ch); - /* ensure no fences are pending */ mutex_lock(&ch->sync_lock); if (ch->sync) @@ -481,6 +471,24 @@ void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt) gk20a_channel_update(ch, 0); } +void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt) +{ + gk20a_dbg_fn(""); + + if (gk20a_is_channel_marked_as_tsg(ch)) + return gk20a_fifo_abort_tsg(ch->g, ch->tsgid, channel_preempt); + + /* make sure new kickoffs are prevented */ + ch->has_timedout = true; + + ch->g->ops.fifo.disable_channel(ch); + + if (channel_preempt) + ch->g->ops.fifo.preempt_channel(ch->g, ch->hw_chid); + + gk20a_channel_abort_clean_up(ch); +} + int gk20a_wait_channel_idle(struct channel_gk20a *ch) { bool channel_idle = false; @@ -1714,7 +1722,7 @@ static void gk20a_channel_timeout_handler(struct work_struct *work) struct tsg_gk20a *tsg = &g->fifo.tsg[ch->tsgid]; gk20a_fifo_set_ctx_mmu_error_tsg(g, tsg); - gk20a_fifo_abort_tsg(g, ch->tsgid); + gk20a_fifo_abort_tsg(g, ch->tsgid, false); } else { gk20a_fifo_set_ctx_mmu_error_ch(g, ch); gk20a_channel_abort(ch, false); -- cgit v1.2.2