@@ -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);
}
@@ -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 */