diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 081ec077e..f16be5a16 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -84,6 +84,7 @@ struct gpu_ops { void (*init_fs_state)(struct gk20a *g); void (*elpg_flush)(struct gk20a *g); void (*isr)(struct gk20a *g); + u32 (*cbc_fix_config)(struct gk20a *g, int base); } ltc; struct { int (*init_fs_state)(struct gk20a *g); diff --git a/drivers/gpu/nvgpu/gk20a/ltc_common.c b/drivers/gpu/nvgpu/gk20a/ltc_common.c index 72477983a..75530b254 100644 --- a/drivers/gpu/nvgpu/gk20a/ltc_common.c +++ b/drivers/gpu/nvgpu/gk20a/ltc_common.c @@ -291,7 +291,7 @@ static void gk20a_ltc_init_cbc(struct gk20a *g, struct gr_gk20a *gr) compbit_base_post_divide64 = compbit_store_base_iova >> ltc_ltcs_ltss_cbc_base_alignment_shift_v(); - do_div(compbit_base_post_divide64, gr->num_fbps); + do_div(compbit_base_post_divide64, g->ltc_count); compbit_base_post_divide = u64_lo32(compbit_base_post_divide64); compbit_base_post_multiply64 = ((u64)compbit_base_post_divide * @@ -300,6 +300,11 @@ static void gk20a_ltc_init_cbc(struct gk20a *g, struct gr_gk20a *gr) if (compbit_base_post_multiply64 < compbit_store_base_iova) compbit_base_post_divide++; + /* Bug 1477079 indicates sw adjustment on the posted divided base. */ + if (g->ops.ltc.cbc_fix_config) + compbit_base_post_divide = + g->ops.ltc.cbc_fix_config(g, compbit_base_post_divide); + gk20a_writel(g, ltc_ltcs_ltss_cbc_base_r(), compbit_base_post_divide); diff --git a/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c b/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c index 43c90970f..91046d932 100644 --- a/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c @@ -237,6 +237,19 @@ static void gm20b_ltc_g_elpg_flush_locked(struct gk20a *g) "g_elpg_flush too many retries"); } +u32 gm20b_ltc_cbc_fix_config(struct gk20a *g, int base) +{ + u32 val = gk20a_readl(g, ltc_ltcs_ltss_cbc_num_active_ltcs_r()); + if (val == 2) { + return base * 2; + } else if (val != 1) { + gk20a_err(dev_from_gk20a(g), + "Invalid number of active ltcs: %08x\n", val); + } + + return base; +} + void gm20b_init_ltc(struct gpu_ops *gops) { /* Gk20a reused ops. */ @@ -255,4 +268,5 @@ void gm20b_init_ltc(struct gpu_ops *gops) gops->ltc.cbc_ctrl = gm20b_ltc_cbc_ctrl; 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; }