[PATCH 15/25] drm/i915/slpc: Add debugfs support to read/write/revert the parameters

Sagar Arun Kamble sagar.a.kamble at intel.com
Mon Mar 13 14:04:36 UTC 2017


This patch adds two debugfs interfaces:
1. i915_slpc_paramlist: List of all parameters that Host can configure.
   Currently listing id and names.
2. i915_slpc_param_ctl: This allows to change the parameters. Syntax is:
   echo "write <id> <value>" > i915_slpc_param_ctl.
   echo "read <id>" > i915_slpc_param_ctl; cat i915_slpc_param_ctl
   revert allows to set to default SLPC internal values. Syntax is:
   "revert <id>" > i915_slpc_param_ctl; cat i915_slpc_param_ctl

Added support to set/read parameters and unset the parameters which will
revert them to default SLPC internal values. Also added RPM ref. cover
around set/unset calls. Explicit SLPC reset is needed on setting/unsetting
some of the parameters.

Signed-off-by: Sagar Arun Kamble <sagar.a.kamble at intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c |  19 ++++
 drivers/gpu/drm/i915/intel_slpc.c   | 184 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_slpc.h   |  13 +++
 3 files changed, 216 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 4c96d45..6a76841 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2394,6 +2394,23 @@ static int i915_huc_load_status_info(struct seq_file *m, void *data)
 	return 0;
 }
 
+static int i915_slpc_paramlist_info(struct seq_file *m, void *data)
+{
+	struct drm_i915_private *dev_priv = node_to_i915(m->private);
+	int i;
+
+	if (!dev_priv->guc.slpc.active) {
+		seq_puts(m, "SLPC not active\n");
+		return 0;
+	}
+
+	seq_puts(m, "Param id\tParam name\n");
+	for (i = 0; i < SLPC_MAX_PARAM; i++)
+		seq_printf(m, "%8d\t%s\n", slpc_paramlist[i].id,
+					   slpc_paramlist[i].name);
+	return 0;
+}
+
 static int i915_guc_load_status_info(struct seq_file *m, void *data)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
@@ -4770,6 +4787,7 @@ static int i915_hpd_storm_ctl_open(struct inode *inode, struct file *file)
 	{"i915_guc_load_status", i915_guc_load_status_info, 0},
 	{"i915_guc_log_dump", i915_guc_log_dump, 0},
 	{"i915_huc_load_status", i915_huc_load_status_info, 0},
+	{"i915_slpc_paramlist", i915_slpc_paramlist_info, 0},
 	{"i915_frequency_info", i915_frequency_info, 0},
 	{"i915_hangcheck_info", i915_hangcheck_info, 0},
 	{"i915_drpc_info", i915_drpc_info, 0},
@@ -4832,6 +4850,7 @@ static int i915_hpd_storm_ctl_open(struct inode *inode, struct file *file)
 	{"i915_dp_test_type", &i915_displayport_test_type_fops},
 	{"i915_dp_test_active", &i915_displayport_test_active_fops},
 	{"i915_guc_log_control", &i915_guc_log_control_fops},
+	{"i915_slpc_param_ctl", &i915_slpc_param_ctl_fops},
 	{"i915_hpd_storm_ctl", &i915_hpd_storm_ctl_fops}
 };
 
diff --git a/drivers/gpu/drm/i915/intel_slpc.c b/drivers/gpu/drm/i915/intel_slpc.c
index 5497e07..de8e287 100644
--- a/drivers/gpu/drm/i915/intel_slpc.c
+++ b/drivers/gpu/drm/i915/intel_slpc.c
@@ -25,6 +25,190 @@
 #include <asm/msr-index.h>
 #include "i915_drv.h"
 #include "intel_uc.h"
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+
+struct slpc_param slpc_paramlist[SLPC_MAX_PARAM] = {
+	{SLPC_PARAM_TASK_ENABLE_GTPERF, "enable_gtperf"},
+	{SLPC_PARAM_TASK_DISABLE_GTPERF, "disable_gtperf"},
+	{SLPC_PARAM_TASK_ENABLE_BALANCER, "enable_balancer"},
+	{SLPC_PARAM_TASK_DISABLE_BALANCER, "disable_balancer"},
+	{SLPC_PARAM_TASK_ENABLE_DCC, "enable_dcc"},
+	{SLPC_PARAM_TASK_DISABLE_DCC, "disable_dcc"},
+	{SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ, "min_unslice_mhz"},
+	{SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ, "max_unslice_mhz"},
+	{SLPC_PARAM_GLOBAL_MIN_GT_SLICE_FREQ_MHZ, "min_slice_mhz"},
+	{SLPC_PARAM_GLOBAL_MAX_GT_SLICE_FREQ_MHZ, "max_slice_mhz"},
+	{SLPC_PARAM_GTPERF_THRESHOLD_MAX_FPS, "gtperf_threshold_max_fps"},
+	{SLPC_PARAM_GLOBAL_DISABLE_GT_FREQ_MANAGEMENT, "disable_freq_mgmt"},
+	{SLPC_PARAM_GTPERF_ENABLE_FRAMERATE_STALLING, "gtperf_fps_stall"},
+	{SLPC_PARAM_GLOBAL_DISABLE_RC6_MODE_CHANGE, "disable_rc6_change"},
+	{SLPC_PARAM_GLOBAL_OC_UNSLICE_FREQ_MHZ, "oc_unslice_mhz"},
+	{SLPC_PARAM_GLOBAL_OC_SLICE_FREQ_MHZ, "oc_slice_mhz"},
+	{SLPC_PARAM_GLOBAL_ENABLE_IA_GT_BALANCING, "enable_ibc"},
+	{SLPC_PARAM_GLOBAL_ENABLE_ADAPTIVE_BURST_TURBO, "enable_abt"},
+	{SLPC_PARAM_GLOBAL_ENABLE_EVAL_MODE, "enable_eval_mode"},
+	{SLPC_PARAM_GLOBAL_ENABLE_BALANCER_IN_NON_GAMING_MODE,
+	 "enable_balancer_in_desktop_mode"}
+};
+
+static int slpc_param_ctl_show(struct seq_file *m, void *data)
+{
+	struct drm_i915_private *dev_priv = m->private;
+	struct intel_slpc *slpc = &dev_priv->guc.slpc;
+
+	if (!dev_priv->guc.slpc.active) {
+		seq_puts(m, "SLPC not active\n");
+		return 0;
+	}
+
+	seq_printf(m, "%s=%u, override=%s\n",
+			slpc_paramlist[slpc->debug_param_id].name,
+			slpc->debug_param_value,
+			yesno(!!slpc->debug_param_override));
+
+	return 0;
+}
+
+static int slpc_param_ctl_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, slpc_param_ctl_show, inode->i_private);
+}
+
+static const char *read_token = "read", *write_token = "write",
+		  *revert_token = "revert";
+
+/*
+ * Parse SLPC parameter control strings: (Similar to Pipe CRC handling)
+ *   command: wsp* op wsp+ param id wsp+ [value] wsp*
+ *   op: "read"/"write"/"revert"
+ *   param id: slpc_param_id
+ *   value: u32 value
+ *   wsp: (#0x20 | #0x9 | #0xA)+
+ *
+ * eg.:
+ *  "read 0"		-> read SLPC_PARAM_TASK_ENABLE_GTPERF
+ *  "write 7 500"	-> set SLPC_PARAM_GLOBAL_MIN_GT_SLICE_FREQ_MHZ to 500MHz
+ *  "revert 7"		-> revert SLPC_PARAM_GLOBAL_MIN_GT_SLICE_FREQ_MHZ to
+ *			   default value.
+ */
+static int slpc_param_ctl_parse(struct drm_i915_private *dev_priv,
+				char *buf, size_t len, char **op,
+				u32 *id, u32 *value)
+{
+#define MAX_WORDS 3
+	int n_words;
+	char *words[MAX_WORDS];
+	ssize_t ret;
+
+	n_words = buffer_tokenize(buf, words, MAX_WORDS);
+	if (!(n_words == 3) && !(n_words == 2)) {
+		DRM_DEBUG_DRIVER("tokenize failed, a command is %d words\n",
+				 MAX_WORDS);
+		return -EINVAL;
+	}
+
+	if (strcmp(words[0], read_token) && strcmp(words[0], write_token) &&
+	    strcmp(words[0], revert_token)) {
+		DRM_DEBUG_DRIVER("unknown operation\n");
+		return -EINVAL;
+	}
+
+	*op = words[0];
+
+	ret = kstrtou32(words[1], 0, id);
+	if (ret)
+		return ret;
+
+	if (n_words == 3) {
+		ret = kstrtou32(words[2], 0, value);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static ssize_t slpc_param_ctl_write(struct file *file, const char __user *ubuf,
+				     size_t len, loff_t *offp)
+{
+	struct seq_file *m = file->private_data;
+	struct drm_i915_private *dev_priv = m->private;
+	struct intel_slpc *slpc = &dev_priv->guc.slpc;
+	char *tmpbuf, *op = NULL;
+	u32 id, value;
+	int ret;
+
+	if (len == 0)
+		return 0;
+
+	if (len > MAX_PARAM_NAME_SIZE + 20) {
+		DRM_DEBUG_DRIVER("expected <%u bytes into slpc param control\n",
+				 (MAX_PARAM_NAME_SIZE + 20));
+		return -E2BIG;
+	}
+
+	tmpbuf = kmalloc(len + 1, GFP_KERNEL);
+	if (!tmpbuf)
+		return -ENOMEM;
+
+	if (copy_from_user(tmpbuf, ubuf, len)) {
+		ret = -EFAULT;
+		goto out;
+	}
+	tmpbuf[len] = '\0';
+
+	ret = slpc_param_ctl_parse(dev_priv, tmpbuf, len, &op, &id, &value);
+
+	if (id >= SLPC_MAX_PARAM) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (!strcmp(op, read_token)) {
+		intel_slpc_get_param(dev_priv, id,
+				     &slpc->debug_param_override,
+				     &slpc->debug_param_value);
+		slpc->debug_param_id = id;
+	} else if (!strcmp(op, write_token) || !strcmp(op, revert_token)) {
+		if ((id >= SLPC_PARAM_TASK_ENABLE_GTPERF) &&
+		    (id <= SLPC_PARAM_TASK_DISABLE_DCC)) {
+			DRM_DEBUG_DRIVER("Tasks are not controlled by \
+					  this interface\n");
+			ret = -EINVAL;
+			goto out;
+		}
+
+		/*
+		 * After updating parameters, RESET event has to be sent to GuC
+		 * SLPC for ensuring parameters take effect.
+		 */
+		intel_runtime_pm_get(dev_priv);
+		if (!strcmp(op, write_token))
+			intel_slpc_set_param(dev_priv, id, value);
+		else if (!strcmp(op, revert_token))
+			intel_slpc_unset_param(dev_priv, id);
+		intel_slpc_enable(dev_priv);
+		intel_runtime_pm_put(dev_priv);
+	}
+
+out:
+	kfree(tmpbuf);
+	if (ret < 0)
+		return ret;
+
+	*offp += len;
+	return len;
+}
+
+const struct file_operations i915_slpc_param_ctl_fops = {
+	.owner = THIS_MODULE,
+	.open = slpc_param_ctl_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = slpc_param_ctl_write
+};
 
 static unsigned int slpc_get_platform_sku(struct drm_i915_private *dev_priv)
 {
diff --git a/drivers/gpu/drm/i915/intel_slpc.h b/drivers/gpu/drm/i915/intel_slpc.h
index 360f3f2..430e894 100644
--- a/drivers/gpu/drm/i915/intel_slpc.h
+++ b/drivers/gpu/drm/i915/intel_slpc.h
@@ -121,6 +121,9 @@ struct slpc_shared_data {
 struct intel_slpc {
 	bool active;
 	struct i915_vma *vma;
+	u32 debug_param_id;
+	u32 debug_param_value;
+	u32 debug_param_override;
 };
 
 #define SLPC_EVENT_MAX_INPUT_ARGS  7
@@ -219,6 +222,16 @@ enum slpc_param_id {
 	SLPC_KMD_MAX_PARAM = 32,
 };
 
+/* Structures for exposing parameter details to user. */
+#define MAX_PARAM_NAME_SIZE	80
+struct slpc_param {
+	enum slpc_param_id id;
+	char name[MAX_PARAM_NAME_SIZE];
+};
+
+extern struct slpc_param slpc_paramlist[];
+extern const struct file_operations i915_slpc_param_ctl_fops;
+
 /* intel_slpc.c */
 void intel_slpc_read_shared_data(struct drm_i915_private *dev_priv,
 				struct slpc_shared_data *data);
-- 
1.9.1



More information about the Intel-gfx-trybot mailing list