diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gv11b/pmu_gv11b.c')
-rw-r--r-- | drivers/gpu/nvgpu/gv11b/pmu_gv11b.c | 117 |
1 files changed, 117 insertions, 0 deletions
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 | ||
290 | void 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 | |||
380 | u32 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 | |||
290 | static void pmu_handle_pg_sub_feature_msg(struct gk20a *g, struct pmu_msg *msg, | 407 | static 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 | { |