drm/msm/adreno: get CP_RPTR from register instead of shadow memory
authorCraig Stout <cstout@chromium.org>
Fri, 19 Feb 2016 00:50:02 +0000 (16:50 -0800)
committerRob Clark <robdclark@gmail.com>
Thu, 3 Mar 2016 16:55:28 +0000 (11:55 -0500)
As described in the downstream/kgsl driver:
Sometimes the RPTR shadow memory is unreliable causing timeouts
in adreno_idle().  Read it directly from the register instead.

Signed-off-by: Craig Stout <cstout@chromium.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
drivers/gpu/drm/msm/adreno/adreno_gpu.c

index e696c54..2859b19 100644 (file)
@@ -71,18 +71,15 @@ int adreno_hw_init(struct msm_gpu *gpu)
        adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_CNTL,
                        /* size is log2(quad-words): */
                        AXXX_CP_RB_CNTL_BUFSZ(ilog2(gpu->rb->size / 8)) |
-                       AXXX_CP_RB_CNTL_BLKSZ(ilog2(RB_BLKSIZE / 8)));
+                       AXXX_CP_RB_CNTL_BLKSZ(ilog2(RB_BLKSIZE / 8)) |
+                       (adreno_is_a430(adreno_gpu) ? AXXX_CP_RB_CNTL_NO_UPDATE : 0));
 
        /* Setup ringbuffer address: */
        adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_BASE, gpu->rb_iova);
-       adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_RPTR_ADDR,
-                       rbmemptr(adreno_gpu, rptr));
 
-       /* Setup scratch/timestamp: */
-       adreno_gpu_write(adreno_gpu, REG_ADRENO_SCRATCH_ADDR,
-                       rbmemptr(adreno_gpu, fence));
-
-       adreno_gpu_write(adreno_gpu, REG_ADRENO_SCRATCH_UMSK, 0x1);
+       if (!adreno_is_a430(adreno_gpu))
+               adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_RPTR_ADDR,
+                                               rbmemptr(adreno_gpu, rptr));
 
        return 0;
 }
@@ -92,6 +89,16 @@ static uint32_t get_wptr(struct msm_ringbuffer *ring)
        return ring->cur - ring->start;
 }
 
+/* Use this helper to read rptr, since a430 doesn't update rptr in memory */
+static uint32_t get_rptr(struct adreno_gpu *adreno_gpu)
+{
+       if (adreno_is_a430(adreno_gpu))
+               return adreno_gpu->memptrs->rptr = adreno_gpu_read(
+                       adreno_gpu, REG_ADRENO_CP_RB_RPTR);
+       else
+               return adreno_gpu->memptrs->rptr;
+}
+
 uint32_t adreno_last_fence(struct msm_gpu *gpu)
 {
        struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -220,9 +227,12 @@ void adreno_idle(struct msm_gpu *gpu)
 {
        struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
        uint32_t wptr = get_wptr(gpu->rb);
+       int ret;
 
        /* wait for CP to drain ringbuffer: */
-       if (spin_until(adreno_gpu->memptrs->rptr == wptr))
+       ret = spin_until(get_rptr(adreno_gpu) == wptr);
+
+       if (ret)
                DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name);
 
        /* TODO maybe we need to reset GPU here to recover from hang? */
@@ -241,7 +251,7 @@ void adreno_show(struct msm_gpu *gpu, struct seq_file *m)
 
        seq_printf(m, "fence:    %d/%d\n", adreno_gpu->memptrs->fence,
                        gpu->submitted_fence);
-       seq_printf(m, "rptr:     %d\n", adreno_gpu->memptrs->rptr);
+       seq_printf(m, "rptr:     %d\n", get_rptr(adreno_gpu));
        seq_printf(m, "wptr:     %d\n", adreno_gpu->memptrs->wptr);
        seq_printf(m, "rb wptr:  %d\n", get_wptr(gpu->rb));
 
@@ -282,7 +292,7 @@ void adreno_dump_info(struct msm_gpu *gpu)
 
        printk("fence:    %d/%d\n", adreno_gpu->memptrs->fence,
                        gpu->submitted_fence);
-       printk("rptr:     %d\n", adreno_gpu->memptrs->rptr);
+       printk("rptr:     %d\n", get_rptr(adreno_gpu));
        printk("wptr:     %d\n", adreno_gpu->memptrs->wptr);
        printk("rb wptr:  %d\n", get_wptr(gpu->rb));
 
@@ -317,7 +327,7 @@ static uint32_t ring_freewords(struct msm_gpu *gpu)
        struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
        uint32_t size = gpu->rb->size / 4;
        uint32_t wptr = get_wptr(gpu->rb);
-       uint32_t rptr = adreno_gpu->memptrs->rptr;
+       uint32_t rptr = get_rptr(adreno_gpu);
        return (rptr + (size - 1) - wptr) % size;
 }