summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gp10b/gr_gp10b.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gp10b/gr_gp10b.c')
-rw-r--r--drivers/gpu/nvgpu/gp10b/gr_gp10b.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gp10b/gr_gp10b.c b/drivers/gpu/nvgpu/gp10b/gr_gp10b.c
index 1b88112e..03462d5f 100644
--- a/drivers/gpu/nvgpu/gp10b/gr_gp10b.c
+++ b/drivers/gpu/nvgpu/gp10b/gr_gp10b.c
@@ -14,6 +14,7 @@
14 */ 14 */
15 15
16#include "gk20a/gk20a.h" /* FERMI and MAXWELL classes defined here */ 16#include "gk20a/gk20a.h" /* FERMI and MAXWELL classes defined here */
17#include <linux/delay.h>
17 18
18#include "gk20a/gr_gk20a.h" 19#include "gk20a/gr_gk20a.h"
19 20
@@ -23,6 +24,7 @@
23#include "hw_fifo_gp10b.h" 24#include "hw_fifo_gp10b.h"
24#include "hw_proj_gp10b.h" 25#include "hw_proj_gp10b.h"
25#include "hw_ctxsw_prog_gp10b.h" 26#include "hw_ctxsw_prog_gp10b.h"
27#include "hw_mc_gp10b.h"
26 28
27static bool gr_gp10b_is_valid_class(struct gk20a *g, u32 class_num) 29static bool gr_gp10b_is_valid_class(struct gk20a *g, u32 class_num)
28{ 30{
@@ -779,6 +781,69 @@ static int gr_gp10b_dump_gr_status_regs(struct gk20a *g,
779 return 0; 781 return 0;
780} 782}
781 783
784static bool gr_activity_empty_or_preempted(u32 val)
785{
786 while(val) {
787 u32 v = val & 7;
788 if (v != gr_activity_4_gpc0_empty_v() &&
789 v != gr_activity_4_gpc0_preempted_v())
790 return false;
791 val >>= 3;
792 }
793
794 return true;
795}
796
797static int gr_gp10b_wait_empty(struct gk20a *g, unsigned long end_jiffies,
798 u32 expect_delay)
799{
800 u32 delay = expect_delay;
801 bool gr_enabled;
802 bool ctxsw_active;
803 bool gr_busy;
804 u32 gr_status;
805 u32 activity0, activity1, activity2, activity4;
806
807 gk20a_dbg_fn("");
808
809 do {
810 /* fmodel: host gets fifo_engine_status(gr) from gr
811 only when gr_status is read */
812 gr_status = gk20a_readl(g, gr_status_r());
813
814 gr_enabled = gk20a_readl(g, mc_enable_r()) &
815 mc_enable_pgraph_enabled_f();
816
817 ctxsw_active = gr_status & 1<<7;
818
819 activity0 = gk20a_readl(g, gr_activity_0_r());
820 activity1 = gk20a_readl(g, gr_activity_1_r());
821 activity2 = gk20a_readl(g, gr_activity_2_r());
822 activity4 = gk20a_readl(g, gr_activity_4_r());
823
824 gr_busy = !(gr_activity_empty_or_preempted(activity0) &&
825 gr_activity_empty_or_preempted(activity1) &&
826 activity2 == 0 &&
827 gr_activity_empty_or_preempted(activity4));
828
829 if (!gr_enabled || (!gr_busy && !ctxsw_active)) {
830 gk20a_dbg_fn("done");
831 return 0;
832 }
833
834 usleep_range(delay, delay * 2);
835 delay = min_t(u32, delay << 1, GR_IDLE_CHECK_MAX);
836
837 } while (time_before(jiffies, end_jiffies)
838 || !tegra_platform_is_silicon());
839
840 gk20a_err(dev_from_gk20a(g),
841 "timeout, ctxsw busy : %d, gr busy : %d, %08x, %08x, %08x, %08x",
842 ctxsw_active, gr_busy, activity0, activity1, activity2, activity4);
843
844 return -EAGAIN;
845}
846
782void gp10b_init_gr(struct gpu_ops *gops) 847void gp10b_init_gr(struct gpu_ops *gops)
783{ 848{
784 gm20b_init_gr(gops); 849 gm20b_init_gr(gops);
@@ -802,4 +867,5 @@ void gp10b_init_gr(struct gpu_ops *gops)
802 gops->gr.update_ctxsw_preemption_mode = 867 gops->gr.update_ctxsw_preemption_mode =
803 gr_gp10b_update_ctxsw_preemption_mode; 868 gr_gp10b_update_ctxsw_preemption_mode;
804 gops->gr.dump_gr_regs = gr_gp10b_dump_gr_status_regs; 869 gops->gr.dump_gr_regs = gr_gp10b_dump_gr_status_regs;
870 gops->gr.wait_empty = gr_gp10b_wait_empty;
805} 871}