From 4bc0a42f32f16b2050b9f190909d0d5df4d80e44 Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Fri, 18 Dec 2015 12:23:05 +0530 Subject: gpu: nvgpu: APIs to suspend/resume single SM Add below APIs to suspend or resume single SM : gk20a_suspend_single_sm() gk20a_resume_single_sm() Also, update gk20a_suspend_all_sms() to make it more generic by passing global_esr_mask and check_errors flag as parameter Bug 200156699 Change-Id: If40f4bcae74a8132673b4dca10b7d9898f23c164 Signed-off-by: Deepak Nibade Reviewed-on: http://git-master/r/925884 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c | 4 +- drivers/gpu/nvgpu/gk20a/gr_gk20a.c | 80 +++++++++++++++++++++++++++++++-- drivers/gpu/nvgpu/gk20a/gr_gk20a.h | 8 +++- 3 files changed, 85 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c index 1397549e..1f1b164f 100644 --- a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c @@ -1,7 +1,7 @@ /* * Tegra GK20A GPU Debugger/Profiler Driver * - * Copyright (c) 2013-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2013-2016, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -867,7 +867,7 @@ static int nvgpu_dbg_gpu_ioctl_suspend_resume_sm( if (ch_is_curr_ctx) { switch (action) { case NVGPU_DBG_GPU_SUSPEND_ALL_SMS: - gk20a_suspend_all_sms(g); + gk20a_suspend_all_sms(g, 0, false); break; case NVGPU_DBG_GPU_RESUME_ALL_SMS: diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c index 6f4669f2..7f02dc43 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c @@ -7021,7 +7021,42 @@ int gk20a_gr_wait_for_sm_lock_down(struct gk20a *g, u32 gpc, u32 tpc, return -EAGAIN; } -void gk20a_suspend_all_sms(struct gk20a *g) +void gk20a_suspend_single_sm(struct gk20a *g, + u32 gpc, u32 tpc, + u32 global_esr_mask, bool check_errors) +{ + u32 offset; + int err; + u32 dbgr_control0; + + offset = proj_gpc_stride_v() * gpc + + proj_tpc_in_gpc_stride_v() * tpc; + + /* if an SM debugger isn't attached, skip suspend */ + if (!gk20a_gr_sm_debugger_attached(g)) { + gk20a_err(dev_from_gk20a(g), + "SM debugger not attached, skipping suspend!\n"); + return; + } + + /* assert stop trigger. */ + dbgr_control0 = gk20a_readl(g, + gr_gpc0_tpc0_sm_dbgr_control0_r() + offset); + dbgr_control0 |= gr_gpcs_tpcs_sm_dbgr_control0_stop_trigger_enable_f(); + gk20a_writel(g, gr_gpc0_tpc0_sm_dbgr_control0_r() + offset, + dbgr_control0); + + err = gk20a_gr_wait_for_sm_lock_down(g, gpc, tpc, + global_esr_mask, check_errors); + if (err) { + gk20a_err(dev_from_gk20a(g), + "SuspendSm failed\n"); + return; + } +} + +void gk20a_suspend_all_sms(struct gk20a *g, + u32 global_esr_mask, bool check_errors) { struct gr_gk20a *gr = &g->gr; u32 gpc, tpc; @@ -7030,8 +7065,8 @@ void gk20a_suspend_all_sms(struct gk20a *g) /* if an SM debugger isn't attached, skip suspend */ if (!gk20a_gr_sm_debugger_attached(g)) { - gk20a_err(dev_from_gk20a(g), "SM debugger not attached, " - "skipping suspend!\n"); + gk20a_err(dev_from_gk20a(g), + "SM debugger not attached, skipping suspend!\n"); return; } @@ -7048,7 +7083,8 @@ void gk20a_suspend_all_sms(struct gk20a *g) for (gpc = 0; gpc < gr->gpc_count; gpc++) { for (tpc = 0; tpc < gr->tpc_count; tpc++) { err = - gk20a_gr_wait_for_sm_lock_down(g, gpc, tpc, 0, false); + gk20a_gr_wait_for_sm_lock_down(g, gpc, tpc, + global_esr_mask, check_errors); if (err) { gk20a_err(dev_from_gk20a(g), "SuspendAllSms failed\n"); @@ -7058,6 +7094,42 @@ void gk20a_suspend_all_sms(struct gk20a *g) } } +void gk20a_resume_single_sm(struct gk20a *g, + u32 gpc, u32 tpc) +{ + u32 dbgr_control0; + u32 offset; + /* + * The following requires some clarification. Despite the fact that both + * RUN_TRIGGER and STOP_TRIGGER have the word "TRIGGER" in their + * names, only one is actually a trigger, and that is the STOP_TRIGGER. + * Merely writing a 1(_TASK) to the RUN_TRIGGER is not sufficient to + * resume the gpu - the _STOP_TRIGGER must explicitly be set to 0 + * (_DISABLE) as well. + + * Advice from the arch group: Disable the stop trigger first, as a + * separate operation, in order to ensure that the trigger has taken + * effect, before enabling the run trigger. + */ + + offset = proj_gpc_stride_v() * gpc + + proj_tpc_in_gpc_stride_v() * tpc; + + /*De-assert stop trigger */ + dbgr_control0 = + gk20a_readl(g, gr_gpc0_tpc0_sm_dbgr_control0_r() + offset); + dbgr_control0 = set_field(dbgr_control0, + gr_gpcs_tpcs_sm_dbgr_control0_stop_trigger_m(), + gr_gpcs_tpcs_sm_dbgr_control0_stop_trigger_disable_f()); + gk20a_writel(g, + gr_gpcs_tpcs_sm_dbgr_control0_r() + offset, dbgr_control0); + + /* Run trigger */ + dbgr_control0 |= gr_gpcs_tpcs_sm_dbgr_control0_run_trigger_task_f(); + gk20a_writel(g, + gr_gpc0_tpc0_sm_dbgr_control0_r() + offset, dbgr_control0); +} + void gk20a_resume_all_sms(struct gk20a *g) { u32 dbgr_control0; diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h index 9fc45ec0..29c2dcf6 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h @@ -498,8 +498,14 @@ void gr_gk20a_load_ctxsw_ucode_boot(struct gk20a *g, u64 addr_base, void gr_gk20a_free_tsg_gr_ctx(struct tsg_gk20a *c); int gr_gk20a_disable_ctxsw(struct gk20a *g); int gr_gk20a_enable_ctxsw(struct gk20a *g); +void gk20a_resume_single_sm(struct gk20a *g, + u32 gpc, u32 tpc); void gk20a_resume_all_sms(struct gk20a *g); -void gk20a_suspend_all_sms(struct gk20a *g); +void gk20a_suspend_single_sm(struct gk20a *g, + u32 gpc, u32 tpc, + u32 global_esr_mask, bool check_errors); +void gk20a_suspend_all_sms(struct gk20a *g, + u32 global_esr_mask, bool check_errors); int gk20a_gr_lock_down_sm(struct gk20a *g, u32 gpc, u32 tpc, u32 global_esr_mask); bool gk20a_is_channel_ctx_resident(struct channel_gk20a *ch); -- cgit v1.2.2