@@ -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 {
@@ -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)
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@gmail.com> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@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(-)