gpu: nvgpu: pg stat read update

- Added struct pmu_pg_stats_data to extract
data from multiple version of pmu pg statistics

- Added pmu_pg_stats_v2 interface to fetch
PG statistics data from PMU

- Added MSCG debugfs node to read mscg
statistics from PMU.

- Added pmu_elpg_statistics HAL support for
  gp106 PG statistics read.

- Made changes to gp104/gp106
  pmu_elpg_statistics HAL to support
  for struct pmu_pg_stats_data

JIRA DNVGPU-165

Change-Id: I2b9e89c0fae90deb45006c4478170b9a97b56603
Signed-off-by: Mahantesh Kumbar <mkumbar@nvidia.com>
Reviewed-on: http://git-master/r/1252798
(cherry picked from commit 3c073b15fd991db8d65b3171b02c161294be40cd)
Reviewed-on: http://git-master/r/1271615
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Mahantesh Kumbar
2016-11-14 19:52:50 +05:30
committed by mobile promotions
parent e239ce69b3
commit f3e0dba8bf
6 changed files with 139 additions and 85 deletions

View File

@@ -1,7 +1,7 @@
/* /*
* GK20A Graphics * GK20A Graphics
* *
* Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -605,8 +605,7 @@ struct gpu_ops {
int (*load_lsfalcon_ucode)(struct gk20a *g, u32 falconidmask); int (*load_lsfalcon_ucode)(struct gk20a *g, u32 falconidmask);
void (*write_dmatrfbase)(struct gk20a *g, u32 addr); void (*write_dmatrfbase)(struct gk20a *g, u32 addr);
void (*pmu_elpg_statistics)(struct gk20a *g, u32 pg_engine_id, void (*pmu_elpg_statistics)(struct gk20a *g, u32 pg_engine_id,
u32 *ingating_time, u32 *ungating_time, struct pmu_pg_stats_data *pg_stat_data);
u32 *gating_cnt);
int (*pmu_pg_init_param)(struct gk20a *g, u32 pg_engine_id); int (*pmu_pg_init_param)(struct gk20a *g, u32 pg_engine_id);
u32 (*pmu_pg_supported_engines_list)(struct gk20a *g); u32 (*pmu_pg_supported_engines_list)(struct gk20a *g);
u32 (*pmu_pg_engines_feature_list)(struct gk20a *g, u32 (*pmu_pg_engines_feature_list)(struct gk20a *g,

View File

@@ -1,7 +1,7 @@
/* /*
* GK20A PMU (aka. gPMU outside gk20a context) * GK20A PMU (aka. gPMU outside gk20a context)
* *
* Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -46,9 +46,9 @@
#define gk20a_dbg_pmu(fmt, arg...) \ #define gk20a_dbg_pmu(fmt, arg...) \
gk20a_dbg(gpu_dbg_pmu, fmt, ##arg) gk20a_dbg(gpu_dbg_pmu, fmt, ##arg)
static int gk20a_pmu_get_elpg_residency_gating(struct gk20a *g, static int gk20a_pmu_get_pg_stats(struct gk20a *g,
u32 pg_engine_id, u32 *ingating_time, u32 pg_engine_id,
u32 *ungating_time, u32 *gating_cnt); struct pmu_pg_stats_data *pg_stat_data);
static void ap_callback_init_and_enable_ctrl( static void ap_callback_init_and_enable_ctrl(
struct gk20a *g, struct pmu_msg *msg, struct gk20a *g, struct pmu_msg *msg,
void *param, u32 seq_desc, u32 status); void *param, u32 seq_desc, u32 status);
@@ -4979,7 +4979,7 @@ int gk20a_pmu_perfmon_enable(struct gk20a *g, bool enable)
int gk20a_pmu_destroy(struct gk20a *g) int gk20a_pmu_destroy(struct gk20a *g)
{ {
struct pmu_gk20a *pmu = &g->pmu; struct pmu_gk20a *pmu = &g->pmu;
u32 elpg_ingating_time, elpg_ungating_time, gating_cnt; struct pmu_pg_stats_data pg_stat_data = { 0 };
gk20a_dbg_fn(""); gk20a_dbg_fn("");
@@ -4989,17 +4989,16 @@ int gk20a_pmu_destroy(struct gk20a *g)
/* make sure the pending operations are finished before we continue */ /* make sure the pending operations are finished before we continue */
cancel_work_sync(&pmu->pg_init); cancel_work_sync(&pmu->pg_init);
gk20a_pmu_get_elpg_residency_gating(g, gk20a_pmu_get_pg_stats(g,
PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &elpg_ingating_time, PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &pg_stat_data);
&elpg_ungating_time, &gating_cnt);
gk20a_pmu_disable_elpg(g); gk20a_pmu_disable_elpg(g);
pmu->initialized = false; pmu->initialized = false;
/* update the s/w ELPG residency counters */ /* update the s/w ELPG residency counters */
g->pg_ingating_time_us += (u64)elpg_ingating_time; g->pg_ingating_time_us += (u64)pg_stat_data.ingating_time;
g->pg_ungating_time_us += (u64)elpg_ungating_time; g->pg_ungating_time_us += (u64)pg_stat_data.ungating_time;
g->pg_gating_cnt += gating_cnt; g->pg_gating_cnt += pg_stat_data.gating_cnt;
mutex_lock(&pmu->isr_mutex); mutex_lock(&pmu->isr_mutex);
pmu->isr_enabled = false; pmu->isr_enabled = false;
@@ -5070,7 +5069,7 @@ void gk20a_pmu_reset_load_counters(struct gk20a *g)
} }
void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id, void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id,
u32 *ingating_time, u32 *ungating_time, u32 *gating_cnt) struct pmu_pg_stats_data *pg_stat_data)
{ {
struct pmu_gk20a *pmu = &g->pmu; struct pmu_gk20a *pmu = &g->pmu;
struct pmu_pg_stats stats; struct pmu_pg_stats stats;
@@ -5079,22 +5078,24 @@ void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id,
pmu->stat_dmem_offset[pg_engine_id], pmu->stat_dmem_offset[pg_engine_id],
(u8 *)&stats, sizeof(struct pmu_pg_stats), 0); (u8 *)&stats, sizeof(struct pmu_pg_stats), 0);
*ingating_time = stats.pg_ingating_time_us; pg_stat_data->ingating_time = stats.pg_ingating_time_us;
*ungating_time = stats.pg_ungating_time_us; pg_stat_data->ungating_time = stats.pg_ungating_time_us;
*gating_cnt = stats.pg_gating_cnt; pg_stat_data->gating_cnt = stats.pg_gating_cnt;
pg_stat_data->avg_entry_latency_us = stats.pg_avg_entry_time_us;
pg_stat_data->avg_exit_latency_us = stats.pg_avg_exit_time_us;
} }
static int gk20a_pmu_get_elpg_residency_gating(struct gk20a *g, static int gk20a_pmu_get_pg_stats(struct gk20a *g,
u32 pg_engine_id, u32 *ingating_time, u32 pg_engine_id,
u32 *ungating_time, u32 *gating_cnt) struct pmu_pg_stats_data *pg_stat_data)
{ {
struct pmu_gk20a *pmu = &g->pmu; struct pmu_gk20a *pmu = &g->pmu;
u32 pg_engine_id_list = 0; u32 pg_engine_id_list = 0;
if (!pmu->initialized) { if (!pmu->initialized) {
*ingating_time = 0; pg_stat_data->ingating_time = 0;
*ungating_time = 0; pg_stat_data->ungating_time = 0;
*gating_cnt = 0; pg_stat_data->gating_cnt = 0;
return 0; return 0;
} }
@@ -5103,8 +5104,7 @@ static int gk20a_pmu_get_elpg_residency_gating(struct gk20a *g,
if (BIT(pg_engine_id) & pg_engine_id_list) if (BIT(pg_engine_id) & pg_engine_id_list)
g->ops.pmu.pmu_elpg_statistics(g, pg_engine_id, g->ops.pmu.pmu_elpg_statistics(g, pg_engine_id,
ingating_time, pg_stat_data);
ungating_time, gating_cnt);
return 0; return 0;
} }
@@ -5257,13 +5257,11 @@ int gk20a_aelpg_init_and_enable(struct gk20a *g, u8 ctrl_id)
} }
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
static int mscg_residency_show(struct seq_file *s, void *data) static int mscg_stat_show(struct seq_file *s, void *data)
{ {
struct gk20a *g = s->private; struct gk20a *g = s->private;
u32 ingating_time = 0;
u32 ungating_time = 0;
u32 gating_cnt;
u64 total_ingating, total_ungating, residency, divisor, dividend; u64 total_ingating, total_ungating, residency, divisor, dividend;
struct pmu_pg_stats_data pg_stat_data = { 0 };
int err; int err;
/* Don't unnecessarily power on the device */ /* Don't unnecessarily power on the device */
@@ -5272,13 +5270,15 @@ static int mscg_residency_show(struct seq_file *s, void *data)
if (err) if (err)
return err; return err;
gk20a_pmu_get_elpg_residency_gating(g, gk20a_pmu_get_pg_stats(g,
PMU_PG_ELPG_ENGINE_ID_MS, &ingating_time, PMU_PG_ELPG_ENGINE_ID_MS, &pg_stat_data);
&ungating_time, &gating_cnt);
gk20a_idle(g->dev); gk20a_idle(g->dev);
} }
total_ingating = g->pg_ingating_time_us + (u64)ingating_time; total_ingating = g->pg_ingating_time_us +
total_ungating = g->pg_ungating_time_us + (u64)ungating_time; (u64)pg_stat_data.ingating_time;
total_ungating = g->pg_ungating_time_us +
(u64)pg_stat_data.ungating_time;
divisor = total_ingating + total_ungating; divisor = total_ingating + total_ungating;
/* We compute the residency on a scale of 1000 */ /* We compute the residency on a scale of 1000 */
@@ -5289,21 +5289,28 @@ static int mscg_residency_show(struct seq_file *s, void *data)
else else
residency = 0; residency = 0;
seq_printf(s, "Time in MSCG: %llu us\n" seq_printf(s,
"Time in MSCG: %llu us\n"
"Time out of MSCG: %llu us\n" "Time out of MSCG: %llu us\n"
"MSCG residency ratio: %llu\n", "MSCG residency ratio: %llu\n"
total_ingating, total_ungating, residency); "MSCG Entry Count: %u\n"
"MSCG Avg Entry latency %u\n"
"MSCG Avg Exit latency %u\n",
total_ingating, total_ungating,
residency, pg_stat_data.gating_cnt,
pg_stat_data.avg_entry_latency_us,
pg_stat_data.avg_exit_latency_us);
return 0; return 0;
} }
static int mscg_residency_open(struct inode *inode, struct file *file) static int mscg_stat_open(struct inode *inode, struct file *file)
{ {
return single_open(file, mscg_residency_show, inode->i_private); return single_open(file, mscg_stat_show, inode->i_private);
} }
static const struct file_operations mscg_residency_fops = { static const struct file_operations mscg_stat_fops = {
.open = mscg_residency_open, .open = mscg_stat_open,
.read = seq_read, .read = seq_read,
.llseek = seq_lseek, .llseek = seq_lseek,
.release = single_release, .release = single_release,
@@ -5312,8 +5319,8 @@ static const struct file_operations mscg_residency_fops = {
static int mscg_transitions_show(struct seq_file *s, void *data) static int mscg_transitions_show(struct seq_file *s, void *data)
{ {
struct gk20a *g = s->private; struct gk20a *g = s->private;
u32 ingating_time, ungating_time, total_gating_cnt; struct pmu_pg_stats_data pg_stat_data = { 0 };
u32 gating_cnt = 0; u32 total_gating_cnt;
int err; int err;
if (g->power_on) { if (g->power_on) {
@@ -5321,12 +5328,11 @@ static int mscg_transitions_show(struct seq_file *s, void *data)
if (err) if (err)
return err; return err;
gk20a_pmu_get_elpg_residency_gating(g, gk20a_pmu_get_pg_stats(g,
PMU_PG_ELPG_ENGINE_ID_MS, &ingating_time, PMU_PG_ELPG_ENGINE_ID_MS, &pg_stat_data);
&ungating_time, &gating_cnt);
gk20a_idle(g->dev); gk20a_idle(g->dev);
} }
total_gating_cnt = g->pg_gating_cnt + gating_cnt; total_gating_cnt = g->pg_gating_cnt + pg_stat_data.gating_cnt;
seq_printf(s, "%u\n", total_gating_cnt); seq_printf(s, "%u\n", total_gating_cnt);
return 0; return 0;
@@ -5345,12 +5351,10 @@ static const struct file_operations mscg_transitions_fops = {
.release = single_release, .release = single_release,
}; };
static int elpg_residency_show(struct seq_file *s, void *data) static int elpg_stat_show(struct seq_file *s, void *data)
{ {
struct gk20a *g = s->private; struct gk20a *g = s->private;
u32 ingating_time = 0; struct pmu_pg_stats_data pg_stat_data = { 0 };
u32 ungating_time = 0;
u32 gating_cnt;
u64 total_ingating, total_ungating, residency, divisor, dividend; u64 total_ingating, total_ungating, residency, divisor, dividend;
int err; int err;
@@ -5360,13 +5364,14 @@ static int elpg_residency_show(struct seq_file *s, void *data)
if (err) if (err)
return err; return err;
gk20a_pmu_get_elpg_residency_gating(g, gk20a_pmu_get_pg_stats(g,
PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &ingating_time, PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &pg_stat_data);
&ungating_time, &gating_cnt);
gk20a_idle(g->dev); gk20a_idle(g->dev);
} }
total_ingating = g->pg_ingating_time_us + (u64)ingating_time; total_ingating = g->pg_ingating_time_us +
total_ungating = g->pg_ungating_time_us + (u64)ungating_time; (u64)pg_stat_data.ingating_time;
total_ungating = g->pg_ungating_time_us +
(u64)pg_stat_data.ungating_time;
divisor = total_ingating + total_ungating; divisor = total_ingating + total_ungating;
/* We compute the residency on a scale of 1000 */ /* We compute the residency on a scale of 1000 */
@@ -5377,21 +5382,28 @@ static int elpg_residency_show(struct seq_file *s, void *data)
else else
residency = 0; residency = 0;
seq_printf(s, "Time in ELPG: %llu us\n" seq_printf(s,
"Time in ELPG: %llu us\n"
"Time out of ELPG: %llu us\n" "Time out of ELPG: %llu us\n"
"ELPG residency ratio: %llu\n", "ELPG residency ratio: %llu\n"
total_ingating, total_ungating, residency); "ELPG Entry Count: %u\n"
"ELPG Avg Entry latency %u us\n"
"ELPG Avg Exit latency %u us\n",
total_ingating, total_ungating,
residency, pg_stat_data.gating_cnt,
pg_stat_data.avg_entry_latency_us,
pg_stat_data.avg_exit_latency_us);
return 0; return 0;
} }
static int elpg_residency_open(struct inode *inode, struct file *file) static int elpg_stat_open(struct inode *inode, struct file *file)
{ {
return single_open(file, elpg_residency_show, inode->i_private); return single_open(file, elpg_stat_show, inode->i_private);
} }
static const struct file_operations elpg_residency_fops = { static const struct file_operations elpg_stat_fops = {
.open = elpg_residency_open, .open = elpg_stat_open,
.read = seq_read, .read = seq_read,
.llseek = seq_lseek, .llseek = seq_lseek,
.release = single_release, .release = single_release,
@@ -5400,8 +5412,8 @@ static const struct file_operations elpg_residency_fops = {
static int elpg_transitions_show(struct seq_file *s, void *data) static int elpg_transitions_show(struct seq_file *s, void *data)
{ {
struct gk20a *g = s->private; struct gk20a *g = s->private;
u32 ingating_time, ungating_time, total_gating_cnt; struct pmu_pg_stats_data pg_stat_data = { 0 };
u32 gating_cnt = 0; u32 total_gating_cnt;
int err; int err;
if (g->power_on) { if (g->power_on) {
@@ -5409,12 +5421,11 @@ static int elpg_transitions_show(struct seq_file *s, void *data)
if (err) if (err)
return err; return err;
gk20a_pmu_get_elpg_residency_gating(g, gk20a_pmu_get_pg_stats(g,
PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &ingating_time, PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &pg_stat_data);
&ungating_time, &gating_cnt);
gk20a_idle(g->dev); gk20a_idle(g->dev);
} }
total_gating_cnt = g->pg_gating_cnt + gating_cnt; total_gating_cnt = g->pg_gating_cnt + pg_stat_data.gating_cnt;
seq_printf(s, "%u\n", total_gating_cnt); seq_printf(s, "%u\n", total_gating_cnt);
return 0; return 0;
@@ -5589,7 +5600,7 @@ int gk20a_pmu_debugfs_init(struct device *dev)
d = debugfs_create_file( d = debugfs_create_file(
"mscg_residency", S_IRUGO|S_IWUSR, platform->debugfs, g, "mscg_residency", S_IRUGO|S_IWUSR, platform->debugfs, g,
&mscg_residency_fops); &mscg_stat_fops);
if (!d) if (!d)
goto err_out; goto err_out;
@@ -5601,7 +5612,7 @@ int gk20a_pmu_debugfs_init(struct device *dev)
d = debugfs_create_file( d = debugfs_create_file(
"elpg_residency", S_IRUGO|S_IWUSR, platform->debugfs, g, "elpg_residency", S_IRUGO|S_IWUSR, platform->debugfs, g,
&elpg_residency_fops); &elpg_stat_fops);
if (!d) if (!d)
goto err_out; goto err_out;

View File

@@ -3,7 +3,7 @@
* *
* GK20A PMU (aka. gPMU outside gk20a context) * GK20A PMU (aka. gPMU outside gk20a context)
* *
* Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -566,6 +566,33 @@ struct pmu_sequence {
void* cb_params; void* cb_params;
}; };
struct pmu_pg_stats_data {
u32 gating_cnt;
u32 ingating_time;
u32 ungating_time;
u32 avg_entry_latency_us;
u32 avg_exit_latency_us;
};
struct pmu_pg_stats_v2 {
u32 entry_count;
u32 exit_count;
u32 abort_count;
u32 detection_count;
u32 prevention_activate_count;
u32 prevention_deactivate_count;
u32 powered_up_time_us;
u32 entry_latency_us;
u32 exit_latency_us;
u32 resident_time_us;
u32 entry_latency_avg_us;
u32 exit_latency_avg_us;
u32 entry_latency_max_us;
u32 exit_latency_max_us;
u32 total_sleep_time_us;
u32 total_non_sleep_time_us;
};
struct pmu_pg_stats_v1 { struct pmu_pg_stats_v1 {
/* Number of time PMU successfully engaged sleep state */ /* Number of time PMU successfully engaged sleep state */
u32 entry_count; u32 entry_count;
@@ -825,7 +852,7 @@ int pmu_wait_message_cond(struct pmu_gk20a *pmu, u32 timeout_ms,
void pmu_handle_fecs_boot_acr_msg(struct gk20a *g, struct pmu_msg *msg, void pmu_handle_fecs_boot_acr_msg(struct gk20a *g, struct pmu_msg *msg,
void *param, u32 handle, u32 status); void *param, u32 handle, u32 status);
void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id, void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id,
u32 *ingating_time, u32 *ungating_time, u32 *gating_cnt); struct pmu_pg_stats_data *pg_stat_data);
int gk20a_pmu_reset(struct gk20a *g); int gk20a_pmu_reset(struct gk20a *g);
int pmu_idle(struct pmu_gk20a *pmu); int pmu_idle(struct pmu_gk20a *pmu);
int pmu_enable_hw(struct pmu_gk20a *pmu, bool enable); int pmu_enable_hw(struct pmu_gk20a *pmu, bool enable);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -258,6 +258,23 @@ static int gp106_pg_param_init(struct gk20a *g, u32 pg_engine_id)
return 0; return 0;
} }
static void gp106_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id,
struct pmu_pg_stats_data *pg_stat_data)
{
struct pmu_gk20a *pmu = &g->pmu;
struct pmu_pg_stats_v2 stats;
pmu_copy_from_dmem(pmu,
pmu->stat_dmem_offset[pg_engine_id],
(u8 *)&stats, sizeof(struct pmu_pg_stats_v2), 0);
pg_stat_data->ingating_time = stats.total_sleep_time_us;
pg_stat_data->ungating_time = stats.total_non_sleep_time_us;
pg_stat_data->gating_cnt = stats.entry_count;
pg_stat_data->avg_entry_latency_us = stats.entry_latency_avg_us;
pg_stat_data->avg_exit_latency_us = stats.exit_latency_avg_us;
}
void gp106_init_pmu_ops(struct gpu_ops *gops) void gp106_init_pmu_ops(struct gpu_ops *gops)
{ {
gk20a_dbg_fn(""); gk20a_dbg_fn("");
@@ -279,7 +296,7 @@ void gp106_init_pmu_ops(struct gpu_ops *gops)
gops->pmu.lspmuwprinitdone = 0; gops->pmu.lspmuwprinitdone = 0;
gops->pmu.fecsbootstrapdone = false; gops->pmu.fecsbootstrapdone = false;
gops->pmu.write_dmatrfbase = gp10b_write_dmatrfbase; gops->pmu.write_dmatrfbase = gp10b_write_dmatrfbase;
gops->pmu.pmu_elpg_statistics = gp10b_pmu_elpg_statistics; gops->pmu.pmu_elpg_statistics = gp106_pmu_elpg_statistics;
gops->pmu.pmu_pg_init_param = gp106_pg_param_init; gops->pmu.pmu_pg_init_param = gp106_pg_param_init;
gops->pmu.pmu_pg_supported_engines_list = gp106_pmu_pg_engines_list; gops->pmu.pmu_pg_supported_engines_list = gp106_pmu_pg_engines_list;
gops->pmu.pmu_pg_engines_feature_list = gp106_pmu_pg_feature_list; gops->pmu.pmu_pg_engines_feature_list = gp106_pmu_pg_feature_list;

View File

@@ -1,7 +1,7 @@
/* /*
* GP10B PMU * GP10B PMU
* *
* Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -250,8 +250,8 @@ int gp10b_pg_gr_init(struct gk20a *g, u32 pg_engine_id)
return 0; return 0;
} }
void gp10b_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id, static void gp10b_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id,
u32 *ingating_time, u32 *ungating_time, u32 *gating_cnt) struct pmu_pg_stats_data *pg_stat_data)
{ {
struct pmu_gk20a *pmu = &g->pmu; struct pmu_gk20a *pmu = &g->pmu;
struct pmu_pg_stats_v1 stats; struct pmu_pg_stats_v1 stats;
@@ -260,9 +260,11 @@ void gp10b_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id,
pmu->stat_dmem_offset[pg_engine_id], pmu->stat_dmem_offset[pg_engine_id],
(u8 *)&stats, sizeof(struct pmu_pg_stats_v1), 0); (u8 *)&stats, sizeof(struct pmu_pg_stats_v1), 0);
*ingating_time = stats.total_sleep_timeus; pg_stat_data->ingating_time = stats.total_sleep_timeus;
*ungating_time = stats.total_nonsleep_timeus; pg_stat_data->ungating_time = stats.total_nonsleep_timeus;
*gating_cnt = stats.entry_count; pg_stat_data->gating_cnt = stats.entry_count;
pg_stat_data->avg_entry_latency_us = stats.entrylatency_avgus;
pg_stat_data->avg_exit_latency_us = stats.exitlatency_avgus;
} }
static int gp10b_pmu_setup_elpg(struct gk20a *g) static int gp10b_pmu_setup_elpg(struct gk20a *g)

View File

@@ -1,7 +1,7 @@
/* /*
* GP10B PMU * GP10B PMU
* *
* Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -20,7 +20,5 @@ void gp10b_init_pmu_ops(struct gpu_ops *gops);
int gp10b_load_falcon_ucode(struct gk20a *g, u32 falconidmask); int gp10b_load_falcon_ucode(struct gk20a *g, u32 falconidmask);
int gp10b_pg_gr_init(struct gk20a *g, u32 pg_engine_id); int gp10b_pg_gr_init(struct gk20a *g, u32 pg_engine_id);
void gp10b_write_dmatrfbase(struct gk20a *g, u32 addr); void gp10b_write_dmatrfbase(struct gk20a *g, u32 addr);
void gp10b_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id,
u32 *ingating_time, u32 *ungating_time, u32 *gating_cnt);
#endif /*__PMU_GP10B_H_*/ #endif /*__PMU_GP10B_H_*/