summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/igt_aux.c134
-rw-r--r--lib/igt_aux.h4
2 files changed, 138 insertions, 0 deletions
diff --git a/lib/igt_aux.c b/lib/igt_aux.c
index d5c70fa2..5392e1a1 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 b2dc2679..9ea50de2 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 */