From 0d4272b65733744c7198b57bd03e3d261fb1740f Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Wed, 25 Oct 2017 18:51:41 +0530 Subject: gpu: nvgpu: don't re-enable TSG if timed out In gk20a_fifo_tsg_unbind_channel(), we disable/preempt TSG, unbind one channel from TSG, and then re-enable rest of the channels in TSG But it is possible that TSG has already timed out due to some error and is already disabled If we re-enable all channels in such case, it can cause random issues right after re-enabling faulted channel Hence do not re-enable TSG if it has timedout Since we disable all channels of TSG if one channel encounters fatal error, it is safe to assume that TSG has timed out if one channel has timed out Bug 1958308 Bug 200327095 Change-Id: I958ca6a2b408ff1338f2e551a79c072f1e203eda Signed-off-by: Deepak Nibade Reviewed-on: https://git-master.nvidia.com/r/1585421 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c index 3b7dce32..194824c3 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c @@ -1952,6 +1952,12 @@ int gk20a_fifo_tsg_unbind_channel(struct channel_gk20a *ch) struct fifo_gk20a *f = &g->fifo; struct tsg_gk20a *tsg = &f->tsg[ch->tsgid]; int err; + bool tsg_timedout = false; + + /* If one channel in TSG times out, we disable all channels */ + nvgpu_rwsem_down_write(&tsg->ch_list_lock); + tsg_timedout = ch->has_timedout; + nvgpu_rwsem_up_write(&tsg->ch_list_lock); /* Disable TSG and examine status before unbinding channel */ g->ops.fifo.disable_tsg(tsg); @@ -1976,14 +1982,22 @@ int gk20a_fifo_tsg_unbind_channel(struct channel_gk20a *ch) nvgpu_list_del(&ch->ch_entry); nvgpu_rwsem_up_write(&tsg->ch_list_lock); - g->ops.fifo.enable_tsg(tsg); + /* + * Don't re-enable all channels if TSG has timed out already + * + * Note that we can skip disabling and preempting TSG too in case of + * time out, but we keep that to ensure TSG is kicked out + */ + if (!tsg_timedout) + g->ops.fifo.enable_tsg(tsg); gk20a_channel_abort_clean_up(ch); return 0; fail_enable_tsg: - g->ops.fifo.enable_tsg(tsg); + if (!tsg_timedout) + g->ops.fifo.enable_tsg(tsg); return err; } -- cgit v1.2.2