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

drm/msm/gpu: Add trace events for tracking GPU submissions

Add trace events to track the progress of a GPU submission
msm_gpu_submit occurs at the beginning of the submissions,
msm_gpu_submit_flush happens when the submission is put on
the ringbuffer and msm_submit_flush_retired is sent when
the operation is retired.

To make it easier to track the operations a unique sequence
number is assigned to each submission and displayed in each
event output so a human or a script can easily associate
the events related to a specific submission.

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>

authored by

Jordan Crouse and committed by
Rob Clark
4241db42 56869210

+139 -6
+2 -1
drivers/gpu/drm/msm/Makefile
··· 90 90 msm_perf.o \ 91 91 msm_rd.o \ 92 92 msm_ringbuffer.o \ 93 - msm_submitqueue.o 93 + msm_submitqueue.o \ 94 + msm_gpu_tracepoints.o 94 95 95 96 msm-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o \ 96 97 disp/dpu1/dpu_dbg.o
+7
drivers/gpu/drm/msm/adreno/a6xx_gpu.c
··· 4 4 5 5 #include "msm_gem.h" 6 6 #include "msm_mmu.h" 7 + #include "msm_gpu_trace.h" 7 8 #include "a6xx_gpu.h" 8 9 #include "a6xx_gmu.xml.h" 9 10 ··· 82 81 { 83 82 unsigned int index = submit->seqno % MSM_GPU_SUBMIT_STATS_COUNT; 84 83 struct msm_drm_private *priv = gpu->dev->dev_private; 84 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 85 + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 85 86 struct msm_ringbuffer *ring = submit->ring; 86 87 unsigned int i; 87 88 ··· 140 137 OUT_RING(ring, lower_32_bits(rbmemptr(ring, fence))); 141 138 OUT_RING(ring, upper_32_bits(rbmemptr(ring, fence))); 142 139 OUT_RING(ring, submit->seqno); 140 + 141 + trace_msm_gpu_submit_flush(submit, 142 + gmu_read64(&a6xx_gpu->gmu, REG_A6XX_GMU_ALWAYS_ON_COUNTER_L, 143 + REG_A6XX_GMU_ALWAYS_ON_COUNTER_H)); 143 144 144 145 a6xx_flush(gpu, ring); 145 146 }
+1
drivers/gpu/drm/msm/msm_gem.h
··· 150 150 struct msm_ringbuffer *ring; 151 151 unsigned int nr_cmds; 152 152 unsigned int nr_bos; 153 + u32 ident; /* A "identifier" for the submit for logging */ 153 154 struct { 154 155 uint32_t type; 155 156 uint32_t size; /* in dwords */
+12 -3
drivers/gpu/drm/msm/msm_gem_submit.c
··· 20 20 #include "msm_drv.h" 21 21 #include "msm_gpu.h" 22 22 #include "msm_gem.h" 23 + #include "msm_gpu_trace.h" 23 24 24 25 /* 25 26 * Cmdstream submission: ··· 49 48 submit->dev = dev; 50 49 submit->gpu = gpu; 51 50 submit->fence = NULL; 52 - submit->pid = get_pid(task_pid(current)); 53 51 submit->cmd = (void *)&submit->bos[nr_bos]; 54 52 submit->queue = queue; 55 53 submit->ring = gpu->rb[queue->prio]; ··· 406 406 int msm_ioctl_gem_submit(struct drm_device *dev, void *data, 407 407 struct drm_file *file) 408 408 { 409 + static atomic_t ident = ATOMIC_INIT(0); 409 410 struct msm_drm_private *priv = dev->dev_private; 410 411 struct drm_msm_gem_submit *args = data; 411 412 struct msm_file_private *ctx = file->driver_priv; ··· 417 416 struct msm_gpu_submitqueue *queue; 418 417 struct msm_ringbuffer *ring; 419 418 int out_fence_fd = -1; 419 + struct pid *pid = get_pid(task_pid(current)); 420 420 unsigned i; 421 - int ret; 422 - 421 + int ret, submitid; 423 422 if (!gpu) 424 423 return -ENXIO; 425 424 ··· 442 441 if (!queue) 443 442 return -ENOENT; 444 443 444 + /* Get a unique identifier for the submission for logging purposes */ 445 + submitid = atomic_inc_return(&ident) - 1; 446 + 445 447 ring = gpu->rb[queue->prio]; 448 + trace_msm_gpu_submit(pid_nr(pid), ring->id, submitid, 449 + args->nr_bos, args->nr_cmds); 446 450 447 451 if (args->flags & MSM_SUBMIT_FENCE_FD_IN) { 448 452 in_fence = sync_file_get_fence(args->fence_fd); ··· 483 477 ret = -ENOMEM; 484 478 goto out_unlock; 485 479 } 480 + 481 + submit->pid = pid; 482 + submit->ident = submitid; 486 483 487 484 if (args->flags & MSM_SUBMIT_SUDO) 488 485 submit->in_rb = true;
+21 -2
drivers/gpu/drm/msm/msm_gpu.c
··· 19 19 #include "msm_gem.h" 20 20 #include "msm_mmu.h" 21 21 #include "msm_fence.h" 22 + #include "msm_gpu_trace.h" 22 23 23 24 #include <generated/utsrelease.h> 24 25 #include <linux/string_helpers.h> ··· 660 659 * Cmdstream submission/retirement: 661 660 */ 662 661 663 - static void retire_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) 662 + static void retire_submit(struct msm_gpu *gpu, struct msm_ringbuffer *ring, 663 + struct msm_gem_submit *submit) 664 664 { 665 + int index = submit->seqno % MSM_GPU_SUBMIT_STATS_COUNT; 666 + volatile struct msm_gpu_submit_stats *stats; 667 + u64 elapsed, clock = 0; 665 668 int i; 669 + 670 + stats = &ring->memptrs->stats[index]; 671 + /* Convert 19.2Mhz alwayson ticks to nanoseconds for elapsed time */ 672 + elapsed = (stats->alwayson_end - stats->alwayson_start) * 10000; 673 + do_div(elapsed, 192); 674 + 675 + /* Calculate the clock frequency from the number of CP cycles */ 676 + if (elapsed) { 677 + clock = (stats->cpcycles_end - stats->cpcycles_start) * 1000; 678 + do_div(clock, elapsed); 679 + } 680 + 681 + trace_msm_gpu_submit_retired(submit, elapsed, clock, 682 + stats->alwayson_start, stats->alwayson_end); 666 683 667 684 for (i = 0; i < submit->nr_bos; i++) { 668 685 struct msm_gem_object *msm_obj = submit->bos[i].obj; ··· 709 690 710 691 list_for_each_entry_safe(submit, tmp, &ring->submits, node) { 711 692 if (dma_fence_is_signaled(submit->fence)) 712 - retire_submit(gpu, submit); 693 + retire_submit(gpu, ring, submit); 713 694 } 714 695 } 715 696 }
+90
drivers/gpu/drm/msm/msm_gpu_trace.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #if !defined(_MSM_GPU_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) 3 + #define _MSM_GPU_TRACE_H_ 4 + 5 + #include <linux/tracepoint.h> 6 + 7 + #undef TRACE_SYSTEM 8 + #define TRACE_SYSTEM drm_msm 9 + #define TRACE_INCLUDE_FILE msm_gpu_trace 10 + 11 + TRACE_EVENT(msm_gpu_submit, 12 + TP_PROTO(pid_t pid, u32 ringid, u32 id, u32 nr_bos, u32 nr_cmds), 13 + TP_ARGS(pid, ringid, id, nr_bos, nr_cmds), 14 + TP_STRUCT__entry( 15 + __field(pid_t, pid) 16 + __field(u32, id) 17 + __field(u32, ringid) 18 + __field(u32, nr_cmds) 19 + __field(u32, nr_bos) 20 + ), 21 + TP_fast_assign( 22 + __entry->pid = pid; 23 + __entry->id = id; 24 + __entry->ringid = ringid; 25 + __entry->nr_bos = nr_bos; 26 + __entry->nr_cmds = nr_cmds 27 + ), 28 + TP_printk("id=%d pid=%d ring=%d bos=%d cmds=%d", 29 + __entry->id, __entry->pid, __entry->ringid, 30 + __entry->nr_bos, __entry->nr_cmds) 31 + ); 32 + 33 + TRACE_EVENT(msm_gpu_submit_flush, 34 + TP_PROTO(struct msm_gem_submit *submit, u64 ticks), 35 + TP_ARGS(submit, ticks), 36 + TP_STRUCT__entry( 37 + __field(pid_t, pid) 38 + __field(u32, id) 39 + __field(u32, ringid) 40 + __field(u32, seqno) 41 + __field(u64, ticks) 42 + ), 43 + TP_fast_assign( 44 + __entry->pid = pid_nr(submit->pid); 45 + __entry->id = submit->ident; 46 + __entry->ringid = submit->ring->id; 47 + __entry->seqno = submit->seqno; 48 + __entry->ticks = ticks; 49 + ), 50 + TP_printk("id=%d pid=%d ring=%d:%d ticks=%lld", 51 + __entry->id, __entry->pid, __entry->ringid, __entry->seqno, 52 + __entry->ticks) 53 + ); 54 + 55 + 56 + TRACE_EVENT(msm_gpu_submit_retired, 57 + TP_PROTO(struct msm_gem_submit *submit, u64 elapsed, u64 clock, 58 + u64 start, u64 end), 59 + TP_ARGS(submit, elapsed, clock, start, end), 60 + TP_STRUCT__entry( 61 + __field(pid_t, pid) 62 + __field(u32, id) 63 + __field(u32, ringid) 64 + __field(u32, seqno) 65 + __field(u64, elapsed) 66 + __field(u64, clock) 67 + __field(u64, start_ticks) 68 + __field(u64, end_ticks) 69 + ), 70 + TP_fast_assign( 71 + __entry->pid = pid_nr(submit->pid); 72 + __entry->id = submit->ident; 73 + __entry->ringid = submit->ring->id; 74 + __entry->seqno = submit->seqno; 75 + __entry->elapsed = elapsed; 76 + __entry->clock = clock; 77 + __entry->start_ticks = start; 78 + __entry->end_ticks = end; 79 + ), 80 + TP_printk("id=%d pid=%d ring=%d:%d elapsed=%lld ns mhz=%lld start=%lld end=%lld", 81 + __entry->id, __entry->pid, __entry->ringid, __entry->seqno, 82 + __entry->elapsed, __entry->clock, 83 + __entry->start_ticks, __entry->end_ticks) 84 + ); 85 + 86 + #endif 87 + 88 + #undef TRACE_INCLUDE_PATH 89 + #define TRACE_INCLUDE_PATH ../../drivers/gpu/drm/msm 90 + #include <trace/define_trace.h>
+6
drivers/gpu/drm/msm/msm_gpu_tracepoints.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include "msm_gem.h" 3 + #include "msm_ringbuffer.h" 4 + 5 + #define CREATE_TRACE_POINTS 6 + #include "msm_gpu_trace.h"