diff options
author | Deepak Nibade <dnibade@nvidia.com> | 2016-06-01 04:53:58 -0400 |
---|---|---|
committer | Terje Bergstrom <tbergstrom@nvidia.com> | 2016-06-01 16:04:02 -0400 |
commit | 8b05c705fb1cfd3d4f9196f1eadedf0c0b4eff69 (patch) | |
tree | f652a9c3454780c8237bf5abb80e78788ed895bf /drivers/gpu/nvgpu/gk20a | |
parent | 31fa6773ef124a4e779e0972e87d4fb681217f19 (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/nvgpu/gk20a')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 32 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | 16 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/fifo_gk20a.h | 2 |
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 | ||
446 | void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt) | 446 | void 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 | ||
474 | void 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 | |||
484 | int gk20a_wait_channel_idle(struct channel_gk20a *ch) | 492 | int 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); |
213 | void gk20a_disable_channel(struct channel_gk20a *ch); | 213 | void gk20a_disable_channel(struct channel_gk20a *ch); |
214 | void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt); | 214 | void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt); |
215 | void gk20a_channel_abort_clean_up(struct channel_gk20a *ch); | ||
215 | int gk20a_channel_finish(struct channel_gk20a *ch, unsigned long timeout); | 216 | int gk20a_channel_finish(struct channel_gk20a *ch, unsigned long timeout); |
216 | void gk20a_set_error_notifier(struct channel_gk20a *ch, __u32 error); | 217 | void gk20a_set_error_notifier(struct channel_gk20a *ch, __u32 error); |
217 | void gk20a_channel_semaphore_wakeup(struct gk20a *g, bool post_events); | 218 | void 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 | ||
956 | void gk20a_fifo_abort_tsg(struct gk20a *g, u32 tsgid) | 956 | void 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); |
208 | bool gk20a_fifo_set_ctx_mmu_error_tsg(struct gk20a *g, | 208 | bool gk20a_fifo_set_ctx_mmu_error_tsg(struct gk20a *g, |
209 | struct tsg_gk20a *tsg); | 209 | struct tsg_gk20a *tsg); |
210 | void gk20a_fifo_abort_tsg(struct gk20a *g, u32 tsgid); | 210 | void gk20a_fifo_abort_tsg(struct gk20a *g, u32 tsgid, bool preempt); |
211 | bool gk20a_fifo_set_ctx_mmu_error_ch(struct gk20a *g, | 211 | bool gk20a_fifo_set_ctx_mmu_error_ch(struct gk20a *g, |
212 | struct channel_gk20a *ch); | 212 | struct channel_gk20a *ch); |
213 | 213 | ||