diff options
author | Aparna Das <aparnad@nvidia.com> | 2018-08-24 13:19:27 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2018-09-12 08:36:13 -0400 |
commit | 092664656c7f70156bf8b0c444b3e3ea1b533323 (patch) | |
tree | 5f97d9f4dc9333f28d90bb264b61009112c4afab /drivers/gpu | |
parent | c7a3b6db10900e0aabc29ca7307908875d685036 (diff) |
gpu: nvgpu: gv11b: skip waiting for runlist preempt to complete in RC
Since RC is triggered due to fatal interrupt always skip
waiting for runlist preemption to complete in RC path.
Also poll PBDMA status to verify TSG is no longer on the PDBMA
before doing engine reset.
Bug 2322245
Change-Id: I3cce3a2c50b527a407ad967b6b9ac964c42f6df9
Signed-off-by: Aparna Das <aparnad@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1806317
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
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++) { |