From 8eac9a50f0e198a83667ddb7daf98d917accbab6 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 24 Jul 2017 10:49:53 -0600 Subject: [PATCH 1/4] drm/msm: Check value of active_cnt in a5xx power functions The generic msm_gpu_pm_resume/msm_gpu_pm_suspend functions have built-in reference counting but the a5xx specific functions are doing unconditional a5xx specific setup / teardown that would behave very badly if they were not accompanied by an actual power up / power down. Change-Id: Ic0dedbad549c4ea9a5c68b0ca43eb98e0449d54b Signed-off-by: Jordan Crouse --- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 35 +++++++++++++++++---------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 37323e962c2c..386050a228a8 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -1168,6 +1168,10 @@ static int a5xx_pm_resume(struct msm_gpu *gpu) if (ret) return ret; + /* If we are already up, don't mess with what works */ + if (gpu->active_cnt > 1) + return 0; + /* Turn the RBCCU domain first to limit the chances of voltage droop */ gpu_write(gpu, REG_A5XX_GPMU_RBCCU_POWER_CNTL, 0x778000); @@ -1198,22 +1202,27 @@ static int a5xx_pm_suspend(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); - /* Clear the VBIF pipe before shutting down */ + /* Only do this next bit if we are about to go down */ + if (gpu->active_cnt == 1) { + /* Clear the VBIF pipe before shutting down */ - gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0xF); - spin_until((gpu_read(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL1) & 0xF) == 0xF); + gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0xF); + spin_until((gpu_read(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL1) & 0xF) + == 0xF); - gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0); + gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0); - /* - * Reset the VBIF before power collapse to avoid issue with FIFO - * entries - */ - - if (adreno_is_a530(adreno_gpu)) { - /* These only need to be done for A530 */ - gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x003C0000); - gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x00000000); + /* + * Reset the VBIF before power collapse to avoid issue with FIFO + * entries + */ + if (adreno_is_a530(adreno_gpu)) { + /* These only need to be done for A530 */ + gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, + 0x003C0000); + gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, + 0x00000000); + } } return msm_gpu_pm_suspend(gpu); From 74910dd6a289792505852c6c071ec9923e891cc4 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 20 Jul 2017 12:20:09 -0600 Subject: [PATCH 2/4] drm/msm: Keep the power on throughout the entire ->show() operation Enabling and disabling the power at various points in the ->show() call flow may have detrimental effects. For all targets make sure power is on before reading any register and leave it on until we are all done. Change-Id: Ic0dedbad4d37a11634174105fc3ee6fe3713a143 Signed-off-by: Jordan Crouse --- drivers/gpu/drm/msm/adreno/a3xx_gpu.c | 2 +- drivers/gpu/drm/msm/adreno/a4xx_gpu.c | 2 +- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 2 +- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 4 ---- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c index e24827590b7c..c085e173232b 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c @@ -409,8 +409,8 @@ static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m) gpu->funcs->pm_resume(gpu); seq_printf(m, "status: %08x\n", gpu_read(gpu, REG_A3XX_RBBM_STATUS)); - gpu->funcs->pm_suspend(gpu); adreno_show(gpu, m); + gpu->funcs->pm_suspend(gpu); } #endif diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c index b612c9a18faf..624c2a87d593 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c @@ -447,9 +447,9 @@ static void a4xx_show(struct msm_gpu *gpu, struct seq_file *m) seq_printf(m, "status: %08x\n", gpu_read(gpu, REG_A4XX_RBBM_STATUS)); - gpu->funcs->pm_suspend(gpu); adreno_show(gpu, m); + gpu->funcs->pm_suspend(gpu); } #endif diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 386050a228a8..47f437fa4fb3 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -1246,9 +1246,9 @@ static void a5xx_show(struct msm_gpu *gpu, struct seq_file *m) seq_printf(m, "status: %08x\n", gpu_read(gpu, REG_A5XX_RBBM_STATUS)); - gpu->funcs->pm_suspend(gpu); adreno_show(gpu, m); + gpu->funcs->pm_suspend(gpu); } #endif diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 2273b06b59a6..04e0056f2a49 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -297,8 +297,6 @@ void adreno_show(struct msm_gpu *gpu, struct seq_file *m) seq_printf(m, "rb wptr: %d\n", get_wptr(ring)); } - gpu->funcs->pm_resume(gpu); - /* dump these out in a form that can be parsed by demsm: */ seq_printf(m, "IO:region %s 00000000 00020000\n", gpu->name); for (i = 0; adreno_gpu->registers[i] != ~0; i += 2) { @@ -311,8 +309,6 @@ void adreno_show(struct msm_gpu *gpu, struct seq_file *m) seq_printf(m, "IO:R %08x %08x\n", addr<<2, val); } } - - gpu->funcs->pm_suspend(gpu); } #endif From a0c5da88c9bdcd496ab1d587e00871fa2634fc73 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 20 Jul 2017 12:04:52 -0600 Subject: [PATCH 3/4] drm/msm: Remember the state of A5XX hardware clock gating Remember if the A5XX hardware clock gating is currently enabled or disabled to avoid inadvertently enabling it. Change-Id: Ic0dedbada3734a257ac966c041d06695f3521ad4 Signed-off-by: Jordan Crouse --- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 6 ++++++ drivers/gpu/drm/msm/adreno/a5xx_gpu.h | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 47f437fa4fb3..e66079cdd53e 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -375,6 +375,7 @@ static const struct { void a5xx_set_hwcg(struct msm_gpu *gpu, bool state) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); unsigned int i; for (i = 0; i < ARRAY_SIZE(a5xx_hwcg); i++) @@ -391,6 +392,11 @@ void a5xx_set_hwcg(struct msm_gpu *gpu, bool state) gpu_write(gpu, REG_A5XX_RBBM_CLOCK_CNTL, state ? 0xAAA8AA00 : 0); gpu_write(gpu, REG_A5XX_RBBM_ISDB_CNT, state ? 0x182 : 0x180); + + if (state) + set_bit(A5XX_HWCG_ENABLED, &a5xx_gpu->flags); + else + clear_bit(A5XX_HWCG_ENABLED, &a5xx_gpu->flags); } static int a5xx_me_init(struct msm_gpu *gpu) diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h index f8b00982fe86..e637237fa811 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h @@ -23,6 +23,7 @@ enum { A5XX_ZAP_SHADER_LOADED = 1, + A5XX_HWCG_ENABLED = 2, }; struct a5xx_gpu { From 3beb8eb46765be81cde0dc413aebf87b7db6dcb7 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 20 Jul 2017 10:52:33 -0600 Subject: [PATCH 4/4] drm/msm: Turn off hardware clock gating before reading A5XX registers On A5XX GPU hardware clock gating needs to be turned off before reading certain GPU registers via AHB. Turn off HWCG before calling adreno_show() to safely dump all the registers without a system hang. Change-Id: Ic0dedbad550ab5d414cea7837672e586a7acd370 Signed-off-by: Jordan Crouse --- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index e66079cdd53e..45a38b247727 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -1248,12 +1248,28 @@ static int a5xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) #ifdef CONFIG_DEBUG_FS static void a5xx_show(struct msm_gpu *gpu, struct seq_file *m) { + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); + bool enabled = test_bit(A5XX_HWCG_ENABLED, &a5xx_gpu->flags); + gpu->funcs->pm_resume(gpu); seq_printf(m, "status: %08x\n", gpu_read(gpu, REG_A5XX_RBBM_STATUS)); + /* + * Temporarily disable hardware clock gating before going into + * adreno_show to avoid issues while reading the registers + */ + + if (enabled) + a5xx_set_hwcg(gpu, false); + adreno_show(gpu, m); + + if (enabled) + a5xx_set_hwcg(gpu, true); + gpu->funcs->pm_suspend(gpu); } #endif