drm/msm/a6xx: Clear shadow on suspend
authorRob Clark <robdclark@chromium.org>
Tue, 10 Nov 2020 18:23:06 +0000 (10:23 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 30 Dec 2020 10:53:06 +0000 (11:53 +0100)
[ Upstream commit e8b0b994c3a5881f0648d53f90435120089c56ad ]

Clear the shadow rptr on suspend.  Otherwise, when we resume, we can
have a stale value until CP_WHERE_AM_I executes.  If we suspend near
the ringbuffer wraparound point, this can lead to a chicken/egg
situation where we are waiting for ringbuffer space to write the
CP_WHERE_AM_I (or CP_INIT) packet, because we mistakenly believe that
the ringbuffer is full (due to stale rptr value in the shadow).

Fixes errors like:

  [drm:adreno_wait_ring [msm]] *ERROR* timeout waiting for space in ringbuffer 0

in the resume path.

Fixes: d3a569fccfa0 ("drm/msm: a6xx: Use WHERE_AM_I for eligible targets")
Signed-off-by: Rob Clark <robdclark@chromium.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/gpu/drm/msm/adreno/a6xx_gpu.c

index 948f365..420ca4a 100644 (file)
@@ -1045,12 +1045,21 @@ 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);
+       int i, ret;
 
        trace_msm_gpu_suspend(0);
 
        devfreq_suspend_device(gpu->devfreq.devfreq);
 
-       return a6xx_gmu_stop(a6xx_gpu);
+       ret = a6xx_gmu_stop(a6xx_gpu);
+       if (ret)
+               return ret;
+
+       if (adreno_gpu->base.hw_apriv || a6xx_gpu->has_whereami)
+               for (i = 0; i < gpu->nr_rings; i++)
+                       a6xx_gpu->shadow[i] = 0;
+
+       return 0;
 }
 
 static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)