[3/6] drm: trace: Add trace events for atomic state lifetime
diff mbox series

Message ID 20191107210316.143216-4-sean@poorly.run
State New
Headers show
Series
  • drm: trace: Introduce drm_trace() and instrument drm_atomic.c
Related show

Commit Message

Sean Paul Nov. 7, 2019, 9:03 p.m. UTC
From: Sean Paul <seanpaul@chromium.org>

Mirror some atomic debug messages which track a state through
allocation/clear/check/commit/free

Change-Id: I0387ddf4b2f1d84137a5b471e347878c04c6d0af
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/gpu/drm/drm_atomic.c | 19 +++++---
 drivers/gpu/drm/drm_trace.h  | 84 ++++++++++++++++++++++++++++++++++++
 2 files changed, 98 insertions(+), 5 deletions(-)

Patch
diff mbox series

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 14aeaf7363210..93ca64af67f55 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -41,6 +41,7 @@ 
 
 #include "drm_crtc_internal.h"
 #include "drm_internal.h"
+#include "drm_trace.h"
 
 void __drm_crtc_commit_free(struct kref *kref)
 {
@@ -118,10 +119,11 @@  struct drm_atomic_state *
 drm_atomic_state_alloc(struct drm_device *dev)
 {
 	struct drm_mode_config *config = &dev->mode_config;
+	struct drm_atomic_state *state;
 
-	if (!config->funcs->atomic_state_alloc) {
-		struct drm_atomic_state *state;
-
+	if (config->funcs->atomic_state_alloc) {
+		state = config->funcs->atomic_state_alloc(dev);
+	} else {
 		state = kzalloc(sizeof(*state), GFP_KERNEL);
 		if (!state)
 			return NULL;
@@ -129,10 +131,10 @@  drm_atomic_state_alloc(struct drm_device *dev)
 			kfree(state);
 			return NULL;
 		}
-		return state;
 	}
 
-	return config->funcs->atomic_state_alloc(dev);
+	drm_trace(atomic, alloc, state);
+	return state;
 }
 EXPORT_SYMBOL(drm_atomic_state_alloc);
 
@@ -239,6 +241,7 @@  void drm_atomic_state_clear(struct drm_atomic_state *state)
 	struct drm_device *dev = state->dev;
 	struct drm_mode_config *config = &dev->mode_config;
 
+	drm_trace(atomic, clear, state);
 	if (config->funcs->atomic_state_clear)
 		config->funcs->atomic_state_clear(state);
 	else
@@ -261,6 +264,7 @@  void __drm_atomic_state_free(struct kref *ref)
 	drm_atomic_state_clear(state);
 
 	DRM_DEBUG_ATOMIC("Freeing atomic state %p\n", state);
+	drm_trace(atomic, free, state);
 
 	if (config->funcs->atomic_state_free) {
 		config->funcs->atomic_state_free(state);
@@ -1145,6 +1149,7 @@  int drm_atomic_check_only(struct drm_atomic_state *state)
 	int i, ret = 0;
 
 	DRM_DEBUG_ATOMIC("checking %p\n", state);
+	drm_trace(atomic, check, state);
 
 	for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
 		ret = drm_atomic_plane_check(old_plane_state, new_plane_state);
@@ -1179,6 +1184,7 @@  int drm_atomic_check_only(struct drm_atomic_state *state)
 		if (ret) {
 			DRM_DEBUG_ATOMIC("atomic driver check for %p failed: %d\n",
 					 state, ret);
+			drm_trace_err(atomic, check_failed, state);
 			return ret;
 		}
 	}
@@ -1193,6 +1199,7 @@  int drm_atomic_check_only(struct drm_atomic_state *state)
 		}
 	}
 
+	drm_trace(atomic, check_passed, state);
 	return 0;
 }
 EXPORT_SYMBOL(drm_atomic_check_only);
@@ -1221,6 +1228,7 @@  int drm_atomic_commit(struct drm_atomic_state *state)
 		return ret;
 
 	DRM_DEBUG_ATOMIC("committing %p\n", state);
+	drm_trace(atomic, commit, state);
 
 	return config->funcs->atomic_commit(state->dev, state, false);
 }
@@ -1250,6 +1258,7 @@  int drm_atomic_nonblocking_commit(struct drm_atomic_state *state)
 		return ret;
 
 	DRM_DEBUG_ATOMIC("committing %p nonblocking\n", state);
+	drm_trace(atomic, commit_nonblock, state);
 
 	return config->funcs->atomic_commit(state->dev, state, true);
 }
diff --git a/drivers/gpu/drm/drm_trace.h b/drivers/gpu/drm/drm_trace.h
index 19e5f04210586..5d56365d0b439 100644
--- a/drivers/gpu/drm/drm_trace.h
+++ b/drivers/gpu/drm/drm_trace.h
@@ -2,6 +2,9 @@ 
 #if !defined(_DRM_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
 #define _DRM_TRACE_H_
 
+#include <drm/drm_atomic.h>
+
+#include <linux/kref.h>
 #include <linux/stringify.h>
 #include <linux/types.h>
 #include <linux/tracepoint.h>
@@ -59,6 +62,12 @@  enum drm_trace_event_class {
 	 * vblanks and vblank events.
 	 */
 	drm_trace_class_vblank		= BIT(1),
+
+	/**
+	 * @drm_trace_class_atomic: This class is used to track the top-level
+	 * atomic state from alloc to free and everywhere in between.
+	 */
+	drm_trace_class_atomic		= BIT(2),
 };
 
 /**
@@ -150,6 +159,81 @@  DEFINE_EVENT(class_drm_vblank_event, drm_vblank_event_delivered,
 	TP_ARGS(event_class, file, crtc, seq)
 );
 
+DECLARE_EVENT_CLASS(class_drm_atomic,
+	TP_PROTO(unsigned int event_class,
+		 const struct drm_atomic_state *state),
+	TP_ARGS(event_class, state),
+	TP_STRUCT__entry(
+		__field(unsigned int, event_class)
+		__field(const struct drm_atomic_state *, state)
+		__field(unsigned int, ref)
+		__field(bool, allow_modeset)
+		__field(bool, legacy_cursor_update)
+		__field(bool, async_update)
+		__field(bool, duplicated)
+		__field(unsigned int, num_connector)
+		__field(unsigned int, num_private_objs)
+	),
+	TP_fast_assign(
+		__entry->event_class = event_class;
+		__entry->state = state; /* Do not de-reference! */
+		__entry->ref = kref_read(&state->ref);
+		__entry->allow_modeset = state->allow_modeset;
+		__entry->legacy_cursor_update = state->legacy_cursor_update;
+		__entry->async_update = state->async_update;
+		__entry->duplicated = state->duplicated;
+		__entry->num_connector = state->num_connector;
+		__entry->num_private_objs = state->num_private_objs;
+	),
+	TP_printk("state=%pK ref=%d allow_modeset=%d legacy_cursor=%d "
+		  "async_update=%d duplicated=%d num_conn=%d num_priv_objs=%d",
+		  __entry->state, __entry->ref, __entry->allow_modeset,
+		  __entry->legacy_cursor_update, __entry->async_update,
+		  __entry->duplicated, __entry->num_connector,
+		  __entry->num_private_objs)
+);
+DEFINE_EVENT_PRINT(class_drm_atomic, drm_atomic_alloc,
+	TP_PROTO(unsigned int event_class,
+		 const struct drm_atomic_state *state),
+	TP_ARGS(event_class, state),
+	TP_printk("state=%pK", __entry->state)
+);
+DEFINE_EVENT(class_drm_atomic, drm_atomic_clear,
+	TP_PROTO(unsigned int event_class,
+		 const struct drm_atomic_state *state),
+	TP_ARGS(event_class, state)
+);
+DEFINE_EVENT(class_drm_atomic, drm_atomic_free,
+	TP_PROTO(unsigned int event_class,
+		 const struct drm_atomic_state *state),
+	TP_ARGS(event_class, state)
+);
+DEFINE_EVENT(class_drm_atomic, drm_atomic_check,
+	TP_PROTO(unsigned int event_class,
+		 const struct drm_atomic_state *state),
+	TP_ARGS(event_class, state)
+);
+DEFINE_EVENT(class_drm_atomic, drm_atomic_commit,
+	TP_PROTO(unsigned int event_class,
+		 const struct drm_atomic_state *state),
+	TP_ARGS(event_class, state)
+);
+DEFINE_EVENT(class_drm_atomic, drm_atomic_commit_nonblock,
+	TP_PROTO(unsigned int event_class,
+		 const struct drm_atomic_state *state),
+	TP_ARGS(event_class, state)
+);
+DEFINE_EVENT(class_drm_atomic, drm_atomic_check_passed,
+	TP_PROTO(unsigned int event_class,
+		 const struct drm_atomic_state *state),
+	TP_ARGS(event_class, state)
+);
+DEFINE_EVENT(class_drm_atomic, drm_atomic_check_failed,
+	TP_PROTO(unsigned int event_class,
+		 const struct drm_atomic_state *state),
+	TP_ARGS(event_class, state)
+);
+
 #endif /* _DRM_TRACE_H_ */
 
 /* This part must be outside protection */