diff options
author | Deepak Nibade <dnibade@nvidia.com> | 2015-12-10 03:58:32 -0500 |
---|---|---|
committer | Terje Bergstrom <tbergstrom@nvidia.com> | 2015-12-10 11:39:42 -0500 |
commit | c4ac1ed369cb5737de10924908d97be9f11ec875 (patch) | |
tree | 294d2bc504f16cad8653413d63a6b47c6753adaa | |
parent | 54f76d1ac6cf0ace524e073076578c891d1b3f79 (diff) |
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>
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 10 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | 6 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/vgpu/fifo_vgpu.c | 2 |
4 files changed, 11 insertions, 9 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 7ec5ade4..b480c80a 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |||
@@ -392,7 +392,7 @@ void channel_gk20a_disable(struct channel_gk20a *ch) | |||
392 | ccsr_channel_enable_clr_true_f()); | 392 | ccsr_channel_enable_clr_true_f()); |
393 | } | 393 | } |
394 | 394 | ||
395 | void gk20a_channel_abort(struct channel_gk20a *ch) | 395 | void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt) |
396 | { | 396 | { |
397 | struct channel_gk20a_job *job, *n; | 397 | struct channel_gk20a_job *job, *n; |
398 | bool released_job_semaphore = false; | 398 | bool released_job_semaphore = false; |
@@ -404,6 +404,9 @@ void gk20a_channel_abort(struct channel_gk20a *ch) | |||
404 | 404 | ||
405 | ch->g->ops.fifo.disable_channel(ch); | 405 | ch->g->ops.fifo.disable_channel(ch); |
406 | 406 | ||
407 | if (channel_preempt) | ||
408 | ch->g->ops.fifo.preempt_channel(ch->g, ch->hw_chid); | ||
409 | |||
407 | /* ensure no fences are pending */ | 410 | /* ensure no fences are pending */ |
408 | mutex_lock(&ch->sync_lock); | 411 | mutex_lock(&ch->sync_lock); |
409 | if (ch->sync) | 412 | if (ch->sync) |
@@ -455,8 +458,7 @@ int gk20a_wait_channel_idle(struct channel_gk20a *ch) | |||
455 | 458 | ||
456 | void gk20a_disable_channel(struct channel_gk20a *ch) | 459 | void gk20a_disable_channel(struct channel_gk20a *ch) |
457 | { | 460 | { |
458 | gk20a_channel_abort(ch); | 461 | gk20a_channel_abort(ch, true); |
459 | ch->g->ops.fifo.preempt_channel(ch->g, ch->hw_chid); | ||
460 | channel_gk20a_update_runlist(ch, false); | 462 | channel_gk20a_update_runlist(ch, false); |
461 | } | 463 | } |
462 | 464 | ||
@@ -1621,7 +1623,7 @@ static void gk20a_channel_timeout_handler(struct work_struct *work) | |||
1621 | gk20a_fifo_abort_tsg(g, ch->tsgid); | 1623 | gk20a_fifo_abort_tsg(g, ch->tsgid); |
1622 | } else { | 1624 | } else { |
1623 | gk20a_fifo_set_ctx_mmu_error_ch(g, ch); | 1625 | gk20a_fifo_set_ctx_mmu_error_ch(g, ch); |
1624 | gk20a_channel_abort(ch); | 1626 | gk20a_channel_abort(ch, false); |
1625 | } | 1627 | } |
1626 | } else { | 1628 | } else { |
1627 | /* If failing engine, trigger recovery */ | 1629 | /* If failing engine, trigger recovery */ |
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h index cb8ffa95..f62d2731 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h | |||
@@ -195,7 +195,7 @@ void gk20a_channel_close(struct channel_gk20a *ch); | |||
195 | bool gk20a_channel_update_and_check_timeout(struct channel_gk20a *ch, | 195 | bool gk20a_channel_update_and_check_timeout(struct channel_gk20a *ch, |
196 | u32 timeout_delta_ms); | 196 | u32 timeout_delta_ms); |
197 | void gk20a_disable_channel(struct channel_gk20a *ch); | 197 | void gk20a_disable_channel(struct channel_gk20a *ch); |
198 | void gk20a_channel_abort(struct channel_gk20a *ch); | 198 | void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt); |
199 | int gk20a_channel_finish(struct channel_gk20a *ch, unsigned long timeout); | 199 | int gk20a_channel_finish(struct channel_gk20a *ch, unsigned long timeout); |
200 | void gk20a_set_error_notifier(struct channel_gk20a *ch, __u32 error); | 200 | void gk20a_set_error_notifier(struct channel_gk20a *ch, __u32 error); |
201 | void gk20a_channel_semaphore_wakeup(struct gk20a *g); | 201 | void gk20a_channel_semaphore_wakeup(struct gk20a *g); |
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c index 11fcc805..1727cf1d 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | |||
@@ -894,7 +894,7 @@ void gk20a_fifo_abort_tsg(struct gk20a *g, u32 tsgid) | |||
894 | mutex_lock(&tsg->ch_list_lock); | 894 | mutex_lock(&tsg->ch_list_lock); |
895 | list_for_each_entry(ch, &tsg->ch_list, ch_entry) { | 895 | list_for_each_entry(ch, &tsg->ch_list, ch_entry) { |
896 | if (gk20a_channel_get(ch)) { | 896 | if (gk20a_channel_get(ch)) { |
897 | gk20a_channel_abort(ch); | 897 | gk20a_channel_abort(ch, false); |
898 | gk20a_channel_put(ch); | 898 | gk20a_channel_put(ch); |
899 | } | 899 | } |
900 | } | 900 | } |
@@ -1064,7 +1064,7 @@ static bool gk20a_fifo_handle_mmu_fault( | |||
1064 | if (referenced_channel) { | 1064 | if (referenced_channel) { |
1065 | if (!g->fifo.deferred_reset_pending) | 1065 | if (!g->fifo.deferred_reset_pending) |
1066 | verbose = gk20a_fifo_set_ctx_mmu_error_ch(g, ch); | 1066 | verbose = gk20a_fifo_set_ctx_mmu_error_ch(g, ch); |
1067 | gk20a_channel_abort(ch); | 1067 | gk20a_channel_abort(ch, false); |
1068 | gk20a_channel_put(ch); | 1068 | gk20a_channel_put(ch); |
1069 | } else { | 1069 | } else { |
1070 | gk20a_err(dev_from_gk20a(g), | 1070 | gk20a_err(dev_from_gk20a(g), |
@@ -1217,7 +1217,7 @@ void gk20a_fifo_recover_ch(struct gk20a *g, u32 hw_chid, bool verbose) | |||
1217 | struct channel_gk20a *ch = &g->fifo.channel[hw_chid]; | 1217 | struct channel_gk20a *ch = &g->fifo.channel[hw_chid]; |
1218 | 1218 | ||
1219 | if (gk20a_channel_get(ch)) { | 1219 | if (gk20a_channel_get(ch)) { |
1220 | gk20a_channel_abort(ch); | 1220 | gk20a_channel_abort(ch, false); |
1221 | 1221 | ||
1222 | if (gk20a_fifo_set_ctx_mmu_error_ch(g, ch)) | 1222 | if (gk20a_fifo_set_ctx_mmu_error_ch(g, ch)) |
1223 | gk20a_debug_dump(g->dev); | 1223 | gk20a_debug_dump(g->dev); |
diff --git a/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c b/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c index dd6630a7..3db215bc 100644 --- a/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c +++ b/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c | |||
@@ -566,7 +566,7 @@ int vgpu_fifo_isr(struct gk20a *g, struct tegra_vgpu_fifo_intr_info *info) | |||
566 | break; | 566 | break; |
567 | case TEGRA_VGPU_FIFO_INTR_MMU_FAULT: | 567 | case TEGRA_VGPU_FIFO_INTR_MMU_FAULT: |
568 | vgpu_fifo_set_ctx_mmu_error(g, ch); | 568 | vgpu_fifo_set_ctx_mmu_error(g, ch); |
569 | gk20a_channel_abort(ch); | 569 | gk20a_channel_abort(ch, false); |
570 | break; | 570 | break; |
571 | default: | 571 | default: |
572 | WARN_ON(1); | 572 | WARN_ON(1); |