diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/nvgpu/gv11b/fifo_gv11b.c | 114 |
1 files changed, 35 insertions, 79 deletions
diff --git a/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c b/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c index 0119c215..64b8084e 100644 --- a/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c +++ b/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c | |||
@@ -763,44 +763,6 @@ static void gv11b_fifo_issue_runlist_preempt(struct gk20a *g, | |||
763 | gk20a_writel(g, fifo_runlist_preempt_r(), reg_val); | 763 | gk20a_writel(g, fifo_runlist_preempt_r(), reg_val); |
764 | } | 764 | } |
765 | 765 | ||
766 | static int gv11b_fifo_poll_runlist_preempt_pending(struct gk20a *g, | ||
767 | u32 runlists_mask) | ||
768 | { | ||
769 | struct nvgpu_timeout timeout; | ||
770 | u32 delay = GR_IDLE_CHECK_DEFAULT; | ||
771 | int ret = -EBUSY; | ||
772 | unsigned int loop_count = 0; | ||
773 | |||
774 | nvgpu_timeout_init(g, &timeout, g->ops.fifo.get_preempt_timeout(g), | ||
775 | NVGPU_TIMER_CPU_TIMER); | ||
776 | do { | ||
777 | if (!nvgpu_platform_is_silicon(g)) { | ||
778 | if (loop_count >= MAX_PRE_SI_RETRIES) { | ||
779 | nvgpu_err(g, "preempt runlist retries: %u", | ||
780 | loop_count); | ||
781 | break; | ||
782 | } | ||
783 | loop_count++; | ||
784 | } | ||
785 | |||
786 | if (!((gk20a_readl(g, fifo_runlist_preempt_r())) & | ||
787 | runlists_mask)) { | ||
788 | ret = 0; | ||
789 | break; | ||
790 | } | ||
791 | |||
792 | nvgpu_usleep_range(delay, delay * 2); | ||
793 | delay = min_t(unsigned long, | ||
794 | delay << 1, GR_IDLE_CHECK_MAX); | ||
795 | } while (!nvgpu_timeout_expired(&timeout)); | ||
796 | |||
797 | if (ret) { | ||
798 | nvgpu_err(g, "preempt runlist timeout, runlists_mask:0x%08x", | ||
799 | runlists_mask); | ||
800 | } | ||
801 | return ret; | ||
802 | } | ||
803 | |||
804 | int gv11b_fifo_is_preempt_pending(struct gk20a *g, u32 id, | 766 | int gv11b_fifo_is_preempt_pending(struct gk20a *g, u32 id, |
805 | unsigned int id_type) | 767 | unsigned int id_type) |
806 | { | 768 | { |
@@ -855,33 +817,6 @@ int gv11b_fifo_preempt_channel(struct gk20a *g, u32 chid) | |||
855 | return g->ops.fifo.preempt_tsg(g, tsgid); | 817 | return g->ops.fifo.preempt_tsg(g, tsgid); |
856 | } | 818 | } |
857 | 819 | ||
858 | static int __locked_fifo_preempt_runlists(struct gk20a *g, u32 runlists_mask) | ||
859 | { | ||
860 | int ret; | ||
861 | |||
862 | /* issue runlist preempt */ | ||
863 | gv11b_fifo_issue_runlist_preempt(g, runlists_mask); | ||
864 | |||
865 | /* poll for runlist preempt done */ | ||
866 | ret = gv11b_fifo_poll_runlist_preempt_pending(g, runlists_mask); | ||
867 | |||
868 | /* | ||
869 | * Even if runlist_event intr is not enabled in fifo_intr_en_0 , it gets | ||
870 | * set in fifo_intr_0 status reg. Current fifo stall interrupt handler | ||
871 | * is checking all set bits in fifo_intr_0 and handling runlist_event | ||
872 | * too while handling other fifo interrupts e.g. pbdma fifo intr or | ||
873 | * ctxsw timeout interrupt. It is better to clear this after runlist | ||
874 | * preempt is done. Clearing runlist_event interrupt makes no | ||
875 | * difference to pending runlist_preempt. | ||
876 | */ | ||
877 | |||
878 | if (!ret) { | ||
879 | gk20a_fifo_handle_runlist_event(g); | ||
880 | } | ||
881 | |||
882 | return ret; | ||
883 | } | ||
884 | |||
885 | /* TSG enable sequence applicable for Volta and onwards */ | 820 | /* TSG enable sequence applicable for Volta and onwards */ |
886 | int gv11b_fifo_enable_tsg(struct tsg_gk20a *tsg) | 821 | int gv11b_fifo_enable_tsg(struct tsg_gk20a *tsg) |
887 | { | 822 | { |
@@ -952,9 +887,9 @@ int gv11b_fifo_preempt_tsg(struct gk20a *g, u32 tsgid) | |||
952 | return ret; | 887 | return ret; |
953 | } | 888 | } |
954 | 889 | ||
955 | static void gv11b_fifo_locked_preempt_runlists(struct gk20a *g, u32 runlists_mask) | 890 | static void gv11b_fifo_locked_preempt_runlists_rc(struct gk20a *g, |
891 | u32 runlists_mask) | ||
956 | { | 892 | { |
957 | int ret = 0; | ||
958 | u32 token = PMU_INVALID_MUTEX_OWNER_ID; | 893 | u32 token = PMU_INVALID_MUTEX_OWNER_ID; |
959 | u32 mutex_ret = 0; | 894 | u32 mutex_ret = 0; |
960 | u32 rlid; | 895 | u32 rlid; |
@@ -964,20 +899,23 @@ static void gv11b_fifo_locked_preempt_runlists(struct gk20a *g, u32 runlists_mas | |||
964 | 899 | ||
965 | mutex_ret = nvgpu_pmu_mutex_acquire(&g->pmu, PMU_MUTEX_ID_FIFO, &token); | 900 | mutex_ret = nvgpu_pmu_mutex_acquire(&g->pmu, PMU_MUTEX_ID_FIFO, &token); |
966 | 901 | ||
967 | ret = __locked_fifo_preempt_runlists(g, runlists_mask); | 902 | /* issue runlist preempt */ |
903 | gv11b_fifo_issue_runlist_preempt(g, runlists_mask); | ||
968 | 904 | ||
969 | if (ret) { | 905 | /* |
970 | /* if preempt timed out, reset engs served by runlists */ | 906 | * Preemption will never complete in RC due to some fatal condition. |
971 | for (rlid = 0; rlid < g->fifo.max_runlists; rlid++) { | 907 | * Do not poll for preemption to complete. Reset engines served by |
972 | if (runlists_mask & | 908 | * runlists. |
973 | fifo_runlist_preempt_runlist_m(rlid)) { | 909 | */ |
974 | g->fifo.runlist_info[rlid].reset_eng_bitmask = | 910 | for (rlid = 0; rlid < g->fifo.max_runlists; rlid++) { |
975 | g->fifo.runlist_info[rlid].eng_bitmask; | 911 | if ((runlists_mask & |
976 | } | 912 | fifo_runlist_preempt_runlist_m(rlid)) != 0U) { |
913 | g->fifo.runlist_info[rlid].reset_eng_bitmask = | ||
914 | g->fifo.runlist_info[rlid].eng_bitmask; | ||
977 | } | 915 | } |
978 | } | 916 | } |
979 | 917 | ||
980 | if (!mutex_ret) { | 918 | if (mutex_ret == 0U) { |
981 | nvgpu_pmu_mutex_release(&g->pmu, PMU_MUTEX_ID_FIFO, &token); | 919 | nvgpu_pmu_mutex_release(&g->pmu, PMU_MUTEX_ID_FIFO, &token); |
982 | } | 920 | } |
983 | } | 921 | } |
@@ -1052,12 +990,13 @@ void gv11b_fifo_teardown_ch_tsg(struct gk20a *g, u32 act_eng_bitmask, | |||
1052 | struct mmu_fault_info *mmfault) | 990 | struct mmu_fault_info *mmfault) |
1053 | { | 991 | { |
1054 | struct tsg_gk20a *tsg = NULL; | 992 | struct tsg_gk20a *tsg = NULL; |
1055 | u32 runlists_mask, rlid; | 993 | u32 runlists_mask, rlid, pbdma_id; |
1056 | struct fifo_runlist_info_gk20a *runlist = NULL; | 994 | struct fifo_runlist_info_gk20a *runlist = NULL; |
1057 | u32 engine_id, client_type = ~0; | 995 | u32 engine_id, client_type = ~0; |
1058 | struct fifo_gk20a *f = &g->fifo; | 996 | struct fifo_gk20a *f = &g->fifo; |
1059 | u32 runlist_id = FIFO_INVAL_RUNLIST_ID; | 997 | u32 runlist_id = FIFO_INVAL_RUNLIST_ID; |
1060 | u32 num_runlists = 0; | 998 | u32 num_runlists = 0; |
999 | unsigned long runlist_served_pbdmas; | ||
1061 | 1000 | ||
1062 | nvgpu_log_fn(g, "acquire runlist_lock for all runlists"); | 1001 | nvgpu_log_fn(g, "acquire runlist_lock for all runlists"); |
1063 | for (rlid = 0; rlid < g->fifo.max_runlists; rlid++) { | 1002 | for (rlid = 0; rlid < g->fifo.max_runlists; rlid++) { |
@@ -1171,7 +1110,24 @@ void gv11b_fifo_teardown_ch_tsg(struct gk20a *g, u32 act_eng_bitmask, | |||
1171 | * that all PBDMAs serving the engine are not loaded when engine is | 1110 | * that all PBDMAs serving the engine are not loaded when engine is |
1172 | * reset. | 1111 | * reset. |
1173 | */ | 1112 | */ |
1174 | gv11b_fifo_locked_preempt_runlists(g, runlists_mask); | 1113 | gv11b_fifo_locked_preempt_runlists_rc(g, runlists_mask); |
1114 | /* | ||
1115 | * For each PBDMA which serves the runlist, poll to verify the TSG is no | ||
1116 | * longer on the PBDMA and the engine phase of the preempt has started. | ||
1117 | */ | ||
1118 | if (tsg != NULL) { | ||
1119 | rlid = f->tsg[id].runlist_id; | ||
1120 | runlist_served_pbdmas = f->runlist_info[rlid].pbdma_bitmask; | ||
1121 | for_each_set_bit(pbdma_id, &runlist_served_pbdmas, | ||
1122 | f->num_pbdma) { | ||
1123 | /* | ||
1124 | * If pbdma preempt fails the only option is to reset | ||
1125 | * GPU. Any sort of hang indicates the entire GPU’s | ||
1126 | * memory system would be blocked. | ||
1127 | */ | ||
1128 | gv11b_fifo_poll_pbdma_chan_status(g, id, pbdma_id); | ||
1129 | } | ||
1130 | } | ||
1175 | 1131 | ||
1176 | /* check if engine reset should be deferred */ | 1132 | /* check if engine reset should be deferred */ |
1177 | for (rlid = 0; rlid < g->fifo.max_runlists; rlid++) { | 1133 | for (rlid = 0; rlid < g->fifo.max_runlists; rlid++) { |