diff --git a/drivers/gpu/nvgpu/gv11b/fb_gv11b.c b/drivers/gpu/nvgpu/gv11b/fb_gv11b.c index 75045800a..d89018e5a 100644 --- a/drivers/gpu/nvgpu/gv11b/fb_gv11b.c +++ b/drivers/gpu/nvgpu/gv11b/fb_gv11b.c @@ -1434,13 +1434,19 @@ static void gv11b_fb_handle_mmu_fault_common(struct gk20a *g, g->ops.fifo.teardown_ch_tsg(g, act_eng_bitmask, id, id_type, RC_TYPE_MMU_FAULT, mmfault); } else { - err = gv11b_fb_fix_page_fault(g, mmfault); - if (err) { + if (mmfault->fault_type == gmmu_fault_type_pte_v()) { + nvgpu_log(g, gpu_dbg_intr, "invalid pte! try to fix"); + err = gv11b_fb_fix_page_fault(g, mmfault); + if (err) + *invalidate_replay_val |= + fb_mmu_invalidate_replay_cancel_global_f(); + else + *invalidate_replay_val |= + fb_mmu_invalidate_replay_start_ack_all_f(); + } else { + /* cancel faults other than invalid pte */ *invalidate_replay_val |= fb_mmu_invalidate_replay_cancel_global_f(); - } else { - *invalidate_replay_val |= - fb_mmu_invalidate_replay_start_ack_all_f(); } /* refch in mmfault is assigned at the time of copying * fault info from snap reg or bar2 fault buf @@ -1960,6 +1966,17 @@ static int gv11b_fb_fix_page_fault(struct gk20a *g, nvgpu_log(g, gpu_dbg_intr | gpu_dbg_pte, "pte: %#08x %#08x", pte[1], pte[0]); + if (pte[0] == 0x0 && pte[1] == 0x0) { + nvgpu_log(g, gpu_dbg_intr | gpu_dbg_pte, + "pte all zeros, do not set valid"); + return -1; + } + if (pte[0] & gmmu_new_pte_valid_true_f()) { + nvgpu_log(g, gpu_dbg_intr | gpu_dbg_pte, + "pte valid already set"); + return -1; + } + pte[0] |= gmmu_new_pte_valid_true_f(); if (pte[0] & gmmu_new_pte_read_only_true_f()) pte[0] &= ~(gmmu_new_pte_read_only_true_f()); diff --git a/drivers/gpu/nvgpu/include/nvgpu/hw/gv11b/hw_gmmu_gv11b.h b/drivers/gpu/nvgpu/include/nvgpu/hw/gv11b/hw_gmmu_gv11b.h index c39cc2d87..0a442b1ff 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/hw/gv11b/hw_gmmu_gv11b.h +++ b/drivers/gpu/nvgpu/include/nvgpu/hw/gv11b/hw_gmmu_gv11b.h @@ -1272,6 +1272,10 @@ static inline u32 gmmu_fault_type_unbound_inst_block_v(void) { return 0x00000004U; } +static inline u32 gmmu_fault_type_pte_v(void) +{ + return 0x00000002U; +} static inline u32 gmmu_fault_mmu_eng_id_bar2_v(void) { return 0x00000005U;