summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
diff options
context:
space:
mode:
authorMahantesh Kumbar <mkumbar@nvidia.com>2016-11-09 09:08:33 -0500
committermobile promotions <svcmobile_promotions@nvidia.com>2016-12-26 01:20:09 -0500
commit98e349ab7eb01ac27e1e18477674294ca80d2093 (patch)
treea1b85feb852037a08ad43c8e92254d3250c6cb44 /drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
parent71fbfdb2b84a4f778f19e44421a66e28e5aadf8d (diff)
gpu: nvgpu: PG statistics update
- PG statistics read support for multiple engines - updated stat_dmem_offset member to array to hold dmem offset of PG engines - PMU allocates memory in DMEM for each PG engine requested, updated gk20a_pmu_get_elpg_residency_gating() to get engine statistics for requested PG engine JIRA DNVGPU-71 Change-Id: I2ddade37f85716f757bf33034dbff816184577eb Signed-off-by: Mahantesh Kumbar <mkumbar@nvidia.com> Reviewed-on: http://git-master/r/1250506 (cherry picked from commit 68ba7a97d6662b87d0e489365d8afb8e2d237a03) Reviewed-on: http://git-master/r/1270972 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/pmu_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/pmu_gk20a.c140
1 files changed, 127 insertions, 13 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
index 2b847008..e221be11 100644
--- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
@@ -47,7 +47,8 @@
47 gk20a_dbg(gpu_dbg_pmu, fmt, ##arg) 47 gk20a_dbg(gpu_dbg_pmu, fmt, ##arg)
48 48
49static int gk20a_pmu_get_elpg_residency_gating(struct gk20a *g, 49static int gk20a_pmu_get_elpg_residency_gating(struct gk20a *g,
50 u32 *ingating_time, u32 *ungating_time, u32 *gating_cnt); 50 u32 pg_engine_id, u32 *ingating_time,
51 u32 *ungating_time, u32 *gating_cnt);
51static void ap_callback_init_and_enable_ctrl( 52static void ap_callback_init_and_enable_ctrl(
52 struct gk20a *g, struct pmu_msg *msg, 53 struct gk20a *g, struct pmu_msg *msg,
53 void *param, u32 seq_desc, u32 status); 54 void *param, u32 seq_desc, u32 status);
@@ -3411,7 +3412,8 @@ static void pmu_handle_pg_stat_msg(struct gk20a *g, struct pmu_msg *msg,
3411 switch (msg->msg.pg.stat.sub_msg_id) { 3412 switch (msg->msg.pg.stat.sub_msg_id) {
3412 case PMU_PG_STAT_MSG_RESP_DMEM_OFFSET: 3413 case PMU_PG_STAT_MSG_RESP_DMEM_OFFSET:
3413 gk20a_dbg_pmu("ALLOC_DMEM_OFFSET is acknowledged from PMU"); 3414 gk20a_dbg_pmu("ALLOC_DMEM_OFFSET is acknowledged from PMU");
3414 pmu->stat_dmem_offset = msg->msg.pg.stat.data; 3415 pmu->stat_dmem_offset[msg->msg.pg.stat.engine_id] =
3416 msg->msg.pg.stat.data;
3415 break; 3417 break;
3416 default: 3418 default:
3417 break; 3419 break;
@@ -3456,7 +3458,7 @@ static int pmu_pg_init_send(struct gk20a *g, u32 pg_engine_id)
3456 pmu_handle_pg_elpg_msg, pmu, &seq, ~0); 3458 pmu_handle_pg_elpg_msg, pmu, &seq, ~0);
3457 3459
3458 /* alloc dmem for powergating state log */ 3460 /* alloc dmem for powergating state log */
3459 pmu->stat_dmem_offset = 0; 3461 pmu->stat_dmem_offset[pg_engine_id] = 0;
3460 memset(&cmd, 0, sizeof(struct pmu_cmd)); 3462 memset(&cmd, 0, sizeof(struct pmu_cmd));
3461 cmd.hdr.unit_id = PMU_UNIT_PG; 3463 cmd.hdr.unit_id = PMU_UNIT_PG;
3462 cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_stat); 3464 cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_stat);
@@ -4122,7 +4124,8 @@ static void pmu_dump_elpg_stats(struct pmu_gk20a *pmu)
4122 struct gk20a *g = gk20a_from_pmu(pmu); 4124 struct gk20a *g = gk20a_from_pmu(pmu);
4123 struct pmu_pg_stats stats; 4125 struct pmu_pg_stats stats;
4124 4126
4125 pmu_copy_from_dmem(pmu, pmu->stat_dmem_offset, 4127 pmu_copy_from_dmem(pmu,
4128 pmu->stat_dmem_offset[PMU_PG_ELPG_ENGINE_ID_GRAPHICS],
4126 (u8 *)&stats, sizeof(struct pmu_pg_stats), 0); 4129 (u8 *)&stats, sizeof(struct pmu_pg_stats), 0);
4127 4130
4128 gk20a_dbg_pmu("pg_entry_start_timestamp : 0x%016llx", 4131 gk20a_dbg_pmu("pg_entry_start_timestamp : 0x%016llx",
@@ -4965,7 +4968,8 @@ int gk20a_pmu_destroy(struct gk20a *g)
4965 /* make sure the pending operations are finished before we continue */ 4968 /* make sure the pending operations are finished before we continue */
4966 cancel_work_sync(&pmu->pg_init); 4969 cancel_work_sync(&pmu->pg_init);
4967 4970
4968 gk20a_pmu_get_elpg_residency_gating(g, &elpg_ingating_time, 4971 gk20a_pmu_get_elpg_residency_gating(g,
4972 PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &elpg_ingating_time,
4969 &elpg_ungating_time, &gating_cnt); 4973 &elpg_ungating_time, &gating_cnt);
4970 4974
4971 gk20a_pmu_disable_elpg(g); 4975 gk20a_pmu_disable_elpg(g);
@@ -5044,14 +5048,15 @@ void gk20a_pmu_reset_load_counters(struct gk20a *g)
5044 gk20a_idle(g->dev); 5048 gk20a_idle(g->dev);
5045} 5049}
5046 5050
5047void gk20a_pmu_elpg_statistics(struct gk20a *g, 5051void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id,
5048 u32 *ingating_time, u32 *ungating_time, u32 *gating_cnt) 5052 u32 *ingating_time, u32 *ungating_time, u32 *gating_cnt)
5049{ 5053{
5050 struct pmu_gk20a *pmu = &g->pmu; 5054 struct pmu_gk20a *pmu = &g->pmu;
5051 struct pmu_pg_stats stats; 5055 struct pmu_pg_stats stats;
5052 5056
5053 pmu_copy_from_dmem(pmu, pmu->stat_dmem_offset, 5057 pmu_copy_from_dmem(pmu,
5054 (u8 *)&stats, sizeof(struct pmu_pg_stats), 0); 5058 pmu->stat_dmem_offset[pg_engine_id],
5059 (u8 *)&stats, sizeof(struct pmu_pg_stats), 0);
5055 5060
5056 *ingating_time = stats.pg_ingating_time_us; 5061 *ingating_time = stats.pg_ingating_time_us;
5057 *ungating_time = stats.pg_ungating_time_us; 5062 *ungating_time = stats.pg_ungating_time_us;
@@ -5059,9 +5064,11 @@ void gk20a_pmu_elpg_statistics(struct gk20a *g,
5059} 5064}
5060 5065
5061static int gk20a_pmu_get_elpg_residency_gating(struct gk20a *g, 5066static int gk20a_pmu_get_elpg_residency_gating(struct gk20a *g,
5062 u32 *ingating_time, u32 *ungating_time, u32 *gating_cnt) 5067 u32 pg_engine_id, u32 *ingating_time,
5068 u32 *ungating_time, u32 *gating_cnt)
5063{ 5069{
5064 struct pmu_gk20a *pmu = &g->pmu; 5070 struct pmu_gk20a *pmu = &g->pmu;
5071 u32 pg_engine_id_list = 0;
5065 5072
5066 if (!pmu->initialized) { 5073 if (!pmu->initialized) {
5067 *ingating_time = 0; 5074 *ingating_time = 0;
@@ -5070,8 +5077,13 @@ static int gk20a_pmu_get_elpg_residency_gating(struct gk20a *g,
5070 return 0; 5077 return 0;
5071 } 5078 }
5072 5079
5073 g->ops.pmu.pmu_elpg_statistics(g, ingating_time, 5080 if (g->ops.pmu.pmu_pg_supported_engines_list)
5074 ungating_time, gating_cnt); 5081 pg_engine_id_list = g->ops.pmu.pmu_pg_supported_engines_list(g);
5082
5083 if (BIT(pg_engine_id) & pg_engine_id_list)
5084 g->ops.pmu.pmu_elpg_statistics(g, pg_engine_id,
5085 ingating_time,
5086 ungating_time, gating_cnt);
5075 5087
5076 return 0; 5088 return 0;
5077} 5089}
@@ -5224,6 +5236,94 @@ int gk20a_aelpg_init_and_enable(struct gk20a *g, u8 ctrl_id)
5224} 5236}
5225 5237
5226#ifdef CONFIG_DEBUG_FS 5238#ifdef CONFIG_DEBUG_FS
5239static int mscg_residency_show(struct seq_file *s, void *data)
5240{
5241 struct gk20a *g = s->private;
5242 u32 ingating_time = 0;
5243 u32 ungating_time = 0;
5244 u32 gating_cnt;
5245 u64 total_ingating, total_ungating, residency, divisor, dividend;
5246 int err;
5247
5248 /* Don't unnecessarily power on the device */
5249 if (g->power_on) {
5250 err = gk20a_busy(g->dev);
5251 if (err)
5252 return err;
5253
5254 gk20a_pmu_get_elpg_residency_gating(g,
5255 PMU_PG_ELPG_ENGINE_ID_MS, &ingating_time,
5256 &ungating_time, &gating_cnt);
5257 gk20a_idle(g->dev);
5258 }
5259 total_ingating = g->pg_ingating_time_us + (u64)ingating_time;
5260 total_ungating = g->pg_ungating_time_us + (u64)ungating_time;
5261 divisor = total_ingating + total_ungating;
5262
5263 /* We compute the residency on a scale of 1000 */
5264 dividend = total_ingating * 1000;
5265
5266 if (divisor)
5267 residency = div64_u64(dividend, divisor);
5268 else
5269 residency = 0;
5270
5271 seq_printf(s, "Time in MSCG: %llu us\n"
5272 "Time out of MSCG: %llu us\n"
5273 "MSCG residency ratio: %llu\n",
5274 total_ingating, total_ungating, residency);
5275 return 0;
5276
5277}
5278
5279static int mscg_residency_open(struct inode *inode, struct file *file)
5280{
5281 return single_open(file, mscg_residency_show, inode->i_private);
5282}
5283
5284static const struct file_operations mscg_residency_fops = {
5285 .open = mscg_residency_open,
5286 .read = seq_read,
5287 .llseek = seq_lseek,
5288 .release = single_release,
5289};
5290
5291static int mscg_transitions_show(struct seq_file *s, void *data)
5292{
5293 struct gk20a *g = s->private;
5294 u32 ingating_time, ungating_time, total_gating_cnt;
5295 u32 gating_cnt = 0;
5296 int err;
5297
5298 if (g->power_on) {
5299 err = gk20a_busy(g->dev);
5300 if (err)
5301 return err;
5302
5303 gk20a_pmu_get_elpg_residency_gating(g,
5304 PMU_PG_ELPG_ENGINE_ID_MS, &ingating_time,
5305 &ungating_time, &gating_cnt);
5306 gk20a_idle(g->dev);
5307 }
5308 total_gating_cnt = g->pg_gating_cnt + gating_cnt;
5309
5310 seq_printf(s, "%u\n", total_gating_cnt);
5311 return 0;
5312
5313}
5314
5315static int mscg_transitions_open(struct inode *inode, struct file *file)
5316{
5317 return single_open(file, mscg_transitions_show, inode->i_private);
5318}
5319
5320static const struct file_operations mscg_transitions_fops = {
5321 .open = mscg_transitions_open,
5322 .read = seq_read,
5323 .llseek = seq_lseek,
5324 .release = single_release,
5325};
5326
5227static int elpg_residency_show(struct seq_file *s, void *data) 5327static int elpg_residency_show(struct seq_file *s, void *data)
5228{ 5328{
5229 struct gk20a *g = s->private; 5329 struct gk20a *g = s->private;
@@ -5239,7 +5339,8 @@ static int elpg_residency_show(struct seq_file *s, void *data)
5239 if (err) 5339 if (err)
5240 return err; 5340 return err;
5241 5341
5242 gk20a_pmu_get_elpg_residency_gating(g, &ingating_time, 5342 gk20a_pmu_get_elpg_residency_gating(g,
5343 PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &ingating_time,
5243 &ungating_time, &gating_cnt); 5344 &ungating_time, &gating_cnt);
5244 gk20a_idle(g->dev); 5345 gk20a_idle(g->dev);
5245 } 5346 }
@@ -5287,7 +5388,8 @@ static int elpg_transitions_show(struct seq_file *s, void *data)
5287 if (err) 5388 if (err)
5288 return err; 5389 return err;
5289 5390
5290 gk20a_pmu_get_elpg_residency_gating(g, &ingating_time, 5391 gk20a_pmu_get_elpg_residency_gating(g,
5392 PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &ingating_time,
5291 &ungating_time, &gating_cnt); 5393 &ungating_time, &gating_cnt);
5292 gk20a_idle(g->dev); 5394 gk20a_idle(g->dev);
5293 } 5395 }
@@ -5465,6 +5567,18 @@ int gk20a_pmu_debugfs_init(struct device *dev)
5465 struct gk20a *g = get_gk20a(dev); 5567 struct gk20a *g = get_gk20a(dev);
5466 5568
5467 d = debugfs_create_file( 5569 d = debugfs_create_file(
5570 "mscg_residency", S_IRUGO|S_IWUSR, platform->debugfs, g,
5571 &mscg_residency_fops);
5572 if (!d)
5573 goto err_out;
5574
5575 d = debugfs_create_file(
5576 "mscg_transitions", S_IRUGO, platform->debugfs, g,
5577 &mscg_transitions_fops);
5578 if (!d)
5579 goto err_out;
5580
5581 d = debugfs_create_file(
5468 "elpg_residency", S_IRUGO|S_IWUSR, platform->debugfs, g, 5582 "elpg_residency", S_IRUGO|S_IWUSR, platform->debugfs, g,
5469 &elpg_residency_fops); 5583 &elpg_residency_fops);
5470 if (!d) 5584 if (!d)