From 6965343d134b977fdc553e4922f0cd9326754bbc Mon Sep 17 00:00:00 2001 From: Debarshi Dutta Date: Mon, 13 Jun 2022 12:18:42 +0530 Subject: [PATCH] gpu: nvgpu: don't skip setting same clk in arbiter In the current setting, clock arbiter skips setting the clock if its already set previously. The value set by the arbiter is stored in "struct nvgpu_clk_arb->actual" whenever the clock is updated via the arbiter. However, DVFS might also update the clock and the updates are not synchronized with the arbiter. Hence, ensure that any clock requests are always updated i.e. the requested rate is set even if the previous rate remains the same. In the devfreq scale() part, scale emc when clk_arb is active and skip setting of clocks. Note that this is cherry-pick from dev-main. Previously merged cherry-pick is not complete. Bug 3666615 Bug 3852824 Change-Id: I480a816434dcd59d18a287954a536fd7061c707c Signed-off-by: Debarshi Dutta Signed-off-by: Sagar Kamble Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2822685 Reviewed-by: Ankur Kishore GVS: Gerrit_Virtual_Submit --- drivers/gpu/nvgpu/common/clk_arb/clk_arb_gp10b.c | 2 ++ drivers/gpu/nvgpu/os/linux/driver_common.c | 3 +++ drivers/gpu/nvgpu/os/linux/scale.c | 9 ++++++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/nvgpu/common/clk_arb/clk_arb_gp10b.c b/drivers/gpu/nvgpu/common/clk_arb/clk_arb_gp10b.c index 575d6ff12..81bda15a7 100644 --- a/drivers/gpu/nvgpu/common/clk_arb/clk_arb_gp10b.c +++ b/drivers/gpu/nvgpu/common/clk_arb/clk_arb_gp10b.c @@ -338,6 +338,8 @@ void gp10b_clk_arb_run_arbiter_cb(struct nvgpu_clk_arb *arb) goto exit_arb; } + g->last_freq = rounded_rate; + actual = ((NV_READ_ONCE(arb->actual)) == &arb->actual_pool[0] ? &arb->actual_pool[1] : &arb->actual_pool[0]); diff --git a/drivers/gpu/nvgpu/os/linux/driver_common.c b/drivers/gpu/nvgpu/os/linux/driver_common.c index 8753f6076..db3ede607 100644 --- a/drivers/gpu/nvgpu/os/linux/driver_common.c +++ b/drivers/gpu/nvgpu/os/linux/driver_common.c @@ -100,6 +100,9 @@ static void nvgpu_init_vars(struct gk20a *g) /* Init the clock req count to 0 */ nvgpu_atomic_set(&g->clk_arb_global_nr, 0); + /* Atomic set doesn't guarantee a barrier */ + nvgpu_smp_wmb(); + nvgpu_mutex_init(&l->ctrl_privs_lock); nvgpu_init_list_node(&l->ctrl_privs); diff --git a/drivers/gpu/nvgpu/os/linux/scale.c b/drivers/gpu/nvgpu/os/linux/scale.c index 3ab9c9331..7e669120a 100644 --- a/drivers/gpu/nvgpu/os/linux/scale.c +++ b/drivers/gpu/nvgpu/os/linux/scale.c @@ -163,11 +163,13 @@ static int gk20a_scale_target(struct device *dev, unsigned long *freq, struct devfreq *devfreq = l->devfreq; #endif unsigned long local_freq = *freq; - unsigned long rounded_rate; + unsigned long rounded_rate = 0; unsigned long min_freq = 0, max_freq = 0; - if (nvgpu_clk_arb_has_active_req(g)) - return 0; + if (nvgpu_clk_arb_has_active_req(g)) { + rounded_rate = g->last_freq; + goto post_scale; + } /* * Calculate floor and cap frequency values * @@ -222,6 +224,7 @@ static int gk20a_scale_target(struct device *dev, unsigned long *freq, g->last_freq = *freq; +post_scale: /* postscale will only scale emc (dram clock) if evaluating * gk20a_tegra_get_emc_rate() produces a new or different emc * target because the load or_and gpufreq has changed */