summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/pm_rc6_residency.c122
1 files changed, 69 insertions, 53 deletions
diff --git a/tests/pm_rc6_residency.c b/tests/pm_rc6_residency.c
index ad05cca4..3f686019 100644
--- a/tests/pm_rc6_residency.c
+++ b/tests/pm_rc6_residency.c
@@ -53,11 +53,11 @@ struct residencies {
static unsigned long get_rc6_enabled_mask(void)
{
- unsigned long rc6_mask;
+ unsigned long enabled;
- rc6_mask = 0;
- igt_sysfs_scanf(sysfs, "power/rc6_enable", "%lu", &rc6_mask);
- return rc6_mask;
+ enabled = 0;
+ igt_sysfs_scanf(sysfs, "power/rc6_enable", "%lu", &enabled);
+ return enabled;
}
static unsigned long read_rc6_residency(const char *name)
@@ -85,63 +85,67 @@ static void residency_accuracy(unsigned int diff,
"Sysfs RC6 residency counter is inaccurate.\n");
}
-static void read_residencies(int devid, unsigned int rc6_mask,
+static unsigned long gettime_ms(void)
+{
+ struct timespec ts;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
+}
+
+static void read_residencies(int devid, unsigned int mask,
struct residencies *res)
{
- if (rc6_mask & RC6_ENABLED)
+ res->duration = gettime_ms();
+
+ if (mask & RC6_ENABLED)
res->rc6 = read_rc6_residency("rc6");
- if ((rc6_mask & RC6_ENABLED) &&
+ if ((mask & RC6_ENABLED) &&
(IS_VALLEYVIEW(devid) || IS_CHERRYVIEW(devid)))
res->media_rc6 = read_rc6_residency("media_rc6");
- if (rc6_mask & RC6P_ENABLED)
+ if (mask & RC6P_ENABLED)
res->rc6p = read_rc6_residency("rc6p");
- if (rc6_mask & RC6PP_ENABLED)
+ if (mask & RC6PP_ENABLED)
res->rc6pp = read_rc6_residency("rc6pp");
-}
-
-static unsigned long gettime_ms(void)
-{
- struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
-
- return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
+ res->duration += (gettime_ms() - res->duration) / 2;
}
-static void measure_residencies(int devid, unsigned int rc6_mask,
+static void measure_residencies(int devid, unsigned int mask,
struct residencies *res)
{
struct residencies start = { };
struct residencies end = { };
int retry;
- unsigned long t;
- if (!rc6_mask)
+ if (!mask)
return;
/*
- * For some reason my ivb isn't idle even after syncing up with the gpu.
- * Let's add a sleep just to make it happy.
- */
- sleep(8);
-
- /*
* Retry in case of counter wrap-around. We simply re-run the
* measurement, since the valid counter range is different on
* different platforms and so fixing it up would be non-trivial.
*/
+ read_residencies(devid, mask, &end);
+ igt_debug("time=%d: rc6=(%d, %d), rc6p=%d, rc6pp=%d\n",
+ end.duration, end.rc6, end.media_rc6, end.rc6p, end.rc6pp);
for (retry = 0; retry < 2; retry++) {
- t = gettime_ms();
- read_residencies(devid, rc6_mask, &start);
+ start = end;
sleep(SLEEP_DURATION);
- read_residencies(devid, rc6_mask, &end);
- t = gettime_ms() - t;
+ read_residencies(devid, mask, &end);
+
+ igt_debug("time=%d: rc6=(%d, %d), rc6p=%d, rc6pp=%d\n",
+ end.duration,
+ end.rc6, end.media_rc6, end.rc6p, end.rc6pp);
- if (end.rc6 >= start.rc6 && end.media_rc6 >= start.media_rc6 &&
- end.rc6p >= start.rc6p && end.rc6pp >= start.rc6pp)
+ if (end.rc6 >= start.rc6 &&
+ end.media_rc6 >= start.media_rc6 &&
+ end.rc6p >= start.rc6p &&
+ end.rc6pp >= start.rc6pp)
break;
}
igt_assert_f(retry < 2, "residency values are not consistent\n");
@@ -150,7 +154,7 @@ static void measure_residencies(int devid, unsigned int rc6_mask,
res->rc6p = end.rc6p - start.rc6p;
res->rc6pp = end.rc6pp - start.rc6pp;
res->media_rc6 = end.media_rc6 - start.media_rc6;
- res->duration = t;
+ res->duration = end.duration - start.duration;
/*
* For the purposes of this test case we want a given residency value
@@ -164,11 +168,23 @@ static void measure_residencies(int devid, unsigned int rc6_mask,
res->rc6 += res->rc6p;
}
+static unsigned long rc6_enable_us(void)
+{
+ /*
+ * To know how long we need to wait for the device to enter rc6 once
+ * idle, we need to look at GEN6_RC_EVALUATION_INTERVAL. Currently,
+ * this is set to 125000 (12500 * 1280ns or 0.16s) on all platforms.
+ * We must complete at least one EI with activity below the
+ * per-platform threshold for RC6 to kick. Therefore, we must wait
+ * at least 2 EI cycles, before we can expect rc6 to start ticking.
+ */
+ return 2 * 160 * 1000;
+}
+
igt_main
{
- unsigned int rc6_mask;
- int devid = 0;
- struct residencies res;
+ unsigned int rc6_enabled = 0;
+ unsigned int devid = 0;
igt_skip_on_simulation();
@@ -179,33 +195,33 @@ igt_main
fd = drm_open_driver(DRIVER_INTEL);
devid = intel_get_drm_devid(fd);
sysfs = igt_sysfs_open(fd, NULL);
- close(fd);
- rc6_mask = get_rc6_enabled_mask();
- igt_require(rc6_mask);
+ /* Make sure rc6 counters are running */
+ igt_drop_caches_set(fd, DROP_IDLE);
+ usleep(rc6_enable_us());
- measure_residencies(devid, rc6_mask, &res);
+ close(fd);
+
+ rc6_enabled = get_rc6_enabled_mask();
+ igt_require(rc6_enabled);
}
igt_subtest("rc6-accuracy") {
- igt_skip_on(!(rc6_mask & RC6_ENABLED));
+ struct residencies res;
+
+ igt_require(rc6_enabled & RC6_ENABLED);
+ measure_residencies(devid, rc6_enabled, &res);
residency_accuracy(res.rc6, res.duration, "rc6");
}
- igt_subtest("media-rc6-accuracy") {
- igt_skip_on(!((rc6_mask & RC6_ENABLED) &&
- (IS_VALLEYVIEW(devid) || IS_CHERRYVIEW(devid))));
- residency_accuracy(res.media_rc6, res.duration, "media_rc6");
- }
- igt_subtest("rc6p-accuracy") {
- igt_skip_on(!(rc6_mask & RC6P_ENABLED));
+ igt_subtest("media-rc6-accuracy") {
+ struct residencies res;
- residency_accuracy(res.rc6p, res.duration, "rc6p");
- }
- igt_subtest("rc6pp-accuracy") {
- igt_skip_on(!(rc6_mask & RC6PP_ENABLED));
+ igt_require((rc6_enabled & RC6_ENABLED) &&
+ (IS_VALLEYVIEW(devid) || IS_CHERRYVIEW(devid)));
- residency_accuracy(res.rc6pp, res.duration, "rc6pp");
+ measure_residencies(devid, rc6_enabled, &res);
+ residency_accuracy(res.media_rc6, res.duration, "media_rc6");
}
}