From e875b4a66c71fbd9b0a978fadfd0de6cd4a70248 Mon Sep 17 00:00:00 2001 From: Deepak Goyal Date: Tue, 12 Jul 2016 11:12:44 +0530 Subject: gpu: nvgpu: Debugfs support for Railgating stats. This patch calculates: -Total time spent by GPU with rails gated. -Total time spent by GPU with rails ungated. -Total Railgating Cycles. and dumps this information in debugfs file. This feature requires CONFIG_DEBUG_FS set to true. Bug 200195100 Change-Id: I1379f11237ce4900076947e18524caaa3304c7cb Signed-off-by: Deepak Goyal Reviewed-on: http://git-master/r/1178308 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Vijayakumar Subbu --- drivers/gpu/nvgpu/gk20a/gk20a.c | 97 +++++++++++++++++++++++++++++++++++++++++ drivers/gpu/nvgpu/gk20a/gk20a.h | 15 +++++++ 2 files changed, 112 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index ab417386..9255c847 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c @@ -94,6 +94,71 @@ u32 gk20a_dbg_ftrace; static int gk20a_pm_prepare_poweroff(struct device *dev); +#ifdef CONFIG_DEBUG_FS +static int railgate_residency_show(struct seq_file *s, void *data) +{ + struct device *dev = s->private; + struct gk20a_platform *platform = dev_get_drvdata(dev); + struct gk20a *g = get_gk20a(dev); + unsigned long time_since_last_state_transition_ms; + unsigned long total_rail_gate_time_ms; + unsigned long total_rail_ungate_time_ms; + + if (platform->is_railgated(dev)) { + time_since_last_state_transition_ms = + jiffies_to_msecs(jiffies - + g->pstats.last_rail_gate_complete); + total_rail_ungate_time_ms = g->pstats.total_rail_ungate_time_ms; + total_rail_gate_time_ms = + g->pstats.total_rail_gate_time_ms + + time_since_last_state_transition_ms; + } else { + time_since_last_state_transition_ms = + jiffies_to_msecs(jiffies - + g->pstats.last_rail_ungate_complete); + total_rail_gate_time_ms = g->pstats.total_rail_gate_time_ms; + total_rail_ungate_time_ms = + g->pstats.total_rail_ungate_time_ms + + time_since_last_state_transition_ms; + } + + seq_printf(s, "Time with Rails Gated: %lu ms\n" + "Time with Rails UnGated: %lu ms\n" + "Total railgating cycles: %lu\n", + total_rail_gate_time_ms, + total_rail_ungate_time_ms, + g->pstats.railgating_cycle_count - 1); + return 0; + +} + +static int railgate_residency_open(struct inode *inode, struct file *file) +{ + return single_open(file, railgate_residency_show, inode->i_private); +} + +static const struct file_operations railgate_residency_fops = { + .open = railgate_residency_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +int gk20a_railgating_debugfs_init(struct device *dev) +{ + struct dentry *d; + struct gk20a_platform *platform = dev_get_drvdata(dev); + + d = debugfs_create_file( + "railgate_residency", S_IRUGO|S_IWUSR, platform->debugfs, dev, + &railgate_residency_fops); + if (!d) + return -ENOMEM; + + return 0; +} +#endif + static inline void set_gk20a(struct platform_device *pdev, struct gk20a *gk20a) { gk20a_get_platform(&pdev->dev)->g = gk20a; @@ -1133,10 +1198,25 @@ static int gk20a_pm_railgate(struct device *dev) { struct gk20a_platform *platform = dev_get_drvdata(dev); int ret = 0; +#ifdef CONFIG_DEBUG_FS + struct gk20a *g = get_gk20a(dev); + + g->pstats.last_rail_gate_start = jiffies; + + if (g->pstats.railgating_cycle_count >= 1) + g->pstats.total_rail_ungate_time_ms = + g->pstats.total_rail_ungate_time_ms + + jiffies_to_msecs(g->pstats.last_rail_gate_start - + g->pstats.last_rail_ungate_complete); +#endif if (platform->railgate) ret = platform->railgate(dev); +#ifdef CONFIG_DEBUG_FS + g->pstats.last_rail_gate_complete = jiffies; +#endif + return ret; } @@ -1144,6 +1224,18 @@ static int gk20a_pm_unrailgate(struct device *dev) { struct gk20a_platform *platform = dev_get_drvdata(dev); int ret = 0; +#ifdef CONFIG_DEBUG_FS + struct gk20a *g = get_gk20a(dev); + + g->pstats.last_rail_ungate_start = jiffies; + if (g->pstats.railgating_cycle_count >= 1) + g->pstats.total_rail_gate_time_ms = + g->pstats.total_rail_gate_time_ms + + jiffies_to_msecs(g->pstats.last_rail_ungate_start - + g->pstats.last_rail_gate_complete); + + g->pstats.railgating_cycle_count++; +#endif trace_gk20a_pm_unrailgate(dev_name(dev)); @@ -1153,6 +1245,10 @@ static int gk20a_pm_unrailgate(struct device *dev) mutex_unlock(&platform->railgate_lock); } +#ifdef CONFIG_DEBUG_FS + g->pstats.last_rail_ungate_complete = jiffies; +#endif + return ret; } @@ -1531,6 +1627,7 @@ static int gk20a_probe(struct platform_device *dev) gr_gk20a_debugfs_init(gk20a); gk20a_pmu_debugfs_init(&dev->dev); + gk20a_railgating_debugfs_init(&dev->dev); gk20a_cde_debugfs_init(&dev->dev); gk20a_alloc_debugfs_init(dev); gk20a_mm_debugfs_init(&dev->dev); diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 949cd4a5..c5da68cc 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -64,6 +64,18 @@ struct cooling_device_gk20a { struct gk20a *g; }; +#ifdef CONFIG_DEBUG_FS +struct railgate_stats { + unsigned long last_rail_gate_start; + unsigned long last_rail_gate_complete; + unsigned long last_rail_ungate_start; + unsigned long last_rail_ungate_complete; + unsigned long total_rail_gate_time_ms; + unsigned long total_rail_ungate_time_ms; + unsigned long railgating_cycle_count; +}; +#endif + enum gk20a_cbc_op { gk20a_cbc_op_clear, gk20a_cbc_op_clean, @@ -687,6 +699,9 @@ struct gk20a { struct acr_desc acr; struct cooling_device_gk20a gk20a_cdev; +#ifdef CONFIG_DEBUG_FS + struct railgate_stats pstats; +#endif /* Save pmu fw here so that it lives cross suspend/resume. pmu suspend destroys all pmu sw/hw states. Loading pmu fw in resume crashes when the resume is from sys_exit. */ -- cgit v1.2.2