diff options
author | Jordan Crouse <jcrouse@codeaurora.org> | 2016-11-28 14:28:27 -0500 |
---|---|---|
committer | Rob Clark <robdclark@gmail.com> | 2016-11-28 15:14:11 -0500 |
commit | c4a8d4756061f72cba52af1e3035c07769cee679 (patch) | |
tree | a48c7d5dd2bc366eb96db6ee44494105a660a9f5 | |
parent | bcc188b77d3e7d77fc7efd5feab148707e095b77 (diff) |
drm/msm: gpu: Return error on hw_init failure
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>
-rw-r--r-- | drivers/gpu/drm/msm/adreno/a3xx_gpu.c | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/a4xx_gpu.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/adreno_gpu.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/adreno_gpu.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gpu.h | 2 |
5 files changed, 30 insertions, 26 deletions
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c index a224fdbcb5f0..ff6489444423 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c | |||
@@ -41,7 +41,7 @@ extern bool hang_debug; | |||
41 | 41 | ||
42 | static void a3xx_dump(struct msm_gpu *gpu); | 42 | static void a3xx_dump(struct msm_gpu *gpu); |
43 | 43 | ||
44 | static void a3xx_me_init(struct msm_gpu *gpu) | 44 | static bool a3xx_me_init(struct msm_gpu *gpu) |
45 | { | 45 | { |
46 | struct msm_ringbuffer *ring = gpu->rb; | 46 | struct msm_ringbuffer *ring = gpu->rb; |
47 | 47 | ||
@@ -65,7 +65,7 @@ static void a3xx_me_init(struct msm_gpu *gpu) | |||
65 | OUT_RING(ring, 0x00000000); | 65 | OUT_RING(ring, 0x00000000); |
66 | 66 | ||
67 | gpu->funcs->flush(gpu); | 67 | gpu->funcs->flush(gpu); |
68 | gpu->funcs->idle(gpu); | 68 | return gpu->funcs->idle(gpu); |
69 | } | 69 | } |
70 | 70 | ||
71 | static int a3xx_hw_init(struct msm_gpu *gpu) | 71 | static int a3xx_hw_init(struct msm_gpu *gpu) |
@@ -294,9 +294,7 @@ static int a3xx_hw_init(struct msm_gpu *gpu) | |||
294 | /* clear ME_HALT to start micro engine */ | 294 | /* clear ME_HALT to start micro engine */ |
295 | gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0); | 295 | gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0); |
296 | 296 | ||
297 | a3xx_me_init(gpu); | 297 | return a3xx_me_init(gpu) ? 0 : -EINVAL; |
298 | |||
299 | return 0; | ||
300 | } | 298 | } |
301 | 299 | ||
302 | static void a3xx_recover(struct msm_gpu *gpu) | 300 | static void a3xx_recover(struct msm_gpu *gpu) |
@@ -337,17 +335,22 @@ static void a3xx_destroy(struct msm_gpu *gpu) | |||
337 | kfree(a3xx_gpu); | 335 | kfree(a3xx_gpu); |
338 | } | 336 | } |
339 | 337 | ||
340 | static void a3xx_idle(struct msm_gpu *gpu) | 338 | static bool a3xx_idle(struct msm_gpu *gpu) |
341 | { | 339 | { |
342 | /* wait for ringbuffer to drain: */ | 340 | /* wait for ringbuffer to drain: */ |
343 | adreno_idle(gpu); | 341 | if (!adreno_idle(gpu)) |
342 | return false; | ||
344 | 343 | ||
345 | /* then wait for GPU to finish: */ | 344 | /* then wait for GPU to finish: */ |
346 | if (spin_until(!(gpu_read(gpu, REG_A3XX_RBBM_STATUS) & | 345 | if (spin_until(!(gpu_read(gpu, REG_A3XX_RBBM_STATUS) & |
347 | A3XX_RBBM_STATUS_GPU_BUSY))) | 346 | A3XX_RBBM_STATUS_GPU_BUSY))) { |
348 | DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name); | 347 | DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name); |
349 | 348 | ||
350 | /* TODO maybe we need to reset GPU here to recover from hang? */ | 349 | /* TODO maybe we need to reset GPU here to recover from hang? */ |
350 | return false; | ||
351 | } | ||
352 | |||
353 | return true; | ||
351 | } | 354 | } |
352 | 355 | ||
353 | static irqreturn_t a3xx_irq(struct msm_gpu *gpu) | 356 | static irqreturn_t a3xx_irq(struct msm_gpu *gpu) |
diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c index 5745cc81eeda..2abf2627f822 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c | |||
@@ -113,7 +113,7 @@ static void a4xx_enable_hwcg(struct msm_gpu *gpu) | |||
113 | } | 113 | } |
114 | 114 | ||
115 | 115 | ||
116 | static void a4xx_me_init(struct msm_gpu *gpu) | 116 | static bool a4xx_me_init(struct msm_gpu *gpu) |
117 | { | 117 | { |
118 | struct msm_ringbuffer *ring = gpu->rb; | 118 | struct msm_ringbuffer *ring = gpu->rb; |
119 | 119 | ||
@@ -137,7 +137,7 @@ static void a4xx_me_init(struct msm_gpu *gpu) | |||
137 | OUT_RING(ring, 0x00000000); | 137 | OUT_RING(ring, 0x00000000); |
138 | 138 | ||
139 | gpu->funcs->flush(gpu); | 139 | gpu->funcs->flush(gpu); |
140 | gpu->funcs->idle(gpu); | 140 | return gpu->funcs->idle(gpu); |
141 | } | 141 | } |
142 | 142 | ||
143 | static int a4xx_hw_init(struct msm_gpu *gpu) | 143 | static int a4xx_hw_init(struct msm_gpu *gpu) |
@@ -292,9 +292,7 @@ static int a4xx_hw_init(struct msm_gpu *gpu) | |||
292 | /* clear ME_HALT to start micro engine */ | 292 | /* clear ME_HALT to start micro engine */ |
293 | gpu_write(gpu, REG_A4XX_CP_ME_CNTL, 0); | 293 | gpu_write(gpu, REG_A4XX_CP_ME_CNTL, 0); |
294 | 294 | ||
295 | a4xx_me_init(gpu); | 295 | return a4xx_me_init(gpu) ? 0 : -EINVAL; |
296 | |||
297 | return 0; | ||
298 | } | 296 | } |
299 | 297 | ||
300 | static void a4xx_recover(struct msm_gpu *gpu) | 298 | static void a4xx_recover(struct msm_gpu *gpu) |
@@ -335,17 +333,21 @@ static void a4xx_destroy(struct msm_gpu *gpu) | |||
335 | kfree(a4xx_gpu); | 333 | kfree(a4xx_gpu); |
336 | } | 334 | } |
337 | 335 | ||
338 | static void a4xx_idle(struct msm_gpu *gpu) | 336 | static bool a4xx_idle(struct msm_gpu *gpu) |
339 | { | 337 | { |
340 | /* wait for ringbuffer to drain: */ | 338 | /* wait for ringbuffer to drain: */ |
341 | adreno_idle(gpu); | 339 | if (!adreno_idle(gpu)) |
340 | return false; | ||
342 | 341 | ||
343 | /* then wait for GPU to finish: */ | 342 | /* then wait for GPU to finish: */ |
344 | if (spin_until(!(gpu_read(gpu, REG_A4XX_RBBM_STATUS) & | 343 | if (spin_until(!(gpu_read(gpu, REG_A4XX_RBBM_STATUS) & |
345 | A4XX_RBBM_STATUS_GPU_BUSY))) | 344 | A4XX_RBBM_STATUS_GPU_BUSY))) { |
346 | DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name); | 345 | DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name); |
346 | /* TODO maybe we need to reset GPU here to recover from hang? */ | ||
347 | return false; | ||
348 | } | ||
347 | 349 | ||
348 | /* TODO maybe we need to reset GPU here to recover from hang? */ | 350 | return true; |
349 | } | 351 | } |
350 | 352 | ||
351 | static irqreturn_t a4xx_irq(struct msm_gpu *gpu) | 353 | static irqreturn_t a4xx_irq(struct msm_gpu *gpu) |
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 3d4eb08d8c28..04080f9b7e09 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c | |||
@@ -218,19 +218,18 @@ void adreno_flush(struct msm_gpu *gpu) | |||
218 | adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_WPTR, wptr); | 218 | adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_WPTR, wptr); |
219 | } | 219 | } |
220 | 220 | ||
221 | void adreno_idle(struct msm_gpu *gpu) | 221 | bool adreno_idle(struct msm_gpu *gpu) |
222 | { | 222 | { |
223 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); | 223 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); |
224 | uint32_t wptr = get_wptr(gpu->rb); | 224 | uint32_t wptr = get_wptr(gpu->rb); |
225 | int ret; | ||
226 | 225 | ||
227 | /* wait for CP to drain ringbuffer: */ | 226 | /* wait for CP to drain ringbuffer: */ |
228 | ret = spin_until(get_rptr(adreno_gpu) == wptr); | 227 | if (!spin_until(get_rptr(adreno_gpu) == wptr)) |
229 | 228 | return true; | |
230 | if (ret) | ||
231 | DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name); | ||
232 | 229 | ||
233 | /* TODO maybe we need to reset GPU here to recover from hang? */ | 230 | /* TODO maybe we need to reset GPU here to recover from hang? */ |
231 | DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name); | ||
232 | return false; | ||
234 | } | 233 | } |
235 | 234 | ||
236 | #ifdef CONFIG_DEBUG_FS | 235 | #ifdef CONFIG_DEBUG_FS |
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index cccc1a508295..d0f9e1e3acd6 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h | |||
@@ -182,7 +182,7 @@ void adreno_recover(struct msm_gpu *gpu); | |||
182 | void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, | 182 | void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, |
183 | struct msm_file_private *ctx); | 183 | struct msm_file_private *ctx); |
184 | void adreno_flush(struct msm_gpu *gpu); | 184 | void adreno_flush(struct msm_gpu *gpu); |
185 | void adreno_idle(struct msm_gpu *gpu); | 185 | bool adreno_idle(struct msm_gpu *gpu); |
186 | #ifdef CONFIG_DEBUG_FS | 186 | #ifdef CONFIG_DEBUG_FS |
187 | void adreno_show(struct msm_gpu *gpu, struct seq_file *m); | 187 | void adreno_show(struct msm_gpu *gpu, struct seq_file *m); |
188 | #endif | 188 | #endif |
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 6a7e78b317f2..10954135130d 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h | |||
@@ -50,7 +50,7 @@ struct msm_gpu_funcs { | |||
50 | void (*submit)(struct msm_gpu *gpu, struct msm_gem_submit *submit, | 50 | void (*submit)(struct msm_gpu *gpu, struct msm_gem_submit *submit, |
51 | struct msm_file_private *ctx); | 51 | struct msm_file_private *ctx); |
52 | void (*flush)(struct msm_gpu *gpu); | 52 | void (*flush)(struct msm_gpu *gpu); |
53 | void (*idle)(struct msm_gpu *gpu); | 53 | bool (*idle)(struct msm_gpu *gpu); |
54 | irqreturn_t (*irq)(struct msm_gpu *irq); | 54 | irqreturn_t (*irq)(struct msm_gpu *irq); |
55 | uint32_t (*last_fence)(struct msm_gpu *gpu); | 55 | uint32_t (*last_fence)(struct msm_gpu *gpu); |
56 | void (*recover)(struct msm_gpu *gpu); | 56 | void (*recover)(struct msm_gpu *gpu); |