Re: [Freedreno] [PATCH v2 5/5] drm/msm/A6xx: Add devfreq support for A6xx

2018-08-27 Thread Jordan Crouse
On Mon, Aug 27, 2018 at 12:47:20PM +0530, Sharat Masetty wrote:
> Implement routines to estimate GPU busy time and fetching the
> current frequency for the polling interval. This is required by
> the devfreq framework which recommends a frequency change if needed.
> The driver code then tries to set this new frequency on the GPU by
> sending an Out Of Band(OOB) request to the GMU.
> 
> Signed-off-by: Sharat Masetty 
> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 39 
> +++
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.h |  2 ++
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 27 
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.h |  2 ++
>  4 files changed, 66 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> index f6634c0..3a7b899 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> @@ -67,7 +67,7 @@ static bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
>   A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF));
>  }
>  
> -static int a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index)
> +static int __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index)
>  {
>   gmu_write(gmu, REG_A6XX_GMU_DCVS_ACK_OPTION, 0);
>  
> @@ -84,7 +84,38 @@ static int a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int 
> index)
>   a6xx_gmu_set_oob(gmu, GMU_OOB_DCVS_SET);
>   a6xx_gmu_clear_oob(gmu, GMU_OOB_DCVS_SET);
>  
> - return gmu_read(gmu, REG_A6XX_GMU_DCVS_RETURN);
> + if (gmu_read(gmu, REG_A6XX_GMU_DCVS_RETURN) != 0)
> + return -EINVAL;
> +
> + gmu->freq = gmu->gpu_freqs[index];
> +
> + return 0;
> +}

While I was working on the interconnect patches it occurred to me that the upper
levels doesn't really care what the value of A6XX_GMU_DCVS_RETURN is so we might
want to just print an error message and return nothing. If the DCVS set didn't
work we might be headed for disaster on the GMU side but its more likely that
we'll just continue along at the current frequency for the next cycle so it
isn't terribly harmful.

Jordan

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH v2 5/5] drm/msm/A6xx: Add devfreq support for A6xx

2018-08-27 Thread Sharat Masetty
Implement routines to estimate GPU busy time and fetching the
current frequency for the polling interval. This is required by
the devfreq framework which recommends a frequency change if needed.
The driver code then tries to set this new frequency on the GPU by
sending an Out Of Band(OOB) request to the GMU.

Signed-off-by: Sharat Masetty 
---
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 39 +++
 drivers/gpu/drm/msm/adreno/a6xx_gmu.h |  2 ++
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 27 
 drivers/gpu/drm/msm/adreno/a6xx_gpu.h |  2 ++
 4 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index f6634c0..3a7b899 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -67,7 +67,7 @@ static bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF));
 }
 
-static int a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index)
+static int __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index)
 {
gmu_write(gmu, REG_A6XX_GMU_DCVS_ACK_OPTION, 0);
 
@@ -84,7 +84,38 @@ static int a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index)
a6xx_gmu_set_oob(gmu, GMU_OOB_DCVS_SET);
a6xx_gmu_clear_oob(gmu, GMU_OOB_DCVS_SET);
 
-   return gmu_read(gmu, REG_A6XX_GMU_DCVS_RETURN);
+   if (gmu_read(gmu, REG_A6XX_GMU_DCVS_RETURN) != 0)
+   return -EINVAL;
+
+   gmu->freq = gmu->gpu_freqs[index];
+
+   return 0;
+}
+
+int a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq)
+{
+   struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+   struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+   struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
+   u32 perf_index = 0;
+
+   if (freq == gmu->freq)
+   return 0;
+
+   for (perf_index = 0; perf_index < gmu->nr_gpu_freqs - 1; perf_index++)
+   if (freq == gmu->gpu_freqs[perf_index])
+   break;
+
+   return  __a6xx_gmu_set_freq(gmu, perf_index);
+}
+
+unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu)
+{
+   struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+   struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+   struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
+
+   return  gmu->freq;
 }
 
 static bool a6xx_gmu_check_idle_level(struct a6xx_gmu *gmu)
@@ -630,7 +661,7 @@ int a6xx_gmu_reset(struct a6xx_gpu *a6xx_gpu)
ret = a6xx_hfi_start(gmu, GMU_COLD_BOOT);
 
/* Set the GPU back to the highest power frequency */
-   a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1);
+   __a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1);
 
 out:
if (ret)
@@ -671,7 +702,7 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
ret = a6xx_hfi_start(gmu, status);
 
/* Set the GPU to the highest power frequency */
-   a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1);
+   __a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1);
 
 out:
/* Make sure to turn off the boot OOB request on error */
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h 
b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index 09fd3a7..13b064f 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -77,6 +77,8 @@ struct a6xx_gmu {
unsigned long gmu_freqs[4];
u32 cx_arc_votes[4];
 
+   unsigned long freq;
+
struct a6xx_hfi_queue queues[2];
 
struct tasklet_struct hfi_tasklet;
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 3429d33a..af90706 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -7,6 +7,8 @@
 #include "a6xx_gpu.h"
 #include "a6xx_gmu.xml.h"
 
+#include 
+
 static inline bool _a6xx_check_idle(struct msm_gpu *gpu)
 {
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -682,6 +684,8 @@ static int a6xx_pm_resume(struct msm_gpu *gpu)
 
gpu->needs_hw_init = true;
 
+   msm_gpu_resume_devfreq(gpu);
+
return ret;
 }
 
@@ -690,6 +694,8 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu)
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
 
+   devfreq_suspend_device(gpu->devfreq.devfreq);
+
/*
 * Make sure the GMU is idle before continuing (because some transitions
 * may use VBIF
@@ -753,6 +759,24 @@ static void a6xx_destroy(struct msm_gpu *gpu)
kfree(a6xx_gpu);
 }
 
+static unsigned long a6xx_gpu_busy(struct msm_gpu *gpu)
+{
+   struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+   struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+   u64 busy_cycles;
+   unsigned long busy_time;
+
+   busy_cycles = gmu_read64(&a6xx_gpu->gmu,
+   REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L,
+   REG_A6XX_GMU_