drm/msm: gpu: Return error on hw_init failure
authorJordan Crouse <jcrouse@codeaurora.org>
Mon, 28 Nov 2016 19:28:27 +0000 (12:28 -0700)
committerRob Clark <robdclark@gmail.com>
Mon, 28 Nov 2016 20:14:11 +0000 (15:14 -0500)
When the GPU hardware init function fails (like say, ME_INIT timed
out) return error instead of blindly continuing on. This gives us
a small chance of saving the system before it goes boom.

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
drivers/gpu/drm/msm/adreno/a3xx_gpu.c
drivers/gpu/drm/msm/adreno/a4xx_gpu.c
drivers/gpu/drm/msm/adreno/adreno_gpu.c
drivers/gpu/drm/msm/adreno/adreno_gpu.h
drivers/gpu/drm/msm/msm_gpu.h

index a224fdbcb5f0b09585982fa4d5b2d10640ad0207..ff6489444423682f39c88333d3ae9e4a0c6a75b6 100644 (file)
@@ -41,7 +41,7 @@ extern bool hang_debug;
 
 static void a3xx_dump(struct msm_gpu *gpu);
 
-static void a3xx_me_init(struct msm_gpu *gpu)
+static bool a3xx_me_init(struct msm_gpu *gpu)
 {
        struct msm_ringbuffer *ring = gpu->rb;
 
@@ -65,7 +65,7 @@ static void a3xx_me_init(struct msm_gpu *gpu)
        OUT_RING(ring, 0x00000000);
 
        gpu->funcs->flush(gpu);
-       gpu->funcs->idle(gpu);
+       return gpu->funcs->idle(gpu);
 }
 
 static int a3xx_hw_init(struct msm_gpu *gpu)
@@ -294,9 +294,7 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
        /* clear ME_HALT to start micro engine */
        gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0);
 
-       a3xx_me_init(gpu);
-
-       return 0;
+       return a3xx_me_init(gpu) ? 0 : -EINVAL;
 }
 
 static void a3xx_recover(struct msm_gpu *gpu)
@@ -337,17 +335,22 @@ static void a3xx_destroy(struct msm_gpu *gpu)
        kfree(a3xx_gpu);
 }
 
-static void a3xx_idle(struct msm_gpu *gpu)
+static bool a3xx_idle(struct msm_gpu *gpu)
 {
        /* wait for ringbuffer to drain: */
-       adreno_idle(gpu);
+       if (!adreno_idle(gpu))
+               return false;
 
        /* then wait for GPU to finish: */
        if (spin_until(!(gpu_read(gpu, REG_A3XX_RBBM_STATUS) &
-                       A3XX_RBBM_STATUS_GPU_BUSY)))
+                       A3XX_RBBM_STATUS_GPU_BUSY))) {
                DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
 
-       /* TODO maybe we need to reset GPU here to recover from hang? */
+               /* TODO maybe we need to reset GPU here to recover from hang? */
+               return false;
+       }
+
+       return true;
 }
 
 static irqreturn_t a3xx_irq(struct msm_gpu *gpu)
index 5745cc81eedac2253a07179a6c8998f5ef6801f6..2abf2627f8220a9426ec7fd8384e9fbc9b497089 100644 (file)
@@ -113,7 +113,7 @@ static void a4xx_enable_hwcg(struct msm_gpu *gpu)
 }
 
 
-static void a4xx_me_init(struct msm_gpu *gpu)
+static bool a4xx_me_init(struct msm_gpu *gpu)
 {
        struct msm_ringbuffer *ring = gpu->rb;
 
@@ -137,7 +137,7 @@ static void a4xx_me_init(struct msm_gpu *gpu)
        OUT_RING(ring, 0x00000000);
 
        gpu->funcs->flush(gpu);
-       gpu->funcs->idle(gpu);
+       return gpu->funcs->idle(gpu);
 }
 
 static int a4xx_hw_init(struct msm_gpu *gpu)
@@ -292,9 +292,7 @@ static int a4xx_hw_init(struct msm_gpu *gpu)
        /* clear ME_HALT to start micro engine */
        gpu_write(gpu, REG_A4XX_CP_ME_CNTL, 0);
 
-       a4xx_me_init(gpu);
-
-       return 0;
+       return a4xx_me_init(gpu) ? 0 : -EINVAL;
 }
 
 static void a4xx_recover(struct msm_gpu *gpu)
@@ -335,17 +333,21 @@ static void a4xx_destroy(struct msm_gpu *gpu)
        kfree(a4xx_gpu);
 }
 
-static void a4xx_idle(struct msm_gpu *gpu)
+static bool a4xx_idle(struct msm_gpu *gpu)
 {
        /* wait for ringbuffer to drain: */
-       adreno_idle(gpu);
+       if (!adreno_idle(gpu))
+               return false;
 
        /* then wait for GPU to finish: */
        if (spin_until(!(gpu_read(gpu, REG_A4XX_RBBM_STATUS) &
-                                       A4XX_RBBM_STATUS_GPU_BUSY)))
+                                       A4XX_RBBM_STATUS_GPU_BUSY))) {
                DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
+               /* TODO maybe we need to reset GPU here to recover from hang? */
+               return false;
+       }
 
-       /* TODO maybe we need to reset GPU here to recover from hang? */
+       return true;
 }
 
 static irqreturn_t a4xx_irq(struct msm_gpu *gpu)
index 3d4eb08d8c28de706995dd1a2840d46f042f22bc..04080f9b7e096918d6c8602a9fc15f1b0bc4e7ea 100644 (file)
@@ -218,19 +218,18 @@ void adreno_flush(struct msm_gpu *gpu)
        adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_WPTR, wptr);
 }
 
-void adreno_idle(struct msm_gpu *gpu)
+bool 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: */
-       ret = spin_until(get_rptr(adreno_gpu) == wptr);
-
-       if (ret)
-               DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name);
+       if (!spin_until(get_rptr(adreno_gpu) == wptr))
+               return true;
 
        /* TODO maybe we need to reset GPU here to recover from hang? */
+       DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name);
+       return false;
 }
 
 #ifdef CONFIG_DEBUG_FS
index cccc1a508295cac9571d8b8bdd6f252c15bc604b..d0f9e1e3acd69ecabc3869f2aa2755811978b274 100644 (file)
@@ -182,7 +182,7 @@ void adreno_recover(struct msm_gpu *gpu);
 void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
                struct msm_file_private *ctx);
 void adreno_flush(struct msm_gpu *gpu);
-void adreno_idle(struct msm_gpu *gpu);
+bool adreno_idle(struct msm_gpu *gpu);
 #ifdef CONFIG_DEBUG_FS
 void adreno_show(struct msm_gpu *gpu, struct seq_file *m);
 #endif
index 6a7e78b317f204f79d9fe2f7f2d9ec9d635e77e6..10954135130d528876150dc0346fb8d8f58abef4 100644 (file)
@@ -50,7 +50,7 @@ struct msm_gpu_funcs {
        void (*submit)(struct msm_gpu *gpu, struct msm_gem_submit *submit,
                        struct msm_file_private *ctx);
        void (*flush)(struct msm_gpu *gpu);
-       void (*idle)(struct msm_gpu *gpu);
+       bool (*idle)(struct msm_gpu *gpu);
        irqreturn_t (*irq)(struct msm_gpu *irq);
        uint32_t (*last_fence)(struct msm_gpu *gpu);
        void (*recover)(struct msm_gpu *gpu);