diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/gr_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gr_gk20a.c | 118 |
1 files changed, 118 insertions, 0 deletions
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 | } |