diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gv11b/fifo_gv11b.c')
-rw-r--r-- | drivers/gpu/nvgpu/gv11b/fifo_gv11b.c | 149 |
1 files changed, 77 insertions, 72 deletions
diff --git a/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c b/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c index 8f0f6b0c..6df1d343 100644 --- a/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c +++ b/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c | |||
@@ -652,29 +652,19 @@ static void gv11b_reset_pbdma_faulted_tsg(struct tsg_gk20a *tsg) | |||
652 | } | 652 | } |
653 | 653 | ||
654 | void gv11b_fifo_reset_pbdma_and_eng_faulted(struct gk20a *g, | 654 | void gv11b_fifo_reset_pbdma_and_eng_faulted(struct gk20a *g, |
655 | struct channel_gk20a *refch, | 655 | struct tsg_gk20a *tsg, |
656 | u32 faulted_pbdma, u32 faulted_engine) | 656 | u32 faulted_pbdma, u32 faulted_engine) |
657 | { | 657 | { |
658 | struct tsg_gk20a *tsg; | 658 | if (!tsg) |
659 | return; | ||
659 | 660 | ||
660 | nvgpu_log(g, gpu_dbg_intr, "reset faulted pbdma:0x%x eng:0x%x", | 661 | nvgpu_log(g, gpu_dbg_intr, "reset faulted pbdma:0x%x eng:0x%x", |
661 | faulted_pbdma, faulted_engine); | 662 | faulted_pbdma, faulted_engine); |
662 | 663 | ||
663 | if (!refch) | 664 | if (faulted_pbdma != FIFO_INVAL_PBDMA_ID) |
664 | return; | 665 | gv11b_reset_pbdma_faulted_tsg(tsg); |
665 | 666 | if (faulted_engine != FIFO_INVAL_ENGINE_ID) | |
666 | if (gk20a_is_channel_marked_as_tsg(refch)) { | 667 | gv11b_reset_eng_faulted_tsg(tsg); |
667 | tsg = &g->fifo.tsg[refch->tsgid]; | ||
668 | if (faulted_pbdma != FIFO_INVAL_PBDMA_ID) | ||
669 | gv11b_reset_pbdma_faulted_tsg(tsg); | ||
670 | if (faulted_engine != FIFO_INVAL_ENGINE_ID) | ||
671 | gv11b_reset_eng_faulted_tsg(tsg); | ||
672 | } else { | ||
673 | if (faulted_pbdma != FIFO_INVAL_PBDMA_ID) | ||
674 | gv11b_reset_pbdma_faulted_ch(g, refch->chid); | ||
675 | if (faulted_engine != FIFO_INVAL_ENGINE_ID) | ||
676 | gv11b_reset_eng_faulted_ch(g, refch->chid); | ||
677 | } | ||
678 | } | 668 | } |
679 | 669 | ||
680 | static u32 gv11b_fifo_get_runlists_mask(struct gk20a *g, u32 act_eng_bitmask, | 670 | static u32 gv11b_fifo_get_runlists_mask(struct gk20a *g, u32 act_eng_bitmask, |
@@ -992,12 +982,74 @@ int gv11b_fifo_preempt_ch_tsg(struct gk20a *g, u32 id, | |||
992 | 982 | ||
993 | } | 983 | } |
994 | 984 | ||
985 | static void gv11b_fifo_locked_abort_runlist_active_tsgs(struct gk20a *g, | ||
986 | unsigned int rc_type, | ||
987 | u32 runlists_mask) | ||
988 | { | ||
989 | bool verbose = false; | ||
990 | struct tsg_gk20a *tsg = NULL; | ||
991 | u32 rlid, tsgid; | ||
992 | struct fifo_runlist_info_gk20a *runlist = NULL; | ||
993 | u32 token = PMU_INVALID_MUTEX_OWNER_ID; | ||
994 | u32 mutex_ret = 0; | ||
995 | bool add = false, wait_for_finish = false; | ||
996 | int err; | ||
997 | |||
998 | nvgpu_err(g, "runlist id unknown, abort active tsgs in runlists"); | ||
999 | |||
1000 | /* runlist_lock are locked by teardown */ | ||
1001 | mutex_ret = nvgpu_pmu_mutex_acquire(&g->pmu, PMU_MUTEX_ID_FIFO, &token); | ||
1002 | |||
1003 | for (rlid = 0; rlid < g->fifo.max_runlists; | ||
1004 | rlid++) { | ||
1005 | if (!(runlists_mask & BIT(rlid))) | ||
1006 | continue; | ||
1007 | nvgpu_log(g, gpu_dbg_info, "abort runlist id %d", | ||
1008 | rlid); | ||
1009 | runlist = &g->fifo.runlist_info[rlid]; | ||
1010 | |||
1011 | for_each_set_bit(tsgid, runlist->active_tsgs, | ||
1012 | g->fifo.num_channels) { | ||
1013 | nvgpu_log(g, gpu_dbg_info, "abort tsg id %d", tsgid); | ||
1014 | tsg = &g->fifo.tsg[tsgid]; | ||
1015 | gk20a_disable_tsg(tsg); | ||
1016 | |||
1017 | /* assume all pbdma and eng faulted are set */ | ||
1018 | nvgpu_log(g, gpu_dbg_info, "reset pbdma and eng faulted"); | ||
1019 | gv11b_reset_pbdma_faulted_tsg(tsg); | ||
1020 | gv11b_reset_eng_faulted_tsg(tsg); | ||
1021 | |||
1022 | #ifdef CONFIG_GK20A_CTXSW_TRACE | ||
1023 | gk20a_ctxsw_trace_tsg_reset(g, tsg); | ||
1024 | #endif | ||
1025 | if (!g->fifo.deferred_reset_pending) { | ||
1026 | if (rc_type == RC_TYPE_MMU_FAULT) { | ||
1027 | gk20a_fifo_set_ctx_mmu_error_tsg(g, tsg); | ||
1028 | verbose = gk20a_fifo_error_tsg(g, tsg); | ||
1029 | } | ||
1030 | } | ||
1031 | |||
1032 | /* (chid == ~0 && !add) remove all act ch from runlist*/ | ||
1033 | err = gk20a_fifo_update_runlist_locked(g, rlid, | ||
1034 | FIFO_INVAL_CHANNEL_ID, add, wait_for_finish); | ||
1035 | if (err) | ||
1036 | nvgpu_err(g, "runlist id %d is not cleaned up", | ||
1037 | rlid); | ||
1038 | |||
1039 | gk20a_fifo_abort_tsg(g, tsg->tsgid, false); | ||
1040 | |||
1041 | nvgpu_log(g, gpu_dbg_info, "aborted tsg id %d", tsgid); | ||
1042 | } | ||
1043 | } | ||
1044 | if (!mutex_ret) | ||
1045 | nvgpu_pmu_mutex_release(&g->pmu, PMU_MUTEX_ID_FIFO, &token); | ||
1046 | } | ||
1047 | |||
995 | void gv11b_fifo_teardown_ch_tsg(struct gk20a *g, u32 act_eng_bitmask, | 1048 | void gv11b_fifo_teardown_ch_tsg(struct gk20a *g, u32 act_eng_bitmask, |
996 | u32 id, unsigned int id_type, unsigned int rc_type, | 1049 | u32 id, unsigned int id_type, unsigned int rc_type, |
997 | struct mmu_fault_info *mmfault) | 1050 | struct mmu_fault_info *mmfault) |
998 | { | 1051 | { |
999 | struct tsg_gk20a *tsg = NULL; | 1052 | struct tsg_gk20a *tsg = NULL; |
1000 | struct channel_gk20a *refch = NULL; | ||
1001 | u32 runlists_mask, rlid; | 1053 | u32 runlists_mask, rlid; |
1002 | struct fifo_runlist_info_gk20a *runlist = NULL; | 1054 | struct fifo_runlist_info_gk20a *runlist = NULL; |
1003 | u32 engine_id, client_type = ~0; | 1055 | u32 engine_id, client_type = ~0; |
@@ -1022,21 +1074,6 @@ void gv11b_fifo_teardown_ch_tsg(struct gk20a *g, u32 act_eng_bitmask, | |||
1022 | } else { | 1074 | } else { |
1023 | nvgpu_log_fn(g, "id type is tsg but tsg id is inval"); | 1075 | nvgpu_log_fn(g, "id type is tsg but tsg id is inval"); |
1024 | } | 1076 | } |
1025 | } else if (id_type == ID_TYPE_CHANNEL) { | ||
1026 | if (id != FIFO_INVAL_CHANNEL_ID) { | ||
1027 | runlist_id = f->channel[id].runlist_id; | ||
1028 | if (runlist_id != FIFO_INVAL_RUNLIST_ID) | ||
1029 | num_runlists++; | ||
1030 | else | ||
1031 | nvgpu_log_fn(g, "ch runlist id is invalid"); | ||
1032 | |||
1033 | if ((u32)f->channel[id].tsgid != FIFO_INVAL_TSG_ID) | ||
1034 | tsg = &f->tsg[f->channel[id].tsgid]; | ||
1035 | else | ||
1036 | nvgpu_log_fn(g, "tsgid for ch is invalid"); | ||
1037 | } else { | ||
1038 | nvgpu_log_fn(g, "id type is ch but ch id is inval"); | ||
1039 | } | ||
1040 | } else { | 1077 | } else { |
1041 | /* | 1078 | /* |
1042 | * id type is unknown, get runlist_id if eng mask is such that | 1079 | * id type is unknown, get runlist_id if eng mask is such that |
@@ -1103,27 +1140,16 @@ void gv11b_fifo_teardown_ch_tsg(struct gk20a *g, u32 act_eng_bitmask, | |||
1103 | 1140 | ||
1104 | gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_RUN); | 1141 | gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_RUN); |
1105 | 1142 | ||
1106 | /* Get tsg/ch */ | ||
1107 | if (rc_type == RC_TYPE_MMU_FAULT) { | 1143 | if (rc_type == RC_TYPE_MMU_FAULT) { |
1108 | gk20a_debug_dump(g); | 1144 | gk20a_debug_dump(g); |
1109 | refch = mmfault->refch; | ||
1110 | client_type = mmfault->client_type; | 1145 | client_type = mmfault->client_type; |
1111 | gv11b_fifo_reset_pbdma_and_eng_faulted(g, refch, | 1146 | gv11b_fifo_reset_pbdma_and_eng_faulted(g, tsg, |
1112 | mmfault->faulted_pbdma, | 1147 | mmfault->faulted_pbdma, |
1113 | mmfault->faulted_engine); | 1148 | mmfault->faulted_engine); |
1114 | } | 1149 | } |
1115 | 1150 | ||
1116 | if (id_type == ID_TYPE_TSG) { | ||
1117 | tsg = &g->fifo.tsg[id]; | ||
1118 | } else if (id_type == ID_TYPE_CHANNEL) { | ||
1119 | if (refch == NULL) | ||
1120 | refch = gk20a_channel_get(&g->fifo.channel[id]); | ||
1121 | } | ||
1122 | /* Disable tsg/ch */ | ||
1123 | if (tsg) | 1151 | if (tsg) |
1124 | gk20a_disable_tsg(tsg); | 1152 | gk20a_disable_tsg(tsg); |
1125 | else if (refch) | ||
1126 | g->ops.fifo.disable_channel(refch); | ||
1127 | 1153 | ||
1128 | /* | 1154 | /* |
1129 | * Even though TSG preempt timed out, the RC sequence would by design | 1155 | * Even though TSG preempt timed out, the RC sequence would by design |
@@ -1134,7 +1160,7 @@ void gv11b_fifo_teardown_ch_tsg(struct gk20a *g, u32 act_eng_bitmask, | |||
1134 | * that all PBDMAs serving the engine are not loaded when engine is | 1160 | * that all PBDMAs serving the engine are not loaded when engine is |
1135 | * reset. | 1161 | * reset. |
1136 | */ | 1162 | */ |
1137 | if (id_type == ID_TYPE_TSG || id_type == ID_TYPE_CHANNEL) { | 1163 | if (tsg) { |
1138 | int preempt_failed; | 1164 | int preempt_failed; |
1139 | 1165 | ||
1140 | preempt_failed = g->ops.fifo.preempt_ch_tsg(g, id, id_type); | 1166 | preempt_failed = g->ops.fifo.preempt_ch_tsg(g, id, id_type); |
@@ -1156,7 +1182,7 @@ void gv11b_fifo_teardown_ch_tsg(struct gk20a *g, u32 act_eng_bitmask, | |||
1156 | 1182 | ||
1157 | for_each_set_bit(engine_id, &__reset_eng_bitmask, | 1183 | for_each_set_bit(engine_id, &__reset_eng_bitmask, |
1158 | g->fifo.max_engines) { | 1184 | g->fifo.max_engines) { |
1159 | if ((refch || tsg) && | 1185 | if (tsg && |
1160 | gk20a_fifo_should_defer_engine_reset(g, | 1186 | gk20a_fifo_should_defer_engine_reset(g, |
1161 | engine_id, client_type, false)) { | 1187 | engine_id, client_type, false)) { |
1162 | 1188 | ||
@@ -1188,13 +1214,9 @@ void gv11b_fifo_teardown_ch_tsg(struct gk20a *g, u32 act_eng_bitmask, | |||
1188 | } | 1214 | } |
1189 | 1215 | ||
1190 | #ifdef CONFIG_GK20A_CTXSW_TRACE | 1216 | #ifdef CONFIG_GK20A_CTXSW_TRACE |
1191 | /* tsg and refch both could be valid for mmu fault. Check tsg first */ | ||
1192 | if (tsg) | 1217 | if (tsg) |
1193 | gk20a_ctxsw_trace_tsg_reset(g, tsg); | 1218 | gk20a_ctxsw_trace_tsg_reset(g, tsg); |
1194 | else if (refch) | ||
1195 | gk20a_ctxsw_trace_channel_reset(g, refch); | ||
1196 | #endif | 1219 | #endif |
1197 | |||
1198 | if (tsg) { | 1220 | if (tsg) { |
1199 | if (g->fifo.deferred_reset_pending) { | 1221 | if (g->fifo.deferred_reset_pending) { |
1200 | gk20a_disable_tsg(tsg); | 1222 | gk20a_disable_tsg(tsg); |
@@ -1204,26 +1226,9 @@ void gv11b_fifo_teardown_ch_tsg(struct gk20a *g, u32 act_eng_bitmask, | |||
1204 | 1226 | ||
1205 | gk20a_fifo_abort_tsg(g, tsg->tsgid, false); | 1227 | gk20a_fifo_abort_tsg(g, tsg->tsgid, false); |
1206 | } | 1228 | } |
1207 | if (refch) | ||
1208 | gk20a_channel_put(refch); | ||
1209 | } else if (refch) { | ||
1210 | if (g->fifo.deferred_reset_pending) { | ||
1211 | g->ops.fifo.disable_channel(refch); | ||
1212 | } else { | ||
1213 | if (rc_type == RC_TYPE_MMU_FAULT) | ||
1214 | gk20a_fifo_set_ctx_mmu_error_ch(g, refch); | ||
1215 | |||
1216 | gk20a_channel_abort(refch, false); | ||
1217 | } | ||
1218 | gk20a_channel_put(refch); | ||
1219 | } else { | 1229 | } else { |
1220 | nvgpu_err(g, "id unknown, abort runlist"); | 1230 | gv11b_fifo_locked_abort_runlist_active_tsgs(g, rc_type, |
1221 | for (rlid = 0; rlid < g->fifo.max_runlists; | 1231 | runlists_mask); |
1222 | rlid++) { | ||
1223 | if (runlists_mask & BIT(rlid)) | ||
1224 | g->ops.fifo.update_runlist(g, rlid, | ||
1225 | FIFO_INVAL_CHANNEL_ID, false, true); | ||
1226 | } | ||
1227 | } | 1232 | } |
1228 | 1233 | ||
1229 | gk20a_fifo_set_runlist_state(g, runlists_mask, RUNLIST_ENABLED); | 1234 | gk20a_fifo_set_runlist_state(g, runlists_mask, RUNLIST_ENABLED); |