From b63c4bced5b01e2aef477ecfca784848e2a2cd3a Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Mon, 21 Dec 2015 15:21:49 +0530 Subject: gpu: nvgpu: IOCTL to suspend/resume context Add below IOCTL to suspend/resume a context NVGPU_DBG_GPU_IOCTL_SUSPEND_RESUME_CONTEXTS: Suspend sequence : - disable ctxsw - loop through list of channels - if channel is ctx resident, suspend all SMs - otherwise, disable channel/TSG - enable ctxsw Resume sequence : - disable ctxsw - loop through list of channels - if channel is ctx resident, resume all SMs - otherwise, enable channel/TSG - enable ctxsw Bug 200156699 Change-Id: Iacf1bf7877b67ddf87cc6891c37c758a4644b014 Signed-off-by: Deepak Nibade Reviewed-on: http://git-master/r/1120332 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c | 81 +++++++++++++--------- drivers/gpu/nvgpu/gk20a/gk20a.h | 3 + drivers/gpu/nvgpu/gk20a/gr_gk20a.c | 118 ++++++++++++++++++++++++++++++++ drivers/gpu/nvgpu/gk20a/gr_gk20a.h | 9 +++ drivers/gpu/nvgpu/gm20b/gr_gm20b.c | 1 + 5 files changed, 181 insertions(+), 31 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c index 34685416..afc1517b 100644 --- a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c @@ -780,6 +780,42 @@ err_free: return err; } +static int +nvgpu_dbg_gpu_ioctl_suspend_resume_contexts(struct dbg_session_gk20a *dbg_s, + struct nvgpu_dbg_gpu_suspend_resume_contexts_args *args) +{ + struct gk20a *g = dbg_s->g; + int err = 0; + int ctx_resident_ch_fd = -1; + + err = gk20a_busy(g->dev); + if (err) + return err; + + switch (args->action) { + case NVGPU_DBG_GPU_SUSPEND_ALL_CONTEXTS: + err = g->ops.gr.suspend_contexts(g, dbg_s, + &ctx_resident_ch_fd); + break; + + case NVGPU_DBG_GPU_RESUME_ALL_CONTEXTS: + err = gr_gk20a_resume_contexts(g, dbg_s, + &ctx_resident_ch_fd); + break; + } + + if (ctx_resident_ch_fd < 0) { + args->is_resident_context = 0; + } else { + args->is_resident_context = 1; + args->resident_context_fd = ctx_resident_ch_fd; + } + + gk20a_idle(g->dev); + + return err; +} + long gk20a_dbg_gpu_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { @@ -897,6 +933,11 @@ long gk20a_dbg_gpu_dev_ioctl(struct file *filp, unsigned int cmd, (struct nvgpu_dbg_gpu_unbind_channel_args *)buf); break; + case NVGPU_DBG_GPU_IOCTL_SUSPEND_RESUME_CONTEXTS: + err = nvgpu_dbg_gpu_ioctl_suspend_resume_contexts(dbg_s, + (struct nvgpu_dbg_gpu_suspend_resume_contexts_args *)buf); + break; + default: gk20a_err(dev_from_gk20a(g), "unrecognized dbg gpu ioctl cmd: 0x%x", @@ -1222,7 +1263,6 @@ static int nvgpu_dbg_gpu_ioctl_suspend_resume_sm( { struct gk20a *g = get_gk20a(dbg_s->dev); struct channel_gk20a *ch; - bool ch_is_curr_ctx; int err = 0, action = args->mode; gk20a_dbg(gpu_dbg_fn | gpu_dbg_gpu_dbg, "action: %d", args->mode); @@ -1234,10 +1274,6 @@ static int nvgpu_dbg_gpu_ioctl_suspend_resume_sm( mutex_lock(&g->dbg_sessions_lock); /* Suspend GPU context switching */ - /* Disable channel switching. - * at that point the hardware state can be inspected to - * determine if the context we're interested in is current. - */ err = gr_gk20a_disable_ctxsw(g); if (err) { gk20a_err(dev_from_gk20a(g), "unable to stop gr ctxsw"); @@ -1245,40 +1281,23 @@ static int nvgpu_dbg_gpu_ioctl_suspend_resume_sm( goto clean_up; } - /* find out whether the current channel is resident */ - ch_is_curr_ctx = gk20a_is_channel_ctx_resident(ch); - - if (ch_is_curr_ctx) { - switch (action) { - case NVGPU_DBG_GPU_SUSPEND_ALL_SMS: - gk20a_suspend_all_sms(g, 0, false); - break; - - case NVGPU_DBG_GPU_RESUME_ALL_SMS: - gk20a_resume_all_sms(g); - break; - } - } else { - switch (action) { - case NVGPU_DBG_GPU_SUSPEND_ALL_SMS: - /* Disable the channel */ - channel_gk20a_disable(ch); - break; + switch (action) { + case NVGPU_DBG_GPU_SUSPEND_ALL_SMS: + gr_gk20a_suspend_context(ch); + break; - case NVGPU_DBG_GPU_RESUME_ALL_SMS: - /* Enable the channel */ - channel_gk20a_enable(ch); - break; - } + case NVGPU_DBG_GPU_RESUME_ALL_SMS: + gr_gk20a_resume_context(ch); + break; } - /* Resume GPU context switching */ err = gr_gk20a_enable_ctxsw(g); if (err) gk20a_err(dev_from_gk20a(g), "unable to restart ctxsw!\n"); - clean_up: +clean_up: mutex_unlock(&g->dbg_sessions_lock); + return err; } diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index b03e779b..5c397ad8 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -248,6 +248,9 @@ struct gpu_ops { sm_error_state); int (*clear_sm_error_state)(struct gk20a *g, struct channel_gk20a *ch, u32 sm_id); + int (*suspend_contexts)(struct gk20a *g, + struct dbg_session_gk20a *dbg_s, + int *ctx_resident_ch_fd); } gr; const char *name; struct { diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c index 4c88751e..3354c05e 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c @@ -8458,6 +8458,123 @@ static void gr_gk20a_get_access_map(struct gk20a *g, *num_entries = ARRAY_SIZE(wl_addr_gk20a); } +/* + * gr_gk20a_suspend_context() + * This API should be called with dbg_session lock held + * and ctxsw disabled + * Returns bool value indicating if context was resident + * or not + */ +bool gr_gk20a_suspend_context(struct channel_gk20a *ch) +{ + struct gk20a *g = ch->g; + bool ctx_resident = false; + + if (gk20a_is_channel_ctx_resident(ch)) { + gk20a_suspend_all_sms(g, 0, false); + ctx_resident = true; + } else { + gk20a_disable_channel_tsg(g, ch); + } + + return ctx_resident; +} + +bool gr_gk20a_resume_context(struct channel_gk20a *ch) +{ + struct gk20a *g = ch->g; + bool ctx_resident = false; + + if (gk20a_is_channel_ctx_resident(ch)) { + gk20a_resume_all_sms(g); + ctx_resident = true; + } else { + gk20a_enable_channel_tsg(g, ch); + } + + return ctx_resident; +} + +int gr_gk20a_suspend_contexts(struct gk20a *g, + struct dbg_session_gk20a *dbg_s, + int *ctx_resident_ch_fd) +{ + int local_ctx_resident_ch_fd = -1; + bool ctx_resident; + struct channel_gk20a *ch; + struct dbg_session_channel_data *ch_data; + int err = 0; + + mutex_lock(&g->dbg_sessions_lock); + + err = gr_gk20a_disable_ctxsw(g); + if (err) { + gk20a_err(dev_from_gk20a(g), "unable to stop gr ctxsw"); + goto clean_up; + } + + mutex_lock(&dbg_s->ch_list_lock); + + list_for_each_entry(ch_data, &dbg_s->ch_list, ch_entry) { + ch = g->fifo.channel + ch_data->chid; + + ctx_resident = gr_gk20a_suspend_context(ch); + if (ctx_resident) + local_ctx_resident_ch_fd = ch_data->channel_fd; + } + + mutex_unlock(&dbg_s->ch_list_lock); + + err = gr_gk20a_enable_ctxsw(g); + if (err) + gk20a_err(dev_from_gk20a(g), "unable to restart ctxsw!\n"); + + *ctx_resident_ch_fd = local_ctx_resident_ch_fd; + +clean_up: + mutex_unlock(&g->dbg_sessions_lock); + + return err; +} + +int gr_gk20a_resume_contexts(struct gk20a *g, + struct dbg_session_gk20a *dbg_s, + int *ctx_resident_ch_fd) +{ + int local_ctx_resident_ch_fd = -1; + bool ctx_resident; + struct channel_gk20a *ch; + int err = 0; + struct dbg_session_channel_data *ch_data; + + mutex_lock(&g->dbg_sessions_lock); + + err = gr_gk20a_disable_ctxsw(g); + if (err) { + gk20a_err(dev_from_gk20a(g), "unable to stop gr ctxsw"); + goto clean_up; + } + + list_for_each_entry(ch_data, &dbg_s->ch_list, ch_entry) { + ch = g->fifo.channel + ch_data->chid; + + ctx_resident = gr_gk20a_resume_context(ch); + if (ctx_resident) + local_ctx_resident_ch_fd = ch_data->channel_fd; + } + + err = gr_gk20a_enable_ctxsw(g); + if (err) + gk20a_err(dev_from_gk20a(g), "unable to restart ctxsw!\n"); + + *ctx_resident_ch_fd = local_ctx_resident_ch_fd; + +clean_up: + mutex_unlock(&g->dbg_sessions_lock); + + return err; +} + void gk20a_init_gr_ops(struct gpu_ops *gops) { gops->gr.access_smpc_reg = gr_gk20a_access_smpc_reg; @@ -8522,4 +8639,5 @@ void gk20a_init_gr_ops(struct gpu_ops *gops) gops->gr.record_sm_error_state = gk20a_gr_record_sm_error_state; gops->gr.update_sm_error_state = gk20a_gr_update_sm_error_state; gops->gr.clear_sm_error_state = gk20a_gr_clear_sm_error_state; + gops->gr.suspend_contexts = gr_gk20a_suspend_contexts; } diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h index 22ff1351..3417610f 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h @@ -614,4 +614,13 @@ int gr_gk20a_get_ctx_id(struct gk20a *g, u32 gk20a_mask_hww_warp_esr(u32 hww_warp_esr); +bool gr_gk20a_suspend_context(struct channel_gk20a *ch); +bool gr_gk20a_resume_context(struct channel_gk20a *ch); +int gr_gk20a_suspend_contexts(struct gk20a *g, + struct dbg_session_gk20a *dbg_s, + int *ctx_resident_ch_fd); +int gr_gk20a_resume_contexts(struct gk20a *g, + struct dbg_session_gk20a *dbg_s, + int *ctx_resident_ch_fd); + #endif /*__GR_GK20A_H__*/ diff --git a/drivers/gpu/nvgpu/gm20b/gr_gm20b.c b/drivers/gpu/nvgpu/gm20b/gr_gm20b.c index 204a90f3..9d269365 100644 --- a/drivers/gpu/nvgpu/gm20b/gr_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/gr_gm20b.c @@ -1397,4 +1397,5 @@ void gm20b_init_gr(struct gpu_ops *gops) gops->gr.record_sm_error_state = gm20b_gr_record_sm_error_state; gops->gr.update_sm_error_state = gm20b_gr_update_sm_error_state; gops->gr.clear_sm_error_state = gm20b_gr_clear_sm_error_state; + gops->gr.suspend_contexts = gr_gk20a_suspend_contexts; } -- cgit v1.2.2