drm/msm: Fix race of GPU init vs timestamp power management.
authorEric Anholt <eric@anholt.net>
Thu, 28 Jan 2021 21:03:30 +0000 (13:03 -0800)
committerRob Clark <robdclark@chromium.org>
Sun, 31 Jan 2021 19:34:36 +0000 (11:34 -0800)
We were using the same force-poweron bit in the two codepaths, so they
could race to have one of them lose GPU power early.

freedreno CI was seeing intermittent errors like:
[drm:_a6xx_gmu_set_oob] *ERROR* Timeout waiting for GMU OOB set GPU_SET: 0x0
and this issue could have contributed to it.

Signed-off-by: Eric Anholt <eric@anholt.net>
Fixes: 4b565ca5a2cb ("drm/msm: Add A6XX device support")
Reviewed-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@chromium.org>
drivers/gpu/drm/msm/adreno/a6xx_gmu.c
drivers/gpu/drm/msm/adreno/a6xx_gmu.h
drivers/gpu/drm/msm/adreno/a6xx_gpu.c

index e6703ae..b3318f8 100644 (file)
@@ -264,6 +264,16 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
                }
                name = "GPU_SET";
                break;
+       case GMU_OOB_PERFCOUNTER_SET:
+               if (gmu->legacy) {
+                       request = GMU_OOB_PERFCOUNTER_REQUEST;
+                       ack = GMU_OOB_PERFCOUNTER_ACK;
+               } else {
+                       request = GMU_OOB_PERFCOUNTER_REQUEST_NEW;
+                       ack = GMU_OOB_PERFCOUNTER_ACK_NEW;
+               }
+               name = "PERFCOUNTER";
+               break;
        case GMU_OOB_BOOT_SLUMBER:
                request = GMU_OOB_BOOT_SLUMBER_REQUEST;
                ack = GMU_OOB_BOOT_SLUMBER_ACK;
@@ -301,9 +311,14 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
 void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
 {
        if (!gmu->legacy) {
-               WARN_ON(state != GMU_OOB_GPU_SET);
-               gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
-                       1 << GMU_OOB_GPU_SET_CLEAR_NEW);
+               if (state == GMU_OOB_GPU_SET) {
+                       gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
+                               1 << GMU_OOB_GPU_SET_CLEAR_NEW);
+               } else {
+                       WARN_ON(state != GMU_OOB_PERFCOUNTER_SET);
+                       gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
+                               1 << GMU_OOB_PERFCOUNTER_CLEAR_NEW);
+               }
                return;
        }
 
@@ -312,6 +327,10 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
                gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
                        1 << GMU_OOB_GPU_SET_CLEAR);
                break;
+       case GMU_OOB_PERFCOUNTER_SET:
+               gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
+                       1 << GMU_OOB_PERFCOUNTER_CLEAR);
+               break;
        case GMU_OOB_BOOT_SLUMBER:
                gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
                        1 << GMU_OOB_BOOT_SLUMBER_CLEAR);
index c6d2bce..9fa278d 100644 (file)
@@ -156,6 +156,7 @@ enum a6xx_gmu_oob_state {
        GMU_OOB_BOOT_SLUMBER = 0,
        GMU_OOB_GPU_SET,
        GMU_OOB_DCVS_SET,
+       GMU_OOB_PERFCOUNTER_SET,
 };
 
 /* These are the interrupt / ack bits for each OOB request that are set
@@ -190,6 +191,13 @@ enum a6xx_gmu_oob_state {
 #define GMU_OOB_GPU_SET_ACK_NEW                31
 #define GMU_OOB_GPU_SET_CLEAR_NEW      31
 
+#define GMU_OOB_PERFCOUNTER_REQUEST    17
+#define GMU_OOB_PERFCOUNTER_ACK                25
+#define GMU_OOB_PERFCOUNTER_CLEAR      25
+
+#define GMU_OOB_PERFCOUNTER_REQUEST_NEW        28
+#define GMU_OOB_PERFCOUNTER_ACK_NEW    30
+#define GMU_OOB_PERFCOUNTER_CLEAR_NEW  30
 
 void a6xx_hfi_init(struct a6xx_gmu *gmu);
 int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state);
index 0a51cad..9be15cf 100644 (file)
@@ -1172,12 +1172,12 @@ static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
        struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
 
        /* Force the GPU power on so we can read this register */
-       a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
+       a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET);
 
        *value = gpu_read64(gpu, REG_A6XX_RBBM_PERFCTR_CP_0_LO,
                REG_A6XX_RBBM_PERFCTR_CP_0_HI);
 
-       a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
+       a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET);
        return 0;
 }