diff options
author | Deepak Nibade <dnibade@nvidia.com> | 2015-12-21 04:51:49 -0500 |
---|---|---|
committer | Terje Bergstrom <tbergstrom@nvidia.com> | 2016-04-19 11:07:45 -0400 |
commit | b63c4bced5b01e2aef477ecfca784848e2a2cd3a (patch) | |
tree | 4309e72334876236efc29fd57bda6f49599c7732 /drivers/gpu/nvgpu | |
parent | dfac8ce70464413c0e3748634c57d49950e71933 (diff) |
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>
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c | 81 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gr_gk20a.c | 118 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gr_gk20a.h | 9 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/gr_gm20b.c | 1 |
5 files changed, 181 insertions, 31 deletions
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: | |||
780 | return err; | 780 | return err; |
781 | } | 781 | } |
782 | 782 | ||
783 | static int | ||
784 | nvgpu_dbg_gpu_ioctl_suspend_resume_contexts(struct dbg_session_gk20a *dbg_s, | ||
785 | struct nvgpu_dbg_gpu_suspend_resume_contexts_args *args) | ||
786 | { | ||
787 | struct gk20a *g = dbg_s->g; | ||
788 | int err = 0; | ||
789 | int ctx_resident_ch_fd = -1; | ||
790 | |||
791 | err = gk20a_busy(g->dev); | ||
792 | if (err) | ||
793 | return err; | ||
794 | |||
795 | switch (args->action) { | ||
796 | case NVGPU_DBG_GPU_SUSPEND_ALL_CONTEXTS: | ||
797 | err = g->ops.gr.suspend_contexts(g, dbg_s, | ||
798 | &ctx_resident_ch_fd); | ||
799 | break; | ||
800 | |||
801 | case NVGPU_DBG_GPU_RESUME_ALL_CONTEXTS: | ||
802 | err = gr_gk20a_resume_contexts(g, dbg_s, | ||
803 | &ctx_resident_ch_fd); | ||
804 | break; | ||
805 | } | ||
806 | |||
807 | if (ctx_resident_ch_fd < 0) { | ||
808 | args->is_resident_context = 0; | ||
809 | } else { | ||
810 | args->is_resident_context = 1; | ||
811 | args->resident_context_fd = ctx_resident_ch_fd; | ||
812 | } | ||
813 | |||
814 | gk20a_idle(g->dev); | ||
815 | |||
816 | return err; | ||
817 | } | ||
818 | |||
783 | long gk20a_dbg_gpu_dev_ioctl(struct file *filp, unsigned int cmd, | 819 | long gk20a_dbg_gpu_dev_ioctl(struct file *filp, unsigned int cmd, |
784 | unsigned long arg) | 820 | unsigned long arg) |
785 | { | 821 | { |
@@ -897,6 +933,11 @@ long gk20a_dbg_gpu_dev_ioctl(struct file *filp, unsigned int cmd, | |||
897 | (struct nvgpu_dbg_gpu_unbind_channel_args *)buf); | 933 | (struct nvgpu_dbg_gpu_unbind_channel_args *)buf); |
898 | break; | 934 | break; |
899 | 935 | ||
936 | case NVGPU_DBG_GPU_IOCTL_SUSPEND_RESUME_CONTEXTS: | ||
937 | err = nvgpu_dbg_gpu_ioctl_suspend_resume_contexts(dbg_s, | ||
938 | (struct nvgpu_dbg_gpu_suspend_resume_contexts_args *)buf); | ||
939 | break; | ||
940 | |||
900 | default: | 941 | default: |
901 | gk20a_err(dev_from_gk20a(g), | 942 | gk20a_err(dev_from_gk20a(g), |
902 | "unrecognized dbg gpu ioctl cmd: 0x%x", | 943 | "unrecognized dbg gpu ioctl cmd: 0x%x", |
@@ -1222,7 +1263,6 @@ static int nvgpu_dbg_gpu_ioctl_suspend_resume_sm( | |||
1222 | { | 1263 | { |
1223 | struct gk20a *g = get_gk20a(dbg_s->dev); | 1264 | struct gk20a *g = get_gk20a(dbg_s->dev); |
1224 | struct channel_gk20a *ch; | 1265 | struct channel_gk20a *ch; |
1225 | bool ch_is_curr_ctx; | ||
1226 | int err = 0, action = args->mode; | 1266 | int err = 0, action = args->mode; |
1227 | 1267 | ||
1228 | gk20a_dbg(gpu_dbg_fn | gpu_dbg_gpu_dbg, "action: %d", args->mode); | 1268 | 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( | |||
1234 | mutex_lock(&g->dbg_sessions_lock); | 1274 | mutex_lock(&g->dbg_sessions_lock); |
1235 | 1275 | ||
1236 | /* Suspend GPU context switching */ | 1276 | /* Suspend GPU context switching */ |
1237 | /* Disable channel switching. | ||
1238 | * at that point the hardware state can be inspected to | ||
1239 | * determine if the context we're interested in is current. | ||
1240 | */ | ||
1241 | err = gr_gk20a_disable_ctxsw(g); | 1277 | err = gr_gk20a_disable_ctxsw(g); |
1242 | if (err) { | 1278 | if (err) { |
1243 | gk20a_err(dev_from_gk20a(g), "unable to stop gr ctxsw"); | 1279 | gk20a_err(dev_from_gk20a(g), "unable to stop gr ctxsw"); |
@@ -1245,40 +1281,23 @@ static int nvgpu_dbg_gpu_ioctl_suspend_resume_sm( | |||
1245 | goto clean_up; | 1281 | goto clean_up; |
1246 | } | 1282 | } |
1247 | 1283 | ||
1248 | /* find out whether the current channel is resident */ | 1284 | switch (action) { |
1249 | ch_is_curr_ctx = gk20a_is_channel_ctx_resident(ch); | 1285 | case NVGPU_DBG_GPU_SUSPEND_ALL_SMS: |
1250 | 1286 | gr_gk20a_suspend_context(ch); | |
1251 | if (ch_is_curr_ctx) { | 1287 | break; |
1252 | switch (action) { | ||
1253 | case NVGPU_DBG_GPU_SUSPEND_ALL_SMS: | ||
1254 | gk20a_suspend_all_sms(g, 0, false); | ||
1255 | break; | ||
1256 | |||
1257 | case NVGPU_DBG_GPU_RESUME_ALL_SMS: | ||
1258 | gk20a_resume_all_sms(g); | ||
1259 | break; | ||
1260 | } | ||
1261 | } else { | ||
1262 | switch (action) { | ||
1263 | case NVGPU_DBG_GPU_SUSPEND_ALL_SMS: | ||
1264 | /* Disable the channel */ | ||
1265 | channel_gk20a_disable(ch); | ||
1266 | break; | ||
1267 | 1288 | ||
1268 | case NVGPU_DBG_GPU_RESUME_ALL_SMS: | 1289 | case NVGPU_DBG_GPU_RESUME_ALL_SMS: |
1269 | /* Enable the channel */ | 1290 | gr_gk20a_resume_context(ch); |
1270 | channel_gk20a_enable(ch); | 1291 | break; |
1271 | break; | ||
1272 | } | ||
1273 | } | 1292 | } |
1274 | 1293 | ||
1275 | /* Resume GPU context switching */ | ||
1276 | err = gr_gk20a_enable_ctxsw(g); | 1294 | err = gr_gk20a_enable_ctxsw(g); |
1277 | if (err) | 1295 | if (err) |
1278 | gk20a_err(dev_from_gk20a(g), "unable to restart ctxsw!\n"); | 1296 | gk20a_err(dev_from_gk20a(g), "unable to restart ctxsw!\n"); |
1279 | 1297 | ||
1280 | clean_up: | 1298 | clean_up: |
1281 | mutex_unlock(&g->dbg_sessions_lock); | 1299 | mutex_unlock(&g->dbg_sessions_lock); |
1300 | |||
1282 | return err; | 1301 | return err; |
1283 | } | 1302 | } |
1284 | 1303 | ||
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 { | |||
248 | sm_error_state); | 248 | sm_error_state); |
249 | int (*clear_sm_error_state)(struct gk20a *g, | 249 | int (*clear_sm_error_state)(struct gk20a *g, |
250 | struct channel_gk20a *ch, u32 sm_id); | 250 | struct channel_gk20a *ch, u32 sm_id); |
251 | int (*suspend_contexts)(struct gk20a *g, | ||
252 | struct dbg_session_gk20a *dbg_s, | ||
253 | int *ctx_resident_ch_fd); | ||
251 | } gr; | 254 | } gr; |
252 | const char *name; | 255 | const char *name; |
253 | struct { | 256 | 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, | |||
8458 | *num_entries = ARRAY_SIZE(wl_addr_gk20a); | 8458 | *num_entries = ARRAY_SIZE(wl_addr_gk20a); |
8459 | } | 8459 | } |
8460 | 8460 | ||
8461 | /* | ||
8462 | * gr_gk20a_suspend_context() | ||
8463 | * This API should be called with dbg_session lock held | ||
8464 | * and ctxsw disabled | ||
8465 | * Returns bool value indicating if context was resident | ||
8466 | * or not | ||
8467 | */ | ||
8468 | bool gr_gk20a_suspend_context(struct channel_gk20a *ch) | ||
8469 | { | ||
8470 | struct gk20a *g = ch->g; | ||
8471 | bool ctx_resident = false; | ||
8472 | |||
8473 | if (gk20a_is_channel_ctx_resident(ch)) { | ||
8474 | gk20a_suspend_all_sms(g, 0, false); | ||
8475 | ctx_resident = true; | ||
8476 | } else { | ||
8477 | gk20a_disable_channel_tsg(g, ch); | ||
8478 | } | ||
8479 | |||
8480 | return ctx_resident; | ||
8481 | } | ||
8482 | |||
8483 | bool gr_gk20a_resume_context(struct channel_gk20a *ch) | ||
8484 | { | ||
8485 | struct gk20a *g = ch->g; | ||
8486 | bool ctx_resident = false; | ||
8487 | |||
8488 | if (gk20a_is_channel_ctx_resident(ch)) { | ||
8489 | gk20a_resume_all_sms(g); | ||
8490 | ctx_resident = true; | ||
8491 | } else { | ||
8492 | gk20a_enable_channel_tsg(g, ch); | ||
8493 | } | ||
8494 | |||
8495 | return ctx_resident; | ||
8496 | } | ||
8497 | |||
8498 | int gr_gk20a_suspend_contexts(struct gk20a *g, | ||
8499 | struct dbg_session_gk20a *dbg_s, | ||
8500 | int *ctx_resident_ch_fd) | ||
8501 | { | ||
8502 | int local_ctx_resident_ch_fd = -1; | ||
8503 | bool ctx_resident; | ||
8504 | struct channel_gk20a *ch; | ||
8505 | struct dbg_session_channel_data *ch_data; | ||
8506 | int err = 0; | ||
8507 | |||
8508 | mutex_lock(&g->dbg_sessions_lock); | ||
8509 | |||
8510 | err = gr_gk20a_disable_ctxsw(g); | ||
8511 | if (err) { | ||
8512 | gk20a_err(dev_from_gk20a(g), "unable to stop gr ctxsw"); | ||
8513 | goto clean_up; | ||
8514 | } | ||
8515 | |||
8516 | mutex_lock(&dbg_s->ch_list_lock); | ||
8517 | |||
8518 | list_for_each_entry(ch_data, &dbg_s->ch_list, ch_entry) { | ||
8519 | ch = g->fifo.channel + ch_data->chid; | ||
8520 | |||
8521 | ctx_resident = gr_gk20a_suspend_context(ch); | ||
8522 | if (ctx_resident) | ||
8523 | local_ctx_resident_ch_fd = ch_data->channel_fd; | ||
8524 | } | ||
8525 | |||
8526 | mutex_unlock(&dbg_s->ch_list_lock); | ||
8527 | |||
8528 | err = gr_gk20a_enable_ctxsw(g); | ||
8529 | if (err) | ||
8530 | gk20a_err(dev_from_gk20a(g), "unable to restart ctxsw!\n"); | ||
8531 | |||
8532 | *ctx_resident_ch_fd = local_ctx_resident_ch_fd; | ||
8533 | |||
8534 | clean_up: | ||
8535 | mutex_unlock(&g->dbg_sessions_lock); | ||
8536 | |||
8537 | return err; | ||
8538 | } | ||
8539 | |||
8540 | int gr_gk20a_resume_contexts(struct gk20a *g, | ||
8541 | struct dbg_session_gk20a *dbg_s, | ||
8542 | int *ctx_resident_ch_fd) | ||
8543 | { | ||
8544 | int local_ctx_resident_ch_fd = -1; | ||
8545 | bool ctx_resident; | ||
8546 | struct channel_gk20a *ch; | ||
8547 | int err = 0; | ||
8548 | struct dbg_session_channel_data *ch_data; | ||
8549 | |||
8550 | mutex_lock(&g->dbg_sessions_lock); | ||
8551 | |||
8552 | err = gr_gk20a_disable_ctxsw(g); | ||
8553 | if (err) { | ||
8554 | gk20a_err(dev_from_gk20a(g), "unable to stop gr ctxsw"); | ||
8555 | goto clean_up; | ||
8556 | } | ||
8557 | |||
8558 | list_for_each_entry(ch_data, &dbg_s->ch_list, ch_entry) { | ||
8559 | ch = g->fifo.channel + ch_data->chid; | ||
8560 | |||
8561 | ctx_resident = gr_gk20a_resume_context(ch); | ||
8562 | if (ctx_resident) | ||
8563 | local_ctx_resident_ch_fd = ch_data->channel_fd; | ||
8564 | } | ||
8565 | |||
8566 | err = gr_gk20a_enable_ctxsw(g); | ||
8567 | if (err) | ||
8568 | gk20a_err(dev_from_gk20a(g), "unable to restart ctxsw!\n"); | ||
8569 | |||
8570 | *ctx_resident_ch_fd = local_ctx_resident_ch_fd; | ||
8571 | |||
8572 | clean_up: | ||
8573 | mutex_unlock(&g->dbg_sessions_lock); | ||
8574 | |||
8575 | return err; | ||
8576 | } | ||
8577 | |||
8461 | void gk20a_init_gr_ops(struct gpu_ops *gops) | 8578 | void gk20a_init_gr_ops(struct gpu_ops *gops) |
8462 | { | 8579 | { |
8463 | gops->gr.access_smpc_reg = gr_gk20a_access_smpc_reg; | 8580 | gops->gr.access_smpc_reg = gr_gk20a_access_smpc_reg; |
@@ -8522,4 +8639,5 @@ void gk20a_init_gr_ops(struct gpu_ops *gops) | |||
8522 | gops->gr.record_sm_error_state = gk20a_gr_record_sm_error_state; | 8639 | gops->gr.record_sm_error_state = gk20a_gr_record_sm_error_state; |
8523 | gops->gr.update_sm_error_state = gk20a_gr_update_sm_error_state; | 8640 | gops->gr.update_sm_error_state = gk20a_gr_update_sm_error_state; |
8524 | gops->gr.clear_sm_error_state = gk20a_gr_clear_sm_error_state; | 8641 | gops->gr.clear_sm_error_state = gk20a_gr_clear_sm_error_state; |
8642 | gops->gr.suspend_contexts = gr_gk20a_suspend_contexts; | ||
8525 | } | 8643 | } |
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, | |||
614 | 614 | ||
615 | u32 gk20a_mask_hww_warp_esr(u32 hww_warp_esr); | 615 | u32 gk20a_mask_hww_warp_esr(u32 hww_warp_esr); |
616 | 616 | ||
617 | bool gr_gk20a_suspend_context(struct channel_gk20a *ch); | ||
618 | bool gr_gk20a_resume_context(struct channel_gk20a *ch); | ||
619 | int gr_gk20a_suspend_contexts(struct gk20a *g, | ||
620 | struct dbg_session_gk20a *dbg_s, | ||
621 | int *ctx_resident_ch_fd); | ||
622 | int gr_gk20a_resume_contexts(struct gk20a *g, | ||
623 | struct dbg_session_gk20a *dbg_s, | ||
624 | int *ctx_resident_ch_fd); | ||
625 | |||
617 | #endif /*__GR_GK20A_H__*/ | 626 | #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) | |||
1397 | gops->gr.record_sm_error_state = gm20b_gr_record_sm_error_state; | 1397 | gops->gr.record_sm_error_state = gm20b_gr_record_sm_error_state; |
1398 | gops->gr.update_sm_error_state = gm20b_gr_update_sm_error_state; | 1398 | gops->gr.update_sm_error_state = gm20b_gr_update_sm_error_state; |
1399 | gops->gr.clear_sm_error_state = gm20b_gr_clear_sm_error_state; | 1399 | gops->gr.clear_sm_error_state = gm20b_gr_clear_sm_error_state; |
1400 | gops->gr.suspend_contexts = gr_gk20a_suspend_contexts; | ||
1400 | } | 1401 | } |