| 1 | /* |
| 2 | * Copyright 2017 Advanced Micro Devices, Inc. |
| 3 | * |
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | * copy of this software and associated documentation files (the "Software"), |
| 6 | * to deal in the Software without restriction, including without limitation |
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| 8 | * and/or sell copies of the Software, and to permit persons to whom the |
| 9 | * Software is furnished to do so, subject to the following conditions: |
| 10 | * |
| 11 | * The above copyright notice and this permission notice shall be included in |
| 12 | * all copies or substantial portions of the Software. |
| 13 | * |
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
| 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| 20 | * OTHER DEALINGS IN THE SOFTWARE. |
| 21 | * |
| 22 | */ |
| 23 | |
| 24 | #if !defined(_GPU_SCHED_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) |
| 25 | #define _GPU_SCHED_TRACE_H_ |
| 26 | |
| 27 | #include <linux/stringify.h> |
| 28 | #include <linux/types.h> |
| 29 | #include <linux/tracepoint.h> |
| 30 | |
| 31 | #undef TRACE_SYSTEM |
| 32 | #define TRACE_SYSTEM gpu_scheduler |
| 33 | #define TRACE_INCLUDE_FILE gpu_scheduler_trace |
| 34 | |
| 35 | /** |
| 36 | * DOC: uAPI trace events |
| 37 | * |
| 38 | * ``drm_sched_job_queue``, ``drm_sched_job_run``, ``drm_sched_job_add_dep``, |
| 39 | * ``drm_sched_job_done`` and ``drm_sched_job_unschedulable`` are considered |
| 40 | * stable uAPI. |
| 41 | * |
| 42 | * Common trace events attributes: |
| 43 | * |
| 44 | * * ``dev`` - the dev_name() of the device running the job. |
| 45 | * |
| 46 | * * ``ring`` - the hardware ring running the job. Together with ``dev`` it |
| 47 | * uniquely identifies where the job is going to be executed. |
| 48 | * |
| 49 | * * ``fence`` - the &struct dma_fence.context and the &struct dma_fence.seqno of |
| 50 | * &struct drm_sched_fence.finished |
| 51 | * |
| 52 | * All the events depends on drm_sched_job_arm() having been called already for |
| 53 | * the job because they use &struct drm_sched_job.sched or |
| 54 | * &struct drm_sched_job.s_fence. |
| 55 | */ |
| 56 | |
| 57 | DECLARE_EVENT_CLASS(drm_sched_job, |
| 58 | TP_PROTO(struct drm_sched_job *sched_job, struct drm_sched_entity *entity), |
| 59 | TP_ARGS(sched_job, entity), |
| 60 | TP_STRUCT__entry( |
| 61 | __string(name, sched_job->sched->name) |
| 62 | __field(u32, job_count) |
| 63 | __field(int, hw_job_count) |
| 64 | __string(dev, dev_name(sched_job->sched->dev)) |
| 65 | __field(u64, fence_context) |
| 66 | __field(u64, fence_seqno) |
| 67 | __field(u64, client_id) |
| 68 | ), |
| 69 | |
| 70 | TP_fast_assign( |
| 71 | __assign_str(name); |
| 72 | __entry->job_count = spsc_queue_count(&entity->job_queue); |
| 73 | __entry->hw_job_count = atomic_read( |
| 74 | &sched_job->sched->credit_count); |
| 75 | __assign_str(dev); |
| 76 | __entry->fence_context = sched_job->s_fence->finished.context; |
| 77 | __entry->fence_seqno = sched_job->s_fence->finished.seqno; |
| 78 | __entry->client_id = sched_job->s_fence->drm_client_id; |
| 79 | ), |
| 80 | TP_printk("dev=%s, fence=%llu:%llu, ring=%s, job count:%u, hw job count:%d, client_id:%llu" , |
| 81 | __get_str(dev), |
| 82 | __entry->fence_context, __entry->fence_seqno, __get_str(name), |
| 83 | __entry->job_count, __entry->hw_job_count, __entry->client_id) |
| 84 | ); |
| 85 | |
| 86 | DEFINE_EVENT(drm_sched_job, drm_sched_job_queue, |
| 87 | TP_PROTO(struct drm_sched_job *sched_job, struct drm_sched_entity *entity), |
| 88 | TP_ARGS(sched_job, entity) |
| 89 | ); |
| 90 | |
| 91 | DEFINE_EVENT(drm_sched_job, drm_sched_job_run, |
| 92 | TP_PROTO(struct drm_sched_job *sched_job, struct drm_sched_entity *entity), |
| 93 | TP_ARGS(sched_job, entity) |
| 94 | ); |
| 95 | |
| 96 | TRACE_EVENT(drm_sched_job_done, |
| 97 | TP_PROTO(struct drm_sched_fence *fence), |
| 98 | TP_ARGS(fence), |
| 99 | TP_STRUCT__entry( |
| 100 | __field(u64, fence_context) |
| 101 | __field(u64, fence_seqno) |
| 102 | ), |
| 103 | |
| 104 | TP_fast_assign( |
| 105 | __entry->fence_context = fence->finished.context; |
| 106 | __entry->fence_seqno = fence->finished.seqno; |
| 107 | ), |
| 108 | TP_printk("fence=%llu:%llu signaled" , |
| 109 | __entry->fence_context, __entry->fence_seqno) |
| 110 | ); |
| 111 | |
| 112 | TRACE_EVENT(drm_sched_job_add_dep, |
| 113 | TP_PROTO(struct drm_sched_job *sched_job, struct dma_fence *fence), |
| 114 | TP_ARGS(sched_job, fence), |
| 115 | TP_STRUCT__entry( |
| 116 | __field(u64, fence_context) |
| 117 | __field(u64, fence_seqno) |
| 118 | __field(u64, ctx) |
| 119 | __field(u64, seqno) |
| 120 | ), |
| 121 | |
| 122 | TP_fast_assign( |
| 123 | __entry->fence_context = sched_job->s_fence->finished.context; |
| 124 | __entry->fence_seqno = sched_job->s_fence->finished.seqno; |
| 125 | __entry->ctx = fence->context; |
| 126 | __entry->seqno = fence->seqno; |
| 127 | ), |
| 128 | TP_printk("fence=%llu:%llu depends on fence=%llu:%llu" , |
| 129 | __entry->fence_context, __entry->fence_seqno, |
| 130 | __entry->ctx, __entry->seqno) |
| 131 | ); |
| 132 | |
| 133 | TRACE_EVENT(drm_sched_job_unschedulable, |
| 134 | TP_PROTO(struct drm_sched_job *sched_job, struct dma_fence *fence), |
| 135 | TP_ARGS(sched_job, fence), |
| 136 | TP_STRUCT__entry( |
| 137 | __field(u64, fence_context) |
| 138 | __field(u64, fence_seqno) |
| 139 | __field(u64, ctx) |
| 140 | __field(u64, seqno) |
| 141 | ), |
| 142 | |
| 143 | TP_fast_assign( |
| 144 | __entry->fence_context = sched_job->s_fence->finished.context; |
| 145 | __entry->fence_seqno = sched_job->s_fence->finished.seqno; |
| 146 | __entry->ctx = fence->context; |
| 147 | __entry->seqno = fence->seqno; |
| 148 | ), |
| 149 | TP_printk("fence=%llu:%llu depends on unsignalled fence=%llu:%llu" , |
| 150 | __entry->fence_context, __entry->fence_seqno, |
| 151 | __entry->ctx, __entry->seqno) |
| 152 | ); |
| 153 | |
| 154 | #endif /* _GPU_SCHED_TRACE_H_ */ |
| 155 | |
| 156 | /* This part must be outside protection */ |
| 157 | #undef TRACE_INCLUDE_PATH |
| 158 | #define TRACE_INCLUDE_PATH ../../drivers/gpu/drm/scheduler |
| 159 | #include <trace/define_trace.h> |
| 160 | |