summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/gr_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/gr_gk20a.c43
1 files changed, 41 insertions, 2 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
index a4c1ce58..788ebf45 100644
--- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
@@ -628,7 +628,14 @@ static int gr_gk20a_ctrl_ctxsw(struct gk20a *g, u32 fecs_method, u32 *ret)
628 .cond.fail = GR_IS_UCODE_OP_EQUAL }, true); 628 .cond.fail = GR_IS_UCODE_OP_EQUAL }, true);
629} 629}
630 630
631/* Stop processing (stall) context switches at FECS. */ 631/**
632 * Stop processing (stall) context switches at FECS:-
633 * If fecs is sent stop_ctxsw method, elpg entry/exit cannot happen
634 * and may timeout. It could manifest as different error signatures
635 * depending on when stop_ctxsw fecs method gets sent with respect
636 * to pmu elpg sequence. It could come as pmu halt or abort or
637 * maybe ext error too.
638*/
632int gr_gk20a_disable_ctxsw(struct gk20a *g) 639int gr_gk20a_disable_ctxsw(struct gk20a *g)
633{ 640{
634 int err = 0; 641 int err = 0;
@@ -638,8 +645,24 @@ int gr_gk20a_disable_ctxsw(struct gk20a *g)
638 nvgpu_mutex_acquire(&g->ctxsw_disable_lock); 645 nvgpu_mutex_acquire(&g->ctxsw_disable_lock);
639 g->ctxsw_disable_count++; 646 g->ctxsw_disable_count++;
640 if (g->ctxsw_disable_count == 1) { 647 if (g->ctxsw_disable_count == 1) {
641 err = gr_gk20a_ctrl_ctxsw(g, 648 err = nvgpu_pg_elpg_disable(g);
649 if (err != 0) {
650 nvgpu_err(g, "failed to disable elpg. not safe to "
651 "stop_ctxsw");
652 /* stop ctxsw command is not sent */
653 g->ctxsw_disable_count--;
654 } else {
655 err = gr_gk20a_ctrl_ctxsw(g,
642 gr_fecs_method_push_adr_stop_ctxsw_v(), NULL); 656 gr_fecs_method_push_adr_stop_ctxsw_v(), NULL);
657 if (err != 0) {
658 nvgpu_err(g, "failed to stop fecs ctxsw");
659 /* stop ctxsw failed */
660 g->ctxsw_disable_count--;
661 }
662 }
663 } else {
664 nvgpu_log_info(g, "ctxsw disabled, ctxsw_disable_count: %d",
665 g->ctxsw_disable_count);
643 } 666 }
644 nvgpu_mutex_release(&g->ctxsw_disable_lock); 667 nvgpu_mutex_release(&g->ctxsw_disable_lock);
645 668
@@ -654,12 +677,28 @@ int gr_gk20a_enable_ctxsw(struct gk20a *g)
654 nvgpu_log(g, gpu_dbg_fn | gpu_dbg_gpu_dbg, " "); 677 nvgpu_log(g, gpu_dbg_fn | gpu_dbg_gpu_dbg, " ");
655 678
656 nvgpu_mutex_acquire(&g->ctxsw_disable_lock); 679 nvgpu_mutex_acquire(&g->ctxsw_disable_lock);
680
681 if (g->ctxsw_disable_count == 0) {
682 goto ctxsw_already_enabled;
683 }
657 g->ctxsw_disable_count--; 684 g->ctxsw_disable_count--;
658 WARN_ON(g->ctxsw_disable_count < 0); 685 WARN_ON(g->ctxsw_disable_count < 0);
659 if (g->ctxsw_disable_count == 0) { 686 if (g->ctxsw_disable_count == 0) {
660 err = gr_gk20a_ctrl_ctxsw(g, 687 err = gr_gk20a_ctrl_ctxsw(g,
661 gr_fecs_method_push_adr_start_ctxsw_v(), NULL); 688 gr_fecs_method_push_adr_start_ctxsw_v(), NULL);
689 if (err != 0) {
690 nvgpu_err(g, "failed to start fecs ctxsw");
691 } else {
692 if (nvgpu_pg_elpg_enable(g) != 0) {
693 nvgpu_err(g, "failed to enable elpg "
694 "after start_ctxsw");
695 }
696 }
697 } else {
698 nvgpu_log_info(g, "ctxsw_disable_count: %d is not 0 yet",
699 g->ctxsw_disable_count);
662 } 700 }
701ctxsw_already_enabled:
663 nvgpu_mutex_release(&g->ctxsw_disable_lock); 702 nvgpu_mutex_release(&g->ctxsw_disable_lock);
664 703
665 return err; 704 return err;