[PATCH 1/3] rps-ring
Chris Wilson
chris at chris-wilson.co.uk
Fri Jun 12 18:29:15 UTC 2020
---
drivers/gpu/drm/i915/gt/intel_llc.c | 3 +-
drivers/gpu/drm/i915/gt/selftest_gt_pm.c | 1 +
drivers/gpu/drm/i915/gt/selftest_llc.c | 39 +++++++
drivers/gpu/drm/i915/gt/selftest_llc.h | 3 +
drivers/gpu/drm/i915/gt/selftest_rps.c | 134 +++++++++++++++++++++++
drivers/gpu/drm/i915/gt/selftest_rps.h | 1 +
6 files changed, 179 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/gt/intel_llc.c b/drivers/gpu/drm/i915/gt/intel_llc.c
index e3f637b3650e..a01b87c74e31 100644
--- a/drivers/gpu/drm/i915/gt/intel_llc.c
+++ b/drivers/gpu/drm/i915/gt/intel_llc.c
@@ -44,8 +44,7 @@ static unsigned int cpu_max_MHz(void)
return max_khz / 1000;
}
-static bool get_ia_constants(struct intel_llc *llc,
- struct ia_constants *consts)
+static bool get_ia_constants(struct intel_llc *llc, struct ia_constants *consts)
{
struct drm_i915_private *i915 = llc_to_gt(llc)->i915;
struct intel_rps *rps = &llc_to_gt(llc)->rps;
diff --git a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c
index 6180a47c1b51..1038b5cf4fea 100644
--- a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c
+++ b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c
@@ -189,6 +189,7 @@ int intel_gt_pm_live_selftests(struct drm_i915_private *i915)
SUBTEST(live_rps_control),
SUBTEST(live_rps_frequency_cs),
SUBTEST(live_rps_frequency_srm),
+ SUBTEST(live_rps_frequency_ring),
SUBTEST(live_rps_power),
SUBTEST(live_rps_interrupt),
SUBTEST(live_rps_dynamic),
diff --git a/drivers/gpu/drm/i915/gt/selftest_llc.c b/drivers/gpu/drm/i915/gt/selftest_llc.c
index a912159693fd..78eab5557df1 100644
--- a/drivers/gpu/drm/i915/gt/selftest_llc.c
+++ b/drivers/gpu/drm/i915/gt/selftest_llc.c
@@ -71,3 +71,42 @@ int st_llc_verify(struct intel_llc *llc)
{
return gen6_verify_ring_freq(llc);
}
+
+static void override_ia_freq(struct intel_llc *llc,
+ const struct ia_constants *consts,
+ bool max,
+ unsigned int *out_ia_freq,
+ unsigned int *out_ring_freq)
+{
+ struct drm_i915_private *i915 = llc_to_gt(llc)->i915;
+ unsigned int ia_freq = 0, ring_freq = 0;
+
+ if (INTEL_GEN(i915) <= 7 && !IS_HASWELL(i915))
+ ia_freq = max ? consts->max_ia_freq : 800;
+ else
+ ring_freq = max ? consts->max_gpu_freq : consts->min_gpu_freq;
+
+ *out_ia_freq = ia_freq;
+ *out_ring_freq = ring_freq;
+}
+
+void st_llc_override(struct intel_llc *llc, bool max)
+{
+ struct drm_i915_private *i915 = llc_to_gt(llc)->i915;
+ unsigned int ia_freq, ring_freq, gpu_freq;
+ struct ia_constants consts;
+
+ if (!get_ia_constants(llc, &consts))
+ return;
+
+ override_ia_freq(llc, &consts, max, &ia_freq, &ring_freq);
+ for (gpu_freq = consts.max_gpu_freq;
+ gpu_freq >= consts.min_gpu_freq;
+ gpu_freq--) {
+ sandybridge_pcode_write(i915,
+ GEN6_PCODE_WRITE_MIN_FREQ_TABLE,
+ ia_freq << GEN6_PCODE_FREQ_IA_RATIO_SHIFT |
+ ring_freq << GEN6_PCODE_FREQ_RING_RATIO_SHIFT |
+ gpu_freq);
+ }
+}
diff --git a/drivers/gpu/drm/i915/gt/selftest_llc.h b/drivers/gpu/drm/i915/gt/selftest_llc.h
index 873f896e72f2..10a86220f5d8 100644
--- a/drivers/gpu/drm/i915/gt/selftest_llc.h
+++ b/drivers/gpu/drm/i915/gt/selftest_llc.h
@@ -7,8 +7,11 @@
#ifndef SELFTEST_LLC_H
#define SELFTEST_LLC_H
+#include <linux/types.h>
+
struct intel_llc;
int st_llc_verify(struct intel_llc *llc);
+void st_llc_override(struct intel_llc *llc, bool max);
#endif /* SELFTEST_LLC_H */
diff --git a/drivers/gpu/drm/i915/gt/selftest_rps.c b/drivers/gpu/drm/i915/gt/selftest_rps.c
index 5049c3dd08a6..5cd514ae2d1b 100644
--- a/drivers/gpu/drm/i915/gt/selftest_rps.c
+++ b/drivers/gpu/drm/i915/gt/selftest_rps.c
@@ -12,6 +12,7 @@
#include "intel_gt_clock_utils.h"
#include "intel_gt_pm.h"
#include "intel_rc6.h"
+#include "selftest_llc.h"
#include "selftest_rps.h"
#include "selftests/igt_flush_test.h"
#include "selftests/igt_spinner.h"
@@ -882,6 +883,139 @@ int live_rps_frequency_srm(void *arg)
return err;
}
+static unsigned long
+__live_rps_frequency_ring(struct intel_engine_cs *engine, int *freq)
+{
+ struct intel_rps *rps = &engine->gt->rps;
+ struct i915_request *rq;
+ struct i915_vma *vma;
+ unsigned long count;
+ u32 *cancel, *cntr;
+
+ engine_heartbeat_disable(engine);
+
+ vma = create_spin_counter(engine,
+ engine->kernel_context->vm, true,
+ &cancel, &cntr);
+ if (IS_ERR(vma)) {
+ engine_heartbeat_enable(engine);
+ return PTR_ERR(vma);
+ }
+
+ rq = intel_engine_create_kernel_request(engine);
+ if (IS_ERR(rq)) {
+ count = PTR_ERR(rq);
+ goto err_vma;
+ }
+
+ i915_vma_lock(vma);
+ count = i915_request_await_object(rq, vma->obj, false);
+ if (!count)
+ count = i915_vma_move_to_active(vma, rq, 0);
+ if (!count)
+ count = rq->engine->emit_bb_start(rq,
+ vma->node.start,
+ PAGE_SIZE, 0);
+ i915_vma_unlock(vma);
+ i915_request_add(rq);
+ if (count)
+ goto err_vma;
+
+ if (wait_for(READ_ONCE(*cntr), 10)) {
+ pr_err("%s: timed loop did not start\n",
+ engine->name);
+ count = -ETIME;
+ goto err_vma;
+ }
+
+ count = measure_frequency_at(rps, cntr, freq);
+
+err_vma:
+ *cancel = MI_BATCH_BUFFER_END;
+ i915_gem_object_flush_map(vma->obj);
+ i915_gem_object_unpin_map(vma->obj);
+ i915_vma_unpin(vma);
+ i915_vma_put(vma);
+
+ engine_heartbeat_enable(engine);
+ if (igt_flush_test(engine->i915))
+ count = -EIO;
+
+ return count;
+}
+
+int live_rps_frequency_ring(void *arg)
+{
+ void (*saved_work)(struct work_struct *wrk);
+ struct intel_gt *gt = arg;
+ struct intel_rps *rps = >->rps;
+ struct intel_engine_cs *engine;
+ struct pm_qos_request qos;
+ enum intel_engine_id id;
+ int err = 0;
+
+ if (!intel_rps_is_enabled(rps))
+ return 0;
+
+ if (!HAS_LLC(gt->i915))
+ return 0;
+
+ if (INTEL_GEN(gt->i915) < 8) /* for CS simplicity */
+ return 0;
+
+ if (CPU_LATENCY >= 0)
+ cpu_latency_qos_add_request(&qos, CPU_LATENCY);
+
+ intel_gt_pm_wait_for_idle(gt);
+ saved_work = rps->work.func;
+ rps->work.func = dummy_rps_work;
+
+ for_each_engine(engine, gt, id) {
+ struct {
+ int freq;
+ unsigned long min, max;
+ } result[2];
+ int pass;
+
+ for (pass = 0; pass <= 1; pass++) {
+ int freq = pass ? rps->max_freq : rps->min_freq;
+
+ intel_gt_pm_wait_for_idle(gt);
+ st_llc_override(>->llc, false);
+
+ result[pass].min = __live_rps_frequency_ring(engine, &freq);
+ if (IS_ERR_VALUE(result[pass].min)) {
+ err = result[pass].min;
+ break;
+ }
+
+ intel_gt_pm_wait_for_idle(gt);
+ st_llc_override(>->llc, true);
+
+ result[pass].max = __live_rps_frequency_ring(engine, &freq);
+ if (IS_ERR_VALUE(result[pass].max)) {
+ err = result[pass].max;
+ break;
+ }
+
+ result[pass].freq = freq;
+ }
+
+ pr_info("%s: freq:%x, min:%lu, max:%lu\n",
+ engine->name, result[0].freq, result[0].min, result[0].max);
+ pr_info("%s: freq:%x, min:%lu, max:%lu\n",
+ engine->name, result[1].freq, result[1].min, result[1].max);
+ }
+
+ intel_gt_pm_wait_for_idle(gt);
+ rps->work.func = saved_work;
+
+ if (CPU_LATENCY >= 0)
+ cpu_latency_qos_remove_request(&qos);
+
+ return err;
+}
+
static void sleep_for_ei(struct intel_rps *rps, int timeout_us)
{
/* Flush any previous EI */
diff --git a/drivers/gpu/drm/i915/gt/selftest_rps.h b/drivers/gpu/drm/i915/gt/selftest_rps.h
index 6e82a631cfa1..fa3135d9d4ee 100644
--- a/drivers/gpu/drm/i915/gt/selftest_rps.h
+++ b/drivers/gpu/drm/i915/gt/selftest_rps.h
@@ -10,6 +10,7 @@ int live_rps_control(void *arg);
int live_rps_clock_interval(void *arg);
int live_rps_frequency_cs(void *arg);
int live_rps_frequency_srm(void *arg);
+int live_rps_frequency_ring(void *arg);
int live_rps_power(void *arg);
int live_rps_interrupt(void *arg);
int live_rps_dynamic(void *arg);
--
2.20.1
More information about the Intel-gfx-trybot
mailing list