linux-arm-msm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] drm/msm: Improved devfreq tuning
@ 2021-07-26 14:46 Rob Clark
  2021-07-26 14:46 ` [PATCH v2 1/3] drm/msm: Split out devfreq handling Rob Clark
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Rob Clark @ 2021-07-26 14:46 UTC (permalink / raw)
  To: dri-devel
  Cc: Rob Clark, Akhil P Oommen, Douglas Anderson,
	open list:DRM DRIVER FOR MSM ADRENO GPU, Jonathan Marek,
	Jordan Crouse, open list:DRM DRIVER FOR MSM ADRENO GPU,
	open list, Sai Prakash Ranjan, Sharat Masetty

From: Rob Clark <robdclark@chromium.org>

This is the outcome of trying to fix some bad gpu freq behavior seen in
some use-cases, in particular mobile games that throttle themselves to
30fps.  With the existing tuning, we'd end up spending most of the time
that we should be running fast at a low freq, and most of the idle time
at a high freq.

First two patches are prep, 3/3 is the interesting bit.  See the patch
description in 3/3 for more details.

v2: struct_mutex serializes the submit path, but not the retire path,
    so add a dedicated lock to serialize active<->idle transitions.

Rob Clark (3):
  drm/msm: Split out devfreq handling
  drm/msm: Split out get_freq() helper
  drm/msm: Devfreq tuning

 drivers/gpu/drm/msm/Makefile          |   1 +
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c |   4 +-
 drivers/gpu/drm/msm/msm_gpu.c         | 132 +++--------------
 drivers/gpu/drm/msm/msm_gpu.h         |  61 +++++++-
 drivers/gpu/drm/msm/msm_gpu_devfreq.c | 203 ++++++++++++++++++++++++++
 5 files changed, 280 insertions(+), 121 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/msm_gpu_devfreq.c

-- 
2.31.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 1/3] drm/msm: Split out devfreq handling
  2021-07-26 14:46 [PATCH v2 0/3] drm/msm: Improved devfreq tuning Rob Clark
@ 2021-07-26 14:46 ` Rob Clark
  2021-07-27 20:11   ` Dmitry Baryshkov
  2021-07-26 14:46 ` [PATCH v2 2/3] drm/msm: Split out get_freq() helper Rob Clark
  2021-07-26 14:46 ` [PATCH v2 3/3] drm/msm: Devfreq tuning Rob Clark
  2 siblings, 1 reply; 6+ messages in thread
From: Rob Clark @ 2021-07-26 14:46 UTC (permalink / raw)
  To: dri-devel
  Cc: Rob Clark, Rob Clark, Sean Paul, David Airlie, Daniel Vetter,
	Jordan Crouse, Jonathan Marek, Akhil P Oommen,
	Sai Prakash Ranjan, Sharat Masetty, Douglas Anderson, open list,
	open list:DRM DRIVER FOR MSM ADRENO GPU,
	open list:DRM DRIVER FOR MSM ADRENO GPU

From: Rob Clark <robdclark@chromium.org>

Before we start adding more cleverness, split it into it's own file.

Signed-off-by: Rob Clark <robdclark@chromium.org>
---
 drivers/gpu/drm/msm/Makefile          |   1 +
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c |   4 +-
 drivers/gpu/drm/msm/msm_gpu.c         | 116 +---------------------
 drivers/gpu/drm/msm/msm_gpu.h         |  32 +++++--
 drivers/gpu/drm/msm/msm_gpu_devfreq.c | 133 ++++++++++++++++++++++++++
 5 files changed, 165 insertions(+), 121 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/msm_gpu_devfreq.c

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 2c00aa70b708..904535eda0c4 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -90,6 +90,7 @@ msm-y := \
 	msm_gem_submit.o \
 	msm_gem_vma.o \
 	msm_gpu.o \
+	msm_gpu_devfreq.o \
 	msm_iommu.o \
 	msm_perf.o \
 	msm_rd.o \
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 9db9f7847ea8..91f637b908f4 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -1477,7 +1477,7 @@ static int a6xx_pm_resume(struct msm_gpu *gpu)
 	if (ret)
 		return ret;
 
-	msm_gpu_resume_devfreq(gpu);
+	msm_devfreq_resume(gpu);
 
 	a6xx_llc_activate(a6xx_gpu);
 
@@ -1494,7 +1494,7 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu)
 
 	a6xx_llc_deactivate(a6xx_gpu);
 
-	devfreq_suspend_device(gpu->devfreq.devfreq);
+	msm_devfreq_suspend(gpu);
 
 	ret = a6xx_gmu_stop(a6xx_gpu);
 	if (ret)
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 647af45cf892..fedbd785e42f 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -13,8 +13,6 @@
 
 #include <generated/utsrelease.h>
 #include <linux/string_helpers.h>
-#include <linux/devfreq.h>
-#include <linux/devfreq_cooling.h>
 #include <linux/devcoredump.h>
 #include <linux/sched/task.h>
 
@@ -22,106 +20,6 @@
  * Power Management:
  */
 
-static int msm_devfreq_target(struct device *dev, unsigned long *freq,
-		u32 flags)
-{
-	struct msm_gpu *gpu = dev_to_gpu(dev);
-	struct dev_pm_opp *opp;
-
-	opp = devfreq_recommended_opp(dev, freq, flags);
-
-	if (IS_ERR(opp))
-		return PTR_ERR(opp);
-
-	trace_msm_gpu_freq_change(dev_pm_opp_get_freq(opp));
-
-	if (gpu->funcs->gpu_set_freq)
-		gpu->funcs->gpu_set_freq(gpu, opp);
-	else
-		clk_set_rate(gpu->core_clk, *freq);
-
-	dev_pm_opp_put(opp);
-
-	return 0;
-}
-
-static int msm_devfreq_get_dev_status(struct device *dev,
-		struct devfreq_dev_status *status)
-{
-	struct msm_gpu *gpu = dev_to_gpu(dev);
-	ktime_t time;
-
-	if (gpu->funcs->gpu_get_freq)
-		status->current_frequency = gpu->funcs->gpu_get_freq(gpu);
-	else
-		status->current_frequency = clk_get_rate(gpu->core_clk);
-
-	status->busy_time = gpu->funcs->gpu_busy(gpu);
-
-	time = ktime_get();
-	status->total_time = ktime_us_delta(time, gpu->devfreq.time);
-	gpu->devfreq.time = time;
-
-	return 0;
-}
-
-static int msm_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
-{
-	struct msm_gpu *gpu = dev_to_gpu(dev);
-
-	if (gpu->funcs->gpu_get_freq)
-		*freq = gpu->funcs->gpu_get_freq(gpu);
-	else
-		*freq = clk_get_rate(gpu->core_clk);
-
-	return 0;
-}
-
-static struct devfreq_dev_profile msm_devfreq_profile = {
-	.polling_ms = 10,
-	.target = msm_devfreq_target,
-	.get_dev_status = msm_devfreq_get_dev_status,
-	.get_cur_freq = msm_devfreq_get_cur_freq,
-};
-
-static void msm_devfreq_init(struct msm_gpu *gpu)
-{
-	/* We need target support to do devfreq */
-	if (!gpu->funcs->gpu_busy)
-		return;
-
-	msm_devfreq_profile.initial_freq = gpu->fast_rate;
-
-	/*
-	 * Don't set the freq_table or max_state and let devfreq build the table
-	 * from OPP
-	 * After a deferred probe, these may have be left to non-zero values,
-	 * so set them back to zero before creating the devfreq device
-	 */
-	msm_devfreq_profile.freq_table = NULL;
-	msm_devfreq_profile.max_state = 0;
-
-	gpu->devfreq.devfreq = devm_devfreq_add_device(&gpu->pdev->dev,
-			&msm_devfreq_profile, DEVFREQ_GOV_SIMPLE_ONDEMAND,
-			NULL);
-
-	if (IS_ERR(gpu->devfreq.devfreq)) {
-		DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n");
-		gpu->devfreq.devfreq = NULL;
-		return;
-	}
-
-	devfreq_suspend_device(gpu->devfreq.devfreq);
-
-	gpu->cooling = of_devfreq_cooling_register(gpu->pdev->dev.of_node,
-			gpu->devfreq.devfreq);
-	if (IS_ERR(gpu->cooling)) {
-		DRM_DEV_ERROR(&gpu->pdev->dev,
-				"Couldn't register GPU cooling device\n");
-		gpu->cooling = NULL;
-	}
-}
-
 static int enable_pwrrail(struct msm_gpu *gpu)
 {
 	struct drm_device *dev = gpu->dev;
@@ -196,14 +94,6 @@ static int disable_axi(struct msm_gpu *gpu)
 	return 0;
 }
 
-void msm_gpu_resume_devfreq(struct msm_gpu *gpu)
-{
-	gpu->devfreq.busy_cycles = 0;
-	gpu->devfreq.time = ktime_get();
-
-	devfreq_resume_device(gpu->devfreq.devfreq);
-}
-
 int msm_gpu_pm_resume(struct msm_gpu *gpu)
 {
 	int ret;
@@ -223,7 +113,7 @@ int msm_gpu_pm_resume(struct msm_gpu *gpu)
 	if (ret)
 		return ret;
 
-	msm_gpu_resume_devfreq(gpu);
+	msm_devfreq_resume(gpu);
 
 	gpu->needs_hw_init = true;
 
@@ -237,7 +127,7 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu)
 	DBG("%s", gpu->name);
 	trace_msm_gpu_suspend(0);
 
-	devfreq_suspend_device(gpu->devfreq.devfreq);
+	msm_devfreq_suspend(gpu);
 
 	ret = disable_axi(gpu);
 	if (ret)
@@ -1116,5 +1006,5 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
 		kthread_destroy_worker(gpu->worker);
 	}
 
-	devfreq_cooling_unregister(gpu->cooling);
+	msm_devfreq_cleanup(gpu);
 }
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index ef41ec09f59c..2e61d05293e6 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -80,6 +80,26 @@ struct msm_gpu_fault_info {
 	const char *block;
 };
 
+/**
+ * struct msm_gpu_devfreq - devfreq related state
+ */
+struct msm_gpu_devfreq {
+	/** devfreq: devfreq instance */
+	struct devfreq *devfreq;
+
+	/**
+	 * busy_cycles:
+	 *
+	 * Used by implementation of gpu->gpu_busy() to track the last
+	 * busy counter value, for calculating elapsed busy cycles since
+	 * last sampling period.
+	 */
+	u64 busy_cycles;
+
+	/** time: Time of last sampling period. */
+	ktime_t time;
+};
+
 struct msm_gpu {
 	const char *name;
 	struct drm_device *dev;
@@ -151,11 +171,7 @@ struct msm_gpu {
 
 	struct drm_gem_object *memptrs_bo;
 
-	struct {
-		struct devfreq *devfreq;
-		u64 busy_cycles;
-		ktime_t time;
-	} devfreq;
+	struct msm_gpu_devfreq devfreq;
 
 	uint32_t suspend_count;
 
@@ -301,7 +317,11 @@ static inline void gpu_write64(struct msm_gpu *gpu, u32 lo, u32 hi, u64 val)
 
 int msm_gpu_pm_suspend(struct msm_gpu *gpu);
 int msm_gpu_pm_resume(struct msm_gpu *gpu);
-void msm_gpu_resume_devfreq(struct msm_gpu *gpu);
+
+void msm_devfreq_init(struct msm_gpu *gpu);
+void msm_devfreq_cleanup(struct msm_gpu *gpu);
+void msm_devfreq_resume(struct msm_gpu *gpu);
+void msm_devfreq_suspend(struct msm_gpu *gpu);
 
 int msm_gpu_hw_init(struct msm_gpu *gpu);
 
diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
new file mode 100644
index 000000000000..3bcea0baddab
--- /dev/null
+++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ */
+
+#include "msm_gpu.h"
+#include "msm_gpu_trace.h"
+
+#include <linux/devfreq.h>
+#include <linux/devfreq_cooling.h>
+
+/*
+ * Power Management:
+ */
+
+static int msm_devfreq_target(struct device *dev, unsigned long *freq,
+		u32 flags)
+{
+	struct msm_gpu *gpu = dev_to_gpu(dev);
+	struct dev_pm_opp *opp;
+
+	opp = devfreq_recommended_opp(dev, freq, flags);
+
+	if (IS_ERR(opp))
+		return PTR_ERR(opp);
+
+	trace_msm_gpu_freq_change(dev_pm_opp_get_freq(opp));
+
+	if (gpu->funcs->gpu_set_freq)
+		gpu->funcs->gpu_set_freq(gpu, opp);
+	else
+		clk_set_rate(gpu->core_clk, *freq);
+
+	dev_pm_opp_put(opp);
+
+	return 0;
+}
+
+static int msm_devfreq_get_dev_status(struct device *dev,
+		struct devfreq_dev_status *status)
+{
+	struct msm_gpu *gpu = dev_to_gpu(dev);
+	ktime_t time;
+
+	if (gpu->funcs->gpu_get_freq)
+		status->current_frequency = gpu->funcs->gpu_get_freq(gpu);
+	else
+		status->current_frequency = clk_get_rate(gpu->core_clk);
+
+	status->busy_time = gpu->funcs->gpu_busy(gpu);
+
+	time = ktime_get();
+	status->total_time = ktime_us_delta(time, gpu->devfreq.time);
+	gpu->devfreq.time = time;
+
+	return 0;
+}
+
+static int msm_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
+{
+	struct msm_gpu *gpu = dev_to_gpu(dev);
+
+	if (gpu->funcs->gpu_get_freq)
+		*freq = gpu->funcs->gpu_get_freq(gpu);
+	else
+		*freq = clk_get_rate(gpu->core_clk);
+
+	return 0;
+}
+
+static struct devfreq_dev_profile msm_devfreq_profile = {
+	.polling_ms = 10,
+	.target = msm_devfreq_target,
+	.get_dev_status = msm_devfreq_get_dev_status,
+	.get_cur_freq = msm_devfreq_get_cur_freq,
+};
+
+void msm_devfreq_init(struct msm_gpu *gpu)
+{
+	/* We need target support to do devfreq */
+	if (!gpu->funcs->gpu_busy)
+		return;
+
+	msm_devfreq_profile.initial_freq = gpu->fast_rate;
+
+	/*
+	 * Don't set the freq_table or max_state and let devfreq build the table
+	 * from OPP
+	 * After a deferred probe, these may have be left to non-zero values,
+	 * so set them back to zero before creating the devfreq device
+	 */
+	msm_devfreq_profile.freq_table = NULL;
+	msm_devfreq_profile.max_state = 0;
+
+	gpu->devfreq.devfreq = devm_devfreq_add_device(&gpu->pdev->dev,
+			&msm_devfreq_profile, DEVFREQ_GOV_SIMPLE_ONDEMAND,
+			NULL);
+
+	if (IS_ERR(gpu->devfreq.devfreq)) {
+		DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n");
+		gpu->devfreq.devfreq = NULL;
+		return;
+	}
+
+	devfreq_suspend_device(gpu->devfreq.devfreq);
+
+	gpu->cooling = of_devfreq_cooling_register(gpu->pdev->dev.of_node,
+			gpu->devfreq.devfreq);
+	if (IS_ERR(gpu->cooling)) {
+		DRM_DEV_ERROR(&gpu->pdev->dev,
+				"Couldn't register GPU cooling device\n");
+		gpu->cooling = NULL;
+	}
+}
+
+void msm_devfreq_cleanup(struct msm_gpu *gpu)
+{
+	devfreq_cooling_unregister(gpu->cooling);
+}
+
+void msm_devfreq_resume(struct msm_gpu *gpu)
+{
+	gpu->devfreq.busy_cycles = 0;
+	gpu->devfreq.time = ktime_get();
+
+	devfreq_resume_device(gpu->devfreq.devfreq);
+}
+
+void msm_devfreq_suspend(struct msm_gpu *gpu)
+{
+	devfreq_suspend_device(gpu->devfreq.devfreq);
+}
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 2/3] drm/msm: Split out get_freq() helper
  2021-07-26 14:46 [PATCH v2 0/3] drm/msm: Improved devfreq tuning Rob Clark
  2021-07-26 14:46 ` [PATCH v2 1/3] drm/msm: Split out devfreq handling Rob Clark
@ 2021-07-26 14:46 ` Rob Clark
  2021-07-27 20:11   ` Dmitry Baryshkov
  2021-07-26 14:46 ` [PATCH v2 3/3] drm/msm: Devfreq tuning Rob Clark
  2 siblings, 1 reply; 6+ messages in thread
From: Rob Clark @ 2021-07-26 14:46 UTC (permalink / raw)
  To: dri-devel
  Cc: Rob Clark, Rob Clark, Sean Paul, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR MSM ADRENO GPU,
	open list:DRM DRIVER FOR MSM ADRENO GPU, open list

From: Rob Clark <robdclark@chromium.org>

In the next patch, it grows a bit more, so lets not duplicate the logic
in multiple places.

Signed-off-by: Rob Clark <robdclark@chromium.org>
---
 drivers/gpu/drm/msm/msm_gpu_devfreq.c | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
index 3bcea0baddab..2e24a97be624 100644
--- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c
+++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
@@ -37,17 +37,21 @@ static int msm_devfreq_target(struct device *dev, unsigned long *freq,
 	return 0;
 }
 
+static unsigned long get_freq(struct msm_gpu *gpu)
+{
+	if (gpu->funcs->gpu_get_freq)
+		return gpu->funcs->gpu_get_freq(gpu);
+
+	return clk_get_rate(gpu->core_clk);
+}
+
 static int msm_devfreq_get_dev_status(struct device *dev,
 		struct devfreq_dev_status *status)
 {
 	struct msm_gpu *gpu = dev_to_gpu(dev);
 	ktime_t time;
 
-	if (gpu->funcs->gpu_get_freq)
-		status->current_frequency = gpu->funcs->gpu_get_freq(gpu);
-	else
-		status->current_frequency = clk_get_rate(gpu->core_clk);
-
+	status->current_frequency = get_freq(gpu);
 	status->busy_time = gpu->funcs->gpu_busy(gpu);
 
 	time = ktime_get();
@@ -59,12 +63,7 @@ static int msm_devfreq_get_dev_status(struct device *dev,
 
 static int msm_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
 {
-	struct msm_gpu *gpu = dev_to_gpu(dev);
-
-	if (gpu->funcs->gpu_get_freq)
-		*freq = gpu->funcs->gpu_get_freq(gpu);
-	else
-		*freq = clk_get_rate(gpu->core_clk);
+	*freq = get_freq(dev_to_gpu(dev));
 
 	return 0;
 }
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 3/3] drm/msm: Devfreq tuning
  2021-07-26 14:46 [PATCH v2 0/3] drm/msm: Improved devfreq tuning Rob Clark
  2021-07-26 14:46 ` [PATCH v2 1/3] drm/msm: Split out devfreq handling Rob Clark
  2021-07-26 14:46 ` [PATCH v2 2/3] drm/msm: Split out get_freq() helper Rob Clark
@ 2021-07-26 14:46 ` Rob Clark
  2 siblings, 0 replies; 6+ messages in thread
From: Rob Clark @ 2021-07-26 14:46 UTC (permalink / raw)
  To: dri-devel
  Cc: Rob Clark, Rob Clark, Sean Paul, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR MSM ADRENO GPU,
	open list:DRM DRIVER FOR MSM ADRENO GPU, open list

From: Rob Clark <robdclark@chromium.org>

This adds a few things to try and make frequency scaling better match
the workload:

1) Longer polling interval to avoid whip-lashing between too-high and
   too-low frequencies in certain workloads, like mobile games which
   throttle themselves to 30fps.

   Previously our polling interval was short enough to let things
   ramp down to minimum freq in the "off" frame, but long enough to
   not react quickly enough when rendering started on the next frame,
   leading to uneven frame times.  (Ie. rather than a consistent 33ms
   it would alternate between 16/33/48ms.)

2) Awareness of when the GPU is active vs idle.  Since we know when
   the GPU is active vs idle, we can clamp the frequency down to the
   minimum while it is idle.  (If it is idle for long enough, then
   the autosuspend delay will eventually kick in and power down the
   GPU.)

   Since devfreq has no knowledge of powered-but-idle, this takes a
   small bit of trickery to maintain a "fake" frequency while idle.
   This, combined with the longer polling period allows devfreq to
   arrive at a reasonable "active" frequency, while still clamping
   to minimum freq when idle to reduce power draw.

3) Boost.  Because simple_ondemand needs to see a certain threshold
   of busyness to ramp up, we could end up needing multiple polling
   cycles before it reacts appropriately on interactive workloads
   (ex. scrolling a web page after reading for some time), on top
   of the already lengthened polling interval, when we see a idle
   to active transition after a period of idle time we boost the
   frequency that we return to.

Signed-off-by: Rob Clark <robdclark@chromium.org>
---
 drivers/gpu/drm/msm/msm_gpu.c         | 16 ++++++
 drivers/gpu/drm/msm/msm_gpu.h         | 29 +++++++++++
 drivers/gpu/drm/msm/msm_gpu_devfreq.c | 73 ++++++++++++++++++++++++++-
 3 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index fedbd785e42f..c4ed8694f721 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -680,6 +680,14 @@ static void retire_submit(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
 	list_del(&submit->node);
 	spin_unlock_irqrestore(&ring->submit_lock, flags);
 
+	/* Update devfreq on transition from active->idle: */
+	mutex_lock(&gpu->active_lock);
+	gpu->active_submits--;
+	WARN_ON(gpu->active_submits < 0);
+	if (!gpu->active_submits)
+		msm_devfreq_idle(gpu);
+	mutex_unlock(&gpu->active_lock);
+
 	msm_gem_submit_put(submit);
 }
 
@@ -781,6 +789,13 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
 	list_add_tail(&submit->node, &ring->submits);
 	spin_unlock_irqrestore(&ring->submit_lock, flags);
 
+	/* Update devfreq on transition from idle->active: */
+	mutex_lock(&gpu->active_lock);
+	if (!gpu->active_submits)
+		msm_devfreq_active(gpu);
+	gpu->active_submits++;
+	mutex_unlock(&gpu->active_lock);
+
 	gpu->funcs->submit(gpu, submit);
 	priv->lastctx = submit->queue->ctx;
 
@@ -866,6 +881,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
 	sched_set_fifo_low(gpu->worker->task);
 
 	INIT_LIST_HEAD(&gpu->active_list);
+	mutex_init(&gpu->active_lock);
 	kthread_init_work(&gpu->retire_work, retire_worker);
 	kthread_init_work(&gpu->recover_work, recover_worker);
 	kthread_init_work(&gpu->fault_work, fault_worker);
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 2e61d05293e6..710c3fedfbf3 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -98,6 +98,20 @@ struct msm_gpu_devfreq {
 
 	/** time: Time of last sampling period. */
 	ktime_t time;
+
+	/** idle_time: Time of last transition to idle: */
+	ktime_t idle_time;
+
+	/**
+	 * idle_freq:
+	 *
+	 * Shadow frequency used while the GPU is idle.  From the PoV of
+	 * the devfreq governor, we are continuing to sample busyness and
+	 * adjust frequency while the GPU is idle, but we use this shadow
+	 * value as the GPU is actually clamped to minimum frequency while
+	 * it is inactive.
+	 */
+	unsigned long idle_freq;
 };
 
 struct msm_gpu {
@@ -129,6 +143,19 @@ struct msm_gpu {
 	 */
 	struct list_head active_list;
 
+	/**
+	 * active_submits:
+	 *
+	 * The number of submitted but not yet retired submits, used to
+	 * determine transitions between active and idle.
+	 *
+	 * Protected by lock
+	 */
+	int active_submits;
+
+	/** lock: protects active_submits and idle/active transitions */
+	struct mutex active_lock;
+
 	/* does gpu need hw_init? */
 	bool needs_hw_init;
 
@@ -322,6 +349,8 @@ void msm_devfreq_init(struct msm_gpu *gpu);
 void msm_devfreq_cleanup(struct msm_gpu *gpu);
 void msm_devfreq_resume(struct msm_gpu *gpu);
 void msm_devfreq_suspend(struct msm_gpu *gpu);
+void msm_devfreq_active(struct msm_gpu *gpu);
+void msm_devfreq_idle(struct msm_gpu *gpu);
 
 int msm_gpu_hw_init(struct msm_gpu *gpu);
 
diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
index 2e24a97be624..0a1ee20296a2 100644
--- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c
+++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
@@ -22,6 +22,15 @@ static int msm_devfreq_target(struct device *dev, unsigned long *freq,
 
 	opp = devfreq_recommended_opp(dev, freq, flags);
 
+	/*
+	 * If the GPU is idle, devfreq is not aware, so just ignore
+	 * it's requests
+	 */
+	if (gpu->devfreq.idle_freq) {
+		gpu->devfreq.idle_freq = *freq;
+		return 0;
+	}
+
 	if (IS_ERR(opp))
 		return PTR_ERR(opp);
 
@@ -39,6 +48,9 @@ static int msm_devfreq_target(struct device *dev, unsigned long *freq,
 
 static unsigned long get_freq(struct msm_gpu *gpu)
 {
+	if (gpu->devfreq.idle_freq)
+		return gpu->devfreq.idle_freq;
+
 	if (gpu->funcs->gpu_get_freq)
 		return gpu->funcs->gpu_get_freq(gpu);
 
@@ -69,7 +81,8 @@ static int msm_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
 }
 
 static struct devfreq_dev_profile msm_devfreq_profile = {
-	.polling_ms = 10,
+	.timer = DEVFREQ_TIMER_DELAYED,
+	.polling_ms = 50,
 	.target = msm_devfreq_target,
 	.get_dev_status = msm_devfreq_get_dev_status,
 	.get_cur_freq = msm_devfreq_get_cur_freq,
@@ -130,3 +143,61 @@ void msm_devfreq_suspend(struct msm_gpu *gpu)
 {
 	devfreq_suspend_device(gpu->devfreq.devfreq);
 }
+
+void msm_devfreq_active(struct msm_gpu *gpu)
+{
+	struct msm_gpu_devfreq *df = &gpu->devfreq;
+	struct devfreq_dev_status status;
+	unsigned int idle_time;
+	unsigned long target_freq = df->idle_freq;
+
+	/*
+	 * Hold devfreq lock to synchronize with get_dev_status()/
+	 * target() callbacks
+	 */
+	mutex_lock(&df->devfreq->lock);
+
+	idle_time = ktime_to_ms(ktime_sub(ktime_get(), df->idle_time));
+
+	/*
+	 * If we've been idle for a significant fraction of a polling
+	 * interval, then we won't meet the threshold of busyness for
+	 * the governor to ramp up the freq.. so give some boost
+	 */
+	if (idle_time > msm_devfreq_profile.polling_ms/2) {
+		target_freq *= 2;
+	}
+
+	df->idle_freq = 0;
+
+	msm_devfreq_target(&gpu->pdev->dev, &target_freq, 0);
+
+	/*
+	 * Reset the polling interval so we aren't inconsistent
+	 * about freq vs busy/total cycles
+	 */
+	msm_devfreq_get_dev_status(&gpu->pdev->dev, &status);
+
+	mutex_unlock(&df->devfreq->lock);
+}
+
+void msm_devfreq_idle(struct msm_gpu *gpu)
+{
+	struct msm_gpu_devfreq *df = &gpu->devfreq;
+	unsigned long idle_freq, target_freq = 0;
+
+	/*
+	 * Hold devfreq lock to synchronize with get_dev_status()/
+	 * target() callbacks
+	 */
+	mutex_lock(&df->devfreq->lock);
+
+	idle_freq = get_freq(gpu);
+
+	msm_devfreq_target(&gpu->pdev->dev, &target_freq, 0);
+
+	df->idle_time = ktime_get();
+	df->idle_freq = idle_freq;
+
+	mutex_unlock(&df->devfreq->lock);
+}
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 1/3] drm/msm: Split out devfreq handling
  2021-07-26 14:46 ` [PATCH v2 1/3] drm/msm: Split out devfreq handling Rob Clark
@ 2021-07-27 20:11   ` Dmitry Baryshkov
  0 siblings, 0 replies; 6+ messages in thread
From: Dmitry Baryshkov @ 2021-07-27 20:11 UTC (permalink / raw)
  To: Rob Clark, dri-devel
  Cc: Rob Clark, Sean Paul, David Airlie, Daniel Vetter, Jordan Crouse,
	Jonathan Marek, Akhil P Oommen, Sai Prakash Ranjan,
	Sharat Masetty, Douglas Anderson, open list,
	open list:DRM DRIVER FOR MSM ADRENO GPU,
	open list:DRM DRIVER FOR MSM ADRENO GPU

On 26/07/2021 17:46, Rob Clark wrote:
> From: Rob Clark <robdclark@chromium.org>
> 
> Before we start adding more cleverness, split it into it's own file.
> 
> Signed-off-by: Rob Clark <robdclark@chromium.org>

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

> ---
>   drivers/gpu/drm/msm/Makefile          |   1 +
>   drivers/gpu/drm/msm/adreno/a6xx_gpu.c |   4 +-
>   drivers/gpu/drm/msm/msm_gpu.c         | 116 +---------------------
>   drivers/gpu/drm/msm/msm_gpu.h         |  32 +++++--
>   drivers/gpu/drm/msm/msm_gpu_devfreq.c | 133 ++++++++++++++++++++++++++
>   5 files changed, 165 insertions(+), 121 deletions(-)
>   create mode 100644 drivers/gpu/drm/msm/msm_gpu_devfreq.c
> 
> diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
> index 2c00aa70b708..904535eda0c4 100644
> --- a/drivers/gpu/drm/msm/Makefile
> +++ b/drivers/gpu/drm/msm/Makefile
> @@ -90,6 +90,7 @@ msm-y := \
>   	msm_gem_submit.o \
>   	msm_gem_vma.o \
>   	msm_gpu.o \
> +	msm_gpu_devfreq.o \
>   	msm_iommu.o \
>   	msm_perf.o \
>   	msm_rd.o \
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 9db9f7847ea8..91f637b908f4 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -1477,7 +1477,7 @@ static int a6xx_pm_resume(struct msm_gpu *gpu)
>   	if (ret)
>   		return ret;
>   
> -	msm_gpu_resume_devfreq(gpu);
> +	msm_devfreq_resume(gpu);
>   
>   	a6xx_llc_activate(a6xx_gpu);
>   
> @@ -1494,7 +1494,7 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu)
>   
>   	a6xx_llc_deactivate(a6xx_gpu);
>   
> -	devfreq_suspend_device(gpu->devfreq.devfreq);
> +	msm_devfreq_suspend(gpu);
>   
>   	ret = a6xx_gmu_stop(a6xx_gpu);
>   	if (ret)
> diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
> index 647af45cf892..fedbd785e42f 100644
> --- a/drivers/gpu/drm/msm/msm_gpu.c
> +++ b/drivers/gpu/drm/msm/msm_gpu.c
> @@ -13,8 +13,6 @@
>   
>   #include <generated/utsrelease.h>
>   #include <linux/string_helpers.h>
> -#include <linux/devfreq.h>
> -#include <linux/devfreq_cooling.h>
>   #include <linux/devcoredump.h>
>   #include <linux/sched/task.h>
>   
> @@ -22,106 +20,6 @@
>    * Power Management:
>    */
>   
> -static int msm_devfreq_target(struct device *dev, unsigned long *freq,
> -		u32 flags)
> -{
> -	struct msm_gpu *gpu = dev_to_gpu(dev);
> -	struct dev_pm_opp *opp;
> -
> -	opp = devfreq_recommended_opp(dev, freq, flags);
> -
> -	if (IS_ERR(opp))
> -		return PTR_ERR(opp);
> -
> -	trace_msm_gpu_freq_change(dev_pm_opp_get_freq(opp));
> -
> -	if (gpu->funcs->gpu_set_freq)
> -		gpu->funcs->gpu_set_freq(gpu, opp);
> -	else
> -		clk_set_rate(gpu->core_clk, *freq);
> -
> -	dev_pm_opp_put(opp);
> -
> -	return 0;
> -}
> -
> -static int msm_devfreq_get_dev_status(struct device *dev,
> -		struct devfreq_dev_status *status)
> -{
> -	struct msm_gpu *gpu = dev_to_gpu(dev);
> -	ktime_t time;
> -
> -	if (gpu->funcs->gpu_get_freq)
> -		status->current_frequency = gpu->funcs->gpu_get_freq(gpu);
> -	else
> -		status->current_frequency = clk_get_rate(gpu->core_clk);
> -
> -	status->busy_time = gpu->funcs->gpu_busy(gpu);
> -
> -	time = ktime_get();
> -	status->total_time = ktime_us_delta(time, gpu->devfreq.time);
> -	gpu->devfreq.time = time;
> -
> -	return 0;
> -}
> -
> -static int msm_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
> -{
> -	struct msm_gpu *gpu = dev_to_gpu(dev);
> -
> -	if (gpu->funcs->gpu_get_freq)
> -		*freq = gpu->funcs->gpu_get_freq(gpu);
> -	else
> -		*freq = clk_get_rate(gpu->core_clk);
> -
> -	return 0;
> -}
> -
> -static struct devfreq_dev_profile msm_devfreq_profile = {
> -	.polling_ms = 10,
> -	.target = msm_devfreq_target,
> -	.get_dev_status = msm_devfreq_get_dev_status,
> -	.get_cur_freq = msm_devfreq_get_cur_freq,
> -};
> -
> -static void msm_devfreq_init(struct msm_gpu *gpu)
> -{
> -	/* We need target support to do devfreq */
> -	if (!gpu->funcs->gpu_busy)
> -		return;
> -
> -	msm_devfreq_profile.initial_freq = gpu->fast_rate;
> -
> -	/*
> -	 * Don't set the freq_table or max_state and let devfreq build the table
> -	 * from OPP
> -	 * After a deferred probe, these may have be left to non-zero values,
> -	 * so set them back to zero before creating the devfreq device
> -	 */
> -	msm_devfreq_profile.freq_table = NULL;
> -	msm_devfreq_profile.max_state = 0;
> -
> -	gpu->devfreq.devfreq = devm_devfreq_add_device(&gpu->pdev->dev,
> -			&msm_devfreq_profile, DEVFREQ_GOV_SIMPLE_ONDEMAND,
> -			NULL);
> -
> -	if (IS_ERR(gpu->devfreq.devfreq)) {
> -		DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n");
> -		gpu->devfreq.devfreq = NULL;
> -		return;
> -	}
> -
> -	devfreq_suspend_device(gpu->devfreq.devfreq);
> -
> -	gpu->cooling = of_devfreq_cooling_register(gpu->pdev->dev.of_node,
> -			gpu->devfreq.devfreq);
> -	if (IS_ERR(gpu->cooling)) {
> -		DRM_DEV_ERROR(&gpu->pdev->dev,
> -				"Couldn't register GPU cooling device\n");
> -		gpu->cooling = NULL;
> -	}
> -}
> -
>   static int enable_pwrrail(struct msm_gpu *gpu)
>   {
>   	struct drm_device *dev = gpu->dev;
> @@ -196,14 +94,6 @@ static int disable_axi(struct msm_gpu *gpu)
>   	return 0;
>   }
>   
> -void msm_gpu_resume_devfreq(struct msm_gpu *gpu)
> -{
> -	gpu->devfreq.busy_cycles = 0;
> -	gpu->devfreq.time = ktime_get();
> -
> -	devfreq_resume_device(gpu->devfreq.devfreq);
> -}
> -
>   int msm_gpu_pm_resume(struct msm_gpu *gpu)
>   {
>   	int ret;
> @@ -223,7 +113,7 @@ int msm_gpu_pm_resume(struct msm_gpu *gpu)
>   	if (ret)
>   		return ret;
>   
> -	msm_gpu_resume_devfreq(gpu);
> +	msm_devfreq_resume(gpu);
>   
>   	gpu->needs_hw_init = true;
>   
> @@ -237,7 +127,7 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu)
>   	DBG("%s", gpu->name);
>   	trace_msm_gpu_suspend(0);
>   
> -	devfreq_suspend_device(gpu->devfreq.devfreq);
> +	msm_devfreq_suspend(gpu);
>   
>   	ret = disable_axi(gpu);
>   	if (ret)
> @@ -1116,5 +1006,5 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
>   		kthread_destroy_worker(gpu->worker);
>   	}
>   
> -	devfreq_cooling_unregister(gpu->cooling);
> +	msm_devfreq_cleanup(gpu);
>   }
> diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
> index ef41ec09f59c..2e61d05293e6 100644
> --- a/drivers/gpu/drm/msm/msm_gpu.h
> +++ b/drivers/gpu/drm/msm/msm_gpu.h
> @@ -80,6 +80,26 @@ struct msm_gpu_fault_info {
>   	const char *block;
>   };
>   
> +/**
> + * struct msm_gpu_devfreq - devfreq related state
> + */
> +struct msm_gpu_devfreq {
> +	/** devfreq: devfreq instance */
> +	struct devfreq *devfreq;
> +
> +	/**
> +	 * busy_cycles:
> +	 *
> +	 * Used by implementation of gpu->gpu_busy() to track the last
> +	 * busy counter value, for calculating elapsed busy cycles since
> +	 * last sampling period.
> +	 */
> +	u64 busy_cycles;
> +
> +	/** time: Time of last sampling period. */
> +	ktime_t time;
> +};
> +
>   struct msm_gpu {
>   	const char *name;
>   	struct drm_device *dev;
> @@ -151,11 +171,7 @@ struct msm_gpu {
>   
>   	struct drm_gem_object *memptrs_bo;
>   
> -	struct {
> -		struct devfreq *devfreq;
> -		u64 busy_cycles;
> -		ktime_t time;
> -	} devfreq;
> +	struct msm_gpu_devfreq devfreq;
>   
>   	uint32_t suspend_count;
>   
> @@ -301,7 +317,11 @@ static inline void gpu_write64(struct msm_gpu *gpu, u32 lo, u32 hi, u64 val)
>   
>   int msm_gpu_pm_suspend(struct msm_gpu *gpu);
>   int msm_gpu_pm_resume(struct msm_gpu *gpu);
> -void msm_gpu_resume_devfreq(struct msm_gpu *gpu);
> +
> +void msm_devfreq_init(struct msm_gpu *gpu);
> +void msm_devfreq_cleanup(struct msm_gpu *gpu);
> +void msm_devfreq_resume(struct msm_gpu *gpu);
> +void msm_devfreq_suspend(struct msm_gpu *gpu);
>   
>   int msm_gpu_hw_init(struct msm_gpu *gpu);
>   
> diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
> new file mode 100644
> index 000000000000..3bcea0baddab
> --- /dev/null
> +++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
> @@ -0,0 +1,133 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2013 Red Hat
> + * Author: Rob Clark <robdclark@gmail.com>
> + */
> +
> +#include "msm_gpu.h"
> +#include "msm_gpu_trace.h"
> +
> +#include <linux/devfreq.h>
> +#include <linux/devfreq_cooling.h>
> +
> +/*
> + * Power Management:
> + */
> +
> +static int msm_devfreq_target(struct device *dev, unsigned long *freq,
> +		u32 flags)
> +{
> +	struct msm_gpu *gpu = dev_to_gpu(dev);
> +	struct dev_pm_opp *opp;
> +
> +	opp = devfreq_recommended_opp(dev, freq, flags);
> +
> +	if (IS_ERR(opp))
> +		return PTR_ERR(opp);
> +
> +	trace_msm_gpu_freq_change(dev_pm_opp_get_freq(opp));
> +
> +	if (gpu->funcs->gpu_set_freq)
> +		gpu->funcs->gpu_set_freq(gpu, opp);
> +	else
> +		clk_set_rate(gpu->core_clk, *freq);
> +
> +	dev_pm_opp_put(opp);
> +
> +	return 0;
> +}
> +
> +static int msm_devfreq_get_dev_status(struct device *dev,
> +		struct devfreq_dev_status *status)
> +{
> +	struct msm_gpu *gpu = dev_to_gpu(dev);
> +	ktime_t time;
> +
> +	if (gpu->funcs->gpu_get_freq)
> +		status->current_frequency = gpu->funcs->gpu_get_freq(gpu);
> +	else
> +		status->current_frequency = clk_get_rate(gpu->core_clk);
> +
> +	status->busy_time = gpu->funcs->gpu_busy(gpu);
> +
> +	time = ktime_get();
> +	status->total_time = ktime_us_delta(time, gpu->devfreq.time);
> +	gpu->devfreq.time = time;
> +
> +	return 0;
> +}
> +
> +static int msm_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
> +{
> +	struct msm_gpu *gpu = dev_to_gpu(dev);
> +
> +	if (gpu->funcs->gpu_get_freq)
> +		*freq = gpu->funcs->gpu_get_freq(gpu);
> +	else
> +		*freq = clk_get_rate(gpu->core_clk);
> +
> +	return 0;
> +}
> +
> +static struct devfreq_dev_profile msm_devfreq_profile = {
> +	.polling_ms = 10,
> +	.target = msm_devfreq_target,
> +	.get_dev_status = msm_devfreq_get_dev_status,
> +	.get_cur_freq = msm_devfreq_get_cur_freq,
> +};
> +
> +void msm_devfreq_init(struct msm_gpu *gpu)
> +{
> +	/* We need target support to do devfreq */
> +	if (!gpu->funcs->gpu_busy)
> +		return;
> +
> +	msm_devfreq_profile.initial_freq = gpu->fast_rate;
> +
> +	/*
> +	 * Don't set the freq_table or max_state and let devfreq build the table
> +	 * from OPP
> +	 * After a deferred probe, these may have be left to non-zero values,
> +	 * so set them back to zero before creating the devfreq device
> +	 */
> +	msm_devfreq_profile.freq_table = NULL;
> +	msm_devfreq_profile.max_state = 0;
> +
> +	gpu->devfreq.devfreq = devm_devfreq_add_device(&gpu->pdev->dev,
> +			&msm_devfreq_profile, DEVFREQ_GOV_SIMPLE_ONDEMAND,
> +			NULL);
> +
> +	if (IS_ERR(gpu->devfreq.devfreq)) {
> +		DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n");
> +		gpu->devfreq.devfreq = NULL;
> +		return;
> +	}
> +
> +	devfreq_suspend_device(gpu->devfreq.devfreq);
> +
> +	gpu->cooling = of_devfreq_cooling_register(gpu->pdev->dev.of_node,
> +			gpu->devfreq.devfreq);
> +	if (IS_ERR(gpu->cooling)) {
> +		DRM_DEV_ERROR(&gpu->pdev->dev,
> +				"Couldn't register GPU cooling device\n");
> +		gpu->cooling = NULL;
> +	}
> +}
> +
> +void msm_devfreq_cleanup(struct msm_gpu *gpu)
> +{
> +	devfreq_cooling_unregister(gpu->cooling);
> +}
> +
> +void msm_devfreq_resume(struct msm_gpu *gpu)
> +{
> +	gpu->devfreq.busy_cycles = 0;
> +	gpu->devfreq.time = ktime_get();
> +
> +	devfreq_resume_device(gpu->devfreq.devfreq);
> +}
> +
> +void msm_devfreq_suspend(struct msm_gpu *gpu)
> +{
> +	devfreq_suspend_device(gpu->devfreq.devfreq);
> +}
> 


-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 2/3] drm/msm: Split out get_freq() helper
  2021-07-26 14:46 ` [PATCH v2 2/3] drm/msm: Split out get_freq() helper Rob Clark
@ 2021-07-27 20:11   ` Dmitry Baryshkov
  0 siblings, 0 replies; 6+ messages in thread
From: Dmitry Baryshkov @ 2021-07-27 20:11 UTC (permalink / raw)
  To: Rob Clark, dri-devel
  Cc: Rob Clark, Sean Paul, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR MSM ADRENO GPU,
	open list:DRM DRIVER FOR MSM ADRENO GPU, open list

On 26/07/2021 17:46, Rob Clark wrote:
> From: Rob Clark <robdclark@chromium.org>
> 
> In the next patch, it grows a bit more, so lets not duplicate the logic
> in multiple places.
> 
> Signed-off-by: Rob Clark <robdclark@chromium.org>

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

> ---
>   drivers/gpu/drm/msm/msm_gpu_devfreq.c | 21 ++++++++++-----------
>   1 file changed, 10 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
> index 3bcea0baddab..2e24a97be624 100644
> --- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c
> +++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
> @@ -37,17 +37,21 @@ static int msm_devfreq_target(struct device *dev, unsigned long *freq,
>   	return 0;
>   }
>   
> +static unsigned long get_freq(struct msm_gpu *gpu)
> +{
> +	if (gpu->funcs->gpu_get_freq)
> +		return gpu->funcs->gpu_get_freq(gpu);
> +
> +	return clk_get_rate(gpu->core_clk);
> +}
> +
>   static int msm_devfreq_get_dev_status(struct device *dev,
>   		struct devfreq_dev_status *status)
>   {
>   	struct msm_gpu *gpu = dev_to_gpu(dev);
>   	ktime_t time;
>   
> -	if (gpu->funcs->gpu_get_freq)
> -		status->current_frequency = gpu->funcs->gpu_get_freq(gpu);
> -	else
> -		status->current_frequency = clk_get_rate(gpu->core_clk);
> -
> +	status->current_frequency = get_freq(gpu);
>   	status->busy_time = gpu->funcs->gpu_busy(gpu);
>   
>   	time = ktime_get();
> @@ -59,12 +63,7 @@ static int msm_devfreq_get_dev_status(struct device *dev,
>   
>   static int msm_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
>   {
> -	struct msm_gpu *gpu = dev_to_gpu(dev);
> -
> -	if (gpu->funcs->gpu_get_freq)
> -		*freq = gpu->funcs->gpu_get_freq(gpu);
> -	else
> -		*freq = clk_get_rate(gpu->core_clk);
> +	*freq = get_freq(dev_to_gpu(dev));
>   
>   	return 0;
>   }
> 


-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-07-27 20:11 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-26 14:46 [PATCH v2 0/3] drm/msm: Improved devfreq tuning Rob Clark
2021-07-26 14:46 ` [PATCH v2 1/3] drm/msm: Split out devfreq handling Rob Clark
2021-07-27 20:11   ` Dmitry Baryshkov
2021-07-26 14:46 ` [PATCH v2 2/3] drm/msm: Split out get_freq() helper Rob Clark
2021-07-27 20:11   ` Dmitry Baryshkov
2021-07-26 14:46 ` [PATCH v2 3/3] drm/msm: Devfreq tuning Rob Clark

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).