summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
diff options
context:
space:
mode:
authorMahantesh Kumbar <mkumbar@nvidia.com>2016-11-14 09:22:50 -0500
committermobile promotions <svcmobile_promotions@nvidia.com>2017-01-10 12:24:06 -0500
commitf3e0dba8bfb20489f23c93a16bc5bd337206705f (patch)
treea341f26b68ad6ec2f7994ee26852c551af32d311 /drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
parente239ce69b38a9a557ed466a3bd9b090916f6cd31 (diff)
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>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/pmu_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/pmu_gk20a.c149
1 files changed, 80 insertions, 69 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
index 58dd6f43..e140b47a 100644
--- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * GK20A PMU (aka. gPMU outside gk20a context) 2 * GK20A PMU (aka. gPMU outside gk20a context)
3 * 3 *
4 * Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved. 4 * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License, 7 * under the terms and conditions of the GNU General Public License,
@@ -46,9 +46,9 @@
46#define gk20a_dbg_pmu(fmt, arg...) \ 46#define gk20a_dbg_pmu(fmt, arg...) \
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_pg_stats(struct gk20a *g,
50 u32 pg_engine_id, u32 *ingating_time, 50 u32 pg_engine_id,
51 u32 *ungating_time, u32 *gating_cnt); 51 struct pmu_pg_stats_data *pg_stat_data);
52static void ap_callback_init_and_enable_ctrl( 52static void ap_callback_init_and_enable_ctrl(
53 struct gk20a *g, struct pmu_msg *msg, 53 struct gk20a *g, struct pmu_msg *msg,
54 void *param, u32 seq_desc, u32 status); 54 void *param, u32 seq_desc, u32 status);
@@ -4979,7 +4979,7 @@ int gk20a_pmu_perfmon_enable(struct gk20a *g, bool enable)
4979int gk20a_pmu_destroy(struct gk20a *g) 4979int gk20a_pmu_destroy(struct gk20a *g)
4980{ 4980{
4981 struct pmu_gk20a *pmu = &g->pmu; 4981 struct pmu_gk20a *pmu = &g->pmu;
4982 u32 elpg_ingating_time, elpg_ungating_time, gating_cnt; 4982 struct pmu_pg_stats_data pg_stat_data = { 0 };
4983 4983
4984 gk20a_dbg_fn(""); 4984 gk20a_dbg_fn("");
4985 4985
@@ -4989,17 +4989,16 @@ int gk20a_pmu_destroy(struct gk20a *g)
4989 /* make sure the pending operations are finished before we continue */ 4989 /* make sure the pending operations are finished before we continue */
4990 cancel_work_sync(&pmu->pg_init); 4990 cancel_work_sync(&pmu->pg_init);
4991 4991
4992 gk20a_pmu_get_elpg_residency_gating(g, 4992 gk20a_pmu_get_pg_stats(g,
4993 PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &elpg_ingating_time, 4993 PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &pg_stat_data);
4994 &elpg_ungating_time, &gating_cnt);
4995 4994
4996 gk20a_pmu_disable_elpg(g); 4995 gk20a_pmu_disable_elpg(g);
4997 pmu->initialized = false; 4996 pmu->initialized = false;
4998 4997
4999 /* update the s/w ELPG residency counters */ 4998 /* update the s/w ELPG residency counters */
5000 g->pg_ingating_time_us += (u64)elpg_ingating_time; 4999 g->pg_ingating_time_us += (u64)pg_stat_data.ingating_time;
5001 g->pg_ungating_time_us += (u64)elpg_ungating_time; 5000 g->pg_ungating_time_us += (u64)pg_stat_data.ungating_time;
5002 g->pg_gating_cnt += gating_cnt; 5001 g->pg_gating_cnt += pg_stat_data.gating_cnt;
5003 5002
5004 mutex_lock(&pmu->isr_mutex); 5003 mutex_lock(&pmu->isr_mutex);
5005 pmu->isr_enabled = false; 5004 pmu->isr_enabled = false;
@@ -5070,7 +5069,7 @@ void gk20a_pmu_reset_load_counters(struct gk20a *g)
5070} 5069}
5071 5070
5072void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id, 5071void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id,
5073 u32 *ingating_time, u32 *ungating_time, u32 *gating_cnt) 5072 struct pmu_pg_stats_data *pg_stat_data)
5074{ 5073{
5075 struct pmu_gk20a *pmu = &g->pmu; 5074 struct pmu_gk20a *pmu = &g->pmu;
5076 struct pmu_pg_stats stats; 5075 struct pmu_pg_stats stats;
@@ -5079,22 +5078,24 @@ void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id,
5079 pmu->stat_dmem_offset[pg_engine_id], 5078 pmu->stat_dmem_offset[pg_engine_id],
5080 (u8 *)&stats, sizeof(struct pmu_pg_stats), 0); 5079 (u8 *)&stats, sizeof(struct pmu_pg_stats), 0);
5081 5080
5082 *ingating_time = stats.pg_ingating_time_us; 5081 pg_stat_data->ingating_time = stats.pg_ingating_time_us;
5083 *ungating_time = stats.pg_ungating_time_us; 5082 pg_stat_data->ungating_time = stats.pg_ungating_time_us;
5084 *gating_cnt = stats.pg_gating_cnt; 5083 pg_stat_data->gating_cnt = stats.pg_gating_cnt;
5084 pg_stat_data->avg_entry_latency_us = stats.pg_avg_entry_time_us;
5085 pg_stat_data->avg_exit_latency_us = stats.pg_avg_exit_time_us;
5085} 5086}
5086 5087
5087static int gk20a_pmu_get_elpg_residency_gating(struct gk20a *g, 5088static int gk20a_pmu_get_pg_stats(struct gk20a *g,
5088 u32 pg_engine_id, u32 *ingating_time, 5089 u32 pg_engine_id,
5089 u32 *ungating_time, u32 *gating_cnt) 5090 struct pmu_pg_stats_data *pg_stat_data)
5090{ 5091{
5091 struct pmu_gk20a *pmu = &g->pmu; 5092 struct pmu_gk20a *pmu = &g->pmu;
5092 u32 pg_engine_id_list = 0; 5093 u32 pg_engine_id_list = 0;
5093 5094
5094 if (!pmu->initialized) { 5095 if (!pmu->initialized) {
5095 *ingating_time = 0; 5096 pg_stat_data->ingating_time = 0;
5096 *ungating_time = 0; 5097 pg_stat_data->ungating_time = 0;
5097 *gating_cnt = 0; 5098 pg_stat_data->gating_cnt = 0;
5098 return 0; 5099 return 0;
5099 } 5100 }
5100 5101
@@ -5103,8 +5104,7 @@ static int gk20a_pmu_get_elpg_residency_gating(struct gk20a *g,
5103 5104
5104 if (BIT(pg_engine_id) & pg_engine_id_list) 5105 if (BIT(pg_engine_id) & pg_engine_id_list)
5105 g->ops.pmu.pmu_elpg_statistics(g, pg_engine_id, 5106 g->ops.pmu.pmu_elpg_statistics(g, pg_engine_id,
5106 ingating_time, 5107 pg_stat_data);
5107 ungating_time, gating_cnt);
5108 5108
5109 return 0; 5109 return 0;
5110} 5110}
@@ -5257,13 +5257,11 @@ int gk20a_aelpg_init_and_enable(struct gk20a *g, u8 ctrl_id)
5257} 5257}
5258 5258
5259#ifdef CONFIG_DEBUG_FS 5259#ifdef CONFIG_DEBUG_FS
5260static int mscg_residency_show(struct seq_file *s, void *data) 5260static int mscg_stat_show(struct seq_file *s, void *data)
5261{ 5261{
5262 struct gk20a *g = s->private; 5262 struct gk20a *g = s->private;
5263 u32 ingating_time = 0;
5264 u32 ungating_time = 0;
5265 u32 gating_cnt;
5266 u64 total_ingating, total_ungating, residency, divisor, dividend; 5263 u64 total_ingating, total_ungating, residency, divisor, dividend;
5264 struct pmu_pg_stats_data pg_stat_data = { 0 };
5267 int err; 5265 int err;
5268 5266
5269 /* Don't unnecessarily power on the device */ 5267 /* Don't unnecessarily power on the device */
@@ -5272,13 +5270,15 @@ static int mscg_residency_show(struct seq_file *s, void *data)
5272 if (err) 5270 if (err)
5273 return err; 5271 return err;
5274 5272
5275 gk20a_pmu_get_elpg_residency_gating(g, 5273 gk20a_pmu_get_pg_stats(g,
5276 PMU_PG_ELPG_ENGINE_ID_MS, &ingating_time, 5274 PMU_PG_ELPG_ENGINE_ID_MS, &pg_stat_data);
5277 &ungating_time, &gating_cnt);
5278 gk20a_idle(g->dev); 5275 gk20a_idle(g->dev);
5279 } 5276 }
5280 total_ingating = g->pg_ingating_time_us + (u64)ingating_time; 5277 total_ingating = g->pg_ingating_time_us +
5281 total_ungating = g->pg_ungating_time_us + (u64)ungating_time; 5278 (u64)pg_stat_data.ingating_time;
5279 total_ungating = g->pg_ungating_time_us +
5280 (u64)pg_stat_data.ungating_time;
5281
5282 divisor = total_ingating + total_ungating; 5282 divisor = total_ingating + total_ungating;
5283 5283
5284 /* We compute the residency on a scale of 1000 */ 5284 /* We compute the residency on a scale of 1000 */
@@ -5289,21 +5289,28 @@ static int mscg_residency_show(struct seq_file *s, void *data)
5289 else 5289 else
5290 residency = 0; 5290 residency = 0;
5291 5291
5292 seq_printf(s, "Time in MSCG: %llu us\n" 5292 seq_printf(s,
5293 "Time in MSCG: %llu us\n"
5293 "Time out of MSCG: %llu us\n" 5294 "Time out of MSCG: %llu us\n"
5294 "MSCG residency ratio: %llu\n", 5295 "MSCG residency ratio: %llu\n"
5295 total_ingating, total_ungating, residency); 5296 "MSCG Entry Count: %u\n"
5297 "MSCG Avg Entry latency %u\n"
5298 "MSCG Avg Exit latency %u\n",
5299 total_ingating, total_ungating,
5300 residency, pg_stat_data.gating_cnt,
5301 pg_stat_data.avg_entry_latency_us,
5302 pg_stat_data.avg_exit_latency_us);
5296 return 0; 5303 return 0;
5297 5304
5298} 5305}
5299 5306
5300static int mscg_residency_open(struct inode *inode, struct file *file) 5307static int mscg_stat_open(struct inode *inode, struct file *file)
5301{ 5308{
5302 return single_open(file, mscg_residency_show, inode->i_private); 5309 return single_open(file, mscg_stat_show, inode->i_private);
5303} 5310}
5304 5311
5305static const struct file_operations mscg_residency_fops = { 5312static const struct file_operations mscg_stat_fops = {
5306 .open = mscg_residency_open, 5313 .open = mscg_stat_open,
5307 .read = seq_read, 5314 .read = seq_read,
5308 .llseek = seq_lseek, 5315 .llseek = seq_lseek,
5309 .release = single_release, 5316 .release = single_release,
@@ -5312,8 +5319,8 @@ static const struct file_operations mscg_residency_fops = {
5312static int mscg_transitions_show(struct seq_file *s, void *data) 5319static int mscg_transitions_show(struct seq_file *s, void *data)
5313{ 5320{
5314 struct gk20a *g = s->private; 5321 struct gk20a *g = s->private;
5315 u32 ingating_time, ungating_time, total_gating_cnt; 5322 struct pmu_pg_stats_data pg_stat_data = { 0 };
5316 u32 gating_cnt = 0; 5323 u32 total_gating_cnt;
5317 int err; 5324 int err;
5318 5325
5319 if (g->power_on) { 5326 if (g->power_on) {
@@ -5321,12 +5328,11 @@ static int mscg_transitions_show(struct seq_file *s, void *data)
5321 if (err) 5328 if (err)
5322 return err; 5329 return err;
5323 5330
5324 gk20a_pmu_get_elpg_residency_gating(g, 5331 gk20a_pmu_get_pg_stats(g,
5325 PMU_PG_ELPG_ENGINE_ID_MS, &ingating_time, 5332 PMU_PG_ELPG_ENGINE_ID_MS, &pg_stat_data);
5326 &ungating_time, &gating_cnt);
5327 gk20a_idle(g->dev); 5333 gk20a_idle(g->dev);
5328 } 5334 }
5329 total_gating_cnt = g->pg_gating_cnt + gating_cnt; 5335 total_gating_cnt = g->pg_gating_cnt + pg_stat_data.gating_cnt;
5330 5336
5331 seq_printf(s, "%u\n", total_gating_cnt); 5337 seq_printf(s, "%u\n", total_gating_cnt);
5332 return 0; 5338 return 0;
@@ -5345,12 +5351,10 @@ static const struct file_operations mscg_transitions_fops = {
5345 .release = single_release, 5351 .release = single_release,
5346}; 5352};
5347 5353
5348static int elpg_residency_show(struct seq_file *s, void *data) 5354static int elpg_stat_show(struct seq_file *s, void *data)
5349{ 5355{
5350 struct gk20a *g = s->private; 5356 struct gk20a *g = s->private;
5351 u32 ingating_time = 0; 5357 struct pmu_pg_stats_data pg_stat_data = { 0 };
5352 u32 ungating_time = 0;
5353 u32 gating_cnt;
5354 u64 total_ingating, total_ungating, residency, divisor, dividend; 5358 u64 total_ingating, total_ungating, residency, divisor, dividend;
5355 int err; 5359 int err;
5356 5360
@@ -5360,13 +5364,14 @@ static int elpg_residency_show(struct seq_file *s, void *data)
5360 if (err) 5364 if (err)
5361 return err; 5365 return err;
5362 5366
5363 gk20a_pmu_get_elpg_residency_gating(g, 5367 gk20a_pmu_get_pg_stats(g,
5364 PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &ingating_time, 5368 PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &pg_stat_data);
5365 &ungating_time, &gating_cnt);
5366 gk20a_idle(g->dev); 5369 gk20a_idle(g->dev);
5367 } 5370 }
5368 total_ingating = g->pg_ingating_time_us + (u64)ingating_time; 5371 total_ingating = g->pg_ingating_time_us +
5369 total_ungating = g->pg_ungating_time_us + (u64)ungating_time; 5372 (u64)pg_stat_data.ingating_time;
5373 total_ungating = g->pg_ungating_time_us +
5374 (u64)pg_stat_data.ungating_time;
5370 divisor = total_ingating + total_ungating; 5375 divisor = total_ingating + total_ungating;
5371 5376
5372 /* We compute the residency on a scale of 1000 */ 5377 /* We compute the residency on a scale of 1000 */
@@ -5377,21 +5382,28 @@ static int elpg_residency_show(struct seq_file *s, void *data)
5377 else 5382 else
5378 residency = 0; 5383 residency = 0;
5379 5384
5380 seq_printf(s, "Time in ELPG: %llu us\n" 5385 seq_printf(s,
5386 "Time in ELPG: %llu us\n"
5381 "Time out of ELPG: %llu us\n" 5387 "Time out of ELPG: %llu us\n"
5382 "ELPG residency ratio: %llu\n", 5388 "ELPG residency ratio: %llu\n"
5383 total_ingating, total_ungating, residency); 5389 "ELPG Entry Count: %u\n"
5390 "ELPG Avg Entry latency %u us\n"
5391 "ELPG Avg Exit latency %u us\n",
5392 total_ingating, total_ungating,
5393 residency, pg_stat_data.gating_cnt,
5394 pg_stat_data.avg_entry_latency_us,
5395 pg_stat_data.avg_exit_latency_us);
5384 return 0; 5396 return 0;
5385 5397
5386} 5398}
5387 5399
5388static int elpg_residency_open(struct inode *inode, struct file *file) 5400static int elpg_stat_open(struct inode *inode, struct file *file)
5389{ 5401{
5390 return single_open(file, elpg_residency_show, inode->i_private); 5402 return single_open(file, elpg_stat_show, inode->i_private);
5391} 5403}
5392 5404
5393static const struct file_operations elpg_residency_fops = { 5405static const struct file_operations elpg_stat_fops = {
5394 .open = elpg_residency_open, 5406 .open = elpg_stat_open,
5395 .read = seq_read, 5407 .read = seq_read,
5396 .llseek = seq_lseek, 5408 .llseek = seq_lseek,
5397 .release = single_release, 5409 .release = single_release,
@@ -5400,8 +5412,8 @@ static const struct file_operations elpg_residency_fops = {
5400static int elpg_transitions_show(struct seq_file *s, void *data) 5412static int elpg_transitions_show(struct seq_file *s, void *data)
5401{ 5413{
5402 struct gk20a *g = s->private; 5414 struct gk20a *g = s->private;
5403 u32 ingating_time, ungating_time, total_gating_cnt; 5415 struct pmu_pg_stats_data pg_stat_data = { 0 };
5404 u32 gating_cnt = 0; 5416 u32 total_gating_cnt;
5405 int err; 5417 int err;
5406 5418
5407 if (g->power_on) { 5419 if (g->power_on) {
@@ -5409,12 +5421,11 @@ static int elpg_transitions_show(struct seq_file *s, void *data)
5409 if (err) 5421 if (err)
5410 return err; 5422 return err;
5411 5423
5412 gk20a_pmu_get_elpg_residency_gating(g, 5424 gk20a_pmu_get_pg_stats(g,
5413 PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &ingating_time, 5425 PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &pg_stat_data);
5414 &ungating_time, &gating_cnt);
5415 gk20a_idle(g->dev); 5426 gk20a_idle(g->dev);
5416 } 5427 }
5417 total_gating_cnt = g->pg_gating_cnt + gating_cnt; 5428 total_gating_cnt = g->pg_gating_cnt + pg_stat_data.gating_cnt;
5418 5429
5419 seq_printf(s, "%u\n", total_gating_cnt); 5430 seq_printf(s, "%u\n", total_gating_cnt);
5420 return 0; 5431 return 0;
@@ -5589,7 +5600,7 @@ int gk20a_pmu_debugfs_init(struct device *dev)
5589 5600
5590 d = debugfs_create_file( 5601 d = debugfs_create_file(
5591 "mscg_residency", S_IRUGO|S_IWUSR, platform->debugfs, g, 5602 "mscg_residency", S_IRUGO|S_IWUSR, platform->debugfs, g,
5592 &mscg_residency_fops); 5603 &mscg_stat_fops);
5593 if (!d) 5604 if (!d)
5594 goto err_out; 5605 goto err_out;
5595 5606
@@ -5601,7 +5612,7 @@ int gk20a_pmu_debugfs_init(struct device *dev)
5601 5612
5602 d = debugfs_create_file( 5613 d = debugfs_create_file(
5603 "elpg_residency", S_IRUGO|S_IWUSR, platform->debugfs, g, 5614 "elpg_residency", S_IRUGO|S_IWUSR, platform->debugfs, g,
5604 &elpg_residency_fops); 5615 &elpg_stat_fops);
5605 if (!d) 5616 if (!d)
5606 goto err_out; 5617 goto err_out;
5607 5618