diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile index 371e5de61..8e00fe600 100644 --- a/drivers/gpu/nvgpu/Makefile +++ b/drivers/gpu/nvgpu/Makefile @@ -204,6 +204,9 @@ nvgpu-y += \ hal/ltc/ltc_gp10b.o \ hal/ltc/ltc_gv11b.o \ hal/ltc/ltc_tu104.o \ + hal/ltc/intr/ltc_intr_gm20b.o \ + hal/ltc/intr/ltc_intr_gp10b.o \ + hal/ltc/intr/ltc_intr_gv11b.o \ hal/fb/fb_gm20b.o \ hal/fb/fb_gp10b.o \ hal/fb/fb_gp106.o \ diff --git a/drivers/gpu/nvgpu/Makefile.sources b/drivers/gpu/nvgpu/Makefile.sources index c11d2b784..0c896b664 100644 --- a/drivers/gpu/nvgpu/Makefile.sources +++ b/drivers/gpu/nvgpu/Makefile.sources @@ -356,8 +356,11 @@ srcs += common/sim.c \ hal/therm/therm_gp106.c \ hal/ltc/ltc_gm20b.c \ hal/ltc/ltc_gp10b.c \ - hal/ltc/ltc_gv11b.c \ - hal/ltc/ltc_tu104.c \ + hal/ltc/ltc_gv11b.c \ + hal/ltc/ltc_tu104.c \ + hal/ltc/intr/ltc_intr_gm20b.c \ + hal/ltc/intr/ltc_intr_gp10b.c \ + hal/ltc/intr/ltc_intr_gv11b.c \ hal/fb/fb_gm20b.c \ hal/fb/fb_gp10b.c \ hal/fb/fb_gp106.c \ diff --git a/drivers/gpu/nvgpu/common/mc/mc_gm20b.c b/drivers/gpu/nvgpu/common/mc/mc_gm20b.c index 7a4e8333f..28c0e207a 100644 --- a/drivers/gpu/nvgpu/common/mc/mc_gm20b.c +++ b/drivers/gpu/nvgpu/common/mc/mc_gm20b.c @@ -356,7 +356,7 @@ void gm20b_mc_fb_reset(struct gk20a *g) void gm20b_mc_ltc_isr(struct gk20a *g) { u32 mc_intr; - unsigned int ltc; + u32 ltc; mc_intr = gk20a_readl(g, mc_intr_ltc_r()); nvgpu_err(g, "mc_ltc_intr: %08x", mc_intr); @@ -364,6 +364,6 @@ void gm20b_mc_ltc_isr(struct gk20a *g) if ((mc_intr & BIT32(ltc)) == 0U) { continue; } - g->ops.ltc.isr(g, ltc); + g->ops.ltc.intr.isr(g, ltc); } } diff --git a/drivers/gpu/nvgpu/common/mc/mc_gp10b.c b/drivers/gpu/nvgpu/common/mc/mc_gp10b.c index 013015d09..2bfbf8236 100644 --- a/drivers/gpu/nvgpu/common/mc/mc_gp10b.c +++ b/drivers/gpu/nvgpu/common/mc/mc_gp10b.c @@ -230,7 +230,7 @@ void mc_gp10b_log_pending_intrs(struct gk20a *g) void mc_gp10b_ltc_isr(struct gk20a *g) { u32 mc_intr; - unsigned int ltc; + u32 ltc; mc_intr = gk20a_readl(g, mc_intr_ltc_r()); nvgpu_err(g, "mc_ltc_intr: %08x", mc_intr); @@ -238,6 +238,6 @@ void mc_gp10b_ltc_isr(struct gk20a *g) if ((mc_intr & BIT32(ltc)) == 0U) { continue; } - g->ops.ltc.isr(g, ltc); + g->ops.ltc.intr.isr(g, ltc); } } diff --git a/drivers/gpu/nvgpu/common/mc/mc_tu104.c b/drivers/gpu/nvgpu/common/mc/mc_tu104.c index 1b6897cec..90d75c19f 100644 --- a/drivers/gpu/nvgpu/common/mc/mc_tu104.c +++ b/drivers/gpu/nvgpu/common/mc/mc_tu104.c @@ -416,10 +416,10 @@ void mc_tu104_fbpa_isr(struct gk20a *g) void mc_tu104_ltc_isr(struct gk20a *g) { - unsigned int ltc; + u32 ltc; /* Go through all the LTCs explicitly */ for (ltc = 0; ltc < nvgpu_ltc_get_ltc_count(g); ltc++) { - g->ops.ltc.isr(g, ltc); + g->ops.ltc.intr.isr(g, ltc); } } diff --git a/drivers/gpu/nvgpu/common/vgpu/gp10b/vgpu_hal_gp10b.c b/drivers/gpu/nvgpu/common/vgpu/gp10b/vgpu_hal_gp10b.c index 8f1728b07..128d737f9 100644 --- a/drivers/gpu/nvgpu/common/vgpu/gp10b/vgpu_hal_gp10b.c +++ b/drivers/gpu/nvgpu/common/vgpu/gp10b/vgpu_hal_gp10b.c @@ -91,7 +91,6 @@ static const struct gpu_ops vgpu_gp10b_ops = { .set_zbc_color_entry = NULL, .set_zbc_depth_entry = NULL, .init_fs_state = vgpu_ltc_init_fs_state, - .isr = NULL, .flush = NULL, .set_enabled = NULL, .pri_is_ltc_addr = gm20b_ltc_pri_is_ltc_addr, @@ -99,6 +98,11 @@ static const struct gpu_ops vgpu_gp10b_ops = { .is_ltcn_ltss_addr = gm20b_ltc_is_ltcn_ltss_addr, .split_lts_broadcast_addr = gm20b_ltc_split_lts_broadcast_addr, .split_ltc_broadcast_addr = gm20b_ltc_split_ltc_broadcast_addr, + .intr = { + .configure = NULL, + .isr = NULL, + .en_illegal_compstat = NULL, + }, }, .cbc = { .init = NULL, diff --git a/drivers/gpu/nvgpu/common/vgpu/gv11b/vgpu_hal_gv11b.c b/drivers/gpu/nvgpu/common/vgpu/gv11b/vgpu_hal_gv11b.c index d0115ccff..df11015f4 100644 --- a/drivers/gpu/nvgpu/common/vgpu/gv11b/vgpu_hal_gv11b.c +++ b/drivers/gpu/nvgpu/common/vgpu/gv11b/vgpu_hal_gv11b.c @@ -114,7 +114,6 @@ static const struct gpu_ops vgpu_gv11b_ops = { .set_zbc_color_entry = NULL, .set_zbc_depth_entry = NULL, .init_fs_state = vgpu_ltc_init_fs_state, - .isr = NULL, .flush = NULL, .set_enabled = NULL, .pri_is_ltc_addr = gm20b_ltc_pri_is_ltc_addr, @@ -122,6 +121,11 @@ static const struct gpu_ops vgpu_gv11b_ops = { .is_ltcn_ltss_addr = gm20b_ltc_is_ltcn_ltss_addr, .split_lts_broadcast_addr = gm20b_ltc_split_lts_broadcast_addr, .split_ltc_broadcast_addr = gm20b_ltc_split_ltc_broadcast_addr, + .intr = { + .configure = NULL, + .isr = NULL, + .en_illegal_compstat = NULL, + }, }, .cbc = { .init = NULL, diff --git a/drivers/gpu/nvgpu/gm20b/hal_gm20b.c b/drivers/gpu/nvgpu/gm20b/hal_gm20b.c index 60f1cecf6..54e5c963d 100644 --- a/drivers/gpu/nvgpu/gm20b/hal_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/hal_gm20b.c @@ -46,6 +46,7 @@ #include "hal/cbc/cbc_gm20b.h" #include "hal/therm/therm_gm20b.h" #include "hal/ltc/ltc_gm20b.h" +#include "hal/ltc/intr/ltc_intr_gm20b.h" #include "hal/fb/fb_gm20b.h" #include "hal/fuse/fuse_gm20b.h" #include "hal/fifo/pbdma_gm20b.h" @@ -214,7 +215,6 @@ static const struct gpu_ops gm20b_ops = { .set_zbc_color_entry = gm20b_ltc_set_zbc_color_entry, .set_zbc_depth_entry = gm20b_ltc_set_zbc_depth_entry, .init_fs_state = gm20b_ltc_init_fs_state, - .isr = gm20b_ltc_isr, .flush = gm20b_flush_ltc, .set_enabled = gm20b_ltc_set_enabled, .pri_is_ltc_addr = gm20b_ltc_pri_is_ltc_addr, @@ -222,6 +222,11 @@ static const struct gpu_ops gm20b_ops = { .is_ltcn_ltss_addr = gm20b_ltc_is_ltcn_ltss_addr, .split_lts_broadcast_addr = gm20b_ltc_split_lts_broadcast_addr, .split_ltc_broadcast_addr = gm20b_ltc_split_ltc_broadcast_addr, + .intr = { + .configure = gm20b_ltc_intr_configure, + .isr = gm20b_ltc_intr_isr, + .en_illegal_compstat = NULL, + }, }, .cbc = { .init = gm20b_cbc_init, diff --git a/drivers/gpu/nvgpu/gp10b/hal_gp10b.c b/drivers/gpu/nvgpu/gp10b/hal_gp10b.c index 57ad51c77..f44c8487b 100644 --- a/drivers/gpu/nvgpu/gp10b/hal_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/hal_gp10b.c @@ -52,6 +52,7 @@ #include "hal/therm/therm_gp10b.h" #include "hal/ltc/ltc_gm20b.h" #include "hal/ltc/ltc_gp10b.h" +#include "hal/ltc/intr/ltc_intr_gp10b.h" #include "hal/fb/fb_gm20b.h" #include "hal/fb/fb_gp10b.h" #include "hal/fuse/fuse_gm20b.h" @@ -238,7 +239,6 @@ static const struct gpu_ops gp10b_ops = { .set_zbc_color_entry = gm20b_ltc_set_zbc_color_entry, .set_zbc_depth_entry = gm20b_ltc_set_zbc_depth_entry, .init_fs_state = gp10b_ltc_init_fs_state, - .isr = gp10b_ltc_isr, .flush = gm20b_flush_ltc, .set_enabled = gp10b_ltc_set_enabled, .pri_is_ltc_addr = gm20b_ltc_pri_is_ltc_addr, @@ -246,6 +246,11 @@ static const struct gpu_ops gp10b_ops = { .is_ltcn_ltss_addr = gm20b_ltc_is_ltcn_ltss_addr, .split_lts_broadcast_addr = gm20b_ltc_split_lts_broadcast_addr, .split_ltc_broadcast_addr = gm20b_ltc_split_ltc_broadcast_addr, + .intr = { + .configure = gp10b_ltc_intr_configure, + .isr = gp10b_ltc_intr_isr, + .en_illegal_compstat = NULL, + }, }, .cbc = { .init = gm20b_cbc_init, diff --git a/drivers/gpu/nvgpu/gv100/hal_gv100.c b/drivers/gpu/nvgpu/gv100/hal_gv100.c index b66bed012..1befd052a 100644 --- a/drivers/gpu/nvgpu/gv100/hal_gv100.c +++ b/drivers/gpu/nvgpu/gv100/hal_gv100.c @@ -37,6 +37,7 @@ #include "hal/ltc/ltc_gm20b.h" #include "hal/ltc/ltc_gp10b.h" #include "hal/ltc/ltc_gv11b.h" +#include "hal/ltc/intr/ltc_intr_gv11b.h" #include "hal/fb/fb_gm20b.h" #include "hal/fb/fb_gp10b.h" #include "hal/fb/fb_gp106.h" @@ -349,15 +350,19 @@ static const struct gpu_ops gv100_ops = { .set_zbc_color_entry = gm20b_ltc_set_zbc_color_entry, .set_zbc_depth_entry = gm20b_ltc_set_zbc_depth_entry, .init_fs_state = gv11b_ltc_init_fs_state, - .isr = gv11b_ltc_isr, .flush = gm20b_flush_ltc, .set_enabled = gp10b_ltc_set_enabled, - .intr_en_illegal_compstat = gv11b_ltc_intr_en_illegal_compstat, .pri_is_ltc_addr = gm20b_ltc_pri_is_ltc_addr, .is_ltcs_ltss_addr = gm20b_ltc_is_ltcs_ltss_addr, .is_ltcn_ltss_addr = gm20b_ltc_is_ltcn_ltss_addr, .split_lts_broadcast_addr = gm20b_ltc_split_lts_broadcast_addr, .split_ltc_broadcast_addr = gm20b_ltc_split_ltc_broadcast_addr, + .intr = { + .configure = gv11b_ltc_intr_configure, + .isr = gv11b_ltc_intr_isr, + .en_illegal_compstat = + gv11b_ltc_intr_en_illegal_compstat, + } }, .cbc = { .init = NULL, diff --git a/drivers/gpu/nvgpu/gv11b/hal_gv11b.c b/drivers/gpu/nvgpu/gv11b/hal_gv11b.c index 0094c22a8..361645dd4 100644 --- a/drivers/gpu/nvgpu/gv11b/hal_gv11b.c +++ b/drivers/gpu/nvgpu/gv11b/hal_gv11b.c @@ -41,6 +41,7 @@ #include "hal/ltc/ltc_gm20b.h" #include "hal/ltc/ltc_gp10b.h" #include "hal/ltc/ltc_gv11b.h" +#include "hal/ltc/intr/ltc_intr_gv11b.h" #include "hal/fb/fb_gm20b.h" #include "hal/fb/fb_gp10b.h" #include "hal/fb/fb_gv11b.h" @@ -300,15 +301,19 @@ static const struct gpu_ops gv11b_ops = { .set_zbc_color_entry = gm20b_ltc_set_zbc_color_entry, .set_zbc_depth_entry = gm20b_ltc_set_zbc_depth_entry, .init_fs_state = gv11b_ltc_init_fs_state, - .isr = gv11b_ltc_isr, .flush = gm20b_flush_ltc, .set_enabled = gp10b_ltc_set_enabled, - .intr_en_illegal_compstat = gv11b_ltc_intr_en_illegal_compstat, .pri_is_ltc_addr = gm20b_ltc_pri_is_ltc_addr, .is_ltcs_ltss_addr = gm20b_ltc_is_ltcs_ltss_addr, .is_ltcn_ltss_addr = gm20b_ltc_is_ltcn_ltss_addr, .split_lts_broadcast_addr = gm20b_ltc_split_lts_broadcast_addr, .split_ltc_broadcast_addr = gm20b_ltc_split_ltc_broadcast_addr, + .intr = { + .configure = gv11b_ltc_intr_configure, + .isr = gv11b_ltc_intr_isr, + .en_illegal_compstat = + gv11b_ltc_intr_en_illegal_compstat, + } }, .cbc = { .init = gv11b_cbc_init, diff --git a/drivers/gpu/nvgpu/hal/ltc/intr/ltc_intr_gm20b.c b/drivers/gpu/nvgpu/hal/ltc/intr/ltc_intr_gm20b.c new file mode 100644 index 000000000..4624389b4 --- /dev/null +++ b/drivers/gpu/nvgpu/hal/ltc/intr/ltc_intr_gm20b.c @@ -0,0 +1,67 @@ +/* + * GM20B L2 INTR + * + * Copyright (c) 2014-2019 NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +#include "ltc_intr_gm20b.h" + +#include + + +void gm20b_ltc_intr_configure(struct gk20a *g) +{ + u32 reg; + + /* Disable interrupts to reduce noise and increase perf */ + reg = nvgpu_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(); + reg &= ~ltc_ltcs_ltss_intr_en_illegal_compstat_m(); + nvgpu_writel(g, ltc_ltcs_ltss_intr_r(), reg); +} + +static void gm20b_ltc_intr_handle_lts_interrupts(struct gk20a *g, + u32 ltc, u32 slice) +{ + 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); + + ltc_intr = nvgpu_readl(g, ltc_ltc0_lts0_intr_r() + + ltc_stride * ltc + lts_stride * slice); + nvgpu_err(g, "ltc%d, slice %d: %08x", ltc, slice, ltc_intr); + nvgpu_writel(g, ltc_ltc0_lts0_intr_r() + ltc_stride * ltc + + lts_stride * slice, ltc_intr); +} + +void gm20b_ltc_intr_isr(struct gk20a *g, u32 ltc) +{ + u32 slice; + + for (slice = 0U; slice < g->ltc->slices_per_ltc; slice++) { + gm20b_ltc_intr_handle_lts_interrupts(g, ltc, slice); + } +} diff --git a/drivers/gpu/nvgpu/hal/ltc/intr/ltc_intr_gm20b.h b/drivers/gpu/nvgpu/hal/ltc/intr/ltc_intr_gm20b.h new file mode 100644 index 000000000..50d6d2f55 --- /dev/null +++ b/drivers/gpu/nvgpu/hal/ltc/intr/ltc_intr_gm20b.h @@ -0,0 +1,35 @@ +/* + * GM20B L2 INTR + * + * Copyright (c) 2014-2019, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef NVGPU_LTC_INTR_GM20B +#define NVGPU_LTC_INTR_GM20B + +#include + +struct gk20a; + +void gm20b_ltc_intr_configure(struct gk20a *g); +void gm20b_ltc_intr_isr(struct gk20a *g, u32 ltc); + +#endif diff --git a/drivers/gpu/nvgpu/hal/ltc/intr/ltc_intr_gp10b.c b/drivers/gpu/nvgpu/hal/ltc/intr/ltc_intr_gp10b.c new file mode 100644 index 000000000..58575848e --- /dev/null +++ b/drivers/gpu/nvgpu/hal/ltc/intr/ltc_intr_gp10b.c @@ -0,0 +1,113 @@ +/* + * GP10B L2 INTR + * + * Copyright (c) 2014-2019, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include + +#include "ltc_intr_gp10b.h" +#include "ltc_intr_gm20b.h" + +void gp10b_ltc_intr_handle_lts_interrupts(struct gk20a *g, u32 ltc, u32 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 = nvgpu_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()) != 0U) { + u32 ecc_stats_reg_val; + + nvgpu_err(g, + "Single bit error detected in GPU L2!"); + + ecc_stats_reg_val = + nvgpu_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); + if (g->ops.mm.l2_flush(g, true) != 0) { + nvgpu_err(g, "l2_flush failed"); + } + } + if ((ltc_intr & + ltc_ltcs_ltss_intr_ecc_ded_error_pending_f()) != 0U) { + u32 ecc_stats_reg_val; + + nvgpu_err(g, + "Double bit error detected in GPU L2!"); + + ecc_stats_reg_val = + nvgpu_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_intr_isr(struct gk20a *g, u32 ltc) +{ + u32 slice; + + for (slice = 0U; slice < g->ltc->slices_per_ltc; slice++) { + gp10b_ltc_intr_handle_lts_interrupts(g, ltc, slice); + } +} + +void gp10b_ltc_intr_configure(struct gk20a *g) +{ + u32 ltc_intr; + + gm20b_ltc_intr_configure(g); + + /* Enable ECC interrupts */ + ltc_intr = nvgpu_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(); + nvgpu_writel(g, ltc_ltcs_ltss_intr_r(), ltc_intr); +} diff --git a/drivers/gpu/nvgpu/hal/ltc/intr/ltc_intr_gp10b.h b/drivers/gpu/nvgpu/hal/ltc/intr/ltc_intr_gp10b.h new file mode 100644 index 000000000..e2a9abc92 --- /dev/null +++ b/drivers/gpu/nvgpu/hal/ltc/intr/ltc_intr_gp10b.h @@ -0,0 +1,36 @@ +/* + * GP10B L2 INTR + * + * Copyright (c) 2014-2019, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef NVGPU_LTC_INTR_GP10B +#define NVGPU_LTC_INTR_GP10B + +#include + +struct gk20a; + +void gp10b_ltc_intr_configure(struct gk20a *g); +void gp10b_ltc_intr_isr(struct gk20a *g, u32 ltc); +void gp10b_ltc_intr_handle_lts_interrupts(struct gk20a *g, u32 ltc, u32 slice); + +#endif diff --git a/drivers/gpu/nvgpu/hal/ltc/intr/ltc_intr_gv11b.c b/drivers/gpu/nvgpu/hal/ltc/intr/ltc_intr_gv11b.c new file mode 100644 index 000000000..766d25725 --- /dev/null +++ b/drivers/gpu/nvgpu/hal/ltc/intr/ltc_intr_gv11b.c @@ -0,0 +1,230 @@ +/* + * GV11B LTC INTR + * + * Copyright (c) 2016-2019, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +#include "ltc_intr_gp10b.h" +#include "ltc_intr_gv11b.h" + +#include + +#include + +void gv11b_ltc_intr_configure(struct gk20a *g) +{ + u32 reg; + + /* Disable ltc interrupts to reduce nosie and increase perf */ + reg = nvgpu_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(); + nvgpu_writel_check(g, ltc_ltcs_ltss_intr_r(), reg); + + /* illegal_compstat interrupts can be also controlled through + * debug_fs, so enable/disable based on g->ltc_intr_en_illegal_compstat + * settings + */ + if (g->ops.ltc.intr.en_illegal_compstat != NULL) { + g->ops.ltc.intr.en_illegal_compstat(g, + g->ltc_intr_en_illegal_compstat); + } + + /* Enable ECC interrupts */ + reg = nvgpu_readl(g, ltc_ltcs_ltss_intr_r()); + reg |= ltc_ltcs_ltss_intr_en_ecc_sec_error_enabled_f() | + ltc_ltcs_ltss_intr_en_ecc_ded_error_enabled_f(); + nvgpu_writel_check(g, ltc_ltcs_ltss_intr_r(), reg); +} + +void gv11b_ltc_intr_en_illegal_compstat(struct gk20a *g, bool enable) +{ + u32 val; + + /* disable/enable illegal_compstat interrupt */ + val = nvgpu_readl(g, ltc_ltcs_ltss_intr_r()); + if (enable) { + val = set_field(val, + ltc_ltcs_ltss_intr_en_illegal_compstat_m(), + ltc_ltcs_ltss_intr_en_illegal_compstat_enabled_f()); + } else { + val = set_field(val, + ltc_ltcs_ltss_intr_en_illegal_compstat_m(), + ltc_ltcs_ltss_intr_en_illegal_compstat_disabled_f()); + } + nvgpu_writel(g, ltc_ltcs_ltss_intr_r(), val); +} + +static void gv11b_ltc_intr_handle_lts_interrupts(struct gk20a *g, + u32 ltc,u32 slice) +{ + u32 offset; + u32 ltc_intr3; + u32 ecc_status, ecc_addr, dstg_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 = nvgpu_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())) != 0U) { + + ecc_status = nvgpu_readl(g, + ltc_ltc0_lts0_l2_cache_ecc_status_r() + offset); + ecc_addr = nvgpu_readl(g, + ltc_ltc0_lts0_l2_cache_ecc_address_r() + offset); + dstg_ecc_addr = nvgpu_readl(g, + ltc_ltc0_lts0_dstg_ecc_address_r() + offset); + corrected_cnt = nvgpu_readl(g, + ltc_ltc0_lts0_l2_cache_ecc_corrected_err_count_r() + + offset); + uncorrected_cnt = nvgpu_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 != 0U)) { + nvgpu_writel_check(g, + ltc_ltc0_lts0_l2_cache_ecc_corrected_err_count_r() + offset, 0); + } + if ((uncorrected_delta > 0U) || (uncorrected_overflow != 0U)) { + 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 != 0U) { + corrected_delta += BIT32( + ltc_ltc0_lts0_l2_cache_ecc_corrected_err_count_total_s()); + } + if (uncorrected_overflow != 0U) { + uncorrected_delta += BIT32( + 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()) != 0U) { + nvgpu_ltc_report_ecc_error(g, ltc, slice, + GPU_LTC_CACHE_RSTG_ECC_CORRECTED, ecc_addr, + g->ecc.ltc.ecc_sec_count[ltc][slice].counter); + nvgpu_log(g, gpu_dbg_intr, "rstg ecc error corrected"); + } + if ((ecc_status & + ltc_ltc0_lts0_l2_cache_ecc_status_uncorrected_err_rstg_m()) != 0U) { + nvgpu_ltc_report_ecc_error(g, ltc, slice, + GPU_LTC_CACHE_RSTG_ECC_UNCORRECTED, ecc_addr, + g->ecc.ltc.ecc_ded_count[ltc][slice].counter); + nvgpu_log(g, gpu_dbg_intr, "rstg ecc error uncorrected"); + } + if ((ecc_status & + ltc_ltc0_lts0_l2_cache_ecc_status_corrected_err_tstg_m()) != 0U) { + nvgpu_ltc_report_ecc_error(g, ltc, slice, + GPU_LTC_CACHE_TSTG_ECC_CORRECTED, ecc_addr, + g->ecc.ltc.ecc_sec_count[ltc][slice].counter); + nvgpu_log(g, gpu_dbg_intr, "tstg ecc error corrected"); + } + if ((ecc_status & + ltc_ltc0_lts0_l2_cache_ecc_status_uncorrected_err_tstg_m()) != 0U) { + nvgpu_ltc_report_ecc_error(g, ltc, slice, + GPU_LTC_CACHE_TSTG_ECC_UNCORRECTED, ecc_addr, + g->ecc.ltc.ecc_ded_count[ltc][slice].counter); + nvgpu_log(g, gpu_dbg_intr, + "tstg ecc error uncorrected"); + } + if ((ecc_status & + ltc_ltc0_lts0_l2_cache_ecc_status_corrected_err_dstg_m()) != 0U) { + if ((dstg_ecc_addr & + ltc_ltc0_lts0_dstg_ecc_address_info_ram_m()) == 0U) { + nvgpu_ltc_report_ecc_error(g, ltc, slice, + GPU_LTC_CACHE_DSTG_ECC_CORRECTED, ecc_addr, + g->ecc.ltc.ecc_sec_count[ltc][slice].counter); + } else { + nvgpu_ltc_report_ecc_error(g, ltc, slice, + GPU_LTC_CACHE_DSTG_BE_ECC_CORRECTED, ecc_addr, + g->ecc.ltc.ecc_sec_count[ltc][slice].counter); + } + nvgpu_log(g, gpu_dbg_intr, "dstg ecc error corrected"); + } + if ((ecc_status & ltc_ltc0_lts0_l2_cache_ecc_status_uncorrected_err_dstg_m()) != 0U) { + if ((dstg_ecc_addr & ltc_ltc0_lts0_dstg_ecc_address_info_ram_m()) == 0U) { + nvgpu_ltc_report_ecc_error(g, ltc, slice, + GPU_LTC_CACHE_DSTG_ECC_UNCORRECTED, ecc_addr, + g->ecc.ltc.ecc_ded_count[ltc][slice].counter); + } else { + nvgpu_ltc_report_ecc_error(g, ltc, slice, + GPU_LTC_CACHE_DSTG_BE_ECC_UNCORRECTED, ecc_addr, + g->ecc.ltc.ecc_ded_count[ltc][slice].counter); + } + nvgpu_log(g, gpu_dbg_intr, + "dstg ecc error uncorrected"); + } + + if ((corrected_overflow != 0U) || + (uncorrected_overflow != 0U)) { + nvgpu_info(g, "ecc counter overflow!"); + } + + nvgpu_log(g, gpu_dbg_intr, "ecc error address: 0x%x", ecc_addr); + } + + gp10b_ltc_intr_handle_lts_interrupts(g, ltc, slice); +} + +void gv11b_ltc_intr_isr(struct gk20a *g, u32 ltc) +{ + u32 slice; + + for (slice = 0U; slice < g->ltc->slices_per_ltc; slice++) { + gv11b_ltc_intr_handle_lts_interrupts(g, ltc, slice); + } +} diff --git a/drivers/gpu/nvgpu/hal/ltc/intr/ltc_intr_gv11b.h b/drivers/gpu/nvgpu/hal/ltc/intr/ltc_intr_gv11b.h new file mode 100644 index 000000000..6c274d538 --- /dev/null +++ b/drivers/gpu/nvgpu/hal/ltc/intr/ltc_intr_gv11b.h @@ -0,0 +1,36 @@ +/* + * GV11B L2 INTR + * + * Copyright (c) 2016-2019, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef NVGPU_LTC_INTR_GV11B +#define NVGPU_LTC_INTR_GV11B + +#include + +struct gk20a; + +void gv11b_ltc_intr_configure(struct gk20a *g); +void gv11b_ltc_intr_isr(struct gk20a *g, u32 ltc); +void gv11b_ltc_intr_en_illegal_compstat(struct gk20a *g, bool enable); + +#endif diff --git a/drivers/gpu/nvgpu/hal/ltc/ltc_gm20b.c b/drivers/gpu/nvgpu/hal/ltc/ltc_gm20b.c index bbca8b762..45fee58b6 100644 --- a/drivers/gpu/nvgpu/hal/ltc/ltc_gm20b.c +++ b/drivers/gpu/nvgpu/hal/ltc/ltc_gm20b.c @@ -63,38 +63,7 @@ void gm20b_ltc_init_fs_state(struct gk20a *g) gk20a_readl(g, ltc_ltc0_lts0_dstg_cfg0_r()) | ltc_ltcs_ltss_dstg_cfg0_vdc_4to2_disable_m()); - /* Disable LTC interrupts */ - 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(); - reg &= ~ltc_ltcs_ltss_intr_en_illegal_compstat_m(); - gk20a_writel(g, ltc_ltcs_ltss_intr_r(), reg); -} - -void gm20b_ltc_lts_isr(struct gk20a *g, unsigned int ltc, unsigned int slice) -{ - 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); - - ltc_intr = gk20a_readl(g, ltc_ltc0_lts0_intr_r() + - ltc_stride * ltc + - lts_stride * slice); - 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); -} - -void gm20b_ltc_isr(struct gk20a *g, unsigned int ltc) -{ - unsigned int slice; - - for (slice = 0U; slice < g->ltc->slices_per_ltc; slice++) { - gm20b_ltc_lts_isr(g, ltc, slice); - } + g->ops.ltc.intr.configure(g); } /* @@ -103,7 +72,7 @@ void gm20b_ltc_isr(struct gk20a *g, unsigned int ltc) void gm20b_flush_ltc(struct gk20a *g) { struct nvgpu_timeout timeout; - unsigned int ltc; + u32 ltc; u32 ltc_stride = nvgpu_get_litter_value(g, GPU_LIT_LTC_STRIDE); bool is_clean_pending_set = false; bool is_invalidate_pending_set = false; @@ -203,8 +172,8 @@ int gm20b_determine_L2_size_bytes(struct gk20a *g) ltc_ltc0_lts0_tstg_cfg1_active_sets_quarter_v()) { sets = 16U; } else { - nvgpu_err(g, "Unknown constant %u for active sets", - (unsigned)active_sets_value); + nvgpu_err(g, "Unknown constant %d for active sets", + active_sets_value); sets = 0U; } diff --git a/drivers/gpu/nvgpu/hal/ltc/ltc_gm20b.h b/drivers/gpu/nvgpu/hal/ltc/ltc_gm20b.h index cff668899..74ae6f2e7 100644 --- a/drivers/gpu/nvgpu/hal/ltc/ltc_gm20b.h +++ b/drivers/gpu/nvgpu/hal/ltc/ltc_gm20b.h @@ -39,8 +39,6 @@ void gm20b_ltc_set_zbc_depth_entry(struct gk20a *g, u32 index); void gm20b_ltc_set_enabled(struct gk20a *g, bool enabled); void gm20b_ltc_init_fs_state(struct gk20a *g); -void gm20b_ltc_isr(struct gk20a *g, unsigned int ltc); -void gm20b_ltc_lts_isr(struct gk20a *g, unsigned int ltc, unsigned int slice); void gm20b_flush_ltc(struct gk20a *g); bool gm20b_ltc_pri_is_ltc_addr(struct gk20a *g, u32 addr); bool gm20b_ltc_is_ltcs_ltss_addr(struct gk20a *g, u32 addr); diff --git a/drivers/gpu/nvgpu/hal/ltc/ltc_gp10b.c b/drivers/gpu/nvgpu/hal/ltc/ltc_gp10b.c index 3566a013e..d69947850 100644 --- a/drivers/gpu/nvgpu/hal/ltc/ltc_gp10b.c +++ b/drivers/gpu/nvgpu/hal/ltc/ltc_gp10b.c @@ -22,13 +22,9 @@ * DEALINGS IN THE SOFTWARE. */ -#include - #include #include -#include #include -#include #include #include @@ -56,88 +52,13 @@ int gp10b_determine_L2_size_bytes(struct gk20a *g) return ret; } -void gp10b_ltc_lts_isr(struct gk20a *g, unsigned int ltc, unsigned int 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()) != 0U) { - 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); - if (g->ops.mm.l2_flush(g, true) != 0) { - nvgpu_err(g, "l2_flush failed"); - } - } - if ((ltc_intr & - ltc_ltcs_ltss_intr_ecc_ded_error_pending_f()) != 0U) { - 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, unsigned int ltc) -{ - unsigned int slice; - - for (slice = 0U; slice < g->ltc->slices_per_ltc; slice++) { - gp10b_ltc_lts_isr(g, ltc, slice); - } -} - void gp10b_ltc_init_fs_state(struct gk20a *g) { - u32 ltc_intr; - gm20b_ltc_init_fs_state(g); gk20a_writel(g, ltc_ltca_g_axi_pctrl_r(), ltc_ltca_g_axi_pctrl_user_sid_f(g->ltc_streamid)); - /* 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(), - ltc_intr); } void gp10b_ltc_set_enabled(struct gk20a *g, bool enabled) diff --git a/drivers/gpu/nvgpu/hal/ltc/ltc_gp10b.h b/drivers/gpu/nvgpu/hal/ltc/ltc_gp10b.h index 387208842..5d7bfb0fe 100644 --- a/drivers/gpu/nvgpu/hal/ltc/ltc_gp10b.h +++ b/drivers/gpu/nvgpu/hal/ltc/ltc_gp10b.h @@ -23,11 +23,8 @@ #ifndef LTC_GP10B_H #define LTC_GP10B_H struct gk20a; -struct gpu_ops; int gp10b_determine_L2_size_bytes(struct gk20a *g); void gp10b_ltc_init_fs_state(struct gk20a *g); void gp10b_ltc_set_enabled(struct gk20a *g, bool enabled); -void gp10b_ltc_isr(struct gk20a *g, unsigned int ltc); -void gp10b_ltc_lts_isr(struct gk20a *g, unsigned int ltc, unsigned int slice); #endif diff --git a/drivers/gpu/nvgpu/hal/ltc/ltc_gv11b.c b/drivers/gpu/nvgpu/hal/ltc/ltc_gv11b.c index 6774fb00e..9cd9be78f 100644 --- a/drivers/gpu/nvgpu/hal/ltc/ltc_gv11b.c +++ b/drivers/gpu/nvgpu/hal/ltc/ltc_gv11b.c @@ -26,13 +26,10 @@ #include #include -#include "ltc_gp10b.h" #include "ltc_gv11b.h" #include -#include #include -#include #include @@ -53,7 +50,6 @@ void gv11b_ltc_set_zbc_stencil_entry(struct gk20a *g, void gv11b_ltc_init_fs_state(struct gk20a *g) { - u32 ltc_intr; u32 reg; nvgpu_log_info(g, "initialize gv11b l2"); @@ -68,179 +64,6 @@ void gv11b_ltc_init_fs_state(struct gk20a *g) g->ltc->cacheline_size = U32(512) << ltc_ltcs_ltss_cbc_param_cache_line_size_v(reg); - /* Disable LTC interrupts */ - 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(); - nvgpu_writel_check(g, ltc_ltcs_ltss_intr_r(), reg); + g->ops.ltc.intr.configure(g); - if (g->ops.ltc.intr_en_illegal_compstat != NULL) { - g->ops.ltc.intr_en_illegal_compstat(g, - g->ltc_intr_en_illegal_compstat); - } - - /* 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(); - nvgpu_writel_check(g, ltc_ltcs_ltss_intr_r(), - ltc_intr); -} - -void gv11b_ltc_intr_en_illegal_compstat(struct gk20a *g, bool enable) -{ - u32 val; - - /* disble/enble illegal_compstat interrupt */ - val = gk20a_readl(g, ltc_ltcs_ltss_intr_r()); - if (enable) { - val = set_field(val, - ltc_ltcs_ltss_intr_en_illegal_compstat_m(), - ltc_ltcs_ltss_intr_en_illegal_compstat_enabled_f()); - } else { - val = set_field(val, - ltc_ltcs_ltss_intr_en_illegal_compstat_m(), - ltc_ltcs_ltss_intr_en_illegal_compstat_disabled_f()); - } - gk20a_writel(g, ltc_ltcs_ltss_intr_r(), val); -} - -void gv11b_ltc_lts_isr(struct gk20a *g, unsigned int ltc, unsigned int slice) -{ - u32 offset; - u32 ltc_intr3; - u32 ecc_status, ecc_addr, dstg_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())) != 0U) { - - 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); - dstg_ecc_addr = gk20a_readl(g, - ltc_ltc0_lts0_dstg_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 != 0U)) { - nvgpu_writel_check(g, - ltc_ltc0_lts0_l2_cache_ecc_corrected_err_count_r() + offset, 0); - } - if ((uncorrected_delta > 0U) || (uncorrected_overflow != 0U)) { - 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 != 0U) { - corrected_delta += BIT32(ltc_ltc0_lts0_l2_cache_ecc_corrected_err_count_total_s()); - } - if (uncorrected_overflow != 0U) { - uncorrected_delta += BIT32(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()) != 0U) { - nvgpu_ltc_report_ecc_error(g, ltc, slice, - GPU_LTC_CACHE_RSTG_ECC_CORRECTED, ecc_addr, - g->ecc.ltc.ecc_sec_count[ltc][slice].counter); - nvgpu_log(g, gpu_dbg_intr, "rstg ecc error corrected"); - } - if ((ecc_status & ltc_ltc0_lts0_l2_cache_ecc_status_uncorrected_err_rstg_m()) != 0U) { - nvgpu_ltc_report_ecc_error(g, ltc, slice, - GPU_LTC_CACHE_RSTG_ECC_UNCORRECTED, ecc_addr, - g->ecc.ltc.ecc_ded_count[ltc][slice].counter); - nvgpu_log(g, gpu_dbg_intr, "rstg ecc error uncorrected"); - } - if ((ecc_status & ltc_ltc0_lts0_l2_cache_ecc_status_corrected_err_tstg_m()) != 0U) { - nvgpu_ltc_report_ecc_error(g, ltc, slice, - GPU_LTC_CACHE_TSTG_ECC_CORRECTED, ecc_addr, - g->ecc.ltc.ecc_sec_count[ltc][slice].counter); - nvgpu_log(g, gpu_dbg_intr, "tstg ecc error corrected"); - } - if ((ecc_status & ltc_ltc0_lts0_l2_cache_ecc_status_uncorrected_err_tstg_m()) != 0U) { - nvgpu_ltc_report_ecc_error(g, ltc, slice, - GPU_LTC_CACHE_TSTG_ECC_UNCORRECTED, ecc_addr, - g->ecc.ltc.ecc_ded_count[ltc][slice].counter); - nvgpu_log(g, gpu_dbg_intr, "tstg ecc error uncorrected"); - } - if ((ecc_status & ltc_ltc0_lts0_l2_cache_ecc_status_corrected_err_dstg_m()) != 0U) { - if ((dstg_ecc_addr & ltc_ltc0_lts0_dstg_ecc_address_info_ram_m()) == 0U) { - nvgpu_ltc_report_ecc_error(g, ltc, slice, - GPU_LTC_CACHE_DSTG_ECC_CORRECTED, ecc_addr, - g->ecc.ltc.ecc_sec_count[ltc][slice].counter); - } else { - nvgpu_ltc_report_ecc_error(g, ltc, slice, - GPU_LTC_CACHE_DSTG_BE_ECC_CORRECTED, ecc_addr, - g->ecc.ltc.ecc_sec_count[ltc][slice].counter); - } - nvgpu_log(g, gpu_dbg_intr, "dstg ecc error corrected"); - } - if ((ecc_status & ltc_ltc0_lts0_l2_cache_ecc_status_uncorrected_err_dstg_m()) != 0U) { - if ((dstg_ecc_addr & ltc_ltc0_lts0_dstg_ecc_address_info_ram_m()) == 0U) { - nvgpu_ltc_report_ecc_error(g, ltc, slice, - GPU_LTC_CACHE_DSTG_ECC_UNCORRECTED, ecc_addr, - g->ecc.ltc.ecc_ded_count[ltc][slice].counter); - } else { - nvgpu_ltc_report_ecc_error(g, ltc, slice, - GPU_LTC_CACHE_DSTG_BE_ECC_UNCORRECTED, ecc_addr, - g->ecc.ltc.ecc_ded_count[ltc][slice].counter); - } - nvgpu_log(g, gpu_dbg_intr, "dstg ecc error uncorrected"); - } - - if ((corrected_overflow != 0U) || - (uncorrected_overflow != 0U)) { - 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, unsigned int ltc) -{ - unsigned int slice; - - for (slice = 0U; slice < g->ltc->slices_per_ltc; slice++) { - gv11b_ltc_lts_isr(g, ltc, slice); - } } diff --git a/drivers/gpu/nvgpu/hal/ltc/ltc_gv11b.h b/drivers/gpu/nvgpu/hal/ltc/ltc_gv11b.h index 9ccb88d32..2486830d7 100644 --- a/drivers/gpu/nvgpu/hal/ltc/ltc_gv11b.h +++ b/drivers/gpu/nvgpu/hal/ltc/ltc_gv11b.h @@ -28,8 +28,5 @@ void gv11b_ltc_set_zbc_stencil_entry(struct gk20a *g, u32 stencil_depth, u32 index); 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, unsigned int ltc); -void gv11b_ltc_lts_isr(struct gk20a *g, unsigned int ltc, unsigned int slice); #endif diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h index 229be9381..ec7d57d5c 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h @@ -219,9 +219,7 @@ struct gpu_ops { u32 index); void (*set_enabled)(struct gk20a *g, bool enabled); void (*init_fs_state)(struct gk20a *g); - void (*isr)(struct gk20a *g, unsigned int ltc); void (*flush)(struct gk20a *g); - void (*intr_en_illegal_compstat)(struct gk20a *g, bool enable); bool (*pri_is_ltc_addr)(struct gk20a *g, u32 addr); bool (*is_ltcs_ltss_addr)(struct gk20a *g, u32 addr); bool (*is_ltcn_ltss_addr)(struct gk20a *g, u32 addr); @@ -231,6 +229,12 @@ struct gpu_ops { void (*split_ltc_broadcast_addr)(struct gk20a *g, u32 addr, u32 *priv_addr_table, u32 *priv_addr_table_index); + struct { + void (*configure)(struct gk20a *g); + void (*isr)(struct gk20a *g, u32 ltc); + void (*en_illegal_compstat)(struct gk20a *g, + bool enable); + } intr; struct { int (*report_ecc_parity_err)(struct gk20a *g, u32 hw_id, u32 inst, u32 err_id, diff --git a/drivers/gpu/nvgpu/os/linux/debug_ltc.c b/drivers/gpu/nvgpu/os/linux/debug_ltc.c index 1b4c221ca..0608adbda 100644 --- a/drivers/gpu/nvgpu/os/linux/debug_ltc.c +++ b/drivers/gpu/nvgpu/os/linux/debug_ltc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 NVIDIA Corporation. All rights reserved. + * Copyright (C) 2018-2019 NVIDIA Corporation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -45,7 +45,7 @@ static ssize_t ltc_intr_illegal_compstat_write(struct file *file, struct gk20a *g = file->private_data; int err; - if (!g->ops.ltc.intr_en_illegal_compstat) + if (!g->ops.ltc.intr.en_illegal_compstat) return -EINVAL; buf_size = min(count, (sizeof(buf)-1)); @@ -57,7 +57,7 @@ static ssize_t ltc_intr_illegal_compstat_write(struct file *file, return err; if (strtobool(buf, &intr_illegal_compstat_enabled) == 0) { - g->ops.ltc.intr_en_illegal_compstat(g, + g->ops.ltc.intr.en_illegal_compstat(g, intr_illegal_compstat_enabled); g->ltc_intr_en_illegal_compstat = intr_illegal_compstat_enabled; } diff --git a/drivers/gpu/nvgpu/tu104/hal_tu104.c b/drivers/gpu/nvgpu/tu104/hal_tu104.c index e749d2d15..f080eed9e 100644 --- a/drivers/gpu/nvgpu/tu104/hal_tu104.c +++ b/drivers/gpu/nvgpu/tu104/hal_tu104.c @@ -40,6 +40,7 @@ #include "hal/ltc/ltc_gp10b.h" #include "hal/ltc/ltc_gv11b.h" #include "hal/ltc/ltc_tu104.h" +#include "hal/ltc/intr/ltc_intr_gv11b.h" #include "hal/fb/fb_gm20b.h" #include "hal/fb/fb_gp10b.h" #include "hal/fb/fb_gp106.h" @@ -367,15 +368,19 @@ static const struct gpu_ops tu104_ops = { .set_zbc_color_entry = gm20b_ltc_set_zbc_color_entry, .set_zbc_depth_entry = gm20b_ltc_set_zbc_depth_entry, .init_fs_state = ltc_tu104_init_fs_state, - .isr = gv11b_ltc_isr, .flush = gm20b_flush_ltc, .set_enabled = gp10b_ltc_set_enabled, - .intr_en_illegal_compstat = gv11b_ltc_intr_en_illegal_compstat, .pri_is_ltc_addr = gm20b_ltc_pri_is_ltc_addr, .is_ltcs_ltss_addr = gm20b_ltc_is_ltcs_ltss_addr, .is_ltcn_ltss_addr = gm20b_ltc_is_ltcn_ltss_addr, .split_lts_broadcast_addr = gm20b_ltc_split_lts_broadcast_addr, .split_ltc_broadcast_addr = gm20b_ltc_split_ltc_broadcast_addr, + .intr = { + .configure = gv11b_ltc_intr_configure, + .isr = gv11b_ltc_intr_isr, + .en_illegal_compstat = + gv11b_ltc_intr_en_illegal_compstat, + } }, .cbc = { .init = tu104_cbc_init,