[Intel-gfx] [PATCH] drm/i915/selftests: Disable heartbeat around RPS interrupt testing

Chris Wilson chris at chris-wilson.co.uk
Wed Apr 22 08:38:55 UTC 2020


For verifying reciving the EI interrupts, we need to hold the GPU in
very precise conditions (in terms of C0 cycles during the EI). If we
preempt the busy load to handle the heartbeat, this may perturb the busy
load causing us to miss the interrupt.

The other tests, while not as time sensitive, may also be slightly
perturbed, so apply the heartbeat protection across all the
measurements.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/gt/selftest_rps.c | 59 ++++++++++++++++++++++++--
 1 file changed, 55 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/selftest_rps.c b/drivers/gpu/drm/i915/gt/selftest_rps.c
index 0d7ed000aff0..9d9c8e0aa2e7 100644
--- a/drivers/gpu/drm/i915/gt/selftest_rps.c
+++ b/drivers/gpu/drm/i915/gt/selftest_rps.c
@@ -6,6 +6,7 @@
 #include <linux/pm_qos.h>
 #include <linux/sort.h>
 
+#include "intel_engine_heartbeat.h"
 #include "intel_engine_pm.h"
 #include "intel_gpu_commands.h"
 #include "intel_gt_pm.h"
@@ -18,6 +19,26 @@
 /* Try to isolate the impact of cstates from determing frequency response */
 #define CPU_LATENCY 0 /* -1 to disable pm_qos, 0 to disable cstates */
 
+static unsigned long engine_heartbeat_disable(struct intel_engine_cs *engine)
+{
+	unsigned long old;
+
+	old = fetch_and_zero(&engine->props.heartbeat_interval_ms);
+
+	intel_engine_pm_get(engine);
+	intel_engine_park_heartbeat(engine);
+
+	return old;
+}
+
+static void engine_heartbeat_enable(struct intel_engine_cs *engine,
+				    unsigned long saved)
+{
+	intel_engine_pm_put(engine);
+
+	engine->props.heartbeat_interval_ms = saved;
+}
+
 static void dummy_rps_work(struct work_struct *wrk)
 {
 }
@@ -218,6 +239,7 @@ int live_rps_control(void *arg)
 
 	intel_gt_pm_get(gt);
 	for_each_engine(engine, gt, id) {
+		unsigned long saved_heartbeat;
 		struct i915_request *rq;
 		ktime_t min_dt, max_dt;
 		int f, limit;
@@ -226,6 +248,8 @@ int live_rps_control(void *arg)
 		if (!intel_engine_can_store_dword(engine))
 			continue;
 
+		saved_heartbeat = engine_heartbeat_disable(engine);
+
 		rq = igt_spinner_create_request(&spin,
 						engine->kernel_context,
 						MI_NOOP);
@@ -240,6 +264,7 @@ int live_rps_control(void *arg)
 			pr_err("%s: RPS spinner did not start\n",
 			       engine->name);
 			igt_spinner_end(&spin);
+			engine_heartbeat_enable(engine, saved_heartbeat);
 			intel_gt_set_wedged(engine->gt);
 			err = -EIO;
 			break;
@@ -249,6 +274,7 @@ int live_rps_control(void *arg)
 			pr_err("%s: could not set minimum frequency [%x], only %x!\n",
 			       engine->name, rps->min_freq, read_cagf(rps));
 			igt_spinner_end(&spin);
+			engine_heartbeat_enable(engine, saved_heartbeat);
 			show_pstate_limits(rps);
 			err = -EINVAL;
 			break;
@@ -265,6 +291,7 @@ int live_rps_control(void *arg)
 			pr_err("%s: could not restore minimum frequency [%x], only %x!\n",
 			       engine->name, rps->min_freq, read_cagf(rps));
 			igt_spinner_end(&spin);
+			engine_heartbeat_enable(engine, saved_heartbeat);
 			show_pstate_limits(rps);
 			err = -EINVAL;
 			break;
@@ -279,6 +306,7 @@ int live_rps_control(void *arg)
 		min_dt = ktime_sub(ktime_get(), min_dt);
 
 		igt_spinner_end(&spin);
+		engine_heartbeat_enable(engine, saved_heartbeat);
 
 		pr_info("%s: range:[%x:%uMHz, %x:%uMHz] limit:[%x:%uMHz], %x:%x response %lluns:%lluns\n",
 			engine->name,
@@ -441,6 +469,7 @@ int live_rps_frequency_cs(void *arg)
 	rps->work.func = dummy_rps_work;
 
 	for_each_engine(engine, gt, id) {
+		unsigned long saved_heartbeat;
 		struct i915_request *rq;
 		struct i915_vma *vma;
 		u32 *cancel, *cntr;
@@ -449,11 +478,14 @@ int live_rps_frequency_cs(void *arg)
 			int freq;
 		} min, max;
 
+		saved_heartbeat = engine_heartbeat_disable(engine);
+
 		vma = create_spin_counter(engine,
 					  engine->kernel_context->vm, false,
 					  &cancel, &cntr);
 		if (IS_ERR(vma)) {
 			err = PTR_ERR(vma);
+			engine_heartbeat_enable(engine, saved_heartbeat);
 			break;
 		}
 
@@ -533,6 +565,7 @@ int live_rps_frequency_cs(void *arg)
 		i915_vma_unpin(vma);
 		i915_vma_put(vma);
 
+		engine_heartbeat_enable(engine, saved_heartbeat);
 		if (igt_flush_test(gt->i915))
 			err = -EIO;
 		if (err)
@@ -578,6 +611,7 @@ int live_rps_frequency_srm(void *arg)
 	rps->work.func = dummy_rps_work;
 
 	for_each_engine(engine, gt, id) {
+		unsigned long saved_heartbeat;
 		struct i915_request *rq;
 		struct i915_vma *vma;
 		u32 *cancel, *cntr;
@@ -586,11 +620,14 @@ int live_rps_frequency_srm(void *arg)
 			int freq;
 		} min, max;
 
+		saved_heartbeat = engine_heartbeat_disable(engine);
+
 		vma = create_spin_counter(engine,
 					  engine->kernel_context->vm, true,
 					  &cancel, &cntr);
 		if (IS_ERR(vma)) {
 			err = PTR_ERR(vma);
+			engine_heartbeat_enable(engine, saved_heartbeat);
 			break;
 		}
 
@@ -669,6 +706,7 @@ int live_rps_frequency_srm(void *arg)
 		i915_vma_unpin(vma);
 		i915_vma_put(vma);
 
+		engine_heartbeat_enable(engine, saved_heartbeat);
 		if (igt_flush_test(gt->i915))
 			err = -EIO;
 		if (err)
@@ -858,12 +896,16 @@ int live_rps_interrupt(void *arg)
 	for_each_engine(engine, gt, id) {
 		/* Keep the engine busy with a spinner; expect an UP! */
 		if (pm_events & GEN6_PM_RP_UP_THRESHOLD) {
+			unsigned long saved_heartbeat;
+
 			intel_gt_pm_wait_for_idle(engine->gt);
 			GEM_BUG_ON(rps->active);
 
-			intel_engine_pm_get(engine);
+			saved_heartbeat = engine_heartbeat_disable(engine);
+
 			err = __rps_up_interrupt(rps, engine, &spin);
-			intel_engine_pm_put(engine);
+
+			engine_heartbeat_enable(engine, saved_heartbeat);
 			if (err)
 				goto out;
 
@@ -872,13 +914,15 @@ int live_rps_interrupt(void *arg)
 
 		/* Keep the engine awake but idle and check for DOWN */
 		if (pm_events & GEN6_PM_RP_DOWN_THRESHOLD) {
-			intel_engine_pm_get(engine);
+			unsigned long saved_heartbeat;
+
+			saved_heartbeat = engine_heartbeat_disable(engine);
 			intel_rc6_disable(&gt->rc6);
 
 			err = __rps_down_interrupt(rps, engine);
 
 			intel_rc6_enable(&gt->rc6);
-			intel_engine_pm_put(engine);
+			engine_heartbeat_enable(engine, saved_heartbeat);
 			if (err)
 				goto out;
 		}
@@ -954,6 +998,7 @@ int live_rps_power(void *arg)
 	rps->work.func = dummy_rps_work;
 
 	for_each_engine(engine, gt, id) {
+		unsigned long saved_heartbeat;
 		struct i915_request *rq;
 		struct {
 			u64 power;
@@ -963,10 +1008,13 @@ int live_rps_power(void *arg)
 		if (!intel_engine_can_store_dword(engine))
 			continue;
 
+		saved_heartbeat = engine_heartbeat_disable(engine);
+
 		rq = igt_spinner_create_request(&spin,
 						engine->kernel_context,
 						MI_NOOP);
 		if (IS_ERR(rq)) {
+			engine_heartbeat_enable(engine, saved_heartbeat);
 			err = PTR_ERR(rq);
 			break;
 		}
@@ -976,6 +1024,8 @@ int live_rps_power(void *arg)
 		if (!igt_wait_for_spinner(&spin, rq)) {
 			pr_err("%s: RPS spinner did not start\n",
 			       engine->name);
+			igt_spinner_end(&spin);
+			engine_heartbeat_enable(engine, saved_heartbeat);
 			intel_gt_set_wedged(engine->gt);
 			err = -EIO;
 			break;
@@ -988,6 +1038,7 @@ int live_rps_power(void *arg)
 		min.power = measure_power_at(rps, &min.freq);
 
 		igt_spinner_end(&spin);
+		engine_heartbeat_enable(engine, saved_heartbeat);
 
 		pr_info("%s: min:%llumW @ %uMHz, max:%llumW @ %uMHz\n",
 			engine->name,
-- 
2.20.1



More information about the Intel-gfx mailing list