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 <chris@xxxxxxxxxxxxxxxxxx> --- 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 5264ff86f235..93db2748c1d6 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); +} + int live_rps_control(void *arg) { struct intel_gt *gt = arg; @@ -933,3 +938,90 @@ int live_rps_power(void *arg) return err; } + +int live_rps_dynamic(void *arg) +{ + struct intel_gt *gt = arg; + struct intel_rps *rps = >->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(>->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(>->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@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx