From a1248d87fe6e20aab3e5f2e0764f9fe8d80d0552 Mon Sep 17 00:00:00 2001 From: Thomas Fleury Date: Tue, 30 Apr 2019 17:19:51 -0700 Subject: [PATCH] gpu: nvgpu: add refcounting for MMU debug mode GPC MMU debug mode should be set if at least one channel in the TSG has requested it. Add refcounting for MMU debug mode, to make sure debug mode is disabled only when no channel in the TSG is using it. Bug 2515097 Change-Id: Ic5530f93523a9ec2cd3bfebc97adf7b7000531e0 Signed-off-by: Thomas Fleury Reviewed-on: https://git-master.nvidia.com/r/2123017 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/common/fifo/tsg.c | 54 +++++++++++++++++++++++ drivers/gpu/nvgpu/hal/gr/gr/gr_gm20b.c | 7 ++- drivers/gpu/nvgpu/include/nvgpu/channel.h | 1 + drivers/gpu/nvgpu/include/nvgpu/tsg.h | 5 +++ drivers/gpu/nvgpu/os/linux/ioctl_dbg.c | 3 +- 5 files changed, 68 insertions(+), 2 deletions(-) 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); }