mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 17:36:20 +03:00
gpu:nvgpu: Enable Falcon trace prints
Dump Falcon trace on PMU Crash and add debugfs node falc_trace. This needs Debug trace to be enabled in GPmu binary. Change-Id: I093ef196202958e46d8d9636a848bd6733b5e4cc Signed-off-by: Vijayakumar <vsubbu@nvidia.com> Reviewed-on: http://git-master/r/432732 Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Tested-by: Bharat Nihalani <bnihalani@nvidia.com>
This commit is contained in:
committed by
Dan Willemsen
parent
c230159665
commit
2d666411ab
@@ -155,6 +155,12 @@ struct gpu_ops {
|
|||||||
u32 (*get_pmu_cmdline_args_size)(struct pmu_gk20a *pmu);
|
u32 (*get_pmu_cmdline_args_size)(struct pmu_gk20a *pmu);
|
||||||
void (*set_pmu_cmdline_args_cpu_freq)(struct pmu_gk20a *pmu,
|
void (*set_pmu_cmdline_args_cpu_freq)(struct pmu_gk20a *pmu,
|
||||||
u32 freq);
|
u32 freq);
|
||||||
|
void (*set_pmu_cmdline_args_trace_size)(struct pmu_gk20a *pmu,
|
||||||
|
u32 size);
|
||||||
|
void (*set_pmu_cmdline_args_trace_dma_base)(
|
||||||
|
struct pmu_gk20a *pmu);
|
||||||
|
void (*set_pmu_cmdline_args_trace_dma_idx)(
|
||||||
|
struct pmu_gk20a *pmu, u32 idx);
|
||||||
void * (*get_pmu_cmdline_args_ptr)(struct pmu_gk20a *pmu);
|
void * (*get_pmu_cmdline_args_ptr)(struct pmu_gk20a *pmu);
|
||||||
u32 (*get_pmu_allocation_struct_size)(struct pmu_gk20a *pmu);
|
u32 (*get_pmu_allocation_struct_size)(struct pmu_gk20a *pmu);
|
||||||
void (*set_pmu_allocation_ptr)(struct pmu_gk20a *pmu,
|
void (*set_pmu_allocation_ptr)(struct pmu_gk20a *pmu,
|
||||||
|
|||||||
@@ -63,6 +63,46 @@ static void set_pmu_cmdline_args_secure_mode_v1(struct pmu_gk20a *pmu, u32 val)
|
|||||||
pmu->args_v1.secure_mode = val;
|
pmu->args_v1.secure_mode = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_pmu_cmdline_args_falctracesize_v1(
|
||||||
|
struct pmu_gk20a *pmu, u32 size)
|
||||||
|
{
|
||||||
|
pmu->args_v1.falc_trace_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printtrace(struct pmu_gk20a *pmu)
|
||||||
|
{
|
||||||
|
u32 i = 0, j = 0;
|
||||||
|
char *trace = pmu->trace_buf.cpuva;
|
||||||
|
u32 *trace1 = pmu->trace_buf.cpuva;
|
||||||
|
struct gk20a *g = gk20a_from_pmu(pmu);
|
||||||
|
gk20a_err(dev_from_gk20a(g), "Dump pmutrace");
|
||||||
|
for (i = 0; i < GK20A_PMU_TRACE_BUFSIZE; i += 0x40) {
|
||||||
|
for (j = 0; j < 0x40; j++)
|
||||||
|
if (trace1[(i / 4) + j])
|
||||||
|
break;
|
||||||
|
if (j == 0x40)
|
||||||
|
return;
|
||||||
|
gk20a_err(dev_from_gk20a(g), "Index %d: ",
|
||||||
|
trace1[(i / 4)]);
|
||||||
|
gk20a_err(dev_from_gk20a(g),
|
||||||
|
"Params: 0x%x 0x%x 0x%x 0x%x Message: ",
|
||||||
|
trace1[(i / 4) + 1], trace1[(i / 4) + 2],
|
||||||
|
trace1[(i / 4) + 3], trace1[(i / 4) + 4]);
|
||||||
|
gk20a_err(dev_from_gk20a(g), "%s", (trace+i+20));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_pmu_cmdline_args_falctracedmabase_v1(struct pmu_gk20a *pmu)
|
||||||
|
{
|
||||||
|
pmu->args_v1.falc_trace_dma_base = ((u32)pmu->trace_buf.pmu_va)/0x100;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_pmu_cmdline_args_falctracedmaidx_v1(
|
||||||
|
struct pmu_gk20a *pmu, u32 idx)
|
||||||
|
{
|
||||||
|
pmu->args_v1.falc_trace_dma_idx = idx;
|
||||||
|
}
|
||||||
|
|
||||||
static void set_pmu_cmdline_args_cpufreq_v0(struct pmu_gk20a *pmu, u32 freq)
|
static void set_pmu_cmdline_args_cpufreq_v0(struct pmu_gk20a *pmu, u32 freq)
|
||||||
{
|
{
|
||||||
pmu->args_v0.cpu_freq_hz = freq;
|
pmu->args_v0.cpu_freq_hz = freq;
|
||||||
@@ -509,6 +549,12 @@ int gk20a_init_pmu(struct pmu_gk20a *pmu)
|
|||||||
set_pmu_cmdline_args_cpufreq_v1;
|
set_pmu_cmdline_args_cpufreq_v1;
|
||||||
g->ops.pmu_ver.set_pmu_cmdline_args_secure_mode =
|
g->ops.pmu_ver.set_pmu_cmdline_args_secure_mode =
|
||||||
set_pmu_cmdline_args_secure_mode_v1;
|
set_pmu_cmdline_args_secure_mode_v1;
|
||||||
|
g->ops.pmu_ver.set_pmu_cmdline_args_trace_size =
|
||||||
|
set_pmu_cmdline_args_falctracesize_v1;
|
||||||
|
g->ops.pmu_ver.set_pmu_cmdline_args_trace_dma_base =
|
||||||
|
set_pmu_cmdline_args_falctracedmabase_v1;
|
||||||
|
g->ops.pmu_ver.set_pmu_cmdline_args_trace_dma_idx =
|
||||||
|
set_pmu_cmdline_args_falctracedmaidx_v1;
|
||||||
g->ops.pmu_ver.get_pmu_cmdline_args_ptr =
|
g->ops.pmu_ver.get_pmu_cmdline_args_ptr =
|
||||||
get_pmu_cmdline_args_ptr_v1;
|
get_pmu_cmdline_args_ptr_v1;
|
||||||
g->ops.pmu_ver.get_pmu_allocation_struct_size =
|
g->ops.pmu_ver.get_pmu_allocation_struct_size =
|
||||||
@@ -951,6 +997,11 @@ static int pmu_bootstrap(struct pmu_gk20a *pmu)
|
|||||||
pwr_pmu_new_instblk_target_sys_coh_f());
|
pwr_pmu_new_instblk_target_sys_coh_f());
|
||||||
|
|
||||||
/* TBD: load all other surfaces */
|
/* TBD: load all other surfaces */
|
||||||
|
g->ops.pmu_ver.set_pmu_cmdline_args_trace_size(
|
||||||
|
pmu, GK20A_PMU_TRACE_BUFSIZE);
|
||||||
|
g->ops.pmu_ver.set_pmu_cmdline_args_trace_dma_base(pmu);
|
||||||
|
g->ops.pmu_ver.set_pmu_cmdline_args_trace_dma_idx(
|
||||||
|
pmu, GK20A_PMU_DMAIDX_VIRT);
|
||||||
|
|
||||||
g->ops.pmu_ver.set_pmu_cmdline_args_cpu_freq(pmu,
|
g->ops.pmu_ver.set_pmu_cmdline_args_cpu_freq(pmu,
|
||||||
clk_get_rate(platform->clk[1]));
|
clk_get_rate(platform->clk[1]));
|
||||||
@@ -1623,6 +1674,7 @@ int gk20a_init_pmu_setup_sw(struct gk20a *g)
|
|||||||
int i, err = 0;
|
int i, err = 0;
|
||||||
u8 *ptr;
|
u8 *ptr;
|
||||||
struct sg_table *sgt_seq_buf;
|
struct sg_table *sgt_seq_buf;
|
||||||
|
struct sg_table *sgt_pmu_buf;
|
||||||
dma_addr_t iova;
|
dma_addr_t iova;
|
||||||
|
|
||||||
gk20a_dbg_fn("");
|
gk20a_dbg_fn("");
|
||||||
@@ -1680,13 +1732,23 @@ int gk20a_init_pmu_setup_sw(struct gk20a *g)
|
|||||||
|
|
||||||
pmu->seq_buf.iova = iova;
|
pmu->seq_buf.iova = iova;
|
||||||
|
|
||||||
|
pmu->trace_buf.cpuva = dma_alloc_coherent(d, GK20A_PMU_TRACE_BUFSIZE,
|
||||||
|
&iova,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!pmu->trace_buf.cpuva) {
|
||||||
|
gk20a_err(d, "failed to allocate trace memory\n");
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto err_free_seq_buf;
|
||||||
|
}
|
||||||
|
pmu->trace_buf.iova = iova;
|
||||||
|
|
||||||
err = gk20a_get_sgtable(d, &sgt_seq_buf,
|
err = gk20a_get_sgtable(d, &sgt_seq_buf,
|
||||||
pmu->seq_buf.cpuva,
|
pmu->seq_buf.cpuva,
|
||||||
pmu->seq_buf.iova,
|
pmu->seq_buf.iova,
|
||||||
GK20A_PMU_SEQ_BUF_SIZE);
|
GK20A_PMU_SEQ_BUF_SIZE);
|
||||||
if (err) {
|
if (err) {
|
||||||
gk20a_err(d, "failed to allocate sg table\n");
|
gk20a_err(d, "failed to allocate seq buf sg table\n");
|
||||||
goto err_free_seq_buf;
|
goto err_free_trace_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
pmu->seq_buf.pmu_va = gk20a_gmmu_map(vm, &sgt_seq_buf,
|
pmu->seq_buf.pmu_va = gk20a_gmmu_map(vm, &sgt_seq_buf,
|
||||||
@@ -1694,14 +1756,34 @@ int gk20a_init_pmu_setup_sw(struct gk20a *g)
|
|||||||
0, /* flags */
|
0, /* flags */
|
||||||
gk20a_mem_flag_none);
|
gk20a_mem_flag_none);
|
||||||
if (!pmu->seq_buf.pmu_va) {
|
if (!pmu->seq_buf.pmu_va) {
|
||||||
gk20a_err(d, "failed to map pmu ucode memory!!");
|
gk20a_err(d, "failed to gmmu map seq buf memory!!");
|
||||||
|
err = -ENOMEM;
|
||||||
goto err_free_seq_buf_sgt;
|
goto err_free_seq_buf_sgt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = gk20a_get_sgtable(d, &sgt_pmu_buf,
|
||||||
|
pmu->trace_buf.cpuva,
|
||||||
|
pmu->trace_buf.iova,
|
||||||
|
GK20A_PMU_TRACE_BUFSIZE);
|
||||||
|
if (err) {
|
||||||
|
gk20a_err(d, "failed to allocate sg table for Trace\n");
|
||||||
|
goto err_unmap_seq_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
pmu->trace_buf.pmu_va = gk20a_gmmu_map(vm, &sgt_pmu_buf,
|
||||||
|
GK20A_PMU_TRACE_BUFSIZE,
|
||||||
|
0, /* flags */
|
||||||
|
gk20a_mem_flag_none);
|
||||||
|
if (!pmu->trace_buf.pmu_va) {
|
||||||
|
gk20a_err(d, "failed to gmmu map pmu trace memory!!");
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto err_free_trace_buf_sgt;
|
||||||
|
}
|
||||||
|
|
||||||
ptr = (u8 *)pmu->seq_buf.cpuva;
|
ptr = (u8 *)pmu->seq_buf.cpuva;
|
||||||
if (!ptr) {
|
if (!ptr) {
|
||||||
gk20a_err(d, "failed to map cpu ptr for zbc buffer");
|
gk20a_err(d, "failed to map cpu ptr for zbc buffer");
|
||||||
goto err_unmap_seq_buf;
|
goto err_unmap_trace_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TBD: remove this if ZBC save/restore is handled by PMU
|
/* TBD: remove this if ZBC save/restore is handled by PMU
|
||||||
@@ -1713,17 +1795,29 @@ int gk20a_init_pmu_setup_sw(struct gk20a *g)
|
|||||||
pmu->seq_buf.size = GK20A_PMU_SEQ_BUF_SIZE;
|
pmu->seq_buf.size = GK20A_PMU_SEQ_BUF_SIZE;
|
||||||
|
|
||||||
gk20a_free_sgtable(&sgt_seq_buf);
|
gk20a_free_sgtable(&sgt_seq_buf);
|
||||||
|
gk20a_free_sgtable(&sgt_pmu_buf);
|
||||||
|
|
||||||
pmu->sw_ready = true;
|
pmu->sw_ready = true;
|
||||||
|
|
||||||
skip_init:
|
skip_init:
|
||||||
gk20a_dbg_fn("done");
|
gk20a_dbg_fn("done");
|
||||||
return 0;
|
return 0;
|
||||||
|
err_unmap_trace_buf:
|
||||||
|
gk20a_gmmu_unmap(vm, pmu->trace_buf.pmu_va,
|
||||||
|
GK20A_PMU_TRACE_BUFSIZE, gk20a_mem_flag_none);
|
||||||
|
err_free_trace_buf_sgt:
|
||||||
|
gk20a_free_sgtable(&sgt_pmu_buf);
|
||||||
err_unmap_seq_buf:
|
err_unmap_seq_buf:
|
||||||
gk20a_gmmu_unmap(vm, pmu->seq_buf.pmu_va,
|
gk20a_gmmu_unmap(vm, pmu->seq_buf.pmu_va,
|
||||||
GK20A_PMU_SEQ_BUF_SIZE, gk20a_mem_flag_none);
|
GK20A_PMU_SEQ_BUF_SIZE, gk20a_mem_flag_none);
|
||||||
err_free_seq_buf_sgt:
|
err_free_seq_buf_sgt:
|
||||||
gk20a_free_sgtable(&sgt_seq_buf);
|
gk20a_free_sgtable(&sgt_seq_buf);
|
||||||
|
err_free_trace_buf:
|
||||||
|
dma_free_coherent(d, GK20A_PMU_TRACE_BUFSIZE,
|
||||||
|
pmu->trace_buf.cpuva, pmu->trace_buf.iova);
|
||||||
|
pmu->trace_buf.cpuva = NULL;
|
||||||
|
pmu->trace_buf.iova = 0;
|
||||||
|
|
||||||
err_free_seq_buf:
|
err_free_seq_buf:
|
||||||
dma_free_coherent(d, GK20A_PMU_SEQ_BUF_SIZE,
|
dma_free_coherent(d, GK20A_PMU_SEQ_BUF_SIZE,
|
||||||
pmu->seq_buf.cpuva, pmu->seq_buf.iova);
|
pmu->seq_buf.cpuva, pmu->seq_buf.iova);
|
||||||
@@ -2870,6 +2964,7 @@ void pmu_dump_falcon_stats(struct pmu_gk20a *pmu)
|
|||||||
|
|
||||||
/* PMU may crash due to FECS crash. Dump FECS status */
|
/* PMU may crash due to FECS crash. Dump FECS status */
|
||||||
gk20a_fecs_dump_falcon_stats(g);
|
gk20a_fecs_dump_falcon_stats(g);
|
||||||
|
printtrace(pmu);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gk20a_pmu_isr(struct gk20a *g)
|
void gk20a_pmu_isr(struct gk20a *g)
|
||||||
@@ -3662,6 +3757,40 @@ static const struct file_operations elpg_transitions_fops = {
|
|||||||
.release = single_release,
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int falc_trace_show(struct seq_file *s, void *data)
|
||||||
|
{
|
||||||
|
struct gk20a *g = s->private;
|
||||||
|
struct pmu_gk20a *pmu = &g->pmu;
|
||||||
|
u32 i = 0, j = 0;
|
||||||
|
char *trace = pmu->trace_buf.cpuva;
|
||||||
|
u32 *trace1 = pmu->trace_buf.cpuva;
|
||||||
|
for (i = 0; i < GK20A_PMU_TRACE_BUFSIZE; i += 0x40) {
|
||||||
|
for (j = 0; j < 0x40; j++)
|
||||||
|
if (trace1[(i / 4) + j])
|
||||||
|
break;
|
||||||
|
if (j == 0x40)
|
||||||
|
return 0;
|
||||||
|
seq_printf(s, "Index %x: ", trace1[(i / 4)]);
|
||||||
|
seq_printf(s, "Params: 0x%x 0x%x 0x%x 0x%x Message: ",
|
||||||
|
trace1[(i / 4) + 1], trace1[(i / 4) + 2],
|
||||||
|
trace1[(i / 4) + 3], trace1[(i / 4) + 4]);
|
||||||
|
seq_printf(s, "%s", (trace+i+20));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int falc_trace_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
return single_open(file, falc_trace_show, inode->i_private);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations falc_trace_fops = {
|
||||||
|
.open = falc_trace_open,
|
||||||
|
.read = seq_read,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
.release = single_release,
|
||||||
|
};
|
||||||
|
|
||||||
static int perfmon_events_enable_show(struct seq_file *s, void *data)
|
static int perfmon_events_enable_show(struct seq_file *s, void *data)
|
||||||
{
|
{
|
||||||
struct gk20a *g = s->private;
|
struct gk20a *g = s->private;
|
||||||
@@ -3759,6 +3888,12 @@ int gk20a_pmu_debugfs_init(struct platform_device *dev)
|
|||||||
if (!d)
|
if (!d)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
|
||||||
|
d = debugfs_create_file(
|
||||||
|
"falc_trace", S_IRUGO, platform->debugfs, g,
|
||||||
|
&falc_trace_fops);
|
||||||
|
if (!d)
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
d = debugfs_create_file(
|
d = debugfs_create_file(
|
||||||
"perfmon_events_enable", S_IRUGO, platform->debugfs, g,
|
"perfmon_events_enable", S_IRUGO, platform->debugfs, g,
|
||||||
&perfmon_events_enable_fops);
|
&perfmon_events_enable_fops);
|
||||||
|
|||||||
@@ -339,6 +339,7 @@ struct pmu_cmdline_args_v1 {
|
|||||||
struct pmu_mem_v1 gc6_ctx; /* dmem offset of gc6 context */
|
struct pmu_mem_v1 gc6_ctx; /* dmem offset of gc6 context */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define GK20A_PMU_TRACE_BUFSIZE 0x4000 /* 4K */
|
||||||
#define GK20A_PMU_DMEM_BLKSIZE2 8
|
#define GK20A_PMU_DMEM_BLKSIZE2 8
|
||||||
|
|
||||||
#define GK20A_PMU_UCODE_NB_MAX_OVERLAY 32
|
#define GK20A_PMU_UCODE_NB_MAX_OVERLAY 32
|
||||||
@@ -1008,6 +1009,7 @@ struct pmu_gk20a {
|
|||||||
struct pmu_mem_desc pg_buf;
|
struct pmu_mem_desc pg_buf;
|
||||||
/* TBD: remove this if ZBC seq is fixed */
|
/* TBD: remove this if ZBC seq is fixed */
|
||||||
struct pmu_mem_desc seq_buf;
|
struct pmu_mem_desc seq_buf;
|
||||||
|
struct pmu_mem_desc trace_buf;
|
||||||
bool buf_loaded;
|
bool buf_loaded;
|
||||||
|
|
||||||
struct pmu_sha1_gid gid_info;
|
struct pmu_sha1_gid gid_info;
|
||||||
|
|||||||
Reference in New Issue
Block a user