From e9a6d179a42e7bdd6bb4876fb14f4ff7ab0df852 Mon Sep 17 00:00:00 2001 From: Arun Kannan Date: Mon, 5 Mar 2018 14:32:08 -0800 Subject: gpu: nvgpu: cache gpu clk rate Cache the rate used in clk_set_rate(). Return that cached rate on clk_get_rate(), don't read from hardware. This cached rate is used to avoid duplicate requests to clk_set_rate(). Motivation is to support multiple governors for gpu clk. Reading clock from hardware is unreliable in multi-governor situation. Relying on hardware clock value could mislead the kernel gpu governor in its scaling calculations. Bug 2051688 Change-Id: I43fc056eea6f69fe0889c45640fcb892b658071c Signed-off-by: Arun Kannan (cherry picked from commit 7f819a9ba707e6e905168b00b0f3bf6348e86188) Reviewed-on: https://git-master.nvidia.com/r/1662759 Reviewed-on: https://git-master.nvidia.com/r/1668919 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: svc-mobile-coverity GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/common/linux/clk.c | 19 ++++++++++++++----- drivers/gpu/nvgpu/common/linux/platform_gk20a.h | 3 +++ drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.c | 2 ++ drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c | 6 +++++- 4 files changed, 24 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/nvgpu/common') diff --git a/drivers/gpu/nvgpu/common/linux/clk.c b/drivers/gpu/nvgpu/common/linux/clk.c index ea5b023d..8bffc07b 100644 --- a/drivers/gpu/nvgpu/common/linux/clk.c +++ b/drivers/gpu/nvgpu/common/linux/clk.c @@ -1,7 +1,7 @@ /* * Linux clock support * - * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -34,9 +34,13 @@ static unsigned long nvgpu_linux_clk_get_rate(struct gk20a *g, u32 api_domain) switch (api_domain) { case CTRL_CLK_DOMAIN_GPCCLK: if (g->clk.tegra_clk) - ret = clk_get_rate(g->clk.tegra_clk); + ret = g->clk.cached_rate ? + g->clk.cached_rate : + clk_get_rate(g->clk.tegra_clk); else - ret = clk_get_rate(platform->clk[0]); + ret = platform->cached_rate ? + platform->cached_rate : + clk_get_rate(platform->clk[0]); break; case CTRL_CLK_DOMAIN_PWRCLK: ret = clk_get_rate(platform->clk[1]); @@ -58,10 +62,15 @@ static int nvgpu_linux_clk_set_rate(struct gk20a *g, switch (api_domain) { case CTRL_CLK_DOMAIN_GPCCLK: - if (g->clk.tegra_clk) + if (g->clk.tegra_clk) { ret = clk_set_rate(g->clk.tegra_clk, rate); - else + if (!ret) + g->clk.cached_rate = rate; + } else { ret = clk_set_rate(platform->clk[0], rate); + if (!ret) + platform->cached_rate = rate; + } break; case CTRL_CLK_DOMAIN_PWRCLK: ret = clk_set_rate(platform->clk[1], rate); diff --git a/drivers/gpu/nvgpu/common/linux/platform_gk20a.h b/drivers/gpu/nvgpu/common/linux/platform_gk20a.h index aed50ed7..43afbbf9 100644 --- a/drivers/gpu/nvgpu/common/linux/platform_gk20a.h +++ b/drivers/gpu/nvgpu/common/linux/platform_gk20a.h @@ -256,6 +256,9 @@ struct gk20a_platform { /* stream id to use */ u32 ltc_streamid; + + /* scaling rate */ + unsigned long cached_rate; }; static inline struct gk20a_platform *gk20a_get_platform( diff --git a/drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.c b/drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.c index 3e1c6996..82648ca3 100644 --- a/drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.c +++ b/drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.c @@ -506,6 +506,8 @@ static int gk20a_tegra_get_clocks(struct device *dev) rate = clk_round_rate(c, rate); clk_set_rate(c, rate); platform->clk[i] = c; + if (i == 0) + platform->cached_rate = rate; } platform->num_clks = i; diff --git a/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c b/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c index 782a3d88..96acf24b 100644 --- a/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c +++ b/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c @@ -57,11 +57,13 @@ gp10b_freq_table[GP10B_MAX_SUPPORTED_FREQS / GP10B_FREQ_SELECT_STEP]; #define EMC_BW_RATIO (TEGRA_GP10B_BW_PER_FREQ / TEGRA_DDR4_BW_PER_FREQ) +#define GPCCLK_INIT_RATE 1000000000 + static struct { char *name; unsigned long default_rate; } tegra_gp10b_clocks[] = { - {"gpu", 1000000000}, + {"gpu", GPCCLK_INIT_RATE}, {"gpu_sys", 204000000} }; static void gr_gp10b_remove_sysfs(struct device *dev); @@ -90,6 +92,8 @@ int gp10b_tegra_get_clocks(struct device *dev) } else { clk_set_rate(c, rate); platform->clk[i] = c; + if (i == 0) + platform->cached_rate = rate; } } platform->num_clks = i; -- cgit v1.2.2