[PATCH v3 3/3] drm: Add self_refresh_state debugfs entry

Sean Paul sean at poorly.run
Thu Sep 19 15:33:58 UTC 2019


From: Sean Paul <seanpaul at chromium.org>

This patch adds a debugfs entry to surface the entry and exit times as
well as the calculated delay.

Suggested-by: Daniel Vetter <daniel at ffwll.ch>
Signed-off-by: Sean Paul <seanpaul at chromium.org>
Link to v2: https://patchwork.freedesktop.org/patch/msgid/20190918200734.149876-3-sean@poorly.run

Changes in v2:
- Added to the set
Changes in v3:
- Move the debugfs out of core and into driver (Daniel)
- Place a debugfs entry per crtc (Daniel)
---

Here's the per-crtc version of this, mostly as an rfc since it still feels 
rough (particularly grabbing drm_minor from crtc->dev->primary). We should
also probably introduce some drm_debugfs helpers for crtc entries
instead of opencoding debugfs goo here and in debugfs_crc.

I've got to switch over to MST-related stuff for the moment, but will
get back to this once we have a clear picture of what we want to do.

 drivers/gpu/drm/drm_self_refresh_helper.c   | 63 ++++++++++++++++++++-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 14 +++++
 include/drm/drm_self_refresh_helper.h       |  5 ++
 3 files changed, 80 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_self_refresh_helper.c b/drivers/gpu/drm/drm_self_refresh_helper.c
index 68f4765a58964..4be7348e105c6 100644
--- a/drivers/gpu/drm/drm_self_refresh_helper.c
+++ b/drivers/gpu/drm/drm_self_refresh_helper.c
@@ -14,7 +14,9 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_connector.h>
 #include <drm/drm_crtc.h>
+#include <drm/drm_debugfs.h>
 #include <drm/drm_device.h>
+#include <drm/drm_file.h>
 #include <drm/drm_mode_config.h>
 #include <drm/drm_modeset_lock.h>
 #include <drm/drm_print.h>
@@ -167,6 +169,16 @@ void drm_self_refresh_helper_update_avg_times(struct drm_atomic_state *state,
 }
 EXPORT_SYMBOL(drm_self_refresh_helper_update_avg_times);
 
+static unsigned int
+drm_self_refresh_calc_idle_delay(struct drm_self_refresh_data *sr_data)
+{
+	if (WARN_ON(!mutex_is_locked(&sr_data->avg_mutex)))
+	    return SELF_REFRESH_AVG_SEED_MS * 4;
+
+	return (ewma_psr_time_read(&sr_data->entry_avg_ms) +
+		ewma_psr_time_read(&sr_data->exit_avg_ms)) * 2;
+}
+
 /**
  * drm_self_refresh_helper_alter_state - Alters the atomic state for SR exit
  * @state: the state currently being checked
@@ -209,8 +221,7 @@ void drm_self_refresh_helper_alter_state(struct drm_atomic_state *state)
 			continue;
 
 		mutex_lock(&sr_data->avg_mutex);
-		delay = (ewma_psr_time_read(&sr_data->entry_avg_ms) +
-			 ewma_psr_time_read(&sr_data->exit_avg_ms)) * 2;
+		delay = drm_self_refresh_calc_idle_delay(sr_data);
 		mutex_unlock(&sr_data->avg_mutex);
 
 		mod_delayed_work(system_wq, &sr_data->entry_work,
@@ -275,3 +286,51 @@ void drm_self_refresh_helper_cleanup(struct drm_crtc *crtc)
 	kfree(sr_data);
 }
 EXPORT_SYMBOL(drm_self_refresh_helper_cleanup);
+
+#ifdef CONFIG_DEBUG_FS
+
+static int drm_self_refresh_debugfs_show(struct seq_file *m, void *data)
+{
+	struct drm_crtc *crtc = m->private;
+	struct drm_self_refresh_data *sr_data = crtc->self_refresh_data;
+	struct drm_printer p = drm_seq_file_printer(m);
+
+	if (!sr_data)
+		return 0;
+
+	mutex_lock(&sr_data->avg_mutex);
+	drm_printf(&p, "entry_avg_ms=%lu\n",
+		   ewma_psr_time_read(&sr_data->entry_avg_ms));
+	drm_printf(&p, "exit_avg_ms=%lu\n",
+		   ewma_psr_time_read(&sr_data->exit_avg_ms));
+	drm_printf(&p, "idle_delay=%u\n",
+		   drm_self_refresh_calc_idle_delay(sr_data));
+	mutex_unlock(&sr_data->avg_mutex);
+	return 0;
+}
+
+static int drm_self_refresh_debugfs_open(struct inode *inode, struct file *file)
+{
+	struct drm_crtc *crtc = inode->i_private;
+
+	return single_open(file, drm_self_refresh_debugfs_show, crtc);
+}
+
+static const struct file_operations drm_self_refresh_debugfs_fops = {
+	.owner = THIS_MODULE,
+	.open = drm_self_refresh_debugfs_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+int drm_self_refresh_debugfs_init(struct drm_crtc *crtc)
+{
+	debugfs_create_file("self_refresh_state", S_IFREG | S_IRUGO,
+			    crtc->debugfs_entry, crtc,
+			    &drm_self_refresh_debugfs_fops);
+	return 0;
+}
+EXPORT_SYMBOL(drm_self_refresh_debugfs_init);
+
+#endif
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 613404f86668d..181873b7146ac 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1303,6 +1303,19 @@ static struct drm_connector *vop_get_edp_connector(struct vop *vop)
 	return NULL;
 }
 
+static int vop_crtc_late_register(struct drm_crtc *crtc)
+{
+	int ret;
+#if defined(CONFIG_DRM_KMS_HELPER)
+	ret = drm_self_refresh_debugfs_init(crtc);
+	if (ret) {
+		DRM_ERROR("Failed to init self refresh debugfs\n");
+		return ret;
+	}
+#endif
+	return ret;
+}
+
 static int vop_crtc_set_crc_source(struct drm_crtc *crtc,
 				   const char *source_name)
 {
@@ -1359,6 +1372,7 @@ static const struct drm_crtc_funcs vop_crtc_funcs = {
 	.atomic_destroy_state = vop_crtc_destroy_state,
 	.enable_vblank = vop_crtc_enable_vblank,
 	.disable_vblank = vop_crtc_disable_vblank,
+	.late_register = vop_crtc_late_register,
 	.set_crc_source = vop_crtc_set_crc_source,
 	.verify_crc_source = vop_crtc_verify_crc_source,
 };
diff --git a/include/drm/drm_self_refresh_helper.h b/include/drm/drm_self_refresh_helper.h
index 5b79d253fb46e..3ed54ce102f1b 100644
--- a/include/drm/drm_self_refresh_helper.h
+++ b/include/drm/drm_self_refresh_helper.h
@@ -17,4 +17,9 @@ void drm_self_refresh_helper_update_avg_times(struct drm_atomic_state *state,
 
 int drm_self_refresh_helper_init(struct drm_crtc *crtc);
 void drm_self_refresh_helper_cleanup(struct drm_crtc *crtc);
+
+#ifdef CONFIG_DEBUG_FS
+int drm_self_refresh_debugfs_init(struct drm_crtc *crtc);
+#endif
+
 #endif
-- 
Sean Paul, Software Engineer, Google / Chromium OS



More information about the dri-devel mailing list