summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2016-11-08 14:40:10 -0500
committermobile promotions <svcmobile_promotions@nvidia.com>2017-01-04 18:53:55 -0500
commit91d977ced46f5db02da077df8703e958c5e2af4e (patch)
tree195b96e91f34933dd56b8aa5206295a093fbff11 /drivers/gpu/nvgpu
parenta0242464f5f12d9f10fbf0d05614bfadde84386c (diff)
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>
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c11
-rw-r--r--drivers/gpu/nvgpu/gk20a/mm_gk20a.c15
2 files changed, 24 insertions, 2 deletions
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)
1038 ch->update_fn_data = NULL; 1038 ch->update_fn_data = NULL;
1039 spin_unlock(&ch->update_fn_lock); 1039 spin_unlock(&ch->update_fn_lock);
1040 cancel_work_sync(&ch->update_fn_work); 1040 cancel_work_sync(&ch->update_fn_work);
1041 cancel_delayed_work_sync(&ch->clean_up.wq);
1042 cancel_delayed_work_sync(&ch->timeout.wq);
1041 1043
1042 /* make sure we don't have deferred interrupts pending that 1044 /* make sure we don't have deferred interrupts pending that
1043 * could still touch the channel */ 1045 * could still touch the channel */
@@ -1177,8 +1179,7 @@ int gk20a_channel_release(struct inode *inode, struct file *filp)
1177 1179
1178 err = gk20a_busy(g->dev); 1180 err = gk20a_busy(g->dev);
1179 if (err) { 1181 if (err) {
1180 gk20a_err(dev_from_gk20a(g), "failed to release channel %d", 1182 gk20a_err(dev_from_gk20a(g), "failed to release a channel!");
1181 ch->hw_chid);
1182 return err; 1183 return err;
1183 } 1184 }
1184 1185
@@ -2108,6 +2109,11 @@ static void gk20a_channel_timeout_handler(struct work_struct *work)
2108 2109
2109 g = ch->g; 2110 g = ch->g;
2110 2111
2112 if (gk20a_busy(dev_from_gk20a(g))) {
2113 gk20a_channel_put(ch);
2114 return;
2115 }
2116
2111 /* Need global lock since multiple channels can timeout at a time */ 2117 /* Need global lock since multiple channels can timeout at a time */
2112 mutex_lock(&g->ch_wdt_lock); 2118 mutex_lock(&g->ch_wdt_lock);
2113 2119
@@ -2139,6 +2145,7 @@ static void gk20a_channel_timeout_handler(struct work_struct *work)
2139fail_unlock: 2145fail_unlock:
2140 mutex_unlock(&g->ch_wdt_lock); 2146 mutex_unlock(&g->ch_wdt_lock);
2141 gk20a_channel_put(ch); 2147 gk20a_channel_put(ch);
2148 gk20a_idle(dev_from_gk20a(g));
2142} 2149}
2143 2150
2144int gk20a_free_priv_cmdbuf(struct channel_gk20a *c, struct priv_cmd_entry *e) 2151int gk20a_free_priv_cmdbuf(struct channel_gk20a *c, struct priv_cmd_entry *e)
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c
index 792fa098..2e338fef 100644
--- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c
@@ -219,6 +219,11 @@ static inline void pramin_access_batch_rd_n(struct gk20a *g, u32 start,
219{ 219{
220 u32 r = start, *dest_u32 = *arg; 220 u32 r = start, *dest_u32 = *arg;
221 221
222 if (!g->regs) {
223 __gk20a_warn_on_no_regs();
224 return;
225 }
226
222 while (words--) { 227 while (words--) {
223 *dest_u32++ = gk20a_readl(g, r); 228 *dest_u32++ = gk20a_readl(g, r);
224 r += sizeof(u32); 229 r += sizeof(u32);
@@ -232,6 +237,11 @@ static inline void pramin_access_batch_wr_n(struct gk20a *g, u32 start,
232{ 237{
233 u32 r = start, *src_u32 = *arg; 238 u32 r = start, *src_u32 = *arg;
234 239
240 if (!g->regs) {
241 __gk20a_warn_on_no_regs();
242 return;
243 }
244
235 while (words--) { 245 while (words--) {
236 writel_relaxed(*src_u32++, g->regs + r); 246 writel_relaxed(*src_u32++, g->regs + r);
237 r += sizeof(u32); 247 r += sizeof(u32);
@@ -245,6 +255,11 @@ static inline void pramin_access_batch_set(struct gk20a *g, u32 start,
245{ 255{
246 u32 r = start, repeat = **arg; 256 u32 r = start, repeat = **arg;
247 257
258 if (!g->regs) {
259 __gk20a_warn_on_no_regs();
260 return;
261 }
262
248 while (words--) { 263 while (words--) {
249 writel_relaxed(repeat, g->regs + r); 264 writel_relaxed(repeat, g->regs + r);
250 r += sizeof(u32); 265 r += sizeof(u32);