summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/nvgpu/gv11b/fifo_gv11b.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c b/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c
index 47c34d32..8f0f6b0c 100644
--- a/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c
+++ b/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c
@@ -755,10 +755,20 @@ static int gv11b_fifo_poll_runlist_preempt_pending(struct gk20a *g,
755 struct nvgpu_timeout timeout; 755 struct nvgpu_timeout timeout;
756 u32 delay = GR_IDLE_CHECK_DEFAULT; 756 u32 delay = GR_IDLE_CHECK_DEFAULT;
757 int ret = -EBUSY; 757 int ret = -EBUSY;
758 unsigned int loop_count = 0;
758 759
759 nvgpu_timeout_init(g, &timeout, g->ops.fifo.get_preempt_timeout(g), 760 nvgpu_timeout_init(g, &timeout, g->ops.fifo.get_preempt_timeout(g),
760 NVGPU_TIMER_CPU_TIMER); 761 NVGPU_TIMER_CPU_TIMER);
761 do { 762 do {
763 if (!nvgpu_platform_is_silicon(g)) {
764 if (loop_count >= MAX_PRE_SI_RETRIES) {
765 nvgpu_err(g, "preempt runlist retries: %u",
766 loop_count);
767 break;
768 }
769 loop_count++;
770 }
771
762 if (!((gk20a_readl(g, fifo_runlist_preempt_r())) & 772 if (!((gk20a_readl(g, fifo_runlist_preempt_r())) &
763 runlists_mask)) { 773 runlists_mask)) {
764 ret = 0; 774 ret = 0;
@@ -768,8 +778,11 @@ static int gv11b_fifo_poll_runlist_preempt_pending(struct gk20a *g,
768 nvgpu_usleep_range(delay, delay * 2); 778 nvgpu_usleep_range(delay, delay * 2);
769 delay = min_t(unsigned long, 779 delay = min_t(unsigned long,
770 delay << 1, GR_IDLE_CHECK_MAX); 780 delay << 1, GR_IDLE_CHECK_MAX);
771 } while (!nvgpu_timeout_expired_msg(&timeout, 781 } while (!nvgpu_timeout_expired(&timeout));
772 "runlist preempt timeout")); 782
783 if (ret)
784 nvgpu_err(g, "preempt runlist timeout, runlists_mask:0x%08x",
785 runlists_mask);
773 return ret; 786 return ret;
774} 787}
775 788
@@ -1068,6 +1081,7 @@ void gv11b_fifo_teardown_ch_tsg(struct gk20a *g, u32 act_eng_bitmask,
1068 runlists_mask = gv11b_fifo_get_runlists_mask(g, act_eng_bitmask, id, 1081 runlists_mask = gv11b_fifo_get_runlists_mask(g, act_eng_bitmask, id,
1069 id_type, rc_type, mmfault); 1082 id_type, rc_type, mmfault);
1070 1083
1084 /* Disable runlist scheduler */
1071 gk20a_fifo_set_runlist_state(g, runlists_mask, RUNLIST_DISABLED); 1085 gk20a_fifo_set_runlist_state(g, runlists_mask, RUNLIST_DISABLED);
1072 1086
1073 g->fifo.deferred_reset_pending = false; 1087 g->fifo.deferred_reset_pending = false;
@@ -1111,9 +1125,21 @@ void gv11b_fifo_teardown_ch_tsg(struct gk20a *g, u32 act_eng_bitmask,
1111 else if (refch) 1125 else if (refch)
1112 g->ops.fifo.disable_channel(refch); 1126 g->ops.fifo.disable_channel(refch);
1113 1127
1114 /* Preempt tsg/ch */ 1128 /*
1129 * Even though TSG preempt timed out, the RC sequence would by design
1130 * require s/w to issue another preempt.
1131 * If recovery includes an ENGINE_RESET, to not have race conditions,
1132 * use RUNLIST_PREEMPT to kick all work off, and cancel any context
1133 * load which may be pending. This is also needed to make sure
1134 * that all PBDMAs serving the engine are not loaded when engine is
1135 * reset.
1136 */
1115 if (id_type == ID_TYPE_TSG || id_type == ID_TYPE_CHANNEL) { 1137 if (id_type == ID_TYPE_TSG || id_type == ID_TYPE_CHANNEL) {
1116 g->ops.fifo.preempt_ch_tsg(g, id, id_type); 1138 int preempt_failed;
1139
1140 preempt_failed = g->ops.fifo.preempt_ch_tsg(g, id, id_type);
1141 if (preempt_failed)
1142 gv11b_fifo_locked_preempt_runlists(g, runlists_mask);
1117 } else { 1143 } else {
1118 gv11b_fifo_locked_preempt_runlists(g, runlists_mask); 1144 gv11b_fifo_locked_preempt_runlists(g, runlists_mask);
1119 } 1145 }