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 <alexw@nvidia.com>
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 <tbergstrom@nvidia.com>
This commit is contained in:
Alex Waterman
2016-11-08 11:40:10 -08:00
committed by mobile promotions
parent a0242464f5
commit 91d977ced4
2 changed files with 24 additions and 2 deletions

View File

@@ -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)

View File

@@ -219,6 +219,11 @@ static inline void pramin_access_batch_rd_n(struct gk20a *g, u32 start,
{
u32 r = start, *dest_u32 = *arg;
if (!g->regs) {
__gk20a_warn_on_no_regs();
return;
}
while (words--) {
*dest_u32++ = gk20a_readl(g, r);
r += sizeof(u32);
@@ -232,6 +237,11 @@ static inline void pramin_access_batch_wr_n(struct gk20a *g, u32 start,
{
u32 r = start, *src_u32 = *arg;
if (!g->regs) {
__gk20a_warn_on_no_regs();
return;
}
while (words--) {
writel_relaxed(*src_u32++, g->regs + r);
r += sizeof(u32);
@@ -245,6 +255,11 @@ static inline void pramin_access_batch_set(struct gk20a *g, u32 start,
{
u32 r = start, repeat = **arg;
if (!g->regs) {
__gk20a_warn_on_no_regs();
return;
}
while (words--) {
writel_relaxed(repeat, g->regs + r);
r += sizeof(u32);