Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/msm/adreno: dump scratch regs and other info on hang

Dump a bit more info when the GPU hangs, without having hang_debug
enabled (which dumps a *lot* of registers). Also dump the scratch
registers, as they are useful for determining where in the cmdstream
the GPU hung (and they seem always safe to read when GPU has hung).

Note that the freedreno gallium driver emits increasing counter values
to SCRATCH6 (to identify tile #) and SCRATCH7 (to identify draw #), so
these two in particular can be used to "triangulate" where in the
cmdstream the GPU hung.

Signed-off-by: Rob Clark <robdclark@gmail.com>

Rob Clark 26716185 3f05eb4e

+25 -3
+3
drivers/gpu/drm/msm/adreno/a3xx_gpu.c
··· 295 295 296 296 static void a3xx_recover(struct msm_gpu *gpu) 297 297 { 298 + adreno_dump_info(gpu); 299 + 298 300 /* dump registers before resetting gpu, if enabled: */ 299 301 if (hang_debug) 300 302 a3xx_dump(gpu); 303 + 301 304 gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1); 302 305 gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD); 303 306 gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0);
+2 -1
drivers/gpu/drm/msm/adreno/a4xx_gpu.c
··· 268 268 269 269 static void a4xx_recover(struct msm_gpu *gpu) 270 270 { 271 + adreno_dump_info(gpu); 272 + 271 273 /* dump registers before resetting gpu, if enabled: */ 272 274 if (hang_debug) 273 275 a4xx_dump(gpu); ··· 507 505 508 506 static void a4xx_dump(struct msm_gpu *gpu) 509 507 { 510 - adreno_dump(gpu); 511 508 printk("status: %08x\n", 512 509 gpu_read(gpu, REG_A4XX_RBBM_STATUS)); 513 510 adreno_dump(gpu);
+19 -2
drivers/gpu/drm/msm/adreno/adreno_gpu.c
··· 249 249 } 250 250 #endif 251 251 252 - /* would be nice to not have to duplicate the _show() stuff with printk(): */ 253 - void adreno_dump(struct msm_gpu *gpu) 252 + /* Dump common gpu status and scratch registers on any hang, to make 253 + * the hangcheck logs more useful. The scratch registers seem always 254 + * safe to read when GPU has hung (unlike some other regs, depending 255 + * on how the GPU hung), and they are useful to match up to cmdstream 256 + * dumps when debugging hangs: 257 + */ 258 + void adreno_dump_info(struct msm_gpu *gpu) 254 259 { 255 260 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 256 261 int i; ··· 270 265 printk("rptr: %d\n", adreno_gpu->memptrs->rptr); 271 266 printk("wptr: %d\n", adreno_gpu->memptrs->wptr); 272 267 printk("rb wptr: %d\n", get_wptr(gpu->rb)); 268 + 269 + for (i = 0; i < 8; i++) { 270 + printk("CP_SCRATCH_REG%d: %u\n", i, 271 + gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i)); 272 + } 273 + } 274 + 275 + /* would be nice to not have to duplicate the _show() stuff with printk(): */ 276 + void adreno_dump(struct msm_gpu *gpu) 277 + { 278 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 279 + int i; 273 280 274 281 /* dump these out in a form that can be parsed by demsm: */ 275 282 printk("IO:region %s 00000000 00020000\n", gpu->name);
+1
drivers/gpu/drm/msm/adreno/adreno_gpu.h
··· 233 233 #ifdef CONFIG_DEBUG_FS 234 234 void adreno_show(struct msm_gpu *gpu, struct seq_file *m); 235 235 #endif 236 + void adreno_dump_info(struct msm_gpu *gpu); 236 237 void adreno_dump(struct msm_gpu *gpu); 237 238 void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords); 238 239