From ac98827c9d81746020dce689f9eb8c4018a8c148 Mon Sep 17 00:00:00 2001 From: Vinod G Date: Tue, 26 Jun 2018 18:09:57 -0700 Subject: gpu: nvgpu: Add L2 register read-backs following writes LTC register write is followed by a register read and if data doesn't match code will report the error. Renamed existing nvgpu_writel_check function as nvgpu_writel_loop as it loops until the write get success. nvgpu_writel_check function write and read back and compare the data. Bug 2039150 Change-Id: I0a49be36aad23936f2d58aa82872710827da1d32 Signed-off-by: Vinod G Reviewed-on: https://git-master.nvidia.com/r/1762344 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/Makefile | 1 + drivers/gpu/nvgpu/Makefile.sources | 1 + drivers/gpu/nvgpu/common/io_common.c | 29 +++++++++++++++++++++++++++++ drivers/gpu/nvgpu/common/posix/io.c | 2 +- drivers/gpu/nvgpu/gm20b/ltc_gm20b.c | 21 ++++++++++----------- drivers/gpu/nvgpu/gp10b/gr_gp10b.c | 10 +++++----- drivers/gpu/nvgpu/gp10b/ltc_gp10b.c | 19 ++++++++++--------- drivers/gpu/nvgpu/gv11b/ltc_gv11b.c | 21 +++++++++++---------- drivers/gpu/nvgpu/include/nvgpu/io.h | 1 + drivers/gpu/nvgpu/os/linux/io.c | 2 +- 10 files changed, 70 insertions(+), 37 deletions(-) create mode 100644 drivers/gpu/nvgpu/common/io_common.c diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile index e715e385..72795e08 100644 --- a/drivers/gpu/nvgpu/Makefile +++ b/drivers/gpu/nvgpu/Makefile @@ -176,6 +176,7 @@ nvgpu-y += \ common/pmu/pmu_perfmon.o \ common/pmu/pmu_debug.o \ common/ltc.o \ + common/io_common.o \ common/clock_gating/gm20b_gating_reglist.o \ common/clock_gating/gp106_gating_reglist.o \ common/clock_gating/gp10b_gating_reglist.o \ diff --git a/drivers/gpu/nvgpu/Makefile.sources b/drivers/gpu/nvgpu/Makefile.sources index c0340545..55d7201c 100644 --- a/drivers/gpu/nvgpu/Makefile.sources +++ b/drivers/gpu/nvgpu/Makefile.sources @@ -48,6 +48,7 @@ srcs := common/mm/nvgpu_allocator.c \ common/as.c \ common/rbtree.c \ common/ltc.c \ + common/io_common.c \ common/vbios/bios.c \ common/falcon/falcon.c \ common/pmu/pmu.c \ diff --git a/drivers/gpu/nvgpu/common/io_common.c b/drivers/gpu/nvgpu/common/io_common.c new file mode 100644 index 00000000..e7041eb7 --- /dev/null +++ b/drivers/gpu/nvgpu/common/io_common.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include + +#include "gk20a/gk20a.h" + +void nvgpu_writel_check(struct gk20a *g, u32 r, u32 v) +{ + u32 read_val = 0U; + + nvgpu_writel(g, r, v); + read_val = nvgpu_readl(g, r); + if (v != read_val) { + nvgpu_log(g, gpu_dbg_reg, "r=0x%x rd=0x%x wr=0x%x (mismatch)", + r, read_val, v); + } +} diff --git a/drivers/gpu/nvgpu/common/posix/io.c b/drivers/gpu/nvgpu/common/posix/io.c index dc32c20e..7bab8af6 100644 --- a/drivers/gpu/nvgpu/common/posix/io.c +++ b/drivers/gpu/nvgpu/common/posix/io.c @@ -54,7 +54,7 @@ u32 __nvgpu_readl(struct gk20a *g, u32 r) return 0; } -void nvgpu_writel_check(struct gk20a *g, u32 r, u32 v) +void nvgpu_writel_loop(struct gk20a *g, u32 r, u32 v) { BUG(); } diff --git a/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c b/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c index a8cbca13..9812c8d8 100644 --- a/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c @@ -276,7 +276,7 @@ void gm20b_flush_ltc(struct gk20a *g) u32 ltc_stride = nvgpu_get_litter_value(g, GPU_LIT_LTC_STRIDE); /* Clean... */ - gk20a_writel(g, ltc_ltcs_ltss_tstg_cmgmt1_r(), + nvgpu_writel_check(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() | @@ -318,7 +318,7 @@ void gm20b_flush_ltc(struct gk20a *g) } /* And invalidate. */ - gk20a_writel(g, ltc_ltcs_ltss_tstg_cmgmt0_r(), + nvgpu_writel_check(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() | @@ -393,15 +393,15 @@ void gm20b_ltc_set_zbc_color_entry(struct gk20a *g, u32 i; u32 real_index = index + GK20A_STARTOF_ZBC_TABLE; - gk20a_writel(g, ltc_ltcs_ltss_dstg_zbc_index_r(), + nvgpu_writel_check(g, ltc_ltcs_ltss_dstg_zbc_index_r(), ltc_ltcs_ltss_dstg_zbc_index_address_f(real_index)); for (i = 0; i < ltc_ltcs_ltss_dstg_zbc_color_clear_value__size_1_v(); i++) { - gk20a_writel(g, ltc_ltcs_ltss_dstg_zbc_color_clear_value_r(i), - color_val->color_l2[i]); + nvgpu_writel_check(g, + ltc_ltcs_ltss_dstg_zbc_color_clear_value_r(i), + color_val->color_l2[i]); } - gk20a_readl(g, ltc_ltcs_ltss_dstg_zbc_index_r()); } /* @@ -413,13 +413,12 @@ void gm20b_ltc_set_zbc_depth_entry(struct gk20a *g, { u32 real_index = index + GK20A_STARTOF_ZBC_TABLE; - gk20a_writel(g, ltc_ltcs_ltss_dstg_zbc_index_r(), + nvgpu_writel_check(g, ltc_ltcs_ltss_dstg_zbc_index_r(), ltc_ltcs_ltss_dstg_zbc_index_address_f(real_index)); - gk20a_writel(g, ltc_ltcs_ltss_dstg_zbc_depth_clear_value_r(), - depth_val->depth); - - gk20a_readl(g, ltc_ltcs_ltss_dstg_zbc_index_r()); + nvgpu_writel_check(g, + ltc_ltcs_ltss_dstg_zbc_depth_clear_value_r(), + depth_val->depth); } void gm20b_ltc_init_cbc(struct gk20a *g, struct gr_gk20a *gr) diff --git a/drivers/gpu/nvgpu/gp10b/gr_gp10b.c b/drivers/gpu/nvgpu/gp10b/gr_gp10b.c index 6249992a..424c8490 100644 --- a/drivers/gpu/nvgpu/gp10b/gr_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/gr_gp10b.c @@ -537,18 +537,18 @@ int gr_gp10b_add_zbc_color(struct gk20a *g, struct gr_gk20a *gr, gr->zbc_col_tbl[index].format = color_val->format; gr->zbc_col_tbl[index].ref_cnt++; - gk20a_writel_check(g, gr_gpcs_swdx_dss_zbc_color_r_r(index), + nvgpu_writel_loop(g, gr_gpcs_swdx_dss_zbc_color_r_r(index), color_val->color_ds[0]); - gk20a_writel_check(g, gr_gpcs_swdx_dss_zbc_color_g_r(index), + nvgpu_writel_loop(g, gr_gpcs_swdx_dss_zbc_color_g_r(index), color_val->color_ds[1]); - gk20a_writel_check(g, gr_gpcs_swdx_dss_zbc_color_b_r(index), + nvgpu_writel_loop(g, gr_gpcs_swdx_dss_zbc_color_b_r(index), color_val->color_ds[2]); - gk20a_writel_check(g, gr_gpcs_swdx_dss_zbc_color_a_r(index), + nvgpu_writel_loop(g, gr_gpcs_swdx_dss_zbc_color_a_r(index), color_val->color_ds[3]); zbc_c = gk20a_readl(g, zbc_c_format_reg + (index & ~3)); zbc_c &= ~(0x7f << ((index % 4) * 7)); zbc_c |= color_val->format << ((index % 4) * 7); - gk20a_writel_check(g, zbc_c_format_reg + (index & ~3), zbc_c); + nvgpu_writel_loop(g, zbc_c_format_reg + (index & ~3), zbc_c); return 0; } diff --git a/drivers/gpu/nvgpu/gp10b/ltc_gp10b.c b/drivers/gpu/nvgpu/gp10b/ltc_gp10b.c index b0938f75..1e5807d5 100644 --- a/drivers/gpu/nvgpu/gp10b/ltc_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/ltc_gp10b.c @@ -156,14 +156,16 @@ int gp10b_ltc_cbc_ctrl(struct gk20a *g, enum gk20a_cbc_op op, nvgpu_log_info(g, "clearing CBC lines %u..%u", min, iter_max); if (op == gk20a_cbc_op_clear) { - gk20a_writel( + nvgpu_writel_check( g, ltc_ltcs_ltss_cbc_ctrl2_r(), ltc_ltcs_ltss_cbc_ctrl2_clear_lower_bound_f( min)); - gk20a_writel( + + nvgpu_writel_check( g, ltc_ltcs_ltss_cbc_ctrl3_r(), ltc_ltcs_ltss_cbc_ctrl3_clear_upper_bound_f( iter_max)); + hw_op = ltc_ltcs_ltss_cbc_ctrl1_clear_active_f(); full_cache_op = false; } else if (op == gk20a_cbc_op_clean) { @@ -251,10 +253,9 @@ void gp10b_ltc_isr(struct gk20a *g) ltc_ltc0_lts0_dstg_ecc_report_sec_count_v(ecc_stats_reg_val); ecc_stats_reg_val &= ~(ltc_ltc0_lts0_dstg_ecc_report_sec_count_m()); - gk20a_writel(g, + nvgpu_writel_check(g, ltc_ltc0_lts0_dstg_ecc_report_r() + offset, ecc_stats_reg_val); - g->ops.mm.l2_flush(g, true); } if (ltc_intr & @@ -271,16 +272,16 @@ void gp10b_ltc_isr(struct gk20a *g) ltc_ltc0_lts0_dstg_ecc_report_ded_count_v(ecc_stats_reg_val); ecc_stats_reg_val &= ~(ltc_ltc0_lts0_dstg_ecc_report_ded_count_m()); - gk20a_writel(g, + nvgpu_writel_check(g, ltc_ltc0_lts0_dstg_ecc_report_r() + offset, ecc_stats_reg_val); } nvgpu_err(g, "ltc%d, slice %d: %08x", ltc, slice, ltc_intr); - gk20a_writel(g, ltc_ltc0_lts0_intr_r() + - ltc_stride * ltc + lts_stride * slice, - ltc_intr); + nvgpu_writel_check(g, ltc_ltc0_lts0_intr_r() + + ltc_stride * ltc + lts_stride * slice, + ltc_intr); } } } @@ -314,5 +315,5 @@ void gp10b_ltc_set_enabled(struct gk20a *g, bool enabled) /* bypass enabled (no caching) */ reg |= reg_f; - gk20a_writel(g, ltc_ltcs_ltss_tstg_set_mgmt_2_r(), reg); + nvgpu_writel_check(g, ltc_ltcs_ltss_tstg_set_mgmt_2_r(), reg); } diff --git a/drivers/gpu/nvgpu/gv11b/ltc_gv11b.c b/drivers/gpu/nvgpu/gv11b/ltc_gv11b.c index b64faaa6..48faa4d2 100644 --- a/drivers/gpu/nvgpu/gv11b/ltc_gv11b.c +++ b/drivers/gpu/nvgpu/gv11b/ltc_gv11b.c @@ -42,13 +42,12 @@ void gv11b_ltc_set_zbc_stencil_entry(struct gk20a *g, { u32 real_index = index + GK20A_STARTOF_ZBC_TABLE; - gk20a_writel(g, ltc_ltcs_ltss_dstg_zbc_index_r(), + nvgpu_writel_check(g, ltc_ltcs_ltss_dstg_zbc_index_r(), ltc_ltcs_ltss_dstg_zbc_index_address_f(real_index)); - gk20a_writel(g, ltc_ltcs_ltss_dstg_zbc_stencil_clear_value_r(), - stencil_val->depth); - - gk20a_readl(g, ltc_ltcs_ltss_dstg_zbc_index_r()); + nvgpu_writel_check(g, + ltc_ltcs_ltss_dstg_zbc_stencil_clear_value_r(), + stencil_val->depth); } void gv11b_ltc_init_fs_state(struct gk20a *g) @@ -72,13 +71,13 @@ void gv11b_ltc_init_fs_state(struct gk20a *g) reg = gk20a_readl(g, ltc_ltcs_ltss_intr_r()); reg &= ~ltc_ltcs_ltss_intr_en_evicted_cb_m(); reg &= ~ltc_ltcs_ltss_intr_en_illegal_compstat_access_m(); - gk20a_writel(g, ltc_ltcs_ltss_intr_r(), reg); + nvgpu_writel_check(g, ltc_ltcs_ltss_intr_r(), reg); /* Enable ECC interrupts */ ltc_intr = gk20a_readl(g, ltc_ltcs_ltss_intr_r()); ltc_intr |= ltc_ltcs_ltss_intr_en_ecc_sec_error_enabled_f() | ltc_ltcs_ltss_intr_en_ecc_ded_error_enabled_f(); - gk20a_writel(g, ltc_ltcs_ltss_intr_r(), + nvgpu_writel_check(g, ltc_ltcs_ltss_intr_r(), ltc_intr); } @@ -133,14 +132,16 @@ void gv11b_ltc_isr(struct gk20a *g) /* clear the interrupt */ if ((corrected_delta > 0U) || corrected_overflow) { - gk20a_writel(g, ltc_ltc0_lts0_l2_cache_ecc_corrected_err_count_r() + offset, 0); + nvgpu_writel_check(g, + ltc_ltc0_lts0_l2_cache_ecc_corrected_err_count_r() + offset, 0); } if ((uncorrected_delta > 0U) || uncorrected_overflow) { - gk20a_writel(g, + nvgpu_writel_check(g, ltc_ltc0_lts0_l2_cache_ecc_uncorrected_err_count_r() + offset, 0); } - gk20a_writel(g, ltc_ltc0_lts0_l2_cache_ecc_status_r() + offset, + nvgpu_writel_check(g, + ltc_ltc0_lts0_l2_cache_ecc_status_r() + offset, ltc_ltc0_lts0_l2_cache_ecc_status_reset_task_f()); /* update counters per slice */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/io.h b/drivers/gpu/nvgpu/include/nvgpu/io.h index 8504829c..fb7783fe 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/io.h +++ b/drivers/gpu/nvgpu/include/nvgpu/io.h @@ -40,6 +40,7 @@ void nvgpu_writel_relaxed(struct gk20a *g, u32 r, u32 v); u32 nvgpu_readl(struct gk20a *g, u32 r); u32 __nvgpu_readl(struct gk20a *g, u32 r); void nvgpu_writel_check(struct gk20a *g, u32 r, u32 v); +void nvgpu_writel_loop(struct gk20a *g, u32 r, u32 v); void nvgpu_bar1_writel(struct gk20a *g, u32 b, u32 v); u32 nvgpu_bar1_readl(struct gk20a *g, u32 b); bool nvgpu_io_exists(struct gk20a *g); diff --git a/drivers/gpu/nvgpu/os/linux/io.c b/drivers/gpu/nvgpu/os/linux/io.c index 9a0e29d7..4b902f28 100644 --- a/drivers/gpu/nvgpu/os/linux/io.c +++ b/drivers/gpu/nvgpu/os/linux/io.c @@ -69,7 +69,7 @@ u32 __nvgpu_readl(struct gk20a *g, u32 r) return v; } -void nvgpu_writel_check(struct gk20a *g, u32 r, u32 v) +void nvgpu_writel_loop(struct gk20a *g, u32 r, u32 v) { struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); -- cgit v1.2.2