From 6559c901cb4840e46893d587d8af435aac9c4c3f Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sat, 5 Nov 2016 11:08:10 -0400 Subject: [PATCH] drm/atomic: add debugfs file to dump out atomic state Useful to dump current state from debugfs, if turning on the drm.debug bit is too much overhead. The drm_state_dump() can also be used by drivers, for example to implement a module param that dumps state on error irqs. Signed-off-by: Rob Clark Reviewed-by: Sean Paul Signed-off-by: Sean Paul Link: http://patchwork.freedesktop.org/patch/msgid/1478358492-30738-6-git-send-email-robdclark@gmail.com --- drivers/gpu/drm/drm_atomic.c | 63 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_debugfs.c | 9 +++++ include/drm/drm_atomic.h | 7 ++++ 3 files changed, 79 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index bd62c959b475..b096c1673969 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1577,6 +1577,69 @@ static void drm_atomic_print_state(const struct drm_atomic_state *state) drm_atomic_connector_print_state(&p, connector_state); } +/** + * drm_state_dump - dump entire device atomic state + * @dev: the drm device + * @p: where to print the state to + * + * Just for debugging. Drivers might want an option to dump state + * to dmesg in case of error irq's. (Hint, you probably want to + * ratelimit this!) + * + * The caller must drm_modeset_lock_all(), or if this is called + * from error irq handler, it should not be enabled by default. + * (Ie. if you are debugging errors you might not care that this + * is racey. But calling this without all modeset locks held is + * not inherently safe.) + */ +void drm_state_dump(struct drm_device *dev, struct drm_printer *p) +{ + struct drm_mode_config *config = &dev->mode_config; + struct drm_plane *plane; + struct drm_crtc *crtc; + struct drm_connector *connector; + + if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) + return; + + list_for_each_entry(plane, &config->plane_list, head) + drm_atomic_plane_print_state(p, plane->state); + + list_for_each_entry(crtc, &config->crtc_list, head) + drm_atomic_crtc_print_state(p, crtc->state); + + list_for_each_entry(connector, &config->connector_list, head) + drm_atomic_connector_print_state(p, connector->state); +} +EXPORT_SYMBOL(drm_state_dump); + +#ifdef CONFIG_DEBUG_FS +static int drm_state_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct drm_printer p = drm_seq_file_printer(m); + + drm_modeset_lock_all(dev); + drm_state_dump(dev, &p); + drm_modeset_unlock_all(dev); + + return 0; +} + +/* any use in debugfs files to dump individual planes/crtc/etc? */ +static const struct drm_info_list drm_atomic_debugfs_list[] = { + {"state", drm_state_info, 0}, +}; + +int drm_atomic_debugfs_init(struct drm_minor *minor) +{ + return drm_debugfs_create_files(drm_atomic_debugfs_list, + ARRAY_SIZE(drm_atomic_debugfs_list), + minor->debugfs_root, minor); +} +#endif + /* * The big monstor ioctl */ diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 800055c39cdb..206a4fe7ea26 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "drm_internal.h" #if defined(CONFIG_DEBUG_FS) @@ -163,6 +164,14 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id, return ret; } + if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { + ret = drm_atomic_debugfs_init(minor); + if (ret) { + DRM_ERROR("Failed to create atomic debugfs files\n"); + return ret; + } + } + if (dev->driver->debugfs_init) { ret = dev->driver->debugfs_init(minor); if (ret) { diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 2d1e9c944b54..331bb100b718 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -366,6 +366,13 @@ int __must_check drm_atomic_check_only(struct drm_atomic_state *state); int __must_check drm_atomic_commit(struct drm_atomic_state *state); int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state); +void drm_state_dump(struct drm_device *dev, struct drm_printer *p); + +#ifdef CONFIG_DEBUG_FS +struct drm_minor; +int drm_atomic_debugfs_init(struct drm_minor *minor); +#endif + #define for_each_connector_in_state(__state, connector, connector_state, __i) \ for ((__i) = 0; \ (__i) < (__state)->num_connector && \