aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/msm
diff options
context:
space:
mode:
authorRob Clark <robdclark@gmail.com>2013-12-22 10:29:43 -0500
committerRob Clark <robdclark@gmail.com>2014-03-31 10:27:45 -0400
commit5b6ef08e4b4e1bcb6b3ac4172c054e4462e2c767 (patch)
treed62e3bc1dfa8d95e241a136e0702ad2c3f28f55b /drivers/gpu/drm/msm
parentc0c0d9eeeb8df43964601a2c4666f0c49bedacb4 (diff)
drm/msm: add hang_debug module param
msm.hang_debug=y will dump out current register values if the gpu locks up, for easier debugging. Signed-off-by: Rob Clark <robdclark@gmail.com>
Diffstat (limited to 'drivers/gpu/drm/msm')
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx_gpu.c34
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c18
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h1
3 files changed, 52 insertions, 1 deletions
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
index 461df93e825e..8b6fb847789e 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -35,6 +35,12 @@
35 A3XX_INT0_CP_AHB_ERROR_HALT | \ 35 A3XX_INT0_CP_AHB_ERROR_HALT | \
36 A3XX_INT0_UCHE_OOB_ACCESS) 36 A3XX_INT0_UCHE_OOB_ACCESS)
37 37
38
39static bool hang_debug = false;
40MODULE_PARM_DESC(hang_debug, "Dump registers when hang is detected (can be slow!)");
41module_param_named(hang_debug, hang_debug, bool, 0600);
42static void a3xx_dump(struct msm_gpu *gpu);
43
38static struct platform_device *a3xx_pdev; 44static struct platform_device *a3xx_pdev;
39 45
40static void a3xx_me_init(struct msm_gpu *gpu) 46static void a3xx_me_init(struct msm_gpu *gpu)
@@ -291,6 +297,9 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
291 297
292static void a3xx_recover(struct msm_gpu *gpu) 298static void a3xx_recover(struct msm_gpu *gpu)
293{ 299{
300 /* dump registers before resetting gpu, if enabled: */
301 if (hang_debug)
302 a3xx_dump(gpu);
294 gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1); 303 gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1);
295 gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD); 304 gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD);
296 gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0); 305 gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0);
@@ -352,7 +361,6 @@ static irqreturn_t a3xx_irq(struct msm_gpu *gpu)
352 return IRQ_HANDLED; 361 return IRQ_HANDLED;
353} 362}
354 363
355#ifdef CONFIG_DEBUG_FS
356static const unsigned int a3xx_registers[] = { 364static const unsigned int a3xx_registers[] = {
357 0x0000, 0x0002, 0x0010, 0x0012, 0x0018, 0x0018, 0x0020, 0x0027, 365 0x0000, 0x0002, 0x0010, 0x0012, 0x0018, 0x0018, 0x0020, 0x0027,
358 0x0029, 0x002b, 0x002e, 0x0033, 0x0040, 0x0042, 0x0050, 0x005c, 366 0x0029, 0x002b, 0x002e, 0x0033, 0x0040, 0x0042, 0x0050, 0x005c,
@@ -392,6 +400,7 @@ static const unsigned int a3xx_registers[] = {
392 0x303c, 0x303c, 0x305e, 0x305f, 400 0x303c, 0x303c, 0x305e, 0x305f,
393}; 401};
394 402
403#ifdef CONFIG_DEBUG_FS
395static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m) 404static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m)
396{ 405{
397 int i; 406 int i;
@@ -415,6 +424,29 @@ static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m)
415} 424}
416#endif 425#endif
417 426
427/* would be nice to not have to duplicate the _show() stuff with printk(): */
428static void a3xx_dump(struct msm_gpu *gpu)
429{
430 int i;
431
432 adreno_dump(gpu);
433 printk("status: %08x\n",
434 gpu_read(gpu, REG_A3XX_RBBM_STATUS));
435
436 /* dump these out in a form that can be parsed by demsm: */
437 printk("IO:region %s 00000000 00020000\n", gpu->name);
438 for (i = 0; i < ARRAY_SIZE(a3xx_registers); i += 2) {
439 uint32_t start = a3xx_registers[i];
440 uint32_t end = a3xx_registers[i+1];
441 uint32_t addr;
442
443 for (addr = start; addr <= end; addr++) {
444 uint32_t val = gpu_read(gpu, addr);
445 printk("IO:R %08x %08x\n", addr<<2, val);
446 }
447 }
448}
449
418static const struct adreno_gpu_funcs funcs = { 450static const struct adreno_gpu_funcs funcs = {
419 .base = { 451 .base = {
420 .get_param = adreno_get_param, 452 .get_param = adreno_get_param,
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index d321099abdd4..cf6eb976dda7 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -260,6 +260,24 @@ void adreno_show(struct msm_gpu *gpu, struct seq_file *m)
260} 260}
261#endif 261#endif
262 262
263/* would be nice to not have to duplicate the _show() stuff with printk(): */
264void adreno_dump(struct msm_gpu *gpu)
265{
266 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
267
268 printk("revision: %d (%d.%d.%d.%d)\n",
269 adreno_gpu->info->revn, adreno_gpu->rev.core,
270 adreno_gpu->rev.major, adreno_gpu->rev.minor,
271 adreno_gpu->rev.patchid);
272
273 printk("fence: %d/%d\n", adreno_gpu->memptrs->fence,
274 gpu->submitted_fence);
275 printk("rptr: %d\n", adreno_gpu->memptrs->rptr);
276 printk("wptr: %d\n", adreno_gpu->memptrs->wptr);
277 printk("rb wptr: %d\n", get_wptr(gpu->rb));
278
279}
280
263void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords) 281void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords)
264{ 282{
265 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 283 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index ca11ea4da165..e16200ddc60b 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -114,6 +114,7 @@ void adreno_idle(struct msm_gpu *gpu);
114#ifdef CONFIG_DEBUG_FS 114#ifdef CONFIG_DEBUG_FS
115void adreno_show(struct msm_gpu *gpu, struct seq_file *m); 115void adreno_show(struct msm_gpu *gpu, struct seq_file *m);
116#endif 116#endif
117void adreno_dump(struct msm_gpu *gpu);
117void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords); 118void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords);
118 119
119int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, 120int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,