gpu: nvgpu: PMU debug reorg

- Moved PMU debug related code to pmu_debug.c
  Print pmu trace buffer
  Moved PMU controller/engine status dump debug code
  Moved ELPG stats  dump code
- Removed PMU falcon controller status dump code & used
nvgpu_flcn_dump_stats() method,
- Method to print ELPG stats.
- PMU HAL to print PMU engine & ELPG debug info upon error

NVGPU JIRA-96

Change-Id: Iaa3d983f1d3b78a1b051beb6c109d3da8f8c90bc
Signed-off-by: Mahantesh Kumbar <mkumbar@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1516640
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com>
This commit is contained in:
Mahantesh Kumbar
2017-07-11 11:42:01 +05:30
committed by mobile promotions
parent b5556c7490
commit 350bb74859
6 changed files with 72 additions and 155 deletions

View File

@@ -69,6 +69,7 @@ nvgpu-y := \
common/pmu/pmu_fw.o \
common/pmu/pmu_pg.o \
common/pmu/pmu_perfmon.o \
common/pmu/pmu_debug.o \
common/ltc.o \
gk20a/gk20a.o \
gk20a/bus_gk20a.o \

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2016-2017, 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 <nvgpu/pmu.h>
#include <nvgpu/log.h>
#include <nvgpu/timers.h>
#include <nvgpu/kmem.h>
#include <nvgpu/dma.h>
#include <nvgpu/pmuif/nvgpu_gpmu_cmdif.h>
#include "gk20a/gk20a.h"
void nvgpu_pmu_dump_elpg_stats(struct nvgpu_pmu *pmu)
{
struct gk20a *g = pmu->g;
/* Print PG stats */
nvgpu_err(g, "Print PG stats");
nvgpu_flcn_print_dmem(pmu->flcn,
pmu->stat_dmem_offset[PMU_PG_ELPG_ENGINE_ID_GRAPHICS],
sizeof(struct pmu_pg_stats_v2));
gk20a_pmu_dump_elpg_stats(pmu);
}
void nvgpu_pmu_dump_falcon_stats(struct nvgpu_pmu *pmu)
{
struct gk20a *g = pmu->g;
nvgpu_flcn_dump_stats(pmu->flcn);
gk20a_pmu_dump_falcon_stats(pmu);
nvgpu_err(g, "pmu state: %d", pmu->pmu_state);
nvgpu_err(g, "elpg state: %d", pmu->elpg_stat);
/* PMU may crash due to FECS crash. Dump FECS status */
gk20a_fecs_dump_falcon_stats(g);
}

View File

@@ -265,8 +265,8 @@ int nvgpu_pmu_disable_elpg(struct gk20a *g)
if (pmu->elpg_stat != PMU_ELPG_STAT_ON) {
nvgpu_err(g, "ELPG_ALLOW_ACK failed, elpg_stat=%d",
pmu->elpg_stat);
pmu_dump_elpg_stats(pmu);
pmu_dump_falcon_stats(pmu);
nvgpu_pmu_dump_elpg_stats(pmu);
nvgpu_pmu_dump_falcon_stats(pmu);
ret = -EBUSY;
goto exit_unlock;
}
@@ -315,8 +315,8 @@ int nvgpu_pmu_disable_elpg(struct gk20a *g)
ptr, PMU_ELPG_STAT_OFF);
if (*ptr != PMU_ELPG_STAT_OFF) {
nvgpu_err(g, "ELPG_DISALLOW_ACK failed");
pmu_dump_elpg_stats(pmu);
pmu_dump_falcon_stats(pmu);
nvgpu_pmu_dump_elpg_stats(pmu);
nvgpu_pmu_dump_falcon_stats(pmu);
ret = -EBUSY;
goto exit_unlock;
}

View File

@@ -39,7 +39,6 @@
#define gk20a_dbg_pmu(fmt, arg...) \
gk20a_dbg(gpu_dbg_pmu, fmt, ##arg)
bool nvgpu_find_hex_in_string(char *strings, struct gk20a *g, u32 *hex_pos)
{
u32 i = 0, j = strlen(strings);
@@ -55,11 +54,11 @@ bool nvgpu_find_hex_in_string(char *strings, struct gk20a *g, u32 *hex_pos)
return false;
}
static void printtrace(struct nvgpu_pmu *pmu)
static void print_pmu_trace(struct nvgpu_pmu *pmu)
{
struct gk20a *g = pmu->g;
u32 i = 0, j = 0, k, l, m, count;
char part_str[40], buf[0x40];
struct gk20a *g = gk20a_from_pmu(pmu);
void *tracebuffer;
char *trace;
u32 *trace1;
@@ -70,13 +69,13 @@ static void printtrace(struct nvgpu_pmu *pmu)
return;
/* read pmu traces into system memory buffer */
nvgpu_mem_rd_n(g, &pmu->trace_buf,
0, tracebuffer, GK20A_PMU_TRACE_BUFSIZE);
nvgpu_mem_rd_n(g, &pmu->trace_buf, 0, tracebuffer,
GK20A_PMU_TRACE_BUFSIZE);
trace = (char *)tracebuffer;
trace1 = (u32 *)tracebuffer;
nvgpu_err(g, "Dump pmutrace");
nvgpu_err(g, "dump PMU trace buffer");
for (i = 0; i < GK20A_PMU_TRACE_BUFSIZE; i += 0x40) {
for (j = 0; j < 0x40; j++)
if (trace1[(i / 4) + j])
@@ -100,6 +99,7 @@ static void printtrace(struct nvgpu_pmu *pmu)
scnprintf((buf + count), 0x40, "%s", (trace+i+20+m));
nvgpu_err(g, "%s", buf);
}
nvgpu_kfree(g, tracebuffer);
}
@@ -597,51 +597,9 @@ int nvgpu_pmu_handle_therm_event(struct nvgpu_pmu *pmu,
return 0;
}
void pmu_dump_elpg_stats(struct nvgpu_pmu *pmu)
void gk20a_pmu_dump_elpg_stats(struct nvgpu_pmu *pmu)
{
struct gk20a *g = gk20a_from_pmu(pmu);
struct pmu_pg_stats stats;
nvgpu_flcn_copy_from_dmem(pmu->flcn,
pmu->stat_dmem_offset[PMU_PG_ELPG_ENGINE_ID_GRAPHICS],
(u8 *)&stats, sizeof(struct pmu_pg_stats), 0);
gk20a_dbg_pmu("pg_entry_start_timestamp : 0x%016llx",
stats.pg_entry_start_timestamp);
gk20a_dbg_pmu("pg_exit_start_timestamp : 0x%016llx",
stats.pg_exit_start_timestamp);
gk20a_dbg_pmu("pg_ingating_start_timestamp : 0x%016llx",
stats.pg_ingating_start_timestamp);
gk20a_dbg_pmu("pg_ungating_start_timestamp : 0x%016llx",
stats.pg_ungating_start_timestamp);
gk20a_dbg_pmu("pg_avg_entry_time_us : 0x%08x",
stats.pg_avg_entry_time_us);
gk20a_dbg_pmu("pg_avg_exit_time_us : 0x%08x",
stats.pg_avg_exit_time_us);
gk20a_dbg_pmu("pg_ingating_cnt : 0x%08x",
stats.pg_ingating_cnt);
gk20a_dbg_pmu("pg_ingating_time_us : 0x%08x",
stats.pg_ingating_time_us);
gk20a_dbg_pmu("pg_ungating_count : 0x%08x",
stats.pg_ungating_count);
gk20a_dbg_pmu("pg_ungating_time_us 0x%08x: ",
stats.pg_ungating_time_us);
gk20a_dbg_pmu("pg_gating_cnt : 0x%08x",
stats.pg_gating_cnt);
gk20a_dbg_pmu("pg_gating_deny_cnt : 0x%08x",
stats.pg_gating_deny_cnt);
/*
Turn on PG_DEBUG in ucode and locate symbol "ElpgLog" offset
in .nm file, e.g. 0x1000066c. use 0x66c.
u32 i, val[20];
nvgpu_flcn_copy_from_dmem(pmu->flcn, 0x66c,
(u8 *)val, sizeof(val), 0);
gk20a_dbg_pmu("elpg log begin");
for (i = 0; i < 20; i++)
gk20a_dbg_pmu("0x%08x", val[i]);
gk20a_dbg_pmu("elpg log end");
*/
gk20a_dbg_pmu("pwr_pmu_idle_mask_supp_r(3): 0x%08x",
gk20a_readl(g, pwr_pmu_idle_mask_supp_r(3)));
@@ -660,40 +618,13 @@ void pmu_dump_elpg_stats(struct nvgpu_pmu *pmu)
gk20a_readl(g, pwr_pmu_idle_count_r(4)));
gk20a_dbg_pmu("pwr_pmu_idle_count_r(7): 0x%08x",
gk20a_readl(g, pwr_pmu_idle_count_r(7)));
/*
TBD: script can't generate those registers correctly
gk20a_dbg_pmu("pwr_pmu_idle_status_r(): 0x%08x",
gk20a_readl(g, pwr_pmu_idle_status_r()));
gk20a_dbg_pmu("pwr_pmu_pg_ctrl_r(): 0x%08x",
gk20a_readl(g, pwr_pmu_pg_ctrl_r()));
*/
}
void pmu_dump_falcon_stats(struct nvgpu_pmu *pmu)
void gk20a_pmu_dump_falcon_stats(struct nvgpu_pmu *pmu)
{
struct gk20a *g = gk20a_from_pmu(pmu);
unsigned int i;
nvgpu_err(g, "pwr_falcon_os_r : %d",
gk20a_readl(g, pwr_falcon_os_r()));
nvgpu_err(g, "pwr_falcon_cpuctl_r : 0x%x",
gk20a_readl(g, pwr_falcon_cpuctl_r()));
nvgpu_err(g, "pwr_falcon_idlestate_r : 0x%x",
gk20a_readl(g, pwr_falcon_idlestate_r()));
nvgpu_err(g, "pwr_falcon_mailbox0_r : 0x%x",
gk20a_readl(g, pwr_falcon_mailbox0_r()));
nvgpu_err(g, "pwr_falcon_mailbox1_r : 0x%x",
gk20a_readl(g, pwr_falcon_mailbox1_r()));
nvgpu_err(g, "pwr_falcon_irqstat_r : 0x%x",
gk20a_readl(g, pwr_falcon_irqstat_r()));
nvgpu_err(g, "pwr_falcon_irqmode_r : 0x%x",
gk20a_readl(g, pwr_falcon_irqmode_r()));
nvgpu_err(g, "pwr_falcon_irqmask_r : 0x%x",
gk20a_readl(g, pwr_falcon_irqmask_r()));
nvgpu_err(g, "pwr_falcon_irqdest_r : 0x%x",
gk20a_readl(g, pwr_falcon_irqdest_r()));
for (i = 0; i < pwr_pmu_mailbox__size_1_v(); i++)
nvgpu_err(g, "pwr_pmu_mailbox_r(%d) : 0x%x",
i, gk20a_readl(g, pwr_pmu_mailbox_r(i)));
@@ -702,14 +633,6 @@ void pmu_dump_falcon_stats(struct nvgpu_pmu *pmu)
nvgpu_err(g, "pwr_pmu_debug_r(%d) : 0x%x",
i, gk20a_readl(g, pwr_pmu_debug_r(i)));
for (i = 0; i < 6/*NV_PPWR_FALCON_ICD_IDX_RSTAT__SIZE_1*/; i++) {
gk20a_writel(g, pwr_pmu_falcon_icd_cmd_r(),
pwr_pmu_falcon_icd_cmd_opc_rstat_f() |
pwr_pmu_falcon_icd_cmd_idx_f(i));
nvgpu_err(g, "pmu_rstat (%d) : 0x%x",
i, gk20a_readl(g, pwr_pmu_falcon_icd_rdata_r()));
}
i = gk20a_readl(g, pwr_pmu_bar0_error_status_r());
nvgpu_err(g, "pwr_pmu_bar0_error_status_r : 0x%x", i);
if (i != 0) {
@@ -736,62 +659,8 @@ void pmu_dump_falcon_stats(struct nvgpu_pmu *pmu)
gk20a_readl(g, mc_enable_r()));
}
nvgpu_err(g, "pwr_falcon_engctl_r : 0x%x",
gk20a_readl(g, pwr_falcon_engctl_r()));
nvgpu_err(g, "pwr_falcon_curctx_r : 0x%x",
gk20a_readl(g, pwr_falcon_curctx_r()));
nvgpu_err(g, "pwr_falcon_nxtctx_r : 0x%x",
gk20a_readl(g, pwr_falcon_nxtctx_r()));
gk20a_writel(g, pwr_pmu_falcon_icd_cmd_r(),
pwr_pmu_falcon_icd_cmd_opc_rreg_f() |
pwr_pmu_falcon_icd_cmd_idx_f(PMU_FALCON_REG_IMB));
nvgpu_err(g, "PMU_FALCON_REG_IMB : 0x%x",
gk20a_readl(g, pwr_pmu_falcon_icd_rdata_r()));
gk20a_writel(g, pwr_pmu_falcon_icd_cmd_r(),
pwr_pmu_falcon_icd_cmd_opc_rreg_f() |
pwr_pmu_falcon_icd_cmd_idx_f(PMU_FALCON_REG_DMB));
nvgpu_err(g, "PMU_FALCON_REG_DMB : 0x%x",
gk20a_readl(g, pwr_pmu_falcon_icd_rdata_r()));
gk20a_writel(g, pwr_pmu_falcon_icd_cmd_r(),
pwr_pmu_falcon_icd_cmd_opc_rreg_f() |
pwr_pmu_falcon_icd_cmd_idx_f(PMU_FALCON_REG_CSW));
nvgpu_err(g, "PMU_FALCON_REG_CSW : 0x%x",
gk20a_readl(g, pwr_pmu_falcon_icd_rdata_r()));
gk20a_writel(g, pwr_pmu_falcon_icd_cmd_r(),
pwr_pmu_falcon_icd_cmd_opc_rreg_f() |
pwr_pmu_falcon_icd_cmd_idx_f(PMU_FALCON_REG_CTX));
nvgpu_err(g, "PMU_FALCON_REG_CTX : 0x%x",
gk20a_readl(g, pwr_pmu_falcon_icd_rdata_r()));
gk20a_writel(g, pwr_pmu_falcon_icd_cmd_r(),
pwr_pmu_falcon_icd_cmd_opc_rreg_f() |
pwr_pmu_falcon_icd_cmd_idx_f(PMU_FALCON_REG_EXCI));
nvgpu_err(g, "PMU_FALCON_REG_EXCI : 0x%x",
gk20a_readl(g, pwr_pmu_falcon_icd_rdata_r()));
for (i = 0; i < 4; i++) {
gk20a_writel(g, pwr_pmu_falcon_icd_cmd_r(),
pwr_pmu_falcon_icd_cmd_opc_rreg_f() |
pwr_pmu_falcon_icd_cmd_idx_f(PMU_FALCON_REG_PC));
nvgpu_err(g, "PMU_FALCON_REG_PC : 0x%x",
gk20a_readl(g, pwr_pmu_falcon_icd_rdata_r()));
gk20a_writel(g, pwr_pmu_falcon_icd_cmd_r(),
pwr_pmu_falcon_icd_cmd_opc_rreg_f() |
pwr_pmu_falcon_icd_cmd_idx_f(PMU_FALCON_REG_SP));
nvgpu_err(g, "PMU_FALCON_REG_SP : 0x%x",
gk20a_readl(g, pwr_pmu_falcon_icd_rdata_r()));
}
nvgpu_err(g, "elpg stat: %d",
pmu->elpg_stat);
/* PMU may crash due to FECS crash. Dump FECS status */
gk20a_fecs_dump_falcon_stats(g);
printtrace(pmu);
/* Print PMU F/W debug prints */
print_pmu_trace(pmu);
}
bool gk20a_pmu_is_interrupted(struct nvgpu_pmu *pmu)
@@ -840,7 +709,7 @@ void gk20a_pmu_isr(struct gk20a *g)
if (intr & pwr_falcon_irqstat_halt_true_f()) {
nvgpu_err(g, "pmu halt intr not implemented");
pmu_dump_falcon_stats(pmu);
nvgpu_pmu_dump_falcon_stats(pmu);
if (gk20a_readl(g, pwr_pmu_mailbox_r
(PMU_MODE_MISMATCH_STATUS_MAILBOX_R)) ==
PMU_MODE_MISMATCH_STATUS_VAL)
@@ -850,7 +719,7 @@ void gk20a_pmu_isr(struct gk20a *g)
if (intr & pwr_falcon_irqstat_exterr_true_f()) {
nvgpu_err(g,
"pmu exterr intr not implemented. Clearing interrupt.");
pmu_dump_falcon_stats(pmu);
nvgpu_pmu_dump_falcon_stats(pmu);
gk20a_writel(g, pwr_falcon_exterrstat_r(),
gk20a_readl(g, pwr_falcon_exterrstat_r()) &

View File

@@ -57,12 +57,10 @@ int gk20a_init_pmu_setup_hw1(struct gk20a *g);
void gk20a_write_dmatrfbase(struct gk20a *g, u32 addr);
bool gk20a_is_pmu_supported(struct gk20a *g);
void pmu_copy_to_dmem(struct nvgpu_pmu *pmu,
u32 dst, u8 *src, u32 size, u8 port);
int pmu_bootstrap(struct nvgpu_pmu *pmu);
void pmu_dump_elpg_stats(struct nvgpu_pmu *pmu);
void pmu_dump_falcon_stats(struct nvgpu_pmu *pmu);
void gk20a_pmu_dump_elpg_stats(struct nvgpu_pmu *pmu);
void gk20a_pmu_dump_falcon_stats(struct nvgpu_pmu *pmu);
void pmu_enable_irq(struct nvgpu_pmu *pmu, bool enable);
int pmu_wait_message_cond(struct nvgpu_pmu *pmu, u32 timeout_ms,
@@ -74,8 +72,4 @@ void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id,
bool gk20a_pmu_is_engine_in_reset(struct gk20a *g);
int gk20a_pmu_engine_reset(struct gk20a *g, bool do_reset);
int pmu_idle(struct nvgpu_pmu *pmu);
bool nvgpu_find_hex_in_string(char *strings, struct gk20a *g, u32 *hex_pos);
#endif /*__PMU_GK20A_H__*/

View File

@@ -449,4 +449,9 @@ int nvgpu_aelpg_init_and_enable(struct gk20a *g, u8 ctrl_id);
int nvgpu_pmu_ap_send_command(struct gk20a *g,
union pmu_ap_cmd *p_ap_cmd, bool b_block);
/* PMU debug */
void nvgpu_pmu_dump_falcon_stats(struct nvgpu_pmu *pmu);
void nvgpu_pmu_dump_elpg_stats(struct nvgpu_pmu *pmu);
bool nvgpu_find_hex_in_string(char *strings, struct gk20a *g, u32 *hex_pos);
#endif /* __NVGPU_PMU_H__ */