From bea4bb915a4a15042057a21170bcc2058f2bfb16 Mon Sep 17 00:00:00 2001 From: Alex Waterman Date: Tue, 10 Jun 2014 13:40:12 -0700 Subject: gpu: nvgpu: Implement L2 flush in fifo recovery Implement a full L2 flush (clean and invalidate) for gm20b in the fifo recovery path. Bug 1512176 Change-Id: Ibf89ede9cca65a6868ebff89825869053302a007 Signed-off-by: Alex Waterman Reviewed-on: http://git-master/r/416435 Reviewed-by: Terje Bergstrom Tested-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | 3 +++ drivers/gpu/nvgpu/gk20a/gk20a.h | 1 + drivers/gpu/nvgpu/gm20b/ltc_gm20b.c | 48 ++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c index f246c73e..cba1f0fd 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c @@ -1200,6 +1200,9 @@ void gk20a_fifo_recover(struct gk20a *g, u32 __engine_ids, if (verbose) gk20a_debug_dump(g->dev); + if (g->ops.ltc.flush) + g->ops.ltc.flush(g); + /* store faulted engines in advance */ g->fifo.mmu_fault_engines = 0; for_each_set_bit(engine_id, &_engine_ids, 32) { diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index d8ceecd7..726994ff 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -82,6 +82,7 @@ struct gpu_ops { void (*elpg_flush)(struct gk20a *g); void (*isr)(struct gk20a *g); u32 (*cbc_fix_config)(struct gk20a *g, int base); + void (*flush)(struct gk20a *g); } ltc; struct { int (*init_fs_state)(struct gk20a *g); diff --git a/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c b/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c index a5056289..1f9bf44c 100644 --- a/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c @@ -250,6 +250,53 @@ u32 gm20b_ltc_cbc_fix_config(struct gk20a *g, int base) return base; } +/* + * Performs a full flush of the L2 cache. + */ +void gm20b_flush_ltc(struct gk20a *g) +{ + u32 op_pending; + + /* Clean... */ + gk20a_writel(g, ltc_ltcs_ltss_tstg_cmgmt1_r(), + ltc_ltcs_ltss_tstg_cmgmt1_clean_pending_f() | + ltc_ltcs_ltss_tstg_cmgmt1_max_cycles_between_cleans_3_f() | + ltc_ltcs_ltss_tstg_cmgmt1_clean_wait_for_fb_to_pull_true_f() | + ltc_ltcs_ltss_tstg_cmgmt1_clean_evict_last_class_true_f() | + ltc_ltcs_ltss_tstg_cmgmt1_clean_evict_normal_class_true_f() | + ltc_ltcs_ltss_tstg_cmgmt1_clean_evict_first_class_true_f()); + + /* Wait on each LTC individually. */ + do { + op_pending = gk20a_readl(g, ltc_ltc0_ltss_tstg_cmgmt1_r()); + } while (op_pending & + ltc_ltc0_ltss_tstg_cmgmt1_clean_pending_f()); + + do { + op_pending = gk20a_readl(g, ltc_ltc1_ltss_tstg_cmgmt1_r()); + } while (op_pending & + ltc_ltc1_ltss_tstg_cmgmt1_clean_pending_f()); + + /* And invalidate. */ + gk20a_writel(g, ltc_ltcs_ltss_tstg_cmgmt0_r(), + ltc_ltcs_ltss_tstg_cmgmt0_invalidate_pending_f() | + ltc_ltcs_ltss_tstg_cmgmt0_max_cycles_between_invalidates_3_f() | + ltc_ltcs_ltss_tstg_cmgmt0_invalidate_evict_last_class_true_f() | + ltc_ltcs_ltss_tstg_cmgmt0_invalidate_evict_normal_class_true_f() | + ltc_ltcs_ltss_tstg_cmgmt0_invalidate_evict_first_class_true_f()); + + /* Wait on each LTC individually. */ + do { + op_pending = gk20a_readl(g, ltc_ltc0_ltss_tstg_cmgmt0_r()); + } while (op_pending & + ltc_ltc0_ltss_tstg_cmgmt0_invalidate_pending_f()); + + do { + op_pending = gk20a_readl(g, ltc_ltc1_ltss_tstg_cmgmt0_r()); + } while (op_pending & + ltc_ltc1_ltss_tstg_cmgmt0_invalidate_pending_f()); +} + void gm20b_init_ltc(struct gpu_ops *gops) { /* Gk20a reused ops. */ @@ -266,4 +313,5 @@ void gm20b_init_ltc(struct gpu_ops *gops) gops->ltc.elpg_flush = gm20b_ltc_g_elpg_flush_locked; gops->ltc.isr = gm20b_ltc_isr; gops->ltc.cbc_fix_config = gm20b_ltc_cbc_fix_config; + gops->ltc.flush = gm20b_flush_ltc; } -- cgit v1.2.2