diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/gr_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gr_gk20a.c | 43 |
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 | */ | ||
632 | int gr_gk20a_disable_ctxsw(struct gk20a *g) | 639 | int 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 | } |
701 | ctxsw_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; |