From 91d977ced46f5db02da077df8703e958c5e2af4e Mon Sep 17 00:00:00 2001 From: Alex Waterman Date: Tue, 8 Nov 2016 11:40:10 -0800 Subject: gpu: nvgpu: Misc fixes for crashes on shutdown Fix miscellaneous issues seen during driver shutdown. o Make sure pointers are valid before accessing them. o Busy the GPU during channel timeout. o Cancel delayed work on channels. o Avoid access to channels that may have been freed. Bug 1816516 Bug 1807277 Change-Id: I62df40373fdfb1c4a011364e8c435176a08a7a96 Signed-off-by: Alex Waterman Reviewed-on: http://git-master/r/1250026 (cherry picked from commit 64a95fc96c8ef7c5af9c53c4bb3402626e0d2f60) Reviewed-on: http://git-master/r/1274474 GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 11 +++++++++-- 1 file changed, 9 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 15170820..7b5013ea 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -1038,6 +1038,8 @@ static void gk20a_free_channel(struct channel_gk20a *ch, bool force) ch->update_fn_data = NULL; spin_unlock(&ch->update_fn_lock); cancel_work_sync(&ch->update_fn_work); + cancel_delayed_work_sync(&ch->clean_up.wq); + cancel_delayed_work_sync(&ch->timeout.wq); /* make sure we don't have deferred interrupts pending that * could still touch the channel */ @@ -1177,8 +1179,7 @@ int gk20a_channel_release(struct inode *inode, struct file *filp) err = gk20a_busy(g->dev); if (err) { - gk20a_err(dev_from_gk20a(g), "failed to release channel %d", - ch->hw_chid); + gk20a_err(dev_from_gk20a(g), "failed to release a channel!"); return err; } @@ -2108,6 +2109,11 @@ static void gk20a_channel_timeout_handler(struct work_struct *work) g = ch->g; + if (gk20a_busy(dev_from_gk20a(g))) { + gk20a_channel_put(ch); + return; + } + /* Need global lock since multiple channels can timeout at a time */ mutex_lock(&g->ch_wdt_lock); @@ -2139,6 +2145,7 @@ static void gk20a_channel_timeout_handler(struct work_struct *work) fail_unlock: mutex_unlock(&g->ch_wdt_lock); gk20a_channel_put(ch); + gk20a_idle(dev_from_gk20a(g)); } int gk20a_free_priv_cmdbuf(struct channel_gk20a *c, struct priv_cmd_entry *e) -- cgit v1.2.2