summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorImre Deak <imre.deak@intel.com>2016-09-30 17:28:53 +0300
committerImre Deak <imre.deak@intel.com>2016-10-13 15:08:55 +0300
commit022e6f8ae7c853e221eb9d8344cf1aa27c5fbe57 (patch)
treeea9d7a00ee3e675c3ae5fbd5063572bc816dc352 /lib
parente442481c9cf35a1c509b836cf076bae597296200 (diff)
lib/igt_aux: Add support for various system suspend/resume options
To have a more accurate idea about any suspend/resume issues we can perform the s/r until various phases in the s/r sequence. This way we can isolate the given problem as being a device driver, kernel core or BIOS related issue. Actual subtests using these new s/r phases will be added as follow-up. While at it also add the freeze suspend target, it's something we also would need to test. Signed-off-by: Imre Deak <imre.deak@intel.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/igt_aux.c171
-rw-r--r--lib/igt_aux.h25
2 files changed, 158 insertions, 38 deletions
diff --git a/lib/igt_aux.c b/lib/igt_aux.c
index 5eaf35ec..f225c2f6 100644
--- a/lib/igt_aux.c
+++ b/lib/igt_aux.c
@@ -63,6 +63,7 @@
#include "ioctl_wrappers.h"
#include "igt_kms.h"
#include "igt_stats.h"
+#include "igt_sysfs.h"
/**
* SECTION:igt_aux
@@ -625,60 +626,158 @@ void igt_cleanup_aperture_trashers(void)
free(trash_bos);
}
+static const char *suspend_state_name[] = {
+ [SUSPEND_STATE_FREEZE] = "freeze",
+ [SUSPEND_STATE_MEM] = "mem",
+ [SUSPEND_STATE_STANDBY] = "standby",
+ [SUSPEND_STATE_DISK] = "disk",
+};
+
+static const char *suspend_test_name[] = {
+ [SUSPEND_TEST_NONE] = "none",
+ [SUSPEND_TEST_FREEZER] = "freezer",
+ [SUSPEND_TEST_DEVICES] = "devices",
+ [SUSPEND_TEST_PLATFORM] = "platform",
+ [SUSPEND_TEST_PROCESSORS] = "processors",
+ [SUSPEND_TEST_CORE] = "core",
+};
+
+static enum igt_suspend_test get_suspend_test(int power_dir)
+{
+ char *test_line;
+ char *test_name;
+ enum igt_suspend_test test;
+
+ if (faccessat(power_dir, "pm_test", R_OK, 0))
+ return SUSPEND_TEST_NONE;
+
+ igt_assert((test_line = igt_sysfs_get(power_dir, "pm_test")));
+ for (test_name = strtok(test_line, " "); test_name;
+ test_name = strtok(NULL, " "))
+ if (test_name[0] == '[') {
+ test_name[strlen(test_name) - 1] = '\0';
+ test_name++;
+ break;
+ }
+
+ for (test = SUSPEND_TEST_NONE; test < SUSPEND_TEST_NUM; test++)
+ if (strcmp(suspend_test_name[test], test_name) == 0)
+ break;
+
+ igt_assert(test < SUSPEND_TEST_NUM);
+
+ free(test_line);
+
+ return test;
+}
+
+static void set_suspend_test(int power_dir, enum igt_suspend_test test)
+{
+ igt_assert(test < SUSPEND_TEST_NUM);
+
+ if (faccessat(power_dir, "pm_test", W_OK, 0)) {
+ igt_require(test == SUSPEND_TEST_NONE);
+ return;
+ }
+
+ igt_assert(igt_sysfs_set(power_dir, "pm_test", suspend_test_name[test]));
+}
+
#define SQUELCH ">/dev/null 2>&1"
-/**
- * igt_system_suspend_autoresume:
- *
- * Execute a system suspend-to-mem cycle and automatically wake up again using
- * the firmware's resume timer.
- *
- * This is very handy for implementing any kind of suspend/resume test.
- */
-void igt_system_suspend_autoresume(void)
+static void suspend_via_rtcwake(enum igt_suspend_state state)
{
- /* FIXME: Simulation doesn't like suspend/resume, and not even a lighter
- * approach using /sys/power/pm_test to just test our driver's callbacks
- * seems to fare better. We need to investigate what's going on. */
- igt_skip_on_simulation();
+ char cmd[128];
+ int delay;
+
+ igt_assert(state < SUSPEND_STATE_NUM);
+
+ delay = state == SUSPEND_STATE_DISK ? 30 : 15;
+
+ /*
+ * Skip if rtcwake would fail for a reason not related to the kernel's
+ * suspend functionality.
+ */
+ snprintf(cmd, sizeof(cmd), "rtcwake -n -s %d -m %s " SQUELCH,
+ delay, suspend_state_name[state]);
+ igt_require(system(cmd) == 0);
+
+ snprintf(cmd, sizeof(cmd), "rtcwake -s %d -m %s ",
+ delay, suspend_state_name[state]);
+ igt_assert_f(system(cmd) == 0,
+ "This failure means that something is wrong with "
+ "the rtcwake tool or how your distro is set up. "
+ "This is not a i915.ko or i-g-t bug.\n");
+}
+
+static void suspend_via_sysfs(int power_dir, enum igt_suspend_state state)
+{
+ igt_assert(state < SUSPEND_STATE_NUM);
+ igt_assert(igt_sysfs_set(power_dir, "state",
+ suspend_state_name[state]));
+}
+
+static uint32_t get_supported_suspend_states(int power_dir)
+{
+ char *states;
+ char *state_name;
+ uint32_t state_mask;
+
+ igt_assert((states = igt_sysfs_get(power_dir, "state")));
+ state_mask = 0;
+ for (state_name = strtok(states, " "); state_name;
+ state_name = strtok(NULL, " ")) {
+ enum igt_suspend_state state;
+
+ for (state = SUSPEND_STATE_FREEZE; state < SUSPEND_STATE_NUM;
+ state++)
+ if (strcmp(state_name, suspend_state_name[state]) == 0)
+ break;
+ igt_assert(state < SUSPEND_STATE_NUM);
+ state_mask |= 1 << state;
+ }
- /* skip if system doesn't support suspend-to-mem */
- igt_require(system("rtcwake -n -s 15 -m mem" SQUELCH) == 0);
+ free(states);
- igt_assert_f(system("rtcwake -s 15 -m mem") == 0,
- "This failure means that something is wrong with the "
- "rtcwake tool or how your distro is set up. This is not "
- "a i915.ko or i-g-t bug.\n");
+ return state_mask;
}
/**
- * igt_system_hibernate_autoresume:
+ * igt_system_suspend_autoresume:
*
- * Execute a system suspend-to-disk cycle and automatically wake up again using
- * the firmware's resume timer.
+ * Execute a system suspend (to idle, memory, disk) cycle optionally
+ * completing the cycle at a given test point and automaically wake up again.
+ * Waking up is either achieved using the RTC wake-up alarm for a full suspend
+ * cycle or a kernel timer for a suspend test cycle.
*
- * This is very handy for implementing any kind of hibernate/resume test.
+ * This is very handy for implementing any kind of suspend/resume test.
*/
-void igt_system_hibernate_autoresume(void)
+void igt_system_suspend_autoresume(enum igt_suspend_state state,
+ enum igt_suspend_test test)
{
- /* FIXME: I'm guessing simulation behaves the same way as with
- * suspend/resume, but it might be prudent to make sure
- */
+ int power_dir;
+ enum igt_suspend_test orig_test;
+
/* FIXME: Simulation doesn't like suspend/resume, and not even a lighter
* approach using /sys/power/pm_test to just test our driver's callbacks
* seems to fare better. We need to investigate what's going on. */
igt_skip_on_simulation();
- /* skip if system doesn't support suspend-to-disk */
- igt_require(system("rtcwake -n -s 30 -m disk" SQUELCH) == 0);
+ igt_require((power_dir = open("/sys/power", O_RDONLY)) >= 0);
+ igt_require(get_supported_suspend_states(power_dir) & (1 << state));
+ igt_require(test == SUSPEND_TEST_NONE ||
+ faccessat(power_dir, "pm_test", R_OK | W_OK, 0) == 0);
- /* The timeout might need to be adjusted if hibernation takes too long
- * or if we have to wait excessively long before resume
- */
- igt_assert_f(system("rtcwake -s 30 -m disk") == 0,
- "This failure means that something is wrong with the "
- "rtcwake tool or how your distro is set up. This is not "
- "a i915.ko or i-g-t bug.\n");
+ orig_test = get_suspend_test(power_dir);
+ set_suspend_test(power_dir, test);
+
+ if (test == SUSPEND_TEST_NONE)
+ suspend_via_rtcwake(state);
+ else
+ suspend_via_sysfs(power_dir, state);
+
+ set_suspend_test(power_dir, orig_test);
+ close(power_dir);
}
/**
diff --git a/lib/igt_aux.h b/lib/igt_aux.h
index 7f5a7cfd..39fd8ea6 100644
--- a/lib/igt_aux.h
+++ b/lib/igt_aux.h
@@ -115,8 +115,29 @@ void igt_trash_aperture(void);
void igt_cleanup_aperture_trashers(void);
/* suspend/hibernate and auto-resume system */
-void igt_system_suspend_autoresume(void);
-void igt_system_hibernate_autoresume(void);
+
+enum igt_suspend_state {
+ SUSPEND_STATE_FREEZE,
+ SUSPEND_STATE_MEM,
+ SUSPEND_STATE_STANDBY,
+ SUSPEND_STATE_DISK,
+
+ SUSPEND_STATE_NUM,
+};
+
+enum igt_suspend_test {
+ SUSPEND_TEST_NONE,
+ SUSPEND_TEST_FREEZER,
+ SUSPEND_TEST_DEVICES,
+ SUSPEND_TEST_PLATFORM,
+ SUSPEND_TEST_PROCESSORS,
+ SUSPEND_TEST_CORE,
+
+ SUSPEND_TEST_NUM,
+};
+
+void igt_system_suspend_autoresume(enum igt_suspend_state state,
+ enum igt_suspend_test test);
/* dropping priviledges */
void igt_drop_root(void);