summaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDeepak Nibade <dnibade@nvidia.com>2016-06-01 04:53:58 -0400
committerTerje Bergstrom <tbergstrom@nvidia.com>2016-06-01 16:04:02 -0400
commit8b05c705fb1cfd3d4f9196f1eadedf0c0b4eff69 (patch)
treef652a9c3454780c8237bf5abb80e78788ed895bf /drivers/gpu
parent31fa6773ef124a4e779e0972e87d4fb681217f19 (diff)
gpu: nvgpu: fix TSG abort sequence
In gk20a_fifo_abort_tsg(), we loop through channels of TSG and call gk20a_channel_abort() for each channel This is incorrect since we disable and preempt each channel separately, whereas we should disable all channels at once and use TSG specific API to preempt TSG Fix this with below sequence : - gk20a_disable_tsg() to disable all channels - preempt tsg if required - for each channel in TSG - set has_timedout flag - call gk20a_channel_abort_clean_up() to clean up channel state Also, separate out common gk20a_channel_abort_clean_up() API which can be called from both channel and TSG abort routines In gk20a_channel_abort(), call gk20a_fifo_abort_tsg() if the channel is part of TSG Add new argument "preempt" to gk20a_fifo_abort_tsg() and preempt TSG if flag is set Bug 200205041 Change-Id: I4eff5394d26fbb53996f2d30b35140b75450f338 Signed-off-by: Deepak Nibade <dnibade@nvidia.com> Reviewed-on: http://git-master/r/1157190 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Alex Waterman <alexw@nvidia.com> Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c32
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.h1
-rw-r--r--drivers/gpu/nvgpu/gk20a/fifo_gk20a.c16
-rw-r--r--drivers/gpu/nvgpu/gk20a/fifo_gk20a.h2
4 files changed, 34 insertions, 17 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
index b1d9fa55..3159f026 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
@@ -443,21 +443,11 @@ int gk20a_disable_channel_tsg(struct gk20a *g, struct channel_gk20a *ch)
443 return 0; 443 return 0;
444} 444}
445 445
446void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt) 446void gk20a_channel_abort_clean_up(struct channel_gk20a *ch)
447{ 447{
448 struct channel_gk20a_job *job, *n; 448 struct channel_gk20a_job *job, *n;
449 bool released_job_semaphore = false; 449 bool released_job_semaphore = false;
450 450
451 gk20a_dbg_fn("");
452
453 /* make sure new kickoffs are prevented */
454 ch->has_timedout = true;
455
456 ch->g->ops.fifo.disable_channel(ch);
457
458 if (channel_preempt)
459 gk20a_fifo_preempt(ch->g, ch);
460
461 /* ensure no fences are pending */ 451 /* ensure no fences are pending */
462 mutex_lock(&ch->sync_lock); 452 mutex_lock(&ch->sync_lock);
463 if (ch->sync) 453 if (ch->sync)
@@ -481,6 +471,24 @@ void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt)
481 gk20a_channel_update(ch, 0); 471 gk20a_channel_update(ch, 0);
482} 472}
483 473
474void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt)
475{
476 gk20a_dbg_fn("");
477
478 if (gk20a_is_channel_marked_as_tsg(ch))
479 return gk20a_fifo_abort_tsg(ch->g, ch->tsgid, channel_preempt);
480
481 /* make sure new kickoffs are prevented */
482 ch->has_timedout = true;
483
484 ch->g->ops.fifo.disable_channel(ch);
485
486 if (channel_preempt)
487 ch->g->ops.fifo.preempt_channel(ch->g, ch->hw_chid);
488
489 gk20a_channel_abort_clean_up(ch);
490}
491
484int gk20a_wait_channel_idle(struct channel_gk20a *ch) 492int gk20a_wait_channel_idle(struct channel_gk20a *ch)
485{ 493{
486 bool channel_idle = false; 494 bool channel_idle = false;
@@ -1714,7 +1722,7 @@ static void gk20a_channel_timeout_handler(struct work_struct *work)
1714 struct tsg_gk20a *tsg = &g->fifo.tsg[ch->tsgid]; 1722 struct tsg_gk20a *tsg = &g->fifo.tsg[ch->tsgid];
1715 1723
1716 gk20a_fifo_set_ctx_mmu_error_tsg(g, tsg); 1724 gk20a_fifo_set_ctx_mmu_error_tsg(g, tsg);
1717 gk20a_fifo_abort_tsg(g, ch->tsgid); 1725 gk20a_fifo_abort_tsg(g, ch->tsgid, false);
1718 } else { 1726 } else {
1719 gk20a_fifo_set_ctx_mmu_error_ch(g, ch); 1727 gk20a_fifo_set_ctx_mmu_error_ch(g, ch);
1720 gk20a_channel_abort(ch, false); 1728 gk20a_channel_abort(ch, false);
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h
index b1355f92..29a13d24 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h
@@ -212,6 +212,7 @@ bool gk20a_channel_update_and_check_timeout(struct channel_gk20a *ch,
212 u32 timeout_delta_ms); 212 u32 timeout_delta_ms);
213void gk20a_disable_channel(struct channel_gk20a *ch); 213void gk20a_disable_channel(struct channel_gk20a *ch);
214void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt); 214void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt);
215void gk20a_channel_abort_clean_up(struct channel_gk20a *ch);
215int gk20a_channel_finish(struct channel_gk20a *ch, unsigned long timeout); 216int gk20a_channel_finish(struct channel_gk20a *ch, unsigned long timeout);
216void gk20a_set_error_notifier(struct channel_gk20a *ch, __u32 error); 217void gk20a_set_error_notifier(struct channel_gk20a *ch, __u32 error);
217void gk20a_channel_semaphore_wakeup(struct gk20a *g, bool post_events); 218void gk20a_channel_semaphore_wakeup(struct gk20a *g, bool post_events);
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
index f8382afe..17efe5ca 100644
--- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
@@ -953,15 +953,23 @@ bool gk20a_fifo_set_ctx_mmu_error_tsg(struct gk20a *g,
953 return ret; 953 return ret;
954} 954}
955 955
956void gk20a_fifo_abort_tsg(struct gk20a *g, u32 tsgid) 956void gk20a_fifo_abort_tsg(struct gk20a *g, u32 tsgid, bool preempt)
957{ 957{
958 struct tsg_gk20a *tsg = &g->fifo.tsg[tsgid]; 958 struct tsg_gk20a *tsg = &g->fifo.tsg[tsgid];
959 struct channel_gk20a *ch; 959 struct channel_gk20a *ch;
960 960
961 gk20a_dbg_fn("");
962
963 gk20a_disable_tsg(tsg);
964
965 if (preempt)
966 g->ops.fifo.preempt_tsg(g, tsgid);
967
961 mutex_lock(&tsg->ch_list_lock); 968 mutex_lock(&tsg->ch_list_lock);
962 list_for_each_entry(ch, &tsg->ch_list, ch_entry) { 969 list_for_each_entry(ch, &tsg->ch_list, ch_entry) {
963 if (gk20a_channel_get(ch)) { 970 if (gk20a_channel_get(ch)) {
964 gk20a_channel_abort(ch, false); 971 ch->has_timedout = true;
972 gk20a_channel_abort_clean_up(ch);
965 gk20a_channel_put(ch); 973 gk20a_channel_put(ch);
966 } 974 }
967 } 975 }
@@ -1129,7 +1137,7 @@ static bool gk20a_fifo_handle_mmu_fault(
1129 verbose = 1137 verbose =
1130 gk20a_fifo_set_ctx_mmu_error_tsg(g, tsg); 1138 gk20a_fifo_set_ctx_mmu_error_tsg(g, tsg);
1131 1139
1132 gk20a_fifo_abort_tsg(g, tsg->tsgid); 1140 gk20a_fifo_abort_tsg(g, tsg->tsgid, false);
1133 1141
1134 /* put back the ref taken early above */ 1142 /* put back the ref taken early above */
1135 if (referenced_channel) 1143 if (referenced_channel)
@@ -1324,7 +1332,7 @@ void gk20a_fifo_recover_tsg(struct gk20a *g, u32 tsgid, bool verbose)
1324 if (gk20a_fifo_set_ctx_mmu_error_tsg(g, tsg)) 1332 if (gk20a_fifo_set_ctx_mmu_error_tsg(g, tsg))
1325 gk20a_debug_dump(g->dev); 1333 gk20a_debug_dump(g->dev);
1326 1334
1327 gk20a_fifo_abort_tsg(g, tsgid); 1335 gk20a_fifo_abort_tsg(g, tsgid, false);
1328 } 1336 }
1329 1337
1330 gr_gk20a_enable_ctxsw(g); 1338 gr_gk20a_enable_ctxsw(g);
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h
index 986db4b1..5fb5f550 100644
--- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h
@@ -207,7 +207,7 @@ u32 gk20a_fifo_get_failing_engine_data(struct gk20a *g,
207 int *__id, bool *__is_tsg); 207 int *__id, bool *__is_tsg);
208bool gk20a_fifo_set_ctx_mmu_error_tsg(struct gk20a *g, 208bool gk20a_fifo_set_ctx_mmu_error_tsg(struct gk20a *g,
209 struct tsg_gk20a *tsg); 209 struct tsg_gk20a *tsg);
210void gk20a_fifo_abort_tsg(struct gk20a *g, u32 tsgid); 210void gk20a_fifo_abort_tsg(struct gk20a *g, u32 tsgid, bool preempt);
211bool gk20a_fifo_set_ctx_mmu_error_ch(struct gk20a *g, 211bool gk20a_fifo_set_ctx_mmu_error_ch(struct gk20a *g,
212 struct channel_gk20a *ch); 212 struct channel_gk20a *ch);
213 213