From 7a28547892bfa73d31c1423b33e98030840a4f6d Mon Sep 17 00:00:00 2001 From: Alex Frid Date: Tue, 8 May 2018 18:58:22 -0700 Subject: gpu: nvgpu: Fix Gpu sysfs access to Fmax@Vmin Currently gpu sysfs retrieves Fmax@Vmin by direct call into Tegra DVFS driver that introduces compile time dependencies on CONFIG_TEGRA_DVFS. In addition incorrect clock is used for DVFS information access. Re-factored sysfs node to use generic GPU clock operation for Fmax@Vmin read. This would fix a bug in target clock selection, and allows to remove dependency of sysfs on CONFIG_TEGRA_DVFS. Updated nvgpu_linux_get_fmax_at_vmin_safe operation itself so it can be called on platforms that does not support Tegra DVFS, although 0 will still be returned as Fmax@Vmin on such platforms. Bug 2045903 Change-Id: I32cce25320df026288c82458c913b0cde9ad4f72 Signed-off-by: Alex Frid Reviewed-on: https://git-master.nvidia.com/r/1710924 Reviewed-by: Alex Waterman GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/common/linux/clk.c | 15 +++++++++------ drivers/gpu/nvgpu/common/linux/sysfs.c | 17 ++++++----------- drivers/gpu/nvgpu/gk20a/gk20a.h | 2 +- drivers/gpu/nvgpu/gm20b/clk_gm20b.c | 2 +- 4 files changed, 17 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/nvgpu/common/linux/clk.c b/drivers/gpu/nvgpu/common/linux/clk.c index 8bffc07b..a0e56455 100644 --- a/drivers/gpu/nvgpu/common/linux/clk.c +++ b/drivers/gpu/nvgpu/common/linux/clk.c @@ -84,15 +84,18 @@ static int nvgpu_linux_clk_set_rate(struct gk20a *g, return ret; } -static unsigned long nvgpu_linux_get_fmax_at_vmin_safe(struct clk_gk20a *clk) +static unsigned long nvgpu_linux_get_fmax_at_vmin_safe(struct gk20a *g) { /* - * On Tegra GPU clock exposed to frequency governor is a shared user on - * GPCPLL bus (gbus). The latter can be accessed as GPU clock parent. - * Respectively the grandparent is PLL reference clock. + * On Tegra platforms with GPCPLL bus (gbus) GPU tegra_clk clock exposed + * to frequency governor is a shared user on the gbus. The latter can be + * accessed as GPU clock parent, and incorporate DVFS related data. */ - return tegra_dvfs_get_fmax_at_vmin_safe_t( - clk_get_parent(clk->tegra_clk)); + if (g->clk.tegra_clk) + return tegra_dvfs_get_fmax_at_vmin_safe_t( + clk_get_parent(g->clk.tegra_clk)); + + return 0; } static u32 nvgpu_linux_get_ref_clock_rate(struct gk20a *g) diff --git a/drivers/gpu/nvgpu/common/linux/sysfs.c b/drivers/gpu/nvgpu/common/linux/sysfs.c index 1f6da803..e425e153 100644 --- a/drivers/gpu/nvgpu/common/linux/sysfs.c +++ b/drivers/gpu/nvgpu/common/linux/sysfs.c @@ -17,9 +17,6 @@ #include #include #include -#ifdef CONFIG_TEGRA_DVFS -#include -#endif #include #include @@ -781,21 +778,19 @@ static ssize_t emc3d_ratio_read(struct device *dev, static DEVICE_ATTR(emc3d_ratio, ROOTRW, emc3d_ratio_read, emc3d_ratio_store); -#ifdef CONFIG_TEGRA_DVFS static ssize_t fmax_at_vmin_safe_read(struct device *dev, struct device_attribute *attr, char *buf) { struct gk20a *g = get_gk20a(dev); unsigned long gpu_fmax_at_vmin_hz = 0; - struct clk *clk = g->clk.tegra_clk; - gpu_fmax_at_vmin_hz = tegra_dvfs_get_fmax_at_vmin_safe_t(clk); + if (g->ops.clk.get_fmax_at_vmin_safe) + gpu_fmax_at_vmin_hz = g->ops.clk.get_fmax_at_vmin_safe(g); return snprintf(buf, PAGE_SIZE, "%d\n", (int)(gpu_fmax_at_vmin_hz)); } static DEVICE_ATTR(fmax_at_vmin_safe, S_IRUGO, fmax_at_vmin_safe_read, NULL); -#endif #ifdef CONFIG_PM static ssize_t force_idle_store(struct device *dev, @@ -1116,9 +1111,9 @@ void nvgpu_remove_sysfs(struct device *dev) device_remove_file(dev, &dev_attr_elpg_enable); device_remove_file(dev, &dev_attr_mscg_enable); device_remove_file(dev, &dev_attr_emc3d_ratio); -#ifdef CONFIG_TEGRA_DVFS + device_remove_file(dev, &dev_attr_fmax_at_vmin_safe); -#endif + device_remove_file(dev, &dev_attr_counters); device_remove_file(dev, &dev_attr_counters_reset); device_remove_file(dev, &dev_attr_load); @@ -1167,9 +1162,9 @@ int nvgpu_create_sysfs(struct device *dev) error |= device_create_file(dev, &dev_attr_mscg_enable); error |= device_create_file(dev, &dev_attr_emc3d_ratio); error |= device_create_file(dev, &dev_attr_ldiv_slowdown_factor); -#ifdef CONFIG_TEGRA_DVFS + error |= device_create_file(dev, &dev_attr_fmax_at_vmin_safe); -#endif + error |= device_create_file(dev, &dev_attr_counters); error |= device_create_file(dev, &dev_attr_counters_reset); error |= device_create_file(dev, &dev_attr_load); diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index aac3380e..c05bc046 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -1002,7 +1002,7 @@ struct gpu_ops { unsigned long (*measure_freq)(struct gk20a *g, u32 api_domain); unsigned long (*get_rate)(struct gk20a *g, u32 api_domain); int (*set_rate)(struct gk20a *g, u32 api_domain, unsigned long rate); - unsigned long (*get_fmax_at_vmin_safe)(struct clk_gk20a *clk); + unsigned long (*get_fmax_at_vmin_safe)(struct gk20a *g); u32 (*get_ref_clock_rate)(struct gk20a *g); int (*predict_mv_at_hz_cur_tfloor)(struct clk_gk20a *clk, unsigned long rate); diff --git a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c index fb89752a..223166d1 100644 --- a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c @@ -1197,7 +1197,7 @@ int gm20b_init_clk_setup_sw(struct gk20a *g) goto fail; } - safe_rate = g->ops.clk.get_fmax_at_vmin_safe(clk); + safe_rate = g->ops.clk.get_fmax_at_vmin_safe(g); safe_rate = safe_rate * (100 - DVFS_SAFE_MARGIN) / 100; clk->dvfs_safe_max_freq = rate_gpu_to_gpc2clk(safe_rate); clk->gpc_pll.PL = (clk->dvfs_safe_max_freq == 0) ? 0 : -- cgit v1.2.2