From: Sean Paul <seanpaul@xxxxxxxxxxxx> This patch is the first step in expanding trace events in drm. It introduces a new enum used to classify trace events as well as a couple helper macros to issue trace events from around drm. It's a bit of a toy right now since we're just converting one class (vblank) and there aren't any error events in this class. However later patches in this series will add more interesting classes. Signed-off-by: Sean Paul <seanpaul@xxxxxxxxxxxx> --- Documentation/gpu/drm-internals.rst | 9 +++ drivers/gpu/drm/drm_trace.h | 109 ++++++++++++++++++++++++++-- drivers/gpu/drm/drm_vblank.c | 8 +- 3 files changed, 114 insertions(+), 12 deletions(-) diff --git a/Documentation/gpu/drm-internals.rst b/Documentation/gpu/drm-internals.rst index 966bd2d9f0ccd..ac87a94b7057a 100644 --- a/Documentation/gpu/drm-internals.rst +++ b/Documentation/gpu/drm-internals.rst @@ -176,6 +176,15 @@ Printer .. kernel-doc:: drivers/gpu/drm/drm_print.c :export: +Tracing +------- + +.. kernel-doc:: drivers/gpu/drm/drm_trace.h + :doc: overview + +.. kernel-doc:: drivers/gpu/drm/drm_trace.h + :internal: + Utilities --------- diff --git a/drivers/gpu/drm/drm_trace.h b/drivers/gpu/drm/drm_trace.h index 487bc3478efec..19e5f04210586 100644 --- a/drivers/gpu/drm/drm_trace.h +++ b/drivers/gpu/drm/drm_trace.h @@ -7,21 +7,109 @@ #include <linux/tracepoint.h> struct drm_file; +/** + * DOC: overview + * + * DRM trace events can be used to trace important moments occurring in the DRM + * core or helpers without incurring a significant performance penalty (like you + * would with console logging). + */ + +#if !defined(_DRM_TRACE_EVENT_CLASS_ENUM) +#define _DRM_TRACE_EVENT_CLASS_ENUM + +/** + * enum drm_trace_event_class - the trace class of an event + * + * Trace events are broken into different classes (much the same as we do for + * console logging) to make sifting through the logs easier. If you want to + * isolate one or more classes (or disable a subset of classes), you can write + * an expession using the event_class entry field as a tracepoints filter. The + * event_class field is not printed as part of the trace log, it's just there + * for filtering. + * + * The classes are bitfields to make filtering easier, but also to allow trace + * events to be classified under multiple classes (ie: if you're tracing an + * error that occurred with a crtc, you can ensure that these events are + * surfaced for filters looking for either crtc or error classes). + * + * An example filter is: + * Assume you want to view all trace events in failure paths, you would + * write a filter which isolates events with the drm_trace_class_error bit + * set in their event_class field. This allows you to enable all trace + * events in the drm trace system and only consume errors. + * + * ; echo "event_class & 0x1" > /sys/kernel/tracing/events/drm/filter + * ; echo 1 > /sys/kernel/tracing/events/drm/enable + * + * Similarly, to view all vblank traces plus any error traces, you select + * both classes in the filter. + * + * ; echo "event_class & 0x3" > /sys/kernel/tracing/events/drm/filter + */ +enum drm_trace_event_class { + /** + * @drm_trace_class_error: Denotes that the trace event is coming from + * an error path. + */ + drm_trace_class_error = BIT(0), + + /** + * @drm_trace_class_vblank: Use this to track trace events that track + * vblanks and vblank events. + */ + drm_trace_class_vblank = BIT(1), +}; + +/** + * drm_trace - add a drm trace event + * @_c: class name (the part that comes after drm_trace_class_) + * @_e: event name (the part that comes after drm_$class_) + * + * Use this macro to simplify adding a trace event for non-failure paths in + * drm code. The macro simply assembles the trace event from the class and name, + * and sets the correct event_code for this trace. + * + * It's recommended that this macro is not used in failure paths. For failure + * paths, use drm_trace_err(). + */ +#define drm_trace(_c, _e, ...) \ + trace_drm_##_c##_##_e(drm_trace_class_##_c, __VA_ARGS__) + +/** + * drm_trace_err - add a drm trace event in a failure path + * @_c: class name (the part that comes after drm_trace_class_) + * @_e: event name (the part that comes after drm_$class_) + * + * This is virtually the same as drm_trace(), however it sets the error class on + * the event as well. This is beneficial for those filtering events by + * class_error. + * + * For non-failure paths, please use drm_trace(). + */ +#define drm_trace_err(_c, _e, ...) \ + trace_drm_##_c##_##_e(drm_trace_class_##_c | drm_trace_class_error, \ + __VA_ARGS__) + +#endif #undef TRACE_SYSTEM #define TRACE_SYSTEM drm #define TRACE_INCLUDE_FILE drm_trace TRACE_EVENT(drm_vblank_event, - TP_PROTO(int crtc, unsigned int seq, ktime_t time, bool high_prec), - TP_ARGS(crtc, seq, time, high_prec), + TP_PROTO(unsigned int event_class, int crtc, unsigned int seq, + ktime_t time, bool high_prec), + TP_ARGS(event_class, crtc, seq, time, high_prec), TP_STRUCT__entry( + __field(unsigned int, event_class) __field(int, crtc) __field(unsigned int, seq) __field(ktime_t, time) __field(bool, high_prec) ), TP_fast_assign( + __entry->event_class = event_class; __entry->crtc = crtc; __entry->seq = seq; __entry->time = time; @@ -33,14 +121,17 @@ TRACE_EVENT(drm_vblank_event, ); DECLARE_EVENT_CLASS(class_drm_vblank_event, - TP_PROTO(struct drm_file *file, int crtc, unsigned int seq), - TP_ARGS(file, crtc, seq), + TP_PROTO(unsigned int event_class, struct drm_file *file, + int crtc, unsigned int seq), + TP_ARGS(event_class, file, crtc, seq), TP_STRUCT__entry( + __field(unsigned int, event_class) __field(struct drm_file *, file) __field(int, crtc) __field(unsigned int, seq) ), TP_fast_assign( + __entry->event_class = event_class; __entry->file = file; __entry->crtc = crtc; __entry->seq = seq; @@ -49,12 +140,14 @@ DECLARE_EVENT_CLASS(class_drm_vblank_event, __entry->seq) ); DEFINE_EVENT(class_drm_vblank_event, drm_vblank_event_queued, - TP_PROTO(struct drm_file *file, int crtc, unsigned int seq), - TP_ARGS(file, crtc, seq) + TP_PROTO(unsigned int event_class, struct drm_file *file, int crtc, + unsigned int seq), + TP_ARGS(event_class, file, crtc, seq) ); DEFINE_EVENT(class_drm_vblank_event, drm_vblank_event_delivered, - TP_PROTO(struct drm_file *file, int crtc, unsigned int seq), - TP_ARGS(file, crtc, seq) + TP_PROTO(unsigned int event_class, struct drm_file *file, int crtc, + unsigned int seq), + TP_ARGS(event_class, file, crtc, seq) ); #endif /* _DRM_TRACE_H_ */ diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 1659b13b178c2..19a63a94586ad 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -880,7 +880,7 @@ static void send_vblank_event(struct drm_device *dev, e->event.seq.time_ns = ktime_to_ns(now); break; } - trace_drm_vblank_event_delivered(e->base.file_priv, e->pipe, seq); + drm_trace(vblank, event_delivered, e->base.file_priv, e->pipe, seq); drm_send_event_locked(dev, &e->base); } @@ -1529,7 +1529,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe, DRM_DEBUG("event on vblank count %llu, current %llu, crtc %u\n", req_seq, seq, pipe); - trace_drm_vblank_event_queued(file_priv, pipe, req_seq); + drm_trace(vblank, event_queued, file_priv, pipe, req_seq); e->sequence = req_seq; if (vblank_passed(seq, req_seq)) { @@ -1760,8 +1760,8 @@ static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe) send_vblank_event(dev, e, seq, now); } - trace_drm_vblank_event(pipe, seq, now, - dev->driver->get_vblank_timestamp != NULL); + drm_trace(vblank, event, pipe, seq, now, + dev->driver->get_vblank_timestamp != NULL); } /** -- Sean Paul, Software Engineer, Google / Chromium OS _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel