After having testing all the RPS controls individually, we need to take
a step back and check how our RPS worker integrates them to perform
dynamic GPU reclocking. So do that by submitting a spinner and wait and
see what happens.

Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk>
Reviewed-by: Mika Kuoppala <mika.kuopp...@linux.intel.com>
---
 drivers/gpu/drm/i915/gt/selftest_gt_pm.c |   1 +
 drivers/gpu/drm/i915/gt/selftest_rps.c   | 112 +++++++++++++++++++++--
 drivers/gpu/drm/i915/gt/selftest_rps.h   |   3 +-
 3 files changed, 105 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c 
b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c
index 9855e6f0ce7c..e02fdec58826 100644
--- a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c
+++ b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c
@@ -58,6 +58,7 @@ int intel_gt_pm_live_selftests(struct drm_i915_private *i915)
                SUBTEST(live_rps_frequency_srm),
                SUBTEST(live_rps_power),
                SUBTEST(live_rps_interrupt),
+               SUBTEST(live_rps_dynamic),
                SUBTEST(live_gt_resume),
        };
 
diff --git a/drivers/gpu/drm/i915/gt/selftest_rps.c 
b/drivers/gpu/drm/i915/gt/selftest_rps.c
index 9ecf694ed08b..6202e1564393 100644
--- a/drivers/gpu/drm/i915/gt/selftest_rps.c
+++ b/drivers/gpu/drm/i915/gt/selftest_rps.c
@@ -110,24 +110,18 @@ create_spin_counter(struct intel_engine_cs *engine,
        return vma;
 }
 
-static u8 rps_set_check(struct intel_rps *rps, u8 freq)
+static u8 wait_for_freq(struct intel_rps *rps, u8 freq, int timeout_ms)
 {
        u8 history[64], i;
        unsigned long end;
        int sleep;
 
-       mutex_lock(&rps->lock);
-       GEM_BUG_ON(!rps->active);
-       intel_rps_set(rps, freq);
-       GEM_BUG_ON(rps->last_freq != freq);
-       mutex_unlock(&rps->lock);
-
        i = 0;
        memset(history, freq, sizeof(history));
        sleep = 20;
 
        /* The PCU does not change instantly, but drifts towards the goal? */
-       end = jiffies + msecs_to_jiffies(50);
+       end = jiffies + msecs_to_jiffies(timeout_ms);
        do {
                u8 act;
 
@@ -148,11 +142,22 @@ static u8 rps_set_check(struct intel_rps *rps, u8 freq)
 
                usleep_range(sleep, 2 * sleep);
                sleep *= 2;
-               if (sleep > 1000)
-                       sleep = 1000;
+               if (sleep > timeout_ms * 20)
+                       sleep = timeout_ms * 20;
        } while (1);
 }
 
+static u8 rps_set_check(struct intel_rps *rps, u8 freq)
+{
+       mutex_lock(&rps->lock);
+       GEM_BUG_ON(!rps->active);
+       intel_rps_set(rps, freq);
+       GEM_BUG_ON(rps->last_freq != freq);
+       mutex_unlock(&rps->lock);
+
+       return wait_for_freq(rps, freq, 50);
+}
+
 static void show_pstate_limits(struct intel_rps *rps)
 {
        struct drm_i915_private *i915 = rps_to_i915(rps);
@@ -951,3 +956,90 @@ int live_rps_power(void *arg)
 
        return err;
 }
+
+int live_rps_dynamic(void *arg)
+{
+       struct intel_gt *gt = arg;
+       struct intel_rps *rps = &gt->rps;
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
+       struct igt_spinner spin;
+       int err = 0;
+
+       /*
+        * We've looked at the bascs, and have established that we
+        * can change the clock frequency and that the HW will generate
+        * interrupts based on load. Now we check how we integrate those
+        * moving parts into dynamic reclocking based on load.
+        */
+
+       if (!rps->enabled || rps->max_freq <= rps->min_freq)
+               return 0;
+
+       if (igt_spinner_init(&spin, gt))
+               return -ENOMEM;
+
+       for_each_engine(engine, gt, id) {
+               struct i915_request *rq;
+               struct {
+                       ktime_t dt;
+                       u8 freq;
+               } min,max;
+
+               if (!intel_engine_can_store_dword(engine))
+                       continue;
+
+               intel_gt_pm_wait_for_idle(gt);
+               GEM_BUG_ON(rps->active);
+               rps->cur_freq = rps->min_freq;
+
+               intel_engine_pm_get(engine);
+               intel_rc6_disable(&gt->rc6);
+               GEM_BUG_ON(rps->last_freq != rps->min_freq);
+
+               rq = igt_spinner_create_request(&spin,
+                                               engine->kernel_context,
+                                               MI_NOOP);
+               if (IS_ERR(rq)) {
+                       err = PTR_ERR(rq);
+                       goto err;
+               }
+
+               i915_request_add(rq);
+
+               max.dt = ktime_get();
+               max.freq = wait_for_freq(rps, rps->max_freq, 500);
+               max.dt = ktime_sub(ktime_get(), max.dt);
+
+               igt_spinner_end(&spin);
+
+               min.dt = ktime_get();
+               min.freq = wait_for_freq(rps, rps->min_freq, 2000);
+               min.dt = ktime_sub(ktime_get(), min.dt);
+
+               pr_info("%s: dynamically reclocked to %u:%uMHz while busy in 
%lluns, and %u:%uMHz while idle in %lluns\n",
+                       engine->name,
+                       max.freq, intel_gpu_freq(rps, max.freq),
+                       ktime_to_ns(max.dt),
+                       min.freq, intel_gpu_freq(rps, min.freq),
+                       ktime_to_ns(min.dt));
+               if (min.freq >= max.freq) {
+                       pr_err("%s: dynamic reclocking of spinner failed\n!",
+                              engine->name);
+                       err = -EINVAL;
+               }
+
+err:
+               intel_rc6_enable(&gt->rc6);
+               intel_engine_pm_put(engine);
+
+               if (igt_flush_test(gt->i915))
+                       err = -EIO;
+               if (err)
+                       break;
+       }
+
+       igt_spinner_fini(&spin);
+
+       return err;
+}
diff --git a/drivers/gpu/drm/i915/gt/selftest_rps.h 
b/drivers/gpu/drm/i915/gt/selftest_rps.h
index 22e46c5341c5..76c4b19553e6 100644
--- a/drivers/gpu/drm/i915/gt/selftest_rps.h
+++ b/drivers/gpu/drm/i915/gt/selftest_rps.h
@@ -9,7 +9,8 @@
 int live_rps_control(void *arg);
 int live_rps_frequency_cs(void *arg);
 int live_rps_frequency_srm(void *arg);
-int live_rps_interrupt(void *arg);
 int live_rps_power(void *arg);
+int live_rps_interrupt(void *arg);
+int live_rps_dynamic(void *arg);
 
 #endif /* SELFTEST_RPS_H */
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to