mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-24 10:34:43 +03:00
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:
committed by
mobile promotions
parent
a0242464f5
commit
91d977ced4
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user