diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 5 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 149 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | 31 |
3 files changed, 111 insertions, 74 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index b955a84a..cf147ae8 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * GK20A Graphics | 2 | * GK20A Graphics |
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, |
@@ -605,8 +605,7 @@ struct gpu_ops { | |||
605 | int (*load_lsfalcon_ucode)(struct gk20a *g, u32 falconidmask); | 605 | int (*load_lsfalcon_ucode)(struct gk20a *g, u32 falconidmask); |
606 | void (*write_dmatrfbase)(struct gk20a *g, u32 addr); | 606 | void (*write_dmatrfbase)(struct gk20a *g, u32 addr); |
607 | void (*pmu_elpg_statistics)(struct gk20a *g, u32 pg_engine_id, | 607 | void (*pmu_elpg_statistics)(struct gk20a *g, u32 pg_engine_id, |
608 | u32 *ingating_time, u32 *ungating_time, | 608 | struct pmu_pg_stats_data *pg_stat_data); |
609 | u32 *gating_cnt); | ||
610 | int (*pmu_pg_init_param)(struct gk20a *g, u32 pg_engine_id); | 609 | int (*pmu_pg_init_param)(struct gk20a *g, u32 pg_engine_id); |
611 | u32 (*pmu_pg_supported_engines_list)(struct gk20a *g); | 610 | u32 (*pmu_pg_supported_engines_list)(struct gk20a *g); |
612 | u32 (*pmu_pg_engines_feature_list)(struct gk20a *g, | 611 | u32 (*pmu_pg_engines_feature_list)(struct gk20a *g, |
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 | ||
49 | static int gk20a_pmu_get_elpg_residency_gating(struct gk20a *g, | 49 | static 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); |
52 | static void ap_callback_init_and_enable_ctrl( | 52 | static 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) | |||
4979 | int gk20a_pmu_destroy(struct gk20a *g) | 4979 | int 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 | ||
5072 | void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id, | 5071 | void 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 | ||
5087 | static int gk20a_pmu_get_elpg_residency_gating(struct gk20a *g, | 5088 | static 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 |
5260 | static int mscg_residency_show(struct seq_file *s, void *data) | 5260 | static 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 | ||
5300 | static int mscg_residency_open(struct inode *inode, struct file *file) | 5307 | static 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 | ||
5305 | static const struct file_operations mscg_residency_fops = { | 5312 | static 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 = { | |||
5312 | static int mscg_transitions_show(struct seq_file *s, void *data) | 5319 | static 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 | ||
5348 | static int elpg_residency_show(struct seq_file *s, void *data) | 5354 | static 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 | ||
5388 | static int elpg_residency_open(struct inode *inode, struct file *file) | 5400 | static 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 | ||
5393 | static const struct file_operations elpg_residency_fops = { | 5405 | static 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 = { | |||
5400 | static int elpg_transitions_show(struct seq_file *s, void *data) | 5412 | static 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 | ||
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h index 32e2ef54..d7ab928b 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * GK20A PMU (aka. gPMU outside gk20a context) | 4 | * GK20A PMU (aka. gPMU outside gk20a context) |
5 | * | 5 | * |
6 | * Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved. | 6 | * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved. |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
9 | * under the terms and conditions of the GNU General Public License, | 9 | * under the terms and conditions of the GNU General Public License, |
@@ -566,6 +566,33 @@ struct pmu_sequence { | |||
566 | void* cb_params; | 566 | void* cb_params; |
567 | }; | 567 | }; |
568 | 568 | ||
569 | struct pmu_pg_stats_data { | ||
570 | u32 gating_cnt; | ||
571 | u32 ingating_time; | ||
572 | u32 ungating_time; | ||
573 | u32 avg_entry_latency_us; | ||
574 | u32 avg_exit_latency_us; | ||
575 | }; | ||
576 | |||
577 | struct pmu_pg_stats_v2 { | ||
578 | u32 entry_count; | ||
579 | u32 exit_count; | ||
580 | u32 abort_count; | ||
581 | u32 detection_count; | ||
582 | u32 prevention_activate_count; | ||
583 | u32 prevention_deactivate_count; | ||
584 | u32 powered_up_time_us; | ||
585 | u32 entry_latency_us; | ||
586 | u32 exit_latency_us; | ||
587 | u32 resident_time_us; | ||
588 | u32 entry_latency_avg_us; | ||
589 | u32 exit_latency_avg_us; | ||
590 | u32 entry_latency_max_us; | ||
591 | u32 exit_latency_max_us; | ||
592 | u32 total_sleep_time_us; | ||
593 | u32 total_non_sleep_time_us; | ||
594 | }; | ||
595 | |||
569 | struct pmu_pg_stats_v1 { | 596 | struct pmu_pg_stats_v1 { |
570 | /* Number of time PMU successfully engaged sleep state */ | 597 | /* Number of time PMU successfully engaged sleep state */ |
571 | u32 entry_count; | 598 | u32 entry_count; |
@@ -825,7 +852,7 @@ int pmu_wait_message_cond(struct pmu_gk20a *pmu, u32 timeout_ms, | |||
825 | void pmu_handle_fecs_boot_acr_msg(struct gk20a *g, struct pmu_msg *msg, | 852 | void pmu_handle_fecs_boot_acr_msg(struct gk20a *g, struct pmu_msg *msg, |
826 | void *param, u32 handle, u32 status); | 853 | void *param, u32 handle, u32 status); |
827 | void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id, | 854 | void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id, |
828 | u32 *ingating_time, u32 *ungating_time, u32 *gating_cnt); | 855 | struct pmu_pg_stats_data *pg_stat_data); |
829 | int gk20a_pmu_reset(struct gk20a *g); | 856 | int gk20a_pmu_reset(struct gk20a *g); |
830 | int pmu_idle(struct pmu_gk20a *pmu); | 857 | int pmu_idle(struct pmu_gk20a *pmu); |
831 | int pmu_enable_hw(struct pmu_gk20a *pmu, bool enable); | 858 | int pmu_enable_hw(struct pmu_gk20a *pmu, bool enable); |