diff mbox

[igt,2/4] lib/igt_aux: add functions to manipulate i915.ko parameters

Message ID 1433428266-1867-2-git-send-email-przanoni@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Paulo Zanoni June 4, 2015, 2:31 p.m. UTC
From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Some i915.ko features have very nice IGT tests, which are never
executed because the features are disabled by default. This leads to
unnoticed regressions both in the Kernel and in the IGT tests.  We
have seen this multiple times, for example, on FBC and PSR.

We want to be able to run IGT and actually test these
disabled-by-default features in order to make sure we at least don't
break them even more. Sometimes they may be disabled for some specific
reason, and we don't want to increase the set of reasons without
noticing.

To help solving this problem, this commit adds some helper functions
that should make it easier to change certain i915.ko parameters and
then restore their original values at the end of the test. With this,
I'm hoping QA will be able to detect any regressions and automatically
bisect them - or, with PRTS, reject the patches before they are even
merged.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 lib/igt_aux.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/igt_aux.h |   4 ++
 2 files changed, 138 insertions(+)
diff mbox

Patch

diff --git a/lib/igt_aux.c b/lib/igt_aux.c
index d5c70fa..5392e1a 100644
--- a/lib/igt_aux.c
+++ b/lib/igt_aux.c
@@ -735,3 +735,137 @@  void igt_unlock_mem(void)
 	free(locked_mem);
 	locked_mem = NULL;
 }
+
+
+#define MODULE_PARAM_DIR "/sys/module/i915/parameters/"
+#define PARAM_NAME_MAX_SZ 32
+#define PARAM_VALUE_MAX_SZ 16
+#define PARAM_FILE_PATH_MAX_SZ (strlen(MODULE_PARAM_DIR) + PARAM_NAME_MAX_SZ)
+
+struct module_param_data {
+	char name[PARAM_NAME_MAX_SZ];
+	char original_value[PARAM_VALUE_MAX_SZ];
+
+	struct module_param_data *next;
+};
+struct module_param_data *module_params = NULL;
+
+static void igt_module_param_exit_handler(int sig)
+{
+	const size_t dir_len = strlen(MODULE_PARAM_DIR);
+	char file_path[PARAM_FILE_PATH_MAX_SZ];
+	struct module_param_data *data;
+	int fd;
+
+	/* We don't need to assert string sizes on this function since they were
+	 * already checked before being stored on the lists. Besides,
+	 * igt_assert() is not AS-Safe. */
+	strcpy(file_path, MODULE_PARAM_DIR);
+
+	for (data = module_params; data != NULL; data = data->next) {
+		strcpy(file_path + dir_len, data->name);
+
+		fd = open(file_path, O_RDWR);
+		if (fd >= 0) {
+			write(fd, data->original_value,
+			      strlen(data->original_value));
+			close(fd);
+		}
+	}
+	/* free() is not AS-Safe, so we can't call it here. */
+}
+
+/**
+ * igt_save_module_param:
+ * @name: name of the i915.ko module parameter
+ * @file_path: full sysfs file path for the parameter
+ *
+ * Reads the current value of an i915.ko module parameter, saves it on an array,
+ * then installs an exit handler to restore it when the program exits.
+ *
+ * It is safe to call this function multiple times for the same parameter.
+ *
+ * Notice that this function is called by igt_set_module_param(), so that one -
+ * or one of its wrappers - is the only function the test programs need to call.
+ */
+static void igt_save_module_param(const char *name, const char *file_path)
+{
+	struct module_param_data *data;
+	size_t n;
+	int fd;
+
+	/* Check if this parameter is already saved. */
+	for (data = module_params; data != NULL; data = data->next)
+		if (strncmp(data->name, name, PARAM_NAME_MAX_SZ) == 0)
+			return;
+
+	if (!module_params)
+		igt_install_exit_handler(igt_module_param_exit_handler);
+
+	data = calloc(1, sizeof (*data));
+	igt_assert(data);
+
+	strncpy(data->name, name, PARAM_NAME_MAX_SZ);
+
+	fd = open(file_path, O_RDONLY);
+	igt_assert(fd >= 0);
+
+	n = read(fd, data->original_value, PARAM_VALUE_MAX_SZ);
+	igt_assert_f(n > 0 && n < PARAM_VALUE_MAX_SZ,
+		     "Need to increase PARAM_VALUE_MAX_SZ\n");
+
+	igt_assert(close(fd) == 0);
+
+	data->next = module_params;
+	module_params = data;
+}
+
+/**
+ * igt_set_module_param:
+ * @name: i915.ko parameter name
+ * @val: i915.ko parameter value
+ *
+ * This function sets the desired value for the given i915.ko parameter. It also
+ * takes care of saving and restoring the values that were already set before
+ * the test was run by calling igt_save_module_param().
+ *
+ * Please consider using igt_set_module_param_int() for the integer and bool
+ * parameters.
+ */
+void igt_set_module_param(const char *name, const char *val)
+{
+	char file_path[PARAM_FILE_PATH_MAX_SZ];
+	size_t len = strlen(val);
+	int fd;
+
+	igt_assert_f(strlen(name) < PARAM_NAME_MAX_SZ,
+		     "Need to increase PARAM_NAME_MAX_SZ\n");
+	strcpy(file_path, MODULE_PARAM_DIR);
+	strcpy(file_path + strlen(MODULE_PARAM_DIR), name);
+
+	igt_save_module_param(name, file_path);
+
+	fd = open(file_path, O_RDWR);
+	igt_assert(write(fd, val, len) == len);
+	igt_assert(close(fd) == 0);
+}
+
+/**
+ * igt_set_module_param_int:
+ * @name: i915.ko parameter name
+ * @val: i915.ko parameter value
+ *
+ * This is a wrapper for igt_set_module_param() that takes an integer instead of
+ * a string. Please see igt_set_module_param().
+ */
+void igt_set_module_param_int(const char *name, int val)
+{
+	char str[PARAM_VALUE_MAX_SZ];
+	int n;
+
+	n = snprintf(str, PARAM_VALUE_MAX_SZ, "%d\n", val);
+	igt_assert_f(n < PARAM_VALUE_MAX_SZ,
+		     "Need to increase PARAM_VALUE_MAX_SZ\n");
+
+	igt_set_module_param(name, str);
+}
diff --git a/lib/igt_aux.h b/lib/igt_aux.h
index b2dc267..9ea50de 100644
--- a/lib/igt_aux.h
+++ b/lib/igt_aux.h
@@ -145,4 +145,8 @@  void igt_unlock_mem(void);
 	ret_;								\
 })
 
+
+void igt_set_module_param(const char *name, const char *val);
+void igt_set_module_param_int(const char *name, int val);
+
 #endif /* IGT_AUX_H */