@@ -53,6 +53,7 @@ int intel_gt_pm_live_selftests(struct drm_i915_private *i915)
static const struct i915_subtest tests[] = {
SUBTEST(live_rc6_busy),
SUBTEST(live_rc6_manual),
+ SUBTEST(live_rc6_threshold),
SUBTEST(live_gt_resume),
};
@@ -250,6 +250,73 @@ static bool is_rc6_active(struct intel_rc6 *rc6)
return !!measure_rc6(uncore, 2 * interval);
}
+int live_rc6_threshold(void *arg)
+{
+ struct intel_gt *gt = arg;
+ struct intel_uncore *uncore = gt->uncore;
+ struct intel_rc6 *rc6 = >->rc6;
+ intel_wakeref_t wakeref;
+ u32 threshold, interval;
+ u32 t_orig, i_orig;
+ int err = 0;
+
+ if (!rc6->manual) /* No interfering PCU! */
+ return 0;
+
+ wakeref = intel_runtime_pm_get(uncore->rpm);
+
+ __intel_rc6_disable(rc6); /* stop before adjusting thresholds */
+
+ t_orig = intel_uncore_read(uncore, GEN6_RC6_THRESHOLD);
+ i_orig = intel_uncore_read(uncore, GEN6_RC_EVALUATION_INTERVAL);
+
+ /*
+ * set the threshold to 50ms
+ *
+ * 50ms * 1000 = 50000us
+ * 50000 / (1.28 * 100) / 100 (we don't have floating point)
+ */
+ threshold = 50 * 1000 / 128 * 100;
+ intel_uncore_write(uncore, GEN6_RC6_THRESHOLD, threshold);
+
+ /* set interval indicatively to half the threshold */
+ interval = threshold / 2;
+ intel_uncore_write(uncore, GEN6_RC_EVALUATION_INTERVAL, interval);
+
+ intel_rc6_unpark(rc6);
+
+ /* interval < threshold */
+ if (is_rc6_active(rc6)) {
+ pr_err("i915 mismatch: rc6 with interval < threshold\n");
+ err = -EINVAL;
+ }
+
+ __intel_rc6_disable(rc6);
+
+ /* set interval indicatively to twice the threshold */
+ interval = threshold * 2;
+ intel_uncore_write(uncore, GEN6_RC_EVALUATION_INTERVAL, interval);
+
+ intel_rc6_unpark(rc6);
+
+ /* interval > threshold */
+ if (!is_rc6_active(rc6)) {
+ pr_err("i915 mismatch: not in rc6 with interval > threshold\n");
+ err = -EINVAL;
+ }
+
+ __intel_rc6_disable(rc6);
+
+ intel_uncore_write(uncore, GEN6_RC6_THRESHOLD, t_orig);
+ intel_uncore_write(uncore, GEN6_RC_EVALUATION_INTERVAL, i_orig);
+
+ intel_rc6_park(rc6);
+
+ intel_runtime_pm_put(uncore->rpm, wakeref);
+
+ return err;
+}
+
int live_rc6_busy(void *arg)
{
struct intel_gt *gt = arg;
@@ -10,5 +10,6 @@
int live_rc6_busy(void *arg);
int live_rc6_ctx_wa(void *arg);
int live_rc6_manual(void *arg);
+int live_rc6_threshold(void *arg);
#endif /* SELFTEST_RC6_H */