On 6/11/26 10:33, Prike Liang wrote:
> From: Pierre-Eric Pelloux-Prayer <[email protected]>
> 
> Add ftrace events for tracking the userq fence emit, signal
> and queue state transition.
> 
> Signed-off-by: Pierre-Eric Pelloux-Prayer <[email protected]>
> Co-developed-by: Prike Liang <[email protected]>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h     | 113 ++++++++++++++++++
>  drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c     |  21 ++++
>  .../gpu/drm/amd/amdgpu/amdgpu_userq_fence.c   |  12 +-
>  3 files changed, 143 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
> index df98be22f1f5..9f8506f04e9e 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
> @@ -28,6 +28,8 @@
>  #include <linux/types.h>
>  #include <linux/tracepoint.h>
>  
> +#include "amdgpu_userq_fence.h"
> +
>  #undef TRACE_SYSTEM
>  #define TRACE_SYSTEM amdgpu
>  #define TRACE_INCLUDE_FILE amdgpu_trace
> @@ -636,6 +638,117 @@ DEFINE_EVENT(amdgpu_userq_queue_result, 
> amdgpu_userq_destroy_end,
>            TP_PROTO(struct amdgpu_usermode_queue *queue, int result),
>            TP_ARGS(queue, result));
>  
> +TRACE_EVENT(amdgpu_userq_emit_fence,
> +         TP_PROTO(struct device *device, struct amdgpu_usermode_queue 
> *queue, struct amdgpu_userq_fence *fence),
> +         TP_ARGS(device, queue, fence),
> +         TP_STRUCT__entry(
> +                          __field(u64, fence_context)
> +                          __field(u64, fence_seqno)
> +                          __string(dev, dev_name(device))
> +                          __field(u64, doorbell_index)
> +                          __field(u64, client_id)
> +                          __field(u32, queue_type)
> +                          ),
> +         TP_fast_assign(
> +                        __entry->fence_context = fence->base.context;
> +                        __entry->fence_seqno = fence->base.seqno;
> +                        __assign_str(dev);
> +                        __entry->doorbell_index = queue->doorbell_index;
> +                        __entry->client_id = 
> queue->userq_mgr->file->client_id;
> +                        __entry->queue_type = queue->queue_type;
> +                        ),
> +         TP_printk("dev=%s, client_id=%llu, type=%u, doorbell=%llu, 
> fence=%llu:%llu",
> +                   __get_str(dev), __entry->client_id, __entry->queue_type, 
> __entry->doorbell_index,
> +                   __entry->fence_context,
> +                   __entry->fence_seqno)
> +);
> +
> +TRACE_EVENT(amdgpu_userq_run_queue,
> +         TP_PROTO(struct device *device,
> +                  struct amdgpu_usermode_queue *queue),
> +         TP_ARGS(device, queue),
> +         TP_STRUCT__entry(__field(u64, context)
> +                          __string(dev, dev_name(device))
> +                          __field(u64, doorbell_index)
> +                          __field(u64, client_id)
> +                          __field(u32, queue_type)
> +                          ),
> +         TP_fast_assign(__assign_str(dev);
> +                        __entry->doorbell_index = queue->doorbell_index;
> +                        __entry->queue_type = queue->queue_type;
> +                        __entry->client_id = 
> queue->userq_mgr->file->client_id;
> +                        __entry->context = queue->fence_drv->context;
> +                       ),
> +         TP_printk("dev=%s, client_id=%llu, type=%u, doorbell=%llu, 
> context=%llu",
> +                   __get_str(dev), __entry->client_id, __entry->queue_type,
> +                   __entry->doorbell_index, __entry->context)
> +);
> +
> +TRACE_EVENT(amdgpu_userq_wait_deps,
> +         TP_PROTO(struct device *device, struct amdgpu_usermode_queue 
> *queue, struct amdgpu_userq_fence *dep),
> +         TP_ARGS(device, queue, dep),
> +         TP_STRUCT__entry(
> +                          __field(u64, context)
> +                          __field(u64, dep_context)
> +                          __field(u64, dep_seqno)
> +                          __string(dev, dev_name(device))
> +                          __field(u64, doorbell_index)
> +                          __field(u64, client_id)
> +                          __field(u32, queue_type)
> +                          ),
> +         TP_fast_assign(
> +                        __assign_str(dev);
> +                        __entry->doorbell_index = queue->doorbell_index;
> +                        __entry->queue_type = queue->queue_type;
> +                        __entry->client_id = 
> queue->userq_mgr->file->client_id;
> +                        __entry->context = queue->fence_drv->context;
> +                        __entry->dep_context = dep->base.context;
> +                        __entry->dep_seqno = dep->base.seqno;
> +                        ),
> +         TP_printk("dev=%s, client_id=%llu, type=%u, doorbell=%llu, 
> context=%llu depends on fence=%llu:%llu",
> +                   __get_str(dev), __entry->client_id, __entry->queue_type, 
> __entry->doorbell_index, __entry->context,
> +                   __entry->dep_context,
> +                   __entry->dep_seqno)
> +);
> +
> +TRACE_EVENT(amdgpu_userq_state_start,
> +         TP_PROTO(struct amdgpu_usermode_queue *queue),
> +         TP_ARGS(queue),
> +         TP_STRUCT__entry(
> +                          __field(u64, doorbell_index)
> +                          __field(u64, client_id)
> +                          __field(u32, queue_type)
> +                          __field(u32, from)
> +                          ),
> +         TP_fast_assign(
> +                        __entry->doorbell_index = queue->doorbell_index;
> +                        __entry->queue_type = queue->queue_type;
> +                        __entry->client_id = 
> queue->userq_mgr->file->client_id;
> +                        __entry->from = queue->state;
> +                        ),
> +         TP_printk("client_id=%llu, type=%u, doorbell=%llu, from=%d",
> +                   __entry->client_id, __entry->queue_type, 
> __entry->doorbell_index, __entry->from)
> +);
> +
> +TRACE_EVENT(amdgpu_userq_state_changed,
> +         TP_PROTO(struct amdgpu_usermode_queue *queue, enum 
> amdgpu_userq_state new_state),
> +         TP_ARGS(queue, new_state),
> +         TP_STRUCT__entry(
> +                          __field(u64, doorbell_index)
> +                          __field(u64, client_id)
> +                          __field(u32, queue_type)
> +                          __field(u32, to)
> +                          ),
> +         TP_fast_assign(
> +                        __entry->doorbell_index = queue->doorbell_index;
> +                        __entry->queue_type = queue->queue_type;
> +                        __entry->client_id = 
> queue->userq_mgr->file->client_id;
> +                        __entry->to = new_state;
> +                        ),
> +         TP_printk("client_id=%llu, type=%u, doorbell=%llu, to=%d",
> +                   __entry->client_id, __entry->queue_type, 
> __entry->doorbell_index, __entry->to)
> +);
> +
>  #undef AMDGPU_JOB_GET_TIMELINE_NAME
>  #endif
>  
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> index 64b9127ef931..ede2263d8458 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> @@ -294,11 +294,15 @@ static int amdgpu_userq_preempt_helper(struct 
> amdgpu_usermode_queue *queue)
>       int r;
>  
>       if (queue->state == AMDGPU_USERQ_STATE_MAPPED) {
> +             trace_amdgpu_userq_state_start(queue);
> +
>               r = userq_funcs->preempt(queue);
>               if (r) {
> +                     trace_amdgpu_userq_state_changed(queue, 
> AMDGPU_USERQ_STATE_HUNG);
>                       queue->state = AMDGPU_USERQ_STATE_HUNG;
>                       return r;
>               } else {
> +                     trace_amdgpu_userq_state_changed(queue, 
> AMDGPU_USERQ_STATE_PREEMPTED);
>                       queue->state = AMDGPU_USERQ_STATE_PREEMPTED;
>               }
>       }
> @@ -314,10 +318,14 @@ static int amdgpu_userq_restore_helper(struct 
> amdgpu_usermode_queue *queue)
>       int r = 0;
>  
>       if (queue->state == AMDGPU_USERQ_STATE_PREEMPTED) {
> +             trace_amdgpu_userq_state_start(queue);
> +
>               r = userq_funcs->restore(queue);
>               if (r) {
> +                     trace_amdgpu_userq_state_changed(queue, 
> AMDGPU_USERQ_STATE_HUNG);
>                       queue->state = AMDGPU_USERQ_STATE_HUNG;
>               } else {
> +                     trace_amdgpu_userq_state_changed(queue, 
> AMDGPU_USERQ_STATE_MAPPED);
>                       queue->state = AMDGPU_USERQ_STATE_MAPPED;
>               }
>       }
> @@ -335,12 +343,15 @@ static int amdgpu_userq_unmap_helper(struct 
> amdgpu_usermode_queue *queue)
>  
>       if ((queue->state == AMDGPU_USERQ_STATE_MAPPED) ||
>           (queue->state == AMDGPU_USERQ_STATE_PREEMPTED)) {
> +             trace_amdgpu_userq_state_start(queue);
>  
>               r = userq_funcs->unmap(queue);
>               if (r) {
> +                     trace_amdgpu_userq_state_changed(queue, 
> AMDGPU_USERQ_STATE_HUNG);
>                       queue->state = AMDGPU_USERQ_STATE_HUNG;
>                       return r;
>               } else {
> +                     trace_amdgpu_userq_state_changed(queue, 
> AMDGPU_USERQ_STATE_UNMAPPED);
>                       queue->state = AMDGPU_USERQ_STATE_UNMAPPED;
>               }
>       }
> @@ -357,11 +368,15 @@ static int amdgpu_userq_map_helper(struct 
> amdgpu_usermode_queue *queue)
>       int r;
>  
>       if (queue->state == AMDGPU_USERQ_STATE_UNMAPPED) {
> +             trace_amdgpu_userq_state_start(queue);
> +
>               r = userq_funcs->map(queue);
>               if (r) {
> +                     trace_amdgpu_userq_state_changed(queue, 
> AMDGPU_USERQ_STATE_HUNG);
>                       queue->state = AMDGPU_USERQ_STATE_HUNG;
>                       return r;
>               } else {
> +                     trace_amdgpu_userq_state_changed(queue, 
> AMDGPU_USERQ_STATE_MAPPED);
>                       queue->state = AMDGPU_USERQ_STATE_MAPPED;
>               }
>       }
> @@ -900,6 +915,7 @@ amdgpu_userq_restore_all(struct amdgpu_userq_mgr *uq_mgr)
>               if (!amdgpu_userq_buffer_vas_mapped(queue)) {
>                       drm_file_err(uq_mgr->file,
>                                    "trying restore queue without va 
> mapping\n");
> +                     trace_amdgpu_userq_state_changed(queue, 
> AMDGPU_USERQ_STATE_INVALID_VA);
>                       queue->state = AMDGPU_USERQ_STATE_INVALID_VA;
>                       continue;
>               }
> @@ -1392,12 +1408,14 @@ void amdgpu_userq_pre_reset(struct amdgpu_device 
> *adev)
>               if (queue->state != AMDGPU_USERQ_STATE_MAPPED)
>                       continue;
>  
> +             trace_amdgpu_userq_state_start(queue);
>               userq_funcs = adev->userq_funcs[queue->queue_type];
>               userq_funcs->unmap(queue);
>               /* just mark all queues as hung at this point.
>                * if unmap succeeds, we could map again
>                * in amdgpu_userq_post_reset() if vram is not lost
>                */
> +             trace_amdgpu_userq_state_changed(queue, 
> AMDGPU_USERQ_STATE_HUNG);
>               queue->state = AMDGPU_USERQ_STATE_HUNG;
>               amdgpu_userq_fence_driver_force_completion(queue);
>       }
> @@ -1416,6 +1434,8 @@ int amdgpu_userq_post_reset(struct amdgpu_device *adev, 
> bool vram_lost)
>  
>       xa_for_each(&adev->userq_doorbell_xa, queue_id, queue) {
>               if (queue->state == AMDGPU_USERQ_STATE_HUNG && !vram_lost) {
> +                     trace_amdgpu_userq_state_start(queue);
> +
>                       userq_funcs = adev->userq_funcs[queue->queue_type];
>                       /* Re-map queue */
>                       r = userq_funcs->map(queue);
> @@ -1423,6 +1443,7 @@ int amdgpu_userq_post_reset(struct amdgpu_device *adev, 
> bool vram_lost)
>                               dev_err(adev->dev, "Failed to remap queue 
> %ld\n", queue_id);
>                               continue;
>                       }
> +                     trace_amdgpu_userq_state_changed(queue, 
> AMDGPU_USERQ_STATE_MAPPED);
>                       queue->state = AMDGPU_USERQ_STATE_MAPPED;
>               }
>       }
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
> index c0d68863fa17..95ee133f749e 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
> @@ -30,7 +30,7 @@
>  #include <drm/drm_syncobj.h>
>  
>  #include "amdgpu.h"
> -#include "amdgpu_userq_fence.h"
> +#include "amdgpu_trace.h"
>  
>  #define AMDGPU_USERQ_MAX_HANDLES     (1U << 16)
>  
> @@ -528,6 +528,8 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, 
> void *data,
>       /* Create the new fence */
>       amdgpu_userq_fence_init(queue, fence, wptr);
>  
> +     trace_amdgpu_userq_emit_fence(dev->dev, queue, fence);
> +
>       mutex_unlock(&userq_mgr->userq_mutex);
>  
>       /*
> @@ -701,7 +703,7 @@ amdgpu_userq_wait_add_fence(struct drm_amdgpu_userq_wait 
> *wait_info,
>  }
>  
>  static int
> -amdgpu_userq_wait_return_fence_info(struct drm_file *filp,
> +amdgpu_userq_wait_return_fence_info(struct drm_device *dev, struct drm_file 
> *filp,
>                                   struct drm_amdgpu_userq_wait *wait_info,
>                                   u32 *syncobj_handles, u64 *timeline_points,
>                                   u32 *timeline_handles,
> @@ -835,6 +837,8 @@ amdgpu_userq_wait_return_fence_info(struct drm_file *filp,
>               goto free_fences;
>       }
>  
> +     trace_amdgpu_userq_run_queue(dev->dev, waitq);

That one clearly needs a better name or we can maybe even completely drop it.

The queue doesn't run, what we do here is to start gathering the fences the 
queue need to wait for.

Apart from that looks good to me,
Christian.

> +
>       for (i = 0, cnt = 0; i < num_fences; i++) {
>               struct amdgpu_userq_fence_driver *fence_drv;
>               struct amdgpu_userq_fence *userq_fence;
> @@ -869,6 +873,8 @@ amdgpu_userq_wait_return_fence_info(struct drm_file *filp,
>  
>               amdgpu_userq_fence_driver_get(fence_drv);
>  
> +             trace_amdgpu_userq_wait_deps(dev->dev, waitq, userq_fence);
> +
>               /* Store drm syncobj's gpu va address and value */
>               fence_info[cnt].va = fence_drv->va;
>               fence_info[cnt].value = fences[i]->seqno;
> @@ -969,7 +975,7 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void 
> *data,
>                                                  gobj_write,
>                                                  gobj_read);
>       } else {
> -             r = amdgpu_userq_wait_return_fence_info(filp, wait_info,
> +             r = amdgpu_userq_wait_return_fence_info(dev, filp, wait_info,
>                                                       syncobj_handles,
>                                                       timeline_points,
>                                                       timeline_handles,

Reply via email to