[Freedreno] [RFC PATCH] drm/msm: tune the devfreq to take into account the load history
Dmitry Baryshkov
dmitry.baryshkov at linaro.org
Tue Feb 21 07:42:21 UTC 2023
Partially restore the handling of the GPU load history. Accumulate the
busy_time and and total_time measured in active state during the polling
period. This results in slightly smoother picture of the GPU frequencies
(measured on the a530/msm8996, using kmscube in different resolutions).
A call to msm_devfreq_get_dev_status() from msm_devfreq_active() was
removed in 69f06a5d854f ("drm/msm: remove explicit devfreq status
reset"), because dev_pm_qos_update_request() triggered that internally.
As the commit fadcc3ab1302 ("drm/msm/gpu: Bypass PM QoS constraint for
idle clamp") removed the calls to dev_pm_qos_update_request(), this
removal was also reverted.
The code doesn't take the frequency into account while accumulating the
data to keep the code simple for the RFC.
Cc: Chia-I Wu <olvaffe at gmail.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
drivers/gpu/drm/msm/msm_gpu.h | 3 +++
drivers/gpu/drm/msm/msm_gpu_devfreq.c | 30 ++++++++++++++++++++++++++-
2 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index fc1c0d8611a8..9d1783375dcc 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -156,6 +156,9 @@ struct msm_gpu_devfreq {
/** suspended: tracks if we're suspended */
bool suspended;
+
+ /* stats for the current period */
+ struct devfreq_dev_status status;
};
struct msm_gpu {
diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
index e27dbf12b5e8..92cb022c8628 100644
--- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c
+++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
@@ -74,7 +74,7 @@ static unsigned long get_freq(struct msm_gpu *gpu)
return clk_get_rate(gpu->core_clk);
}
-static int msm_devfreq_get_dev_status(struct device *dev,
+static int msm_devfreq_get_dev_status_int(struct device *dev,
struct devfreq_dev_status *status)
{
struct msm_gpu *gpu = dev_to_gpu(dev);
@@ -112,6 +112,22 @@ static int msm_devfreq_get_dev_status(struct device *dev,
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);
+ struct msm_gpu_devfreq *df = &gpu->devfreq;
+
+ msm_devfreq_get_dev_status_int(&gpu->pdev->dev, status);
+ status->busy_time += df->status.busy_time;
+ status->total_time += df->status.total_time;
+
+ df->status.busy_time = 0;
+ df->status.total_time = 0;
+
+ return 0;
+}
+
static int msm_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
{
*freq = get_freq(dev_to_gpu(dev));
@@ -290,6 +306,7 @@ void msm_devfreq_active(struct msm_gpu *gpu)
struct msm_gpu_devfreq *df = &gpu->devfreq;
unsigned int idle_time;
unsigned long target_freq;
+ struct devfreq_dev_status status;
if (!has_devfreq(gpu))
return;
@@ -319,6 +336,12 @@ void msm_devfreq_active(struct msm_gpu *gpu)
if (target_freq)
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_int(&gpu->pdev->dev, &status);
+
mutex_unlock(&df->devfreq->lock);
/*
@@ -339,6 +362,7 @@ static void msm_devfreq_idle_work(struct kthread_work *work)
struct msm_gpu *gpu = container_of(df, struct msm_gpu, devfreq);
struct msm_drm_private *priv = gpu->dev->dev_private;
unsigned long idle_freq, target_freq = 0;
+ struct devfreq_dev_status status;
/*
* Hold devfreq lock to synchronize with get_dev_status()/
@@ -346,6 +370,10 @@ static void msm_devfreq_idle_work(struct kthread_work *work)
*/
mutex_lock(&df->devfreq->lock);
+ msm_devfreq_get_dev_status_int(&gpu->pdev->dev, &status);
+ df->status.busy_time += status.busy_time;
+ df->status.total_time += status.total_time;
+
idle_freq = get_freq(gpu);
if (priv->gpu_clamp_to_idle)
--
2.30.2
More information about the Freedreno
mailing list