gpu: nvgpu: preempt before adjusting fences

Current sequence in gk20a_disable_channel() is
- disable channel in gk20a_channel_abort()
- adjust pending fence in gk20a_channel_abort()
- preempt channel

But this leads to scenarios where syncpoint has
min > max value

Hence to fix this, make sequence in gk20a_disable_channel()
- disable channel in gk20a_channel_abort()
- preempt channel in gk20a_channel_abort()
- adjust pending fence in gk20a_channel_abort()

If gk20a_channel_abort() is called from other API where
preemption is not needed, then use channel_preempt
flag and do not preempt channel in those cases

Bug 1683059

Change-Id: I4d46d4294cf8597ae5f05f79dfe1b95c4187f2e3
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/921290
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
This commit is contained in:
Deepak Nibade
2015-12-10 14:28:32 +05:30
committed by Terje Bergstrom
parent 54f76d1ac6
commit c4ac1ed369
4 changed files with 11 additions and 9 deletions

View File

@@ -392,7 +392,7 @@ void channel_gk20a_disable(struct channel_gk20a *ch)
ccsr_channel_enable_clr_true_f());
}
void gk20a_channel_abort(struct channel_gk20a *ch)
void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt)
{
struct channel_gk20a_job *job, *n;
bool released_job_semaphore = false;
@@ -404,6 +404,9 @@ void gk20a_channel_abort(struct channel_gk20a *ch)
ch->g->ops.fifo.disable_channel(ch);
if (channel_preempt)
ch->g->ops.fifo.preempt_channel(ch->g, ch->hw_chid);
/* ensure no fences are pending */
mutex_lock(&ch->sync_lock);
if (ch->sync)
@@ -455,8 +458,7 @@ int gk20a_wait_channel_idle(struct channel_gk20a *ch)
void gk20a_disable_channel(struct channel_gk20a *ch)
{
gk20a_channel_abort(ch);
ch->g->ops.fifo.preempt_channel(ch->g, ch->hw_chid);
gk20a_channel_abort(ch, true);
channel_gk20a_update_runlist(ch, false);
}
@@ -1621,7 +1623,7 @@ static void gk20a_channel_timeout_handler(struct work_struct *work)
gk20a_fifo_abort_tsg(g, ch->tsgid);
} else {
gk20a_fifo_set_ctx_mmu_error_ch(g, ch);
gk20a_channel_abort(ch);
gk20a_channel_abort(ch, false);
}
} else {
/* If failing engine, trigger recovery */

View File

@@ -195,7 +195,7 @@ void gk20a_channel_close(struct channel_gk20a *ch);
bool gk20a_channel_update_and_check_timeout(struct channel_gk20a *ch,
u32 timeout_delta_ms);
void gk20a_disable_channel(struct channel_gk20a *ch);
void gk20a_channel_abort(struct channel_gk20a *ch);
void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt);
int gk20a_channel_finish(struct channel_gk20a *ch, unsigned long timeout);
void gk20a_set_error_notifier(struct channel_gk20a *ch, __u32 error);
void gk20a_channel_semaphore_wakeup(struct gk20a *g);

View File

@@ -894,7 +894,7 @@ void gk20a_fifo_abort_tsg(struct gk20a *g, u32 tsgid)
mutex_lock(&tsg->ch_list_lock);
list_for_each_entry(ch, &tsg->ch_list, ch_entry) {
if (gk20a_channel_get(ch)) {
gk20a_channel_abort(ch);
gk20a_channel_abort(ch, false);
gk20a_channel_put(ch);
}
}
@@ -1064,7 +1064,7 @@ static bool gk20a_fifo_handle_mmu_fault(
if (referenced_channel) {
if (!g->fifo.deferred_reset_pending)
verbose = gk20a_fifo_set_ctx_mmu_error_ch(g, ch);
gk20a_channel_abort(ch);
gk20a_channel_abort(ch, false);
gk20a_channel_put(ch);
} else {
gk20a_err(dev_from_gk20a(g),
@@ -1217,7 +1217,7 @@ void gk20a_fifo_recover_ch(struct gk20a *g, u32 hw_chid, bool verbose)
struct channel_gk20a *ch = &g->fifo.channel[hw_chid];
if (gk20a_channel_get(ch)) {
gk20a_channel_abort(ch);
gk20a_channel_abort(ch, false);
if (gk20a_fifo_set_ctx_mmu_error_ch(g, ch))
gk20a_debug_dump(g->dev);

View File

@@ -566,7 +566,7 @@ int vgpu_fifo_isr(struct gk20a *g, struct tegra_vgpu_fifo_intr_info *info)
break;
case TEGRA_VGPU_FIFO_INTR_MMU_FAULT:
vgpu_fifo_set_ctx_mmu_error(g, ch);
gk20a_channel_abort(ch);
gk20a_channel_abort(ch, false);
break;
default:
WARN_ON(1);