mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-23 01:50:07 +03:00
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 <dnibade@nvidia.com> Reviewed-on: http://git-master/r/1120332 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
This commit is contained in:
committed by
Terje Bergstrom
parent
dfac8ce704
commit
b63c4bced5
@@ -780,6 +780,42 @@ err_free:
|
|||||||
return err;
|
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,
|
long gk20a_dbg_gpu_dev_ioctl(struct file *filp, unsigned int cmd,
|
||||||
unsigned long arg)
|
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);
|
(struct nvgpu_dbg_gpu_unbind_channel_args *)buf);
|
||||||
break;
|
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:
|
default:
|
||||||
gk20a_err(dev_from_gk20a(g),
|
gk20a_err(dev_from_gk20a(g),
|
||||||
"unrecognized dbg gpu ioctl cmd: 0x%x",
|
"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 gk20a *g = get_gk20a(dbg_s->dev);
|
||||||
struct channel_gk20a *ch;
|
struct channel_gk20a *ch;
|
||||||
bool ch_is_curr_ctx;
|
|
||||||
int err = 0, action = args->mode;
|
int err = 0, action = args->mode;
|
||||||
|
|
||||||
gk20a_dbg(gpu_dbg_fn | gpu_dbg_gpu_dbg, "action: %d", 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);
|
mutex_lock(&g->dbg_sessions_lock);
|
||||||
|
|
||||||
/* Suspend GPU context switching */
|
/* 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);
|
err = gr_gk20a_disable_ctxsw(g);
|
||||||
if (err) {
|
if (err) {
|
||||||
gk20a_err(dev_from_gk20a(g), "unable to stop gr ctxsw");
|
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;
|
goto clean_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find out whether the current channel is resident */
|
switch (action) {
|
||||||
ch_is_curr_ctx = gk20a_is_channel_ctx_resident(ch);
|
case NVGPU_DBG_GPU_SUSPEND_ALL_SMS:
|
||||||
|
gr_gk20a_suspend_context(ch);
|
||||||
|
break;
|
||||||
|
|
||||||
if (ch_is_curr_ctx) {
|
case NVGPU_DBG_GPU_RESUME_ALL_SMS:
|
||||||
switch (action) {
|
gr_gk20a_resume_context(ch);
|
||||||
case NVGPU_DBG_GPU_SUSPEND_ALL_SMS:
|
break;
|
||||||
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;
|
|
||||||
|
|
||||||
case NVGPU_DBG_GPU_RESUME_ALL_SMS:
|
|
||||||
/* Enable the channel */
|
|
||||||
channel_gk20a_enable(ch);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resume GPU context switching */
|
|
||||||
err = gr_gk20a_enable_ctxsw(g);
|
err = gr_gk20a_enable_ctxsw(g);
|
||||||
if (err)
|
if (err)
|
||||||
gk20a_err(dev_from_gk20a(g), "unable to restart ctxsw!\n");
|
gk20a_err(dev_from_gk20a(g), "unable to restart ctxsw!\n");
|
||||||
|
|
||||||
clean_up:
|
clean_up:
|
||||||
mutex_unlock(&g->dbg_sessions_lock);
|
mutex_unlock(&g->dbg_sessions_lock);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -248,6 +248,9 @@ struct gpu_ops {
|
|||||||
sm_error_state);
|
sm_error_state);
|
||||||
int (*clear_sm_error_state)(struct gk20a *g,
|
int (*clear_sm_error_state)(struct gk20a *g,
|
||||||
struct channel_gk20a *ch, u32 sm_id);
|
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;
|
} gr;
|
||||||
const char *name;
|
const char *name;
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
@@ -8458,6 +8458,123 @@ static void gr_gk20a_get_access_map(struct gk20a *g,
|
|||||||
*num_entries = ARRAY_SIZE(wl_addr_gk20a);
|
*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)
|
void gk20a_init_gr_ops(struct gpu_ops *gops)
|
||||||
{
|
{
|
||||||
gops->gr.access_smpc_reg = gr_gk20a_access_smpc_reg;
|
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.record_sm_error_state = gk20a_gr_record_sm_error_state;
|
||||||
gops->gr.update_sm_error_state = gk20a_gr_update_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.clear_sm_error_state = gk20a_gr_clear_sm_error_state;
|
||||||
|
gops->gr.suspend_contexts = gr_gk20a_suspend_contexts;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -614,4 +614,13 @@ int gr_gk20a_get_ctx_id(struct gk20a *g,
|
|||||||
|
|
||||||
u32 gk20a_mask_hww_warp_esr(u32 hww_warp_esr);
|
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__*/
|
#endif /*__GR_GK20A_H__*/
|
||||||
|
|||||||
@@ -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.record_sm_error_state = gm20b_gr_record_sm_error_state;
|
||||||
gops->gr.update_sm_error_state = gm20b_gr_update_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.clear_sm_error_state = gm20b_gr_clear_sm_error_state;
|
||||||
|
gops->gr.suspend_contexts = gr_gk20a_suspend_contexts;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -738,8 +738,22 @@ struct nvgpu_dbg_gpu_unbind_channel_args {
|
|||||||
_IOW(NVGPU_DBG_GPU_IOCTL_MAGIC, 17, struct nvgpu_dbg_gpu_unbind_channel_args)
|
_IOW(NVGPU_DBG_GPU_IOCTL_MAGIC, 17, struct nvgpu_dbg_gpu_unbind_channel_args)
|
||||||
|
|
||||||
|
|
||||||
|
#define NVGPU_DBG_GPU_SUSPEND_ALL_CONTEXTS 1
|
||||||
|
#define NVGPU_DBG_GPU_RESUME_ALL_CONTEXTS 2
|
||||||
|
|
||||||
|
struct nvgpu_dbg_gpu_suspend_resume_contexts_args {
|
||||||
|
__u32 action;
|
||||||
|
__u32 is_resident_context;
|
||||||
|
__s32 resident_context_fd;
|
||||||
|
__u32 padding;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NVGPU_DBG_GPU_IOCTL_SUSPEND_RESUME_CONTEXTS \
|
||||||
|
_IOWR(NVGPU_DBG_GPU_IOCTL_MAGIC, 18, struct nvgpu_dbg_gpu_suspend_resume_contexts_args)
|
||||||
|
|
||||||
|
|
||||||
#define NVGPU_DBG_GPU_IOCTL_LAST \
|
#define NVGPU_DBG_GPU_IOCTL_LAST \
|
||||||
_IOC_NR(NVGPU_DBG_GPU_IOCTL_UNBIND_CHANNEL)
|
_IOC_NR(NVGPU_DBG_GPU_IOCTL_SUSPEND_RESUME_CONTEXTS)
|
||||||
|
|
||||||
#define NVGPU_DBG_GPU_IOCTL_MAX_ARG_SIZE \
|
#define NVGPU_DBG_GPU_IOCTL_MAX_ARG_SIZE \
|
||||||
sizeof(struct nvgpu_dbg_gpu_perfbuf_map_args)
|
sizeof(struct nvgpu_dbg_gpu_perfbuf_map_args)
|
||||||
|
|||||||
Reference in New Issue
Block a user