diff --git a/drivers/gpu/nvgpu/common/fifo/tsg.c b/drivers/gpu/nvgpu/common/fifo/tsg.c index c7454956b..3f690b310 100644 --- a/drivers/gpu/nvgpu/common/fifo/tsg.c +++ b/drivers/gpu/nvgpu/common/fifo/tsg.c @@ -215,6 +215,14 @@ int nvgpu_tsg_unbind_channel_common(struct nvgpu_tsg *tsg, g->ops.channel.disable(ch); nvgpu_rwsem_up_write(&tsg->ch_list_lock); + if (ch->mmu_debug_mode_enabled) { + err = nvgpu_tsg_set_mmu_debug_mode(tsg, ch, false); + if (err != 0) { + nvgpu_err(g, "disable mmu debug mode failed ch:%u", + ch->chid); + } + } + /* * Don't re-enable all channels if TSG has timed out already * @@ -876,3 +884,49 @@ void nvgpu_tsg_reset_faulted_eng_pbdma(struct gk20a *g, struct nvgpu_tsg *tsg, } nvgpu_rwsem_up_read(&tsg->ch_list_lock); } + +int nvgpu_tsg_set_mmu_debug_mode(struct nvgpu_tsg *tsg, + struct nvgpu_channel *ch, bool enable) +{ + struct gk20a *g; + int err = 0; + u32 tsg_refcnt; + + if ((ch == NULL) || (tsg == NULL)) { + return -EINVAL; + } + g = ch->g; + + if (g->ops.gr.set_mmu_debug_mode == NULL) { + return -ENOSYS; + } + + if (enable) { + if (ch->mmu_debug_mode_enabled) { + /* already enabled for this channel */ + return 0; + } + tsg_refcnt = tsg->mmu_debug_mode_refcnt + 1U; + } else { + if (!ch->mmu_debug_mode_enabled) { + /* already disabled for this channel */ + return 0; + } + tsg_refcnt = tsg->mmu_debug_mode_refcnt - 1U; + } + + /* + * enable GPC MMU debug mode if it was requested for at + * least one channel in the TSG + */ + err = g->ops.gr.set_mmu_debug_mode(g, ch, tsg_refcnt > 0U); + if (err != 0) { + nvgpu_err(g, "set mmu debug mode failed, err=%d", err); + return err; + } + + ch->mmu_debug_mode_enabled = enable; + tsg->mmu_debug_mode_refcnt = tsg_refcnt; + + return err; +} diff --git a/drivers/gpu/nvgpu/hal/gr/gr/gr_gm20b.c b/drivers/gpu/nvgpu/hal/gr/gr/gr_gm20b.c index bd1b41220..4a46a5f14 100644 --- a/drivers/gpu/nvgpu/hal/gr/gr/gr_gm20b.c +++ b/drivers/gpu/nvgpu/hal/gr/gr/gr_gm20b.c @@ -686,10 +686,15 @@ int gm20b_gr_set_mmu_debug_mode(struct gk20a *g, gr_gpcs_pri_mmu_debug_ctrl_debug_disabled_f(), }; int err; + struct nvgpu_tsg *tsg = nvgpu_tsg_from_ch(ch); + + if (tsg == NULL) { + return enable ? -EINVAL : 0; + } err = gr_gk20a_exec_ctx_ops(ch, &ctx_ops, 1, 1, 0, NULL); if (err != 0) { - nvgpu_err(g, "Failed to access register"); + nvgpu_err(g, "update MMU debug mode failed"); } return err; } diff --git a/drivers/gpu/nvgpu/include/nvgpu/channel.h b/drivers/gpu/nvgpu/include/nvgpu/channel.h index 91b856522..eec69c6a3 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/channel.h +++ b/drivers/gpu/nvgpu/include/nvgpu/channel.h @@ -382,6 +382,7 @@ struct nvgpu_channel { bool has_os_fence_framework_support; bool is_privileged_channel; + bool mmu_debug_mode_enabled; }; static inline struct nvgpu_channel * nvgpu_channel_from_free_chs(struct nvgpu_list_node *node) diff --git a/drivers/gpu/nvgpu/include/nvgpu/tsg.h b/drivers/gpu/nvgpu/include/nvgpu/tsg.h index 16e173510..3eb66f9ad 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/tsg.h +++ b/drivers/gpu/nvgpu/include/nvgpu/tsg.h @@ -83,6 +83,9 @@ struct nvgpu_tsg { bool in_use; bool abortable; + /* MMU debug mode enabled if mmu_debug_mode_refcnt > 0 */ + u32 mmu_debug_mode_refcnt; + struct nvgpu_tsg_sm_error_state *sm_error_states; #define NVGPU_SM_EXCEPTION_TYPE_MASK_NONE (0x0U) @@ -172,4 +175,6 @@ void nvgpu_tsg_set_ctxsw_timeout_accumulated_ms(struct nvgpu_tsg *tsg, u32 ms); void nvgpu_tsg_abort(struct gk20a *g, struct nvgpu_tsg *tsg, bool preempt); void nvgpu_tsg_reset_faulted_eng_pbdma(struct gk20a *g, struct nvgpu_tsg *tsg, bool eng, bool pbdma); +int nvgpu_tsg_set_mmu_debug_mode(struct nvgpu_tsg *tsg, + struct nvgpu_channel *ch, bool enable); #endif /* NVGPU_TSG_H */ diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_dbg.c b/drivers/gpu/nvgpu/os/linux/ioctl_dbg.c index 648a9f549..e2e55d6c7 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_dbg.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_dbg.c @@ -1114,10 +1114,11 @@ static int nvgpu_dbg_gpu_ioctl_set_mmu_debug_mode( ch = nvgpu_dbg_gpu_get_session_channel(dbg_s); if (!ch) { nvgpu_err(g, "no bound channel for mmu debug mode"); + err = -EINVAL; goto clean_up; } - err = g->ops.gr.set_mmu_debug_mode(g, ch, enable); + err = nvgpu_tsg_set_mmu_debug_mode(nvgpu_tsg_from_ch(ch), ch, enable); if (err) { nvgpu_err(g, "set mmu debug mode failed, err=%d", err); }