summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gv11b
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gv11b')
-rw-r--r--drivers/gpu/nvgpu/gv11b/ecc_gv11b.h2
-rw-r--r--drivers/gpu/nvgpu/gv11b/hal_gv11b.c2
-rw-r--r--drivers/gpu/nvgpu/gv11b/pmu_gv11b.c117
-rw-r--r--drivers/gpu/nvgpu/gv11b/pmu_gv11b.h2
4 files changed, 123 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gv11b/ecc_gv11b.h b/drivers/gpu/nvgpu/gv11b/ecc_gv11b.h
index 94b25c02..ebce46ce 100644
--- a/drivers/gpu/nvgpu/gv11b/ecc_gv11b.h
+++ b/drivers/gpu/nvgpu/gv11b/ecc_gv11b.h
@@ -59,6 +59,8 @@ struct ecc_eng_t19x {
59 struct gk20a_ecc_stat mmu_fillunit_corrected_err_count; 59 struct gk20a_ecc_stat mmu_fillunit_corrected_err_count;
60 struct gk20a_ecc_stat mmu_fillunit_uncorrected_err_count; 60 struct gk20a_ecc_stat mmu_fillunit_uncorrected_err_count;
61 /* PMU */ 61 /* PMU */
62 struct gk20a_ecc_stat pmu_corrected_err_count;
63 struct gk20a_ecc_stat pmu_uncorrected_err_count;
62}; 64};
63 65
64#endif 66#endif
diff --git a/drivers/gpu/nvgpu/gv11b/hal_gv11b.c b/drivers/gpu/nvgpu/gv11b/hal_gv11b.c
index 6a21eb2d..f6bdf6e5 100644
--- a/drivers/gpu/nvgpu/gv11b/hal_gv11b.c
+++ b/drivers/gpu/nvgpu/gv11b/hal_gv11b.c
@@ -611,6 +611,8 @@ static const struct gpu_ops gv11b_ops = {
611 .pmu_nsbootstrap = gv11b_pmu_bootstrap, 611 .pmu_nsbootstrap = gv11b_pmu_bootstrap,
612 .pmu_pg_set_sub_feature_mask = gv11b_pg_set_subfeature_mask, 612 .pmu_pg_set_sub_feature_mask = gv11b_pg_set_subfeature_mask,
613 .is_pmu_supported = gv11b_is_pmu_supported, 613 .is_pmu_supported = gv11b_is_pmu_supported,
614 .get_irqdest = gv11b_pmu_get_irqdest,
615 .handle_ext_irq = gv11b_pmu_handle_ext_irq,
614 }, 616 },
615 .regops = { 617 .regops = {
616 .get_global_whitelist_ranges = 618 .get_global_whitelist_ranges =
diff --git a/drivers/gpu/nvgpu/gv11b/pmu_gv11b.c b/drivers/gpu/nvgpu/gv11b/pmu_gv11b.c
index 4b244f5a..a972510f 100644
--- a/drivers/gpu/nvgpu/gv11b/pmu_gv11b.c
+++ b/drivers/gpu/nvgpu/gv11b/pmu_gv11b.c
@@ -287,6 +287,123 @@ int gv11b_pmu_bootstrap(struct nvgpu_pmu *pmu)
287 return 0; 287 return 0;
288} 288}
289 289
290void gv11b_pmu_handle_ext_irq(struct gk20a *g, u32 intr0)
291{
292 u32 intr1;
293 u32 ecc_status, ecc_addr, corrected_cnt, uncorrected_cnt;
294 u32 corrected_delta, uncorrected_delta;
295 u32 corrected_overflow, uncorrected_overflow;
296
297 /*
298 * handle the ECC interrupt
299 */
300 if (intr0 & pwr_falcon_irqstat_ext_ecc_parity_true_f()) {
301 intr1 = gk20a_readl(g, pwr_pmu_ecc_intr_status_r());
302 if (intr1 & (pwr_pmu_ecc_intr_status_corrected_m() |
303 pwr_pmu_ecc_intr_status_uncorrected_m())) {
304
305 ecc_status = gk20a_readl(g,
306 pwr_pmu_falcon_ecc_status_r());
307 ecc_addr = gk20a_readl(g,
308 pwr_pmu_falcon_ecc_address_r());
309 corrected_cnt = gk20a_readl(g,
310 pwr_pmu_falcon_ecc_corrected_err_count_r());
311 uncorrected_cnt = gk20a_readl(g,
312 pwr_pmu_falcon_ecc_uncorrected_err_count_r());
313
314 corrected_delta =
315 pwr_pmu_falcon_ecc_corrected_err_count_total_v(corrected_cnt);
316 uncorrected_delta =
317 pwr_pmu_falcon_ecc_uncorrected_err_count_total_v(uncorrected_cnt);
318 corrected_overflow = ecc_status &
319 pwr_pmu_falcon_ecc_status_corrected_err_total_counter_overflow_m();
320
321 uncorrected_overflow = ecc_status &
322 pwr_pmu_falcon_ecc_status_uncorrected_err_total_counter_overflow_m();
323 corrected_overflow = ecc_status &
324 pwr_pmu_falcon_ecc_status_corrected_err_total_counter_overflow_m();
325
326 /* clear the interrupt */
327 if ((intr1 & pwr_pmu_ecc_intr_status_corrected_m()) ||
328 corrected_overflow) {
329 gk20a_writel(g, pwr_pmu_falcon_ecc_corrected_err_count_r(), 0);
330 }
331 if ((intr1 & pwr_pmu_ecc_intr_status_uncorrected_m()) ||
332 uncorrected_overflow) {
333 gk20a_writel(g,
334 pwr_pmu_falcon_ecc_uncorrected_err_count_r(), 0);
335 }
336
337 gk20a_writel(g, pwr_pmu_falcon_ecc_status_r(),
338 pwr_pmu_falcon_ecc_status_reset_task_f());
339
340 /* update counters per slice */
341 if (corrected_overflow)
342 corrected_delta += (0x1UL << pwr_pmu_falcon_ecc_corrected_err_count_total_s());
343 if (uncorrected_overflow)
344 uncorrected_delta += (0x1UL << pwr_pmu_falcon_ecc_uncorrected_err_count_total_s());
345
346 g->ecc.eng.t19x.pmu_corrected_err_count.counters[0] += corrected_delta;
347 g->ecc.eng.t19x.pmu_uncorrected_err_count.counters[0] += uncorrected_delta;
348
349 nvgpu_log(g, gpu_dbg_intr,
350 "pmu ecc interrupt intr1: 0x%x", intr1);
351
352 if (ecc_status & pwr_pmu_falcon_ecc_status_corrected_err_imem_m())
353 nvgpu_log(g, gpu_dbg_intr,
354 "imem ecc error corrected");
355 if (ecc_status & pwr_pmu_falcon_ecc_status_uncorrected_err_imem_m())
356 nvgpu_log(g, gpu_dbg_intr,
357 "imem ecc error uncorrected");
358 if (ecc_status & pwr_pmu_falcon_ecc_status_corrected_err_dmem_m())
359 nvgpu_log(g, gpu_dbg_intr,
360 "dmem ecc error corrected");
361 if (ecc_status & pwr_pmu_falcon_ecc_status_uncorrected_err_dmem_m())
362 nvgpu_log(g, gpu_dbg_intr,
363 "dmem ecc error uncorrected");
364
365 if (corrected_overflow || uncorrected_overflow)
366 nvgpu_info(g, "ecc counter overflow!");
367
368 nvgpu_log(g, gpu_dbg_intr,
369 "ecc error row address: 0x%x",
370 pwr_pmu_falcon_ecc_address_row_address_v(ecc_addr));
371
372 nvgpu_log(g, gpu_dbg_intr,
373 "ecc error count corrected: %d, uncorrected %d",
374 g->ecc.eng.t19x.pmu_corrected_err_count.counters[0],
375 g->ecc.eng.t19x.pmu_uncorrected_err_count.counters[0]);
376 }
377 }
378}
379
380u32 gv11b_pmu_get_irqdest(struct gk20a *g)
381{
382 u32 intr_dest;
383
384 /* dest 0=falcon, 1=host; level 0=irq0, 1=irq1 */
385 intr_dest = pwr_falcon_irqdest_host_gptmr_f(0) |
386 pwr_falcon_irqdest_host_wdtmr_f(1) |
387 pwr_falcon_irqdest_host_mthd_f(0) |
388 pwr_falcon_irqdest_host_ctxsw_f(0) |
389 pwr_falcon_irqdest_host_halt_f(1) |
390 pwr_falcon_irqdest_host_exterr_f(0) |
391 pwr_falcon_irqdest_host_swgen0_f(1) |
392 pwr_falcon_irqdest_host_swgen1_f(0) |
393 pwr_falcon_irqdest_host_ext_ecc_parity_f(1) |
394 pwr_falcon_irqdest_target_gptmr_f(1) |
395 pwr_falcon_irqdest_target_wdtmr_f(0) |
396 pwr_falcon_irqdest_target_mthd_f(0) |
397 pwr_falcon_irqdest_target_ctxsw_f(0) |
398 pwr_falcon_irqdest_target_halt_f(0) |
399 pwr_falcon_irqdest_target_exterr_f(0) |
400 pwr_falcon_irqdest_target_swgen0_f(0) |
401 pwr_falcon_irqdest_target_swgen1_f(0) |
402 pwr_falcon_irqdest_target_ext_ecc_parity_f(0);
403
404 return intr_dest;
405}
406
290static void pmu_handle_pg_sub_feature_msg(struct gk20a *g, struct pmu_msg *msg, 407static void pmu_handle_pg_sub_feature_msg(struct gk20a *g, struct pmu_msg *msg,
291 void *param, u32 handle, u32 status) 408 void *param, u32 handle, u32 status)
292{ 409{
diff --git a/drivers/gpu/nvgpu/gv11b/pmu_gv11b.h b/drivers/gpu/nvgpu/gv11b/pmu_gv11b.h
index e917188d..dd6db10c 100644
--- a/drivers/gpu/nvgpu/gv11b/pmu_gv11b.h
+++ b/drivers/gpu/nvgpu/gv11b/pmu_gv11b.h
@@ -35,4 +35,6 @@ bool gv11b_is_lazy_bootstrap(u32 falcon_id);
35bool gv11b_is_priv_load(u32 falcon_id); 35bool gv11b_is_priv_load(u32 falcon_id);
36int gv11b_pmu_setup_elpg(struct gk20a *g); 36int gv11b_pmu_setup_elpg(struct gk20a *g);
37 37
38u32 gv11b_pmu_get_irqdest(struct gk20a *g);
39void gv11b_pmu_handle_ext_irq(struct gk20a *g, u32 intr0);
38#endif /*__PMU_GV11B_H_*/ 40#endif /*__PMU_GV11B_H_*/