From d29300017aa1cd8ef1d2daef4383224bf00aff37 Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Wed, 12 Sep 2018 17:59:52 +0530 Subject: gpu: nvgpu: move lts intr servicing to separate functions We right now service LTS interrupts as part of LTC interrupt service routine Separate out the LTS interrupt handling in separate functions e.g. gp10b_ltc_lts_isr() for gp10b and gv11b_ltc_lts_isr() for gv11b gv11b_ltc_lts_isr() now calls gp10b_ltc_lts_isr() to service legacy LTS interrupts instead of calling gp10b_ltc_isr() directly Bug 2216662 Jira NVGPU-767 Change-Id: Ia8499feca83f67ac455cee311edf32390acb83b8 Signed-off-by: Deepak Nibade Reviewed-on: https://git-master.nvidia.com/r/1821430 Reviewed-by: svc-misra-checker GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/common/ltc/ltc_gp10b.c | 109 +++++++++-------- drivers/gpu/nvgpu/common/ltc/ltc_gp10b.h | 3 + drivers/gpu/nvgpu/common/ltc/ltc_gv11b.c | 195 ++++++++++++++++--------------- drivers/gpu/nvgpu/common/ltc/ltc_gv11b.h | 2 + 4 files changed, 163 insertions(+), 146 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/nvgpu/common/ltc/ltc_gp10b.c b/drivers/gpu/nvgpu/common/ltc/ltc_gp10b.c index 9aabf543..4d11b44b 100644 --- a/drivers/gpu/nvgpu/common/ltc/ltc_gp10b.c +++ b/drivers/gpu/nvgpu/common/ltc/ltc_gp10b.c @@ -233,13 +233,68 @@ out: return err; } -void gp10b_ltc_isr(struct gk20a *g) +void gp10b_ltc_lts_isr(struct gk20a *g, + unsigned int ltc, unsigned int slice) { - u32 mc_intr, ltc_intr; - unsigned int ltc, slice; + u32 offset; + u32 ltc_intr; u32 ltc_stride = nvgpu_get_litter_value(g, GPU_LIT_LTC_STRIDE); u32 lts_stride = nvgpu_get_litter_value(g, GPU_LIT_LTS_STRIDE); + offset = ltc_stride * ltc + lts_stride * slice; + ltc_intr = gk20a_readl(g, ltc_ltc0_lts0_intr_r() + offset); + + /* Detect and handle ECC errors */ + if (ltc_intr & + ltc_ltcs_ltss_intr_ecc_sec_error_pending_f()) { + u32 ecc_stats_reg_val; + + nvgpu_err(g, + "Single bit error detected in GPU L2!"); + + ecc_stats_reg_val = + gk20a_readl(g, + ltc_ltc0_lts0_dstg_ecc_report_r() + offset); + g->ecc.ltc.ecc_sec_count[ltc][slice].counter += + 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()); + 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 & + ltc_ltcs_ltss_intr_ecc_ded_error_pending_f()) { + u32 ecc_stats_reg_val; + + nvgpu_err(g, + "Double bit error detected in GPU L2!"); + + ecc_stats_reg_val = + gk20a_readl(g, + ltc_ltc0_lts0_dstg_ecc_report_r() + offset); + g->ecc.ltc.ecc_ded_count[ltc][slice].counter += + 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()); + 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); + nvgpu_writel_check(g, ltc_ltc0_lts0_intr_r() + + ltc_stride * ltc + lts_stride * slice, + ltc_intr); +} + +void gp10b_ltc_isr(struct gk20a *g) +{ + u32 mc_intr; + unsigned int ltc, slice; + mc_intr = gk20a_readl(g, mc_intr_ltc_r()); nvgpu_err(g, "mc_ltc_intr: %08x", mc_intr); for (ltc = 0; ltc < g->ltc_count; ltc++) { @@ -247,53 +302,7 @@ void gp10b_ltc_isr(struct gk20a *g) continue; } for (slice = 0; slice < g->gr.slices_per_ltc; slice++) { - u32 offset = ltc_stride * ltc + lts_stride * slice; - ltc_intr = gk20a_readl(g, ltc_ltc0_lts0_intr_r() + offset); - - /* Detect and handle ECC errors */ - if (ltc_intr & - ltc_ltcs_ltss_intr_ecc_sec_error_pending_f()) { - u32 ecc_stats_reg_val; - - nvgpu_err(g, - "Single bit error detected in GPU L2!"); - - ecc_stats_reg_val = - gk20a_readl(g, - ltc_ltc0_lts0_dstg_ecc_report_r() + offset); - g->ecc.ltc.ecc_sec_count[ltc][slice].counter += - 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()); - 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 & - ltc_ltcs_ltss_intr_ecc_ded_error_pending_f()) { - u32 ecc_stats_reg_val; - - nvgpu_err(g, - "Double bit error detected in GPU L2!"); - - ecc_stats_reg_val = - gk20a_readl(g, - ltc_ltc0_lts0_dstg_ecc_report_r() + offset); - g->ecc.ltc.ecc_ded_count[ltc][slice].counter += - 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()); - 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); - nvgpu_writel_check(g, ltc_ltc0_lts0_intr_r() + - ltc_stride * ltc + lts_stride * slice, - ltc_intr); + gp10b_ltc_lts_isr(g, ltc, slice); } } } diff --git a/drivers/gpu/nvgpu/common/ltc/ltc_gp10b.h b/drivers/gpu/nvgpu/common/ltc/ltc_gp10b.h index c1a2bf64..2be3f33e 100644 --- a/drivers/gpu/nvgpu/common/ltc/ltc_gp10b.h +++ b/drivers/gpu/nvgpu/common/ltc/ltc_gp10b.h @@ -22,6 +22,7 @@ #ifndef LTC_GP10B_H #define LTC_GP10B_H +struct gk20a; struct gpu_ops; void gp10b_ltc_isr(struct gk20a *g); @@ -32,4 +33,6 @@ void gp10b_ltc_init_fs_state(struct gk20a *g); int gp10b_ltc_cbc_ctrl(struct gk20a *g, enum gk20a_cbc_op op, u32 min, u32 max); void gp10b_ltc_set_enabled(struct gk20a *g, bool enabled); +void gp10b_ltc_lts_isr(struct gk20a *g, + unsigned int ltc, unsigned int slice); #endif diff --git a/drivers/gpu/nvgpu/common/ltc/ltc_gv11b.c b/drivers/gpu/nvgpu/common/ltc/ltc_gv11b.c index c5bf40c1..69c1ce02 100644 --- a/drivers/gpu/nvgpu/common/ltc/ltc_gv11b.c +++ b/drivers/gpu/nvgpu/common/ltc/ltc_gv11b.c @@ -106,16 +106,108 @@ void gv11b_ltc_intr_en_illegal_compstat(struct gk20a *g, bool enable) gk20a_writel(g, ltc_ltcs_ltss_intr_r(), val); } - -void gv11b_ltc_isr(struct gk20a *g) +void gv11b_ltc_lts_isr(struct gk20a *g, + unsigned int ltc, unsigned int slice) { - u32 mc_intr, ltc_intr3; - unsigned int ltc, slice; - u32 ltc_stride = nvgpu_get_litter_value(g, GPU_LIT_LTC_STRIDE); - u32 lts_stride = nvgpu_get_litter_value(g, GPU_LIT_LTS_STRIDE); + u32 offset; + u32 ltc_intr3; u32 ecc_status, ecc_addr, corrected_cnt, uncorrected_cnt; u32 corrected_delta, uncorrected_delta; u32 corrected_overflow, uncorrected_overflow; + u32 ltc_stride = nvgpu_get_litter_value(g, GPU_LIT_LTC_STRIDE); + u32 lts_stride = nvgpu_get_litter_value(g, GPU_LIT_LTS_STRIDE); + + offset = ltc_stride * ltc + lts_stride * slice; + ltc_intr3 = gk20a_readl(g, ltc_ltc0_lts0_intr3_r() + + offset); + + /* Detect and handle ECC PARITY errors */ + if (ltc_intr3 & + (ltc_ltcs_ltss_intr3_ecc_uncorrected_m() | + ltc_ltcs_ltss_intr3_ecc_corrected_m())) { + + ecc_status = gk20a_readl(g, + ltc_ltc0_lts0_l2_cache_ecc_status_r() + + offset); + ecc_addr = gk20a_readl(g, + ltc_ltc0_lts0_l2_cache_ecc_address_r() + + offset); + corrected_cnt = gk20a_readl(g, + ltc_ltc0_lts0_l2_cache_ecc_corrected_err_count_r() + offset); + uncorrected_cnt = gk20a_readl(g, + ltc_ltc0_lts0_l2_cache_ecc_uncorrected_err_count_r() + offset); + + corrected_delta = + ltc_ltc0_lts0_l2_cache_ecc_corrected_err_count_total_v(corrected_cnt); + uncorrected_delta = + ltc_ltc0_lts0_l2_cache_ecc_uncorrected_err_count_total_v(uncorrected_cnt); + corrected_overflow = ecc_status & + ltc_ltc0_lts0_l2_cache_ecc_status_corrected_err_total_counter_overflow_m(); + + uncorrected_overflow = ecc_status & + ltc_ltc0_lts0_l2_cache_ecc_status_uncorrected_err_total_counter_overflow_m(); + + /* clear the interrupt */ + if ((corrected_delta > 0U) || corrected_overflow) { + nvgpu_writel_check(g, + ltc_ltc0_lts0_l2_cache_ecc_corrected_err_count_r() + offset, 0); + } + if ((uncorrected_delta > 0U) || uncorrected_overflow) { + nvgpu_writel_check(g, + ltc_ltc0_lts0_l2_cache_ecc_uncorrected_err_count_r() + offset, 0); + } + + 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 */ + if (corrected_overflow) { + corrected_delta += (0x1U << ltc_ltc0_lts0_l2_cache_ecc_corrected_err_count_total_s()); + } + if (uncorrected_overflow) { + uncorrected_delta += (0x1U << ltc_ltc0_lts0_l2_cache_ecc_uncorrected_err_count_total_s()); + } + + g->ecc.ltc.ecc_sec_count[ltc][slice].counter += corrected_delta; + g->ecc.ltc.ecc_ded_count[ltc][slice].counter += uncorrected_delta; + nvgpu_log(g, gpu_dbg_intr, + "ltc:%d lts: %d cache ecc interrupt intr: 0x%x", ltc, slice, ltc_intr3); + + if (ecc_status & ltc_ltc0_lts0_l2_cache_ecc_status_corrected_err_rstg_m()) { + nvgpu_log(g, gpu_dbg_intr, "rstg ecc error corrected"); + } + if (ecc_status & ltc_ltc0_lts0_l2_cache_ecc_status_uncorrected_err_rstg_m()) { + nvgpu_log(g, gpu_dbg_intr, "rstg ecc error uncorrected"); + } + if (ecc_status & ltc_ltc0_lts0_l2_cache_ecc_status_corrected_err_tstg_m()) { + nvgpu_log(g, gpu_dbg_intr, "tstg ecc error corrected"); + } + if (ecc_status & ltc_ltc0_lts0_l2_cache_ecc_status_uncorrected_err_tstg_m()) { + nvgpu_log(g, gpu_dbg_intr, "tstg ecc error uncorrected"); + } + if (ecc_status & ltc_ltc0_lts0_l2_cache_ecc_status_corrected_err_dstg_m()) { + nvgpu_log(g, gpu_dbg_intr, "dstg ecc error corrected"); + } + if (ecc_status & ltc_ltc0_lts0_l2_cache_ecc_status_uncorrected_err_dstg_m()) { + nvgpu_log(g, gpu_dbg_intr, "dstg ecc error uncorrected"); + } + + if (corrected_overflow || uncorrected_overflow) { + nvgpu_info(g, "ecc counter overflow!"); + } + + nvgpu_log(g, gpu_dbg_intr, + "ecc error address: 0x%x", ecc_addr); + } + + gp10b_ltc_lts_isr(g, ltc, slice); +} + +void gv11b_ltc_isr(struct gk20a *g) +{ + u32 mc_intr; + unsigned int ltc, slice; mc_intr = gk20a_readl(g, mc_intr_ltc_r()); for (ltc = 0; ltc < g->ltc_count; ltc++) { @@ -124,96 +216,7 @@ void gv11b_ltc_isr(struct gk20a *g) } for (slice = 0; slice < g->gr.slices_per_ltc; slice++) { - u32 offset = ltc_stride * ltc + lts_stride * slice; - ltc_intr3 = gk20a_readl(g, ltc_ltc0_lts0_intr3_r() + - offset); - - /* Detect and handle ECC PARITY errors */ - - if (ltc_intr3 & - (ltc_ltcs_ltss_intr3_ecc_uncorrected_m() | - ltc_ltcs_ltss_intr3_ecc_corrected_m())) { - - ecc_status = gk20a_readl(g, - ltc_ltc0_lts0_l2_cache_ecc_status_r() + - offset); - ecc_addr = gk20a_readl(g, - ltc_ltc0_lts0_l2_cache_ecc_address_r() + - offset); - corrected_cnt = gk20a_readl(g, - ltc_ltc0_lts0_l2_cache_ecc_corrected_err_count_r() + offset); - uncorrected_cnt = gk20a_readl(g, - ltc_ltc0_lts0_l2_cache_ecc_uncorrected_err_count_r() + offset); - - corrected_delta = - ltc_ltc0_lts0_l2_cache_ecc_corrected_err_count_total_v(corrected_cnt); - uncorrected_delta = - ltc_ltc0_lts0_l2_cache_ecc_uncorrected_err_count_total_v(uncorrected_cnt); - corrected_overflow = ecc_status & - ltc_ltc0_lts0_l2_cache_ecc_status_corrected_err_total_counter_overflow_m(); - - uncorrected_overflow = ecc_status & - ltc_ltc0_lts0_l2_cache_ecc_status_uncorrected_err_total_counter_overflow_m(); - - /* clear the interrupt */ - if ((corrected_delta > 0U) || corrected_overflow) { - nvgpu_writel_check(g, - ltc_ltc0_lts0_l2_cache_ecc_corrected_err_count_r() + offset, 0); - } - if ((uncorrected_delta > 0U) || uncorrected_overflow) { - nvgpu_writel_check(g, - ltc_ltc0_lts0_l2_cache_ecc_uncorrected_err_count_r() + offset, 0); - } - - 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 */ - if (corrected_overflow) { - corrected_delta += (0x1U << ltc_ltc0_lts0_l2_cache_ecc_corrected_err_count_total_s()); - } - if (uncorrected_overflow) { - uncorrected_delta += (0x1U << ltc_ltc0_lts0_l2_cache_ecc_uncorrected_err_count_total_s()); - } - - g->ecc.ltc.ecc_sec_count[ltc][slice].counter += corrected_delta; - g->ecc.ltc.ecc_ded_count[ltc][slice].counter += uncorrected_delta; - nvgpu_log(g, gpu_dbg_intr, - "ltc:%d lts: %d cache ecc interrupt intr: 0x%x", ltc, slice, ltc_intr3); - - if (ecc_status & ltc_ltc0_lts0_l2_cache_ecc_status_corrected_err_rstg_m()) { - nvgpu_log(g, gpu_dbg_intr, "rstg ecc error corrected"); - } - if (ecc_status & ltc_ltc0_lts0_l2_cache_ecc_status_uncorrected_err_rstg_m()) { - nvgpu_log(g, gpu_dbg_intr, "rstg ecc error uncorrected"); - } - if (ecc_status & ltc_ltc0_lts0_l2_cache_ecc_status_corrected_err_tstg_m()) { - nvgpu_log(g, gpu_dbg_intr, "tstg ecc error corrected"); - } - if (ecc_status & ltc_ltc0_lts0_l2_cache_ecc_status_uncorrected_err_tstg_m()) { - nvgpu_log(g, gpu_dbg_intr, "tstg ecc error uncorrected"); - } - if (ecc_status & ltc_ltc0_lts0_l2_cache_ecc_status_corrected_err_dstg_m()) { - nvgpu_log(g, gpu_dbg_intr, "dstg ecc error corrected"); - } - if (ecc_status & ltc_ltc0_lts0_l2_cache_ecc_status_uncorrected_err_dstg_m()) { - nvgpu_log(g, gpu_dbg_intr, "dstg ecc error uncorrected"); - } - - if (corrected_overflow || uncorrected_overflow) { - nvgpu_info(g, "ecc counter overflow!"); - } - - nvgpu_log(g, gpu_dbg_intr, - "ecc error address: 0x%x", ecc_addr); - - } - + gv11b_ltc_lts_isr(g, ltc, slice); } - } - - /* fallback to other interrupts */ - gp10b_ltc_isr(g); } diff --git a/drivers/gpu/nvgpu/common/ltc/ltc_gv11b.h b/drivers/gpu/nvgpu/common/ltc/ltc_gv11b.h index 9d33b9fb..bad68661 100644 --- a/drivers/gpu/nvgpu/common/ltc/ltc_gv11b.h +++ b/drivers/gpu/nvgpu/common/ltc/ltc_gv11b.h @@ -30,5 +30,7 @@ void gv11b_ltc_set_zbc_stencil_entry(struct gk20a *g, void gv11b_ltc_init_fs_state(struct gk20a *g); void gv11b_ltc_intr_en_illegal_compstat(struct gk20a *g, bool enable); void gv11b_ltc_isr(struct gk20a *g); +void gv11b_ltc_lts_isr(struct gk20a *g, + unsigned int ltc, unsigned int slice); #endif -- cgit v1.2.2