From c99819ffd8c4fe4270aee461da377bb1d0f68436 Mon Sep 17 00:00:00 2001 From: Sagar Kamble Date: Sat, 2 Jul 2022 22:12:02 +0530 Subject: [PATCH] gpu: nvgpu: acquire platforms clocks on floorsweeping gpc bpmp will floorsweep GPCs as per parameters to tpc_pg_mask sysfs. While doing that corresponding GPC clocks are also disabled. nvgpu should re-initialize the clocks every time the GPC/TPC pg_masks are passed to bpmp mrq. Also print error when clk_prepare_enable fails. Introduce platform->clks_lock to protect access to platform->clks and platform->num_clks done from unrailgate/railgate and bpmp mrq set calls from sysfs. Acquire static_pg_lock in railgate path to synchronize railgate with sysfs. Bug 3688506 Change-Id: I3203d78b87289e7a847d78b3117e2d3119be3425 Signed-off-by: Sagar Kamble Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2738920 (cherry picked from commit 28ddb0996ff19c21fbefd4cf8d8359e6d6bce779) Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2741029 Reviewed-by: svc-mobile-coverity Reviewed-by: Vijayakumar Subbu GVS: Gerrit_Virtual_Submit --- drivers/gpu/nvgpu/os/linux/module.c | 5 +++ .../gpu/nvgpu/os/linux/platform_ga10b_tegra.c | 44 ++++++++++++++----- drivers/gpu/nvgpu/os/linux/platform_gk20a.h | 3 ++ .../gpu/nvgpu/os/linux/platform_gp10b_tegra.c | 16 ++++++- .../gpu/nvgpu/os/linux/platform_gv11b_tegra.c | 3 ++ 5 files changed, 60 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/nvgpu/os/linux/module.c b/drivers/gpu/nvgpu/os/linux/module.c index 0fd9ca926..163ab1f74 100644 --- a/drivers/gpu/nvgpu/os/linux/module.c +++ b/drivers/gpu/nvgpu/os/linux/module.c @@ -1177,12 +1177,17 @@ static int gk20a_pm_railgate(struct device *dev) g->pstats.last_rail_ungate_complete); #endif + nvgpu_mutex_acquire(&g->static_pg_lock); + ret = platform->railgate(dev); if (ret) { nvgpu_err(g, "failed to railgate platform, err=%d", ret); + nvgpu_mutex_release(&g->static_pg_lock); return ret; } + nvgpu_mutex_release(&g->static_pg_lock); + #ifdef CONFIG_DEBUG_FS g->pstats.last_rail_gate_complete = jiffies; #endif diff --git a/drivers/gpu/nvgpu/os/linux/platform_ga10b_tegra.c b/drivers/gpu/nvgpu/os/linux/platform_ga10b_tegra.c index 19bb0a4b4..2dbb06853 100644 --- a/drivers/gpu/nvgpu/os/linux/platform_ga10b_tegra.c +++ b/drivers/gpu/nvgpu/os/linux/platform_ga10b_tegra.c @@ -123,14 +123,16 @@ static bool ga10b_tegra_is_clock_available(struct gk20a *g, char *clk_name) } if ((strcmp(clk_name, "gpc0clk") == 0) && - (gpc_disable & NVGPU_GPC0_DISABLE)) { - nvgpu_info(g, "GPC0 is floor-swept"); + ((gpc_disable & NVGPU_GPC0_DISABLE) || + (g->gpc_pg_mask & NVGPU_GPC0_DISABLE))) { + nvgpu_log_info(g, "GPC0 is floor-swept"); return false; } if ((strcmp(clk_name, "gpc1clk") == 0) && - (gpc_disable & NVGPU_GPC1_DISABLE)) { - nvgpu_info(g, "GPC1 is floor-swept"); + ((gpc_disable & NVGPU_GPC1_DISABLE) || + (g->gpc_pg_mask & NVGPU_GPC1_DISABLE))) { + nvgpu_log_info(g, "GPC1 is floor-swept"); return false; } @@ -149,7 +151,7 @@ static int ga10b_tegra_acquire_platform_clocks(struct device *dev, struct gk20a_platform *platform = dev_get_drvdata(dev); struct gk20a *g = platform->g; struct device_node *np = nvgpu_get_node(g); - unsigned int i, num_clks_dt; + unsigned int i, j = 0, num_clks_dt; int err; /* Get clocks only on supported platforms(silicon and fpga) */ @@ -167,6 +169,8 @@ static int ga10b_tegra_acquire_platform_clocks(struct device *dev, return -ENODEV; } + nvgpu_mutex_acquire(&platform->clks_lock); + platform->num_clks = 0; for (i = 0; i < num_clks_dt; i++) { @@ -187,11 +191,17 @@ static int ga10b_tegra_acquire_platform_clocks(struct device *dev, } else { rate = clk_entries[i].default_rate; clk_set_rate(c, rate); - platform->clk[i] = c; + + /* + * Note that DT clocks are iterated by index 'i' and + * available clocks are iterated by index 'j' in the + * platform->clk array. + */ + platform->clk[j++] = c; } } - platform->num_clks = i; + platform->num_clks = j; #ifdef CONFIG_NV_TEGRA_BPMP if (platform->clk[0]) { @@ -202,14 +212,18 @@ static int ga10b_tegra_acquire_platform_clocks(struct device *dev, } #endif + nvgpu_mutex_release(&platform->clks_lock); + return 0; err_get_clock: - while (i > 0 && i--) { - clk_put(platform->clk[i]); - platform->clk[i] = NULL; + while (j > 0 && j--) { + clk_put(platform->clk[j]); + platform->clk[j] = NULL; } + nvgpu_mutex_release(&platform->clks_lock); + return err; } @@ -292,6 +306,8 @@ static int ga10b_tegra_probe(struct device *dev) nvgpu_set_enabled(g, NVGPU_CAN_RAILGATE, false); } + nvgpu_mutex_init(&platform->clks_lock); + err = ga10b_tegra_get_clocks(dev); if (err != 0) { return err; @@ -326,6 +342,7 @@ static int ga10b_tegra_remove(struct device *dev) #endif nvgpu_mutex_destroy(&platform->clk_get_freq_lock); + nvgpu_mutex_destroy(&platform->clks_lock); return 0; } @@ -434,6 +451,13 @@ static int ga10b_tegra_bpmp_mrq_set(struct device *dev) return ret; } } + + /* re-initialize the clocks */ + ret = ga10b_tegra_get_clocks(dev); + if (ret != 0) { + nvgpu_err(g, "get clocks failed "); + return ret; + } } } return 0; diff --git a/drivers/gpu/nvgpu/os/linux/platform_gk20a.h b/drivers/gpu/nvgpu/os/linux/platform_gk20a.h index a9255fa87..62fdb9f63 100644 --- a/drivers/gpu/nvgpu/os/linux/platform_gk20a.h +++ b/drivers/gpu/nvgpu/os/linux/platform_gk20a.h @@ -342,6 +342,9 @@ struct gk20a_platform { /* synchronized access to platform->clk_get_freqs */ struct nvgpu_mutex clk_get_freq_lock; + + /* synchronized access to platform->clks */ + struct nvgpu_mutex clks_lock; }; static inline struct gk20a_platform *gk20a_get_platform( diff --git a/drivers/gpu/nvgpu/os/linux/platform_gp10b_tegra.c b/drivers/gpu/nvgpu/os/linux/platform_gp10b_tegra.c index 487c559f8..c9e46ecaf 100644 --- a/drivers/gpu/nvgpu/os/linux/platform_gp10b_tegra.c +++ b/drivers/gpu/nvgpu/os/linux/platform_gp10b_tegra.c @@ -96,6 +96,8 @@ int gp10b_tegra_acquire_platform_clocks(struct device *dev, return -ENODEV; } + nvgpu_mutex_acquire(&platform->clks_lock); + platform->num_clks = 0; for (i = 0; i < num_clks_dt; i++) { @@ -124,6 +126,8 @@ int gp10b_tegra_acquire_platform_clocks(struct device *dev, } #endif + nvgpu_mutex_release(&platform->clks_lock); + return 0; err_get_clock: @@ -132,6 +136,8 @@ err_get_clock: platform->clk[i] = NULL; } + nvgpu_mutex_release(&platform->clks_lock); + return err; } @@ -166,8 +172,11 @@ void gp10b_tegra_clks_control(struct device *dev, bool enable) { struct gk20a_platform *platform = gk20a_get_platform(dev); struct gk20a *g = get_gk20a(dev); + int err; int i; + nvgpu_mutex_acquire(&platform->clks_lock); + for (i = 0; i < platform->num_clks; i++) { if (!platform->clk[i]) { continue; @@ -176,13 +185,18 @@ void gp10b_tegra_clks_control(struct device *dev, bool enable) if (enable) { nvgpu_log(g, gpu_dbg_info, "clk_prepare_enable"); - clk_prepare_enable(platform->clk[i]); + err = clk_prepare_enable(platform->clk[i]); + if (err != 0) { + nvgpu_err(g, "could not turn on clock %d", i); + } } else { nvgpu_log(g, gpu_dbg_info, "clk_disable_unprepare"); clk_disable_unprepare(platform->clk[i]); } } + + nvgpu_mutex_release(&platform->clks_lock); } int gp10b_tegra_reset_assert(struct device *dev) diff --git a/drivers/gpu/nvgpu/os/linux/platform_gv11b_tegra.c b/drivers/gpu/nvgpu/os/linux/platform_gv11b_tegra.c index b0ca6538d..62e4f132a 100644 --- a/drivers/gpu/nvgpu/os/linux/platform_gv11b_tegra.c +++ b/drivers/gpu/nvgpu/os/linux/platform_gv11b_tegra.c @@ -105,6 +105,8 @@ static int gv11b_tegra_probe(struct device *dev) nvgpu_set_enabled(g, NVGPU_CAN_RAILGATE, false); } + nvgpu_mutex_init(&platform->clks_lock); + err = gp10b_tegra_get_clocks(dev); if (err != 0) { return err; @@ -140,6 +142,7 @@ static int gv11b_tegra_remove(struct device *dev) #endif nvgpu_mutex_destroy(&platform->clk_get_freq_lock); + nvgpu_mutex_destroy(&platform->clks_lock); return 0; }