Commit 1b90e4a4 authored by Chris Wilson's avatar Chris Wilson

drm/i915/selftests: Enable selftesting of busy-stats

A couple of very simple tests to ensure that the basic properties of
per-engine busyness accounting [0% and 100% busy] are faithful.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarMika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200617130916.15261-1-chris@chris-wilson.co.uk
parent 0ff0fc97
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "intel_gt_requests.h" #include "intel_gt_requests.h"
#include "i915_selftest.h" #include "i915_selftest.h"
#include "selftest_engine_heartbeat.h"
static int timeline_sync(struct intel_timeline *tl) static int timeline_sync(struct intel_timeline *tl)
{ {
...@@ -142,24 +143,6 @@ static int __live_idle_pulse(struct intel_engine_cs *engine, ...@@ -142,24 +143,6 @@ static int __live_idle_pulse(struct intel_engine_cs *engine,
return err; return err;
} }
static void engine_heartbeat_disable(struct intel_engine_cs *engine,
unsigned long *saved)
{
*saved = engine->props.heartbeat_interval_ms;
engine->props.heartbeat_interval_ms = 0;
intel_engine_pm_get(engine);
intel_engine_park_heartbeat(engine);
}
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 int live_idle_flush(void *arg) static int live_idle_flush(void *arg)
{ {
struct intel_gt *gt = arg; struct intel_gt *gt = arg;
...@@ -170,11 +153,9 @@ static int live_idle_flush(void *arg) ...@@ -170,11 +153,9 @@ static int live_idle_flush(void *arg)
/* Check that we can flush the idle barriers */ /* Check that we can flush the idle barriers */
for_each_engine(engine, gt, id) { for_each_engine(engine, gt, id) {
unsigned long heartbeat; st_engine_heartbeat_disable(engine);
engine_heartbeat_disable(engine, &heartbeat);
err = __live_idle_pulse(engine, intel_engine_flush_barriers); err = __live_idle_pulse(engine, intel_engine_flush_barriers);
engine_heartbeat_enable(engine, heartbeat); st_engine_heartbeat_enable(engine);
if (err) if (err)
break; break;
} }
...@@ -192,11 +173,9 @@ static int live_idle_pulse(void *arg) ...@@ -192,11 +173,9 @@ static int live_idle_pulse(void *arg)
/* Check that heartbeat pulses flush the idle barriers */ /* Check that heartbeat pulses flush the idle barriers */
for_each_engine(engine, gt, id) { for_each_engine(engine, gt, id) {
unsigned long heartbeat; st_engine_heartbeat_disable(engine);
engine_heartbeat_disable(engine, &heartbeat);
err = __live_idle_pulse(engine, intel_engine_pulse); err = __live_idle_pulse(engine, intel_engine_pulse);
engine_heartbeat_enable(engine, heartbeat); st_engine_heartbeat_enable(engine);
if (err && err != -ENODEV) if (err && err != -ENODEV)
break; break;
...@@ -394,3 +373,19 @@ int intel_heartbeat_live_selftests(struct drm_i915_private *i915) ...@@ -394,3 +373,19 @@ int intel_heartbeat_live_selftests(struct drm_i915_private *i915)
i915_modparams.enable_hangcheck = saved_hangcheck; i915_modparams.enable_hangcheck = saved_hangcheck;
return err; return err;
} }
void st_engine_heartbeat_disable(struct intel_engine_cs *engine)
{
engine->props.heartbeat_interval_ms = 0;
intel_engine_pm_get(engine);
intel_engine_park_heartbeat(engine);
}
void st_engine_heartbeat_enable(struct intel_engine_cs *engine)
{
intel_engine_pm_put(engine);
engine->props.heartbeat_interval_ms =
engine->defaults.heartbeat_interval_ms;
}
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2020 Intel Corporation
*/
#ifndef SELFTEST_ENGINE_HEARTBEAT_H
#define SELFTEST_ENGINE_HEARTBEAT_H
struct intel_engine_cs;
void st_engine_heartbeat_disable(struct intel_engine_cs *engine);
void st_engine_heartbeat_enable(struct intel_engine_cs *engine);
#endif /* SELFTEST_ENGINE_HEARTBEAT_H */
...@@ -6,7 +6,109 @@ ...@@ -6,7 +6,109 @@
#include "i915_selftest.h" #include "i915_selftest.h"
#include "selftest_engine.h" #include "selftest_engine.h"
#include "selftest_engine_heartbeat.h"
#include "selftests/igt_atomic.h" #include "selftests/igt_atomic.h"
#include "selftests/igt_flush_test.h"
#include "selftests/igt_spinner.h"
static int live_engine_busy_stats(void *arg)
{
struct intel_gt *gt = arg;
struct intel_engine_cs *engine;
enum intel_engine_id id;
struct igt_spinner spin;
int err = 0;
/*
* Check that if an engine supports busy-stats, they tell the truth.
*/
if (igt_spinner_init(&spin, gt))
return -ENOMEM;
GEM_BUG_ON(intel_gt_pm_is_awake(gt));
for_each_engine(engine, gt, id) {
struct i915_request *rq;
ktime_t de;
u64 dt;
if (!intel_engine_supports_stats(engine))
continue;
if (!intel_engine_can_store_dword(engine))
continue;
if (intel_gt_pm_wait_for_idle(gt)) {
err = -EBUSY;
break;
}
st_engine_heartbeat_disable(engine);
ENGINE_TRACE(engine, "measuring idle time\n");
preempt_disable();
dt = ktime_to_ns(ktime_get());
de = intel_engine_get_busy_time(engine);
udelay(100);
de = ktime_sub(intel_engine_get_busy_time(engine), de);
dt = ktime_to_ns(ktime_get()) - dt;
preempt_enable();
if (de < 0 || de > 10) {
pr_err("%s: reported %lldns [%d%%] busyness while sleeping [for %lldns]\n",
engine->name,
de, (int)div64_u64(100 * de, dt), dt);
GEM_TRACE_DUMP();
err = -EINVAL;
goto end;
}
/* 100% busy */
rq = igt_spinner_create_request(&spin,
engine->kernel_context,
MI_NOOP);
if (IS_ERR(rq)) {
err = PTR_ERR(rq);
goto end;
}
i915_request_add(rq);
if (!igt_wait_for_spinner(&spin, rq)) {
intel_gt_set_wedged(engine->gt);
err = -ETIME;
goto end;
}
ENGINE_TRACE(engine, "measuring busy time\n");
preempt_disable();
dt = ktime_to_ns(ktime_get());
de = intel_engine_get_busy_time(engine);
udelay(100);
de = ktime_sub(intel_engine_get_busy_time(engine), de);
dt = ktime_to_ns(ktime_get()) - dt;
preempt_enable();
if (100 * de < 95 * dt || 95 * de > 100 * dt) {
pr_err("%s: reported %lldns [%d%%] busyness while spinning [for %lldns]\n",
engine->name,
de, (int)div64_u64(100 * de, dt), dt);
GEM_TRACE_DUMP();
err = -EINVAL;
goto end;
}
end:
st_engine_heartbeat_enable(engine);
igt_spinner_end(&spin);
if (igt_flush_test(gt->i915))
err = -EIO;
if (err)
break;
}
igt_spinner_fini(&spin);
if (igt_flush_test(gt->i915))
err = -EIO;
return err;
}
static int live_engine_pm(void *arg) static int live_engine_pm(void *arg)
{ {
...@@ -77,6 +179,7 @@ static int live_engine_pm(void *arg) ...@@ -77,6 +179,7 @@ static int live_engine_pm(void *arg)
int live_engine_pm_selftests(struct intel_gt *gt) int live_engine_pm_selftests(struct intel_gt *gt)
{ {
static const struct i915_subtest tests[] = { static const struct i915_subtest tests[] = {
SUBTEST(live_engine_busy_stats),
SUBTEST(live_engine_pm), SUBTEST(live_engine_pm),
}; };
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "intel_gt.h" #include "intel_gt.h"
#include "intel_engine_heartbeat.h" #include "intel_engine_heartbeat.h"
#include "intel_engine_pm.h" #include "intel_engine_pm.h"
#include "selftest_engine_heartbeat.h"
#include "i915_selftest.h" #include "i915_selftest.h"
#include "selftests/i915_random.h" #include "selftests/i915_random.h"
...@@ -310,22 +311,6 @@ static bool wait_until_running(struct hang *h, struct i915_request *rq) ...@@ -310,22 +311,6 @@ static bool wait_until_running(struct hang *h, struct i915_request *rq)
1000)); 1000));
} }
static void engine_heartbeat_disable(struct intel_engine_cs *engine)
{
engine->props.heartbeat_interval_ms = 0;
intel_engine_pm_get(engine);
intel_engine_park_heartbeat(engine);
}
static void engine_heartbeat_enable(struct intel_engine_cs *engine)
{
intel_engine_pm_put(engine);
engine->props.heartbeat_interval_ms =
engine->defaults.heartbeat_interval_ms;
}
static int igt_hang_sanitycheck(void *arg) static int igt_hang_sanitycheck(void *arg)
{ {
struct intel_gt *gt = arg; struct intel_gt *gt = arg;
...@@ -482,7 +467,7 @@ static int igt_reset_nop_engine(void *arg) ...@@ -482,7 +467,7 @@ static int igt_reset_nop_engine(void *arg)
reset_engine_count = i915_reset_engine_count(global, engine); reset_engine_count = i915_reset_engine_count(global, engine);
count = 0; count = 0;
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
set_bit(I915_RESET_ENGINE + id, &gt->reset.flags); set_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
do { do {
int i; int i;
...@@ -540,7 +525,7 @@ static int igt_reset_nop_engine(void *arg) ...@@ -540,7 +525,7 @@ static int igt_reset_nop_engine(void *arg)
} }
} while (time_before(jiffies, end_time)); } while (time_before(jiffies, end_time));
clear_bit(I915_RESET_ENGINE + id, &gt->reset.flags); clear_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
pr_info("%s(%s): %d resets\n", __func__, engine->name, count); pr_info("%s(%s): %d resets\n", __func__, engine->name, count);
...@@ -590,7 +575,7 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active) ...@@ -590,7 +575,7 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active)
reset_count = i915_reset_count(global); reset_count = i915_reset_count(global);
reset_engine_count = i915_reset_engine_count(global, engine); reset_engine_count = i915_reset_engine_count(global, engine);
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
set_bit(I915_RESET_ENGINE + id, &gt->reset.flags); set_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
do { do {
if (active) { if (active) {
...@@ -642,7 +627,7 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active) ...@@ -642,7 +627,7 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active)
} }
} while (time_before(jiffies, end_time)); } while (time_before(jiffies, end_time));
clear_bit(I915_RESET_ENGINE + id, &gt->reset.flags); clear_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
if (err) if (err)
break; break;
...@@ -841,7 +826,7 @@ static int __igt_reset_engines(struct intel_gt *gt, ...@@ -841,7 +826,7 @@ static int __igt_reset_engines(struct intel_gt *gt,
yield(); /* start all threads before we begin */ yield(); /* start all threads before we begin */
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
set_bit(I915_RESET_ENGINE + id, &gt->reset.flags); set_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
do { do {
struct i915_request *rq = NULL; struct i915_request *rq = NULL;
...@@ -931,7 +916,7 @@ static int __igt_reset_engines(struct intel_gt *gt, ...@@ -931,7 +916,7 @@ static int __igt_reset_engines(struct intel_gt *gt,
} }
} while (time_before(jiffies, end_time)); } while (time_before(jiffies, end_time));
clear_bit(I915_RESET_ENGINE + id, &gt->reset.flags); clear_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
pr_info("i915_reset_engine(%s:%s): %lu resets\n", pr_info("i915_reset_engine(%s:%s): %lu resets\n",
engine->name, test_name, count); engine->name, test_name, count);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "gem/i915_gem_pm.h" #include "gem/i915_gem_pm.h"
#include "gt/intel_engine_heartbeat.h" #include "gt/intel_engine_heartbeat.h"
#include "gt/intel_reset.h" #include "gt/intel_reset.h"
#include "gt/selftest_engine_heartbeat.h"
#include "i915_selftest.h" #include "i915_selftest.h"
#include "selftests/i915_random.h" #include "selftests/i915_random.h"
...@@ -51,22 +52,6 @@ static struct i915_vma *create_scratch(struct intel_gt *gt) ...@@ -51,22 +52,6 @@ static struct i915_vma *create_scratch(struct intel_gt *gt)
return vma; return vma;
} }
static void engine_heartbeat_disable(struct intel_engine_cs *engine)
{
engine->props.heartbeat_interval_ms = 0;
intel_engine_pm_get(engine);
intel_engine_park_heartbeat(engine);
}
static void engine_heartbeat_enable(struct intel_engine_cs *engine)
{
intel_engine_pm_put(engine);
engine->props.heartbeat_interval_ms =
engine->defaults.heartbeat_interval_ms;
}
static bool is_active(struct i915_request *rq) static bool is_active(struct i915_request *rq)
{ {
if (i915_request_is_active(rq)) if (i915_request_is_active(rq))
...@@ -234,7 +219,7 @@ static int live_unlite_restore(struct intel_gt *gt, int prio) ...@@ -234,7 +219,7 @@ static int live_unlite_restore(struct intel_gt *gt, int prio)
err = -EIO; err = -EIO;
break; break;
} }
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
for (n = 0; n < ARRAY_SIZE(ce); n++) { for (n = 0; n < ARRAY_SIZE(ce); n++) {
struct intel_context *tmp; struct intel_context *tmp;
...@@ -342,7 +327,7 @@ static int live_unlite_restore(struct intel_gt *gt, int prio) ...@@ -342,7 +327,7 @@ static int live_unlite_restore(struct intel_gt *gt, int prio)
intel_context_put(ce[n]); intel_context_put(ce[n]);
} }
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
if (igt_live_test_end(&t)) if (igt_live_test_end(&t))
err = -EIO; err = -EIO;
if (err) if (err)
...@@ -396,7 +381,7 @@ static int live_unlite_ring(void *arg) ...@@ -396,7 +381,7 @@ static int live_unlite_ring(void *arg)
err = -EIO; err = -EIO;
break; break;
} }
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
for (n = 0; n < ARRAY_SIZE(ce); n++) { for (n = 0; n < ARRAY_SIZE(ce); n++) {
struct intel_context *tmp; struct intel_context *tmp;
...@@ -502,7 +487,7 @@ static int live_unlite_ring(void *arg) ...@@ -502,7 +487,7 @@ static int live_unlite_ring(void *arg)
intel_context_unpin(ce[n]); intel_context_unpin(ce[n]);
intel_context_put(ce[n]); intel_context_put(ce[n]);
} }
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
if (igt_live_test_end(&t)) if (igt_live_test_end(&t))
err = -EIO; err = -EIO;
if (err) if (err)
...@@ -621,7 +606,7 @@ static int live_hold_reset(void *arg) ...@@ -621,7 +606,7 @@ static int live_hold_reset(void *arg)
break; break;
} }
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
rq = igt_spinner_create_request(&spin, ce, MI_ARB_CHECK); rq = igt_spinner_create_request(&spin, ce, MI_ARB_CHECK);
if (IS_ERR(rq)) { if (IS_ERR(rq)) {
...@@ -681,7 +666,7 @@ static int live_hold_reset(void *arg) ...@@ -681,7 +666,7 @@ static int live_hold_reset(void *arg)
i915_request_put(rq); i915_request_put(rq);
out: out:
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
intel_context_put(ce); intel_context_put(ce);
if (err) if (err)
break; break;
...@@ -728,7 +713,7 @@ static int live_error_interrupt(void *arg) ...@@ -728,7 +713,7 @@ static int live_error_interrupt(void *arg)
const struct error_phase *p; const struct error_phase *p;
int err = 0; int err = 0;
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
for (p = phases; p->error[0] != GOOD; p++) { for (p = phases; p->error[0] != GOOD; p++) {
struct i915_request *client[ARRAY_SIZE(phases->error)]; struct i915_request *client[ARRAY_SIZE(phases->error)];
...@@ -827,7 +812,7 @@ static int live_error_interrupt(void *arg) ...@@ -827,7 +812,7 @@ static int live_error_interrupt(void *arg)
} }
} }
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
if (err) { if (err) {
intel_gt_set_wedged(gt); intel_gt_set_wedged(gt);
return err; return err;
...@@ -1042,9 +1027,9 @@ static int live_timeslice_preempt(void *arg) ...@@ -1042,9 +1027,9 @@ static int live_timeslice_preempt(void *arg)
memset(vaddr, 0, PAGE_SIZE); memset(vaddr, 0, PAGE_SIZE);
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
err = slice_semaphore_queue(engine, vma, 5); err = slice_semaphore_queue(engine, vma, 5);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
if (err) if (err)
goto err_pin; goto err_pin;
...@@ -1166,7 +1151,7 @@ static int live_timeslice_rewind(void *arg) ...@@ -1166,7 +1151,7 @@ static int live_timeslice_rewind(void *arg)
* Expect execution/evaluation order XZY * Expect execution/evaluation order XZY
*/ */
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
timeslice = xchg(&engine->props.timeslice_duration_ms, 1); timeslice = xchg(&engine->props.timeslice_duration_ms, 1);
slot = memset32(engine->status_page.addr + 1000, 0, 4); slot = memset32(engine->status_page.addr + 1000, 0, 4);
...@@ -1261,7 +1246,7 @@ static int live_timeslice_rewind(void *arg) ...@@ -1261,7 +1246,7 @@ static int live_timeslice_rewind(void *arg)
wmb(); wmb();
engine->props.timeslice_duration_ms = timeslice; engine->props.timeslice_duration_ms = timeslice;
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
i915_request_put(rq[i]); i915_request_put(rq[i]);
if (igt_flush_test(gt->i915)) if (igt_flush_test(gt->i915))
...@@ -1353,7 +1338,7 @@ static int live_timeslice_queue(void *arg) ...@@ -1353,7 +1338,7 @@ static int live_timeslice_queue(void *arg)
if (!intel_engine_has_preemption(engine)) if (!intel_engine_has_preemption(engine))
continue; continue;
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
memset(vaddr, 0, PAGE_SIZE); memset(vaddr, 0, PAGE_SIZE);
/* ELSP[0]: semaphore wait */ /* ELSP[0]: semaphore wait */
...@@ -1414,7 +1399,7 @@ static int live_timeslice_queue(void *arg) ...@@ -1414,7 +1399,7 @@ static int live_timeslice_queue(void *arg)
err_rq: err_rq:
i915_request_put(rq); i915_request_put(rq);
err_heartbeat: err_heartbeat:
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
if (err) if (err)
break; break;
} }
...@@ -1460,7 +1445,7 @@ static int live_timeslice_nopreempt(void *arg) ...@@ -1460,7 +1445,7 @@ static int live_timeslice_nopreempt(void *arg)
break; break;
} }
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
timeslice = xchg(&engine->props.timeslice_duration_ms, 1); timeslice = xchg(&engine->props.timeslice_duration_ms, 1);
/* Create an unpreemptible spinner */ /* Create an unpreemptible spinner */
...@@ -1529,7 +1514,7 @@ static int live_timeslice_nopreempt(void *arg) ...@@ -1529,7 +1514,7 @@ static int live_timeslice_nopreempt(void *arg)
igt_spinner_end(&spin); igt_spinner_end(&spin);
out_heartbeat: out_heartbeat:
xchg(&engine->props.timeslice_duration_ms, timeslice); xchg(&engine->props.timeslice_duration_ms, timeslice);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
if (err) if (err)
break; break;
...@@ -2433,7 +2418,7 @@ static int live_suppress_self_preempt(void *arg) ...@@ -2433,7 +2418,7 @@ static int live_suppress_self_preempt(void *arg)
if (igt_flush_test(gt->i915)) if (igt_flush_test(gt->i915))
goto err_wedged; goto err_wedged;
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
engine->execlists.preempt_hang.count = 0; engine->execlists.preempt_hang.count = 0;
rq_a = spinner_create_request(&a.spin, rq_a = spinner_create_request(&a.spin,
...@@ -2441,14 +2426,14 @@ static int live_suppress_self_preempt(void *arg) ...@@ -2441,14 +2426,14 @@ static int live_suppress_self_preempt(void *arg)
MI_NOOP); MI_NOOP);
if (IS_ERR(rq_a)) { if (IS_ERR(rq_a)) {
err = PTR_ERR(rq_a); err = PTR_ERR(rq_a);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
goto err_client_b; goto err_client_b;
} }
i915_request_add(rq_a); i915_request_add(rq_a);
if (!igt_wait_for_spinner(&a.spin, rq_a)) { if (!igt_wait_for_spinner(&a.spin, rq_a)) {
pr_err("First client failed to start\n"); pr_err("First client failed to start\n");
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
goto err_wedged; goto err_wedged;
} }
...@@ -2460,7 +2445,7 @@ static int live_suppress_self_preempt(void *arg) ...@@ -2460,7 +2445,7 @@ static int live_suppress_self_preempt(void *arg)
MI_NOOP); MI_NOOP);
if (IS_ERR(rq_b)) { if (IS_ERR(rq_b)) {
err = PTR_ERR(rq_b); err = PTR_ERR(rq_b);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
goto err_client_b; goto err_client_b;
} }
i915_request_add(rq_b); i915_request_add(rq_b);
...@@ -2471,7 +2456,7 @@ static int live_suppress_self_preempt(void *arg) ...@@ -2471,7 +2456,7 @@ static int live_suppress_self_preempt(void *arg)
if (!igt_wait_for_spinner(&b.spin, rq_b)) { if (!igt_wait_for_spinner(&b.spin, rq_b)) {
pr_err("Second client failed to start\n"); pr_err("Second client failed to start\n");
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
goto err_wedged; goto err_wedged;
} }
...@@ -2485,12 +2470,12 @@ static int live_suppress_self_preempt(void *arg) ...@@ -2485,12 +2470,12 @@ static int live_suppress_self_preempt(void *arg)
engine->name, engine->name,
engine->execlists.preempt_hang.count, engine->execlists.preempt_hang.count,
depth); depth);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
err = -EINVAL; err = -EINVAL;
goto err_client_b; goto err_client_b;
} }
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
if (igt_flush_test(gt->i915)) if (igt_flush_test(gt->i915))
goto err_wedged; goto err_wedged;
} }
...@@ -2902,7 +2887,7 @@ static int live_preempt_ring(void *arg) ...@@ -2902,7 +2887,7 @@ static int live_preempt_ring(void *arg)
if (!intel_engine_can_store_dword(engine)) if (!intel_engine_can_store_dword(engine))
continue; continue;
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
for (n = 0; n <= 3; n++) { for (n = 0; n <= 3; n++) {
err = __live_preempt_ring(engine, &spin, err = __live_preempt_ring(engine, &spin,
...@@ -2911,7 +2896,7 @@ static int live_preempt_ring(void *arg) ...@@ -2911,7 +2896,7 @@ static int live_preempt_ring(void *arg)
break; break;
} }
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
if (err) if (err)
break; break;
} }
...@@ -4568,7 +4553,7 @@ static int reset_virtual_engine(struct intel_gt *gt, ...@@ -4568,7 +4553,7 @@ static int reset_virtual_engine(struct intel_gt *gt,
} }
for (n = 0; n < nsibling; n++) for (n = 0; n < nsibling; n++)
engine_heartbeat_disable(siblings[n]); st_engine_heartbeat_disable(siblings[n]);
rq = igt_spinner_create_request(&spin, ve, MI_ARB_CHECK); rq = igt_spinner_create_request(&spin, ve, MI_ARB_CHECK);
if (IS_ERR(rq)) { if (IS_ERR(rq)) {
...@@ -4639,7 +4624,7 @@ static int reset_virtual_engine(struct intel_gt *gt, ...@@ -4639,7 +4624,7 @@ static int reset_virtual_engine(struct intel_gt *gt,
i915_request_put(rq); i915_request_put(rq);
out_heartbeat: out_heartbeat:
for (n = 0; n < nsibling; n++) for (n = 0; n < nsibling; n++)
engine_heartbeat_enable(siblings[n]); st_engine_heartbeat_enable(siblings[n]);
intel_context_put(ve); intel_context_put(ve);
out_spin: out_spin:
...@@ -5314,7 +5299,7 @@ static int live_lrc_gpr(void *arg) ...@@ -5314,7 +5299,7 @@ static int live_lrc_gpr(void *arg)
return PTR_ERR(scratch); return PTR_ERR(scratch);
for_each_engine(engine, gt, id) { for_each_engine(engine, gt, id) {
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
err = __live_lrc_gpr(engine, scratch, false); err = __live_lrc_gpr(engine, scratch, false);
if (err) if (err)
...@@ -5325,7 +5310,7 @@ static int live_lrc_gpr(void *arg) ...@@ -5325,7 +5310,7 @@ static int live_lrc_gpr(void *arg)
goto err; goto err;
err: err:
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
if (igt_flush_test(gt->i915)) if (igt_flush_test(gt->i915))
err = -EIO; err = -EIO;
if (err) if (err)
...@@ -5474,7 +5459,7 @@ static int live_lrc_timestamp(void *arg) ...@@ -5474,7 +5459,7 @@ static int live_lrc_timestamp(void *arg)
for_each_engine(data.engine, gt, id) { for_each_engine(data.engine, gt, id) {
int i, err = 0; int i, err = 0;
engine_heartbeat_disable(data.engine); st_engine_heartbeat_disable(data.engine);
for (i = 0; i < ARRAY_SIZE(data.ce); i++) { for (i = 0; i < ARRAY_SIZE(data.ce); i++) {
struct intel_context *tmp; struct intel_context *tmp;
...@@ -5507,7 +5492,7 @@ static int live_lrc_timestamp(void *arg) ...@@ -5507,7 +5492,7 @@ static int live_lrc_timestamp(void *arg)
} }
err: err:
engine_heartbeat_enable(data.engine); st_engine_heartbeat_enable(data.engine);
for (i = 0; i < ARRAY_SIZE(data.ce); i++) { for (i = 0; i < ARRAY_SIZE(data.ce); i++) {
if (!data.ce[i]) if (!data.ce[i])
break; break;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "intel_gt_clock_utils.h" #include "intel_gt_clock_utils.h"
#include "intel_gt_pm.h" #include "intel_gt_pm.h"
#include "intel_rc6.h" #include "intel_rc6.h"
#include "selftest_engine_heartbeat.h"
#include "selftest_rps.h" #include "selftest_rps.h"
#include "selftests/igt_flush_test.h" #include "selftests/igt_flush_test.h"
#include "selftests/igt_spinner.h" #include "selftests/igt_spinner.h"
...@@ -20,22 +21,6 @@ ...@@ -20,22 +21,6 @@
/* Try to isolate the impact of cstates from determing frequency response */ /* Try to isolate the impact of cstates from determing frequency response */
#define CPU_LATENCY 0 /* -1 to disable pm_qos, 0 to disable cstates */ #define CPU_LATENCY 0 /* -1 to disable pm_qos, 0 to disable cstates */
static void engine_heartbeat_disable(struct intel_engine_cs *engine)
{
engine->props.heartbeat_interval_ms = 0;
intel_engine_pm_get(engine);
intel_engine_park_heartbeat(engine);
}
static void engine_heartbeat_enable(struct intel_engine_cs *engine)
{
intel_engine_pm_put(engine);
engine->props.heartbeat_interval_ms =
engine->defaults.heartbeat_interval_ms;
}
static void dummy_rps_work(struct work_struct *wrk) static void dummy_rps_work(struct work_struct *wrk)
{ {
} }
...@@ -249,13 +234,13 @@ int live_rps_clock_interval(void *arg) ...@@ -249,13 +234,13 @@ int live_rps_clock_interval(void *arg)
if (!intel_engine_can_store_dword(engine)) if (!intel_engine_can_store_dword(engine))
continue; continue;
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
rq = igt_spinner_create_request(&spin, rq = igt_spinner_create_request(&spin,
engine->kernel_context, engine->kernel_context,
MI_NOOP); MI_NOOP);
if (IS_ERR(rq)) { if (IS_ERR(rq)) {
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
err = PTR_ERR(rq); err = PTR_ERR(rq);
break; break;
} }
...@@ -266,7 +251,7 @@ int live_rps_clock_interval(void *arg) ...@@ -266,7 +251,7 @@ int live_rps_clock_interval(void *arg)
pr_err("%s: RPS spinner did not start\n", pr_err("%s: RPS spinner did not start\n",
engine->name); engine->name);
igt_spinner_end(&spin); igt_spinner_end(&spin);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
intel_gt_set_wedged(engine->gt); intel_gt_set_wedged(engine->gt);
err = -EIO; err = -EIO;
break; break;
...@@ -322,7 +307,7 @@ int live_rps_clock_interval(void *arg) ...@@ -322,7 +307,7 @@ int live_rps_clock_interval(void *arg)
intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL); intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL);
igt_spinner_end(&spin); igt_spinner_end(&spin);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
if (err == 0) { if (err == 0) {
u64 time = intel_gt_pm_interval_to_ns(gt, cycles); u64 time = intel_gt_pm_interval_to_ns(gt, cycles);
...@@ -408,7 +393,7 @@ int live_rps_control(void *arg) ...@@ -408,7 +393,7 @@ int live_rps_control(void *arg)
if (!intel_engine_can_store_dword(engine)) if (!intel_engine_can_store_dword(engine))
continue; continue;
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
rq = igt_spinner_create_request(&spin, rq = igt_spinner_create_request(&spin,
engine->kernel_context, engine->kernel_context,
...@@ -424,7 +409,7 @@ int live_rps_control(void *arg) ...@@ -424,7 +409,7 @@ int live_rps_control(void *arg)
pr_err("%s: RPS spinner did not start\n", pr_err("%s: RPS spinner did not start\n",
engine->name); engine->name);
igt_spinner_end(&spin); igt_spinner_end(&spin);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
intel_gt_set_wedged(engine->gt); intel_gt_set_wedged(engine->gt);
err = -EIO; err = -EIO;
break; break;
...@@ -434,7 +419,7 @@ int live_rps_control(void *arg) ...@@ -434,7 +419,7 @@ int live_rps_control(void *arg)
pr_err("%s: could not set minimum frequency [%x], only %x!\n", pr_err("%s: could not set minimum frequency [%x], only %x!\n",
engine->name, rps->min_freq, read_cagf(rps)); engine->name, rps->min_freq, read_cagf(rps));
igt_spinner_end(&spin); igt_spinner_end(&spin);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
show_pstate_limits(rps); show_pstate_limits(rps);
err = -EINVAL; err = -EINVAL;
break; break;
...@@ -451,7 +436,7 @@ int live_rps_control(void *arg) ...@@ -451,7 +436,7 @@ int live_rps_control(void *arg)
pr_err("%s: could not restore minimum frequency [%x], only %x!\n", pr_err("%s: could not restore minimum frequency [%x], only %x!\n",
engine->name, rps->min_freq, read_cagf(rps)); engine->name, rps->min_freq, read_cagf(rps));
igt_spinner_end(&spin); igt_spinner_end(&spin);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
show_pstate_limits(rps); show_pstate_limits(rps);
err = -EINVAL; err = -EINVAL;
break; break;
...@@ -466,7 +451,7 @@ int live_rps_control(void *arg) ...@@ -466,7 +451,7 @@ int live_rps_control(void *arg)
min_dt = ktime_sub(ktime_get(), min_dt); min_dt = ktime_sub(ktime_get(), min_dt);
igt_spinner_end(&spin); igt_spinner_end(&spin);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
pr_info("%s: range:[%x:%uMHz, %x:%uMHz] limit:[%x:%uMHz], %x:%x response %lluns:%lluns\n", pr_info("%s: range:[%x:%uMHz, %x:%uMHz] limit:[%x:%uMHz], %x:%x response %lluns:%lluns\n",
engine->name, engine->name,
...@@ -637,14 +622,14 @@ int live_rps_frequency_cs(void *arg) ...@@ -637,14 +622,14 @@ int live_rps_frequency_cs(void *arg)
int freq; int freq;
} min, max; } min, max;
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
vma = create_spin_counter(engine, vma = create_spin_counter(engine,
engine->kernel_context->vm, false, engine->kernel_context->vm, false,
&cancel, &cntr); &cancel, &cntr);
if (IS_ERR(vma)) { if (IS_ERR(vma)) {
err = PTR_ERR(vma); err = PTR_ERR(vma);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
break; break;
} }
...@@ -725,7 +710,7 @@ int live_rps_frequency_cs(void *arg) ...@@ -725,7 +710,7 @@ int live_rps_frequency_cs(void *arg)
i915_vma_unpin(vma); i915_vma_unpin(vma);
i915_vma_put(vma); i915_vma_put(vma);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
if (igt_flush_test(gt->i915)) if (igt_flush_test(gt->i915))
err = -EIO; err = -EIO;
if (err) if (err)
...@@ -779,14 +764,14 @@ int live_rps_frequency_srm(void *arg) ...@@ -779,14 +764,14 @@ int live_rps_frequency_srm(void *arg)
int freq; int freq;
} min, max; } min, max;
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
vma = create_spin_counter(engine, vma = create_spin_counter(engine,
engine->kernel_context->vm, true, engine->kernel_context->vm, true,
&cancel, &cntr); &cancel, &cntr);
if (IS_ERR(vma)) { if (IS_ERR(vma)) {
err = PTR_ERR(vma); err = PTR_ERR(vma);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
break; break;
} }
...@@ -866,7 +851,7 @@ int live_rps_frequency_srm(void *arg) ...@@ -866,7 +851,7 @@ int live_rps_frequency_srm(void *arg)
i915_vma_unpin(vma); i915_vma_unpin(vma);
i915_vma_put(vma); i915_vma_put(vma);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
if (igt_flush_test(gt->i915)) if (igt_flush_test(gt->i915))
err = -EIO; err = -EIO;
if (err) if (err)
...@@ -1061,11 +1046,11 @@ int live_rps_interrupt(void *arg) ...@@ -1061,11 +1046,11 @@ int live_rps_interrupt(void *arg)
intel_gt_pm_wait_for_idle(engine->gt); intel_gt_pm_wait_for_idle(engine->gt);
GEM_BUG_ON(intel_rps_is_active(rps)); GEM_BUG_ON(intel_rps_is_active(rps));
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
err = __rps_up_interrupt(rps, engine, &spin); err = __rps_up_interrupt(rps, engine, &spin);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
if (err) if (err)
goto out; goto out;
...@@ -1074,13 +1059,13 @@ int live_rps_interrupt(void *arg) ...@@ -1074,13 +1059,13 @@ int live_rps_interrupt(void *arg)
/* Keep the engine awake but idle and check for DOWN */ /* Keep the engine awake but idle and check for DOWN */
if (pm_events & GEN6_PM_RP_DOWN_THRESHOLD) { if (pm_events & GEN6_PM_RP_DOWN_THRESHOLD) {
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
intel_rc6_disable(&gt->rc6); intel_rc6_disable(&gt->rc6);
err = __rps_down_interrupt(rps, engine); err = __rps_down_interrupt(rps, engine);
intel_rc6_enable(&gt->rc6); intel_rc6_enable(&gt->rc6);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
if (err) if (err)
goto out; goto out;
} }
...@@ -1165,13 +1150,13 @@ int live_rps_power(void *arg) ...@@ -1165,13 +1150,13 @@ int live_rps_power(void *arg)
if (!intel_engine_can_store_dword(engine)) if (!intel_engine_can_store_dword(engine))
continue; continue;
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
rq = igt_spinner_create_request(&spin, rq = igt_spinner_create_request(&spin,
engine->kernel_context, engine->kernel_context,
MI_NOOP); MI_NOOP);
if (IS_ERR(rq)) { if (IS_ERR(rq)) {
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
err = PTR_ERR(rq); err = PTR_ERR(rq);
break; break;
} }
...@@ -1182,7 +1167,7 @@ int live_rps_power(void *arg) ...@@ -1182,7 +1167,7 @@ int live_rps_power(void *arg)
pr_err("%s: RPS spinner did not start\n", pr_err("%s: RPS spinner did not start\n",
engine->name); engine->name);
igt_spinner_end(&spin); igt_spinner_end(&spin);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
intel_gt_set_wedged(engine->gt); intel_gt_set_wedged(engine->gt);
err = -EIO; err = -EIO;
break; break;
...@@ -1195,7 +1180,7 @@ int live_rps_power(void *arg) ...@@ -1195,7 +1180,7 @@ int live_rps_power(void *arg)
min.power = measure_power_at(rps, &min.freq); min.power = measure_power_at(rps, &min.freq);
igt_spinner_end(&spin); igt_spinner_end(&spin);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
pr_info("%s: min:%llumW @ %uMHz, max:%llumW @ %uMHz\n", pr_info("%s: min:%llumW @ %uMHz, max:%llumW @ %uMHz\n",
engine->name, engine->name,
...@@ -1252,6 +1237,11 @@ int live_rps_dynamic(void *arg) ...@@ -1252,6 +1237,11 @@ int live_rps_dynamic(void *arg)
if (igt_spinner_init(&spin, gt)) if (igt_spinner_init(&spin, gt))
return -ENOMEM; return -ENOMEM;
if (intel_rps_has_interrupts(rps))
pr_info("RPS has interrupt support\n");
if (intel_rps_uses_timer(rps))
pr_info("RPS has timer support\n");
for_each_engine(engine, gt, id) { for_each_engine(engine, gt, id) {
struct i915_request *rq; struct i915_request *rq;
struct { struct {
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "intel_gt.h" #include "intel_gt.h"
#include "intel_gt_requests.h" #include "intel_gt_requests.h"
#include "intel_ring.h" #include "intel_ring.h"
#include "selftest_engine_heartbeat.h"
#include "../selftests/i915_random.h" #include "../selftests/i915_random.h"
#include "../i915_selftest.h" #include "../i915_selftest.h"
...@@ -751,22 +752,6 @@ static int live_hwsp_wrap(void *arg) ...@@ -751,22 +752,6 @@ static int live_hwsp_wrap(void *arg)
return err; return err;
} }
static void engine_heartbeat_disable(struct intel_engine_cs *engine)
{
engine->props.heartbeat_interval_ms = 0;
intel_engine_pm_get(engine);
intel_engine_park_heartbeat(engine);
}
static void engine_heartbeat_enable(struct intel_engine_cs *engine)
{
intel_engine_pm_put(engine);
engine->props.heartbeat_interval_ms =
engine->defaults.heartbeat_interval_ms;
}
static int live_hwsp_rollover_kernel(void *arg) static int live_hwsp_rollover_kernel(void *arg)
{ {
struct intel_gt *gt = arg; struct intel_gt *gt = arg;
...@@ -785,7 +770,7 @@ static int live_hwsp_rollover_kernel(void *arg) ...@@ -785,7 +770,7 @@ static int live_hwsp_rollover_kernel(void *arg)
struct i915_request *rq[3] = {}; struct i915_request *rq[3] = {};
int i; int i;
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
if (intel_gt_wait_for_idle(gt, HZ / 2)) { if (intel_gt_wait_for_idle(gt, HZ / 2)) {
err = -EIO; err = -EIO;
goto out; goto out;
...@@ -836,7 +821,7 @@ static int live_hwsp_rollover_kernel(void *arg) ...@@ -836,7 +821,7 @@ static int live_hwsp_rollover_kernel(void *arg)
out: out:
for (i = 0; i < ARRAY_SIZE(rq); i++) for (i = 0; i < ARRAY_SIZE(rq); i++)
i915_request_put(rq[i]); i915_request_put(rq[i]);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
if (err) if (err)
break; break;
} }
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "gt/intel_engine_user.h" #include "gt/intel_engine_user.h"
#include "gt/intel_gt.h" #include "gt/intel_gt.h"
#include "gt/intel_gt_requests.h" #include "gt/intel_gt_requests.h"
#include "gt/selftest_engine_heartbeat.h"
#include "i915_random.h" #include "i915_random.h"
#include "i915_selftest.h" #include "i915_selftest.h"
...@@ -2270,22 +2271,6 @@ static void rps_unpin(struct intel_gt *gt) ...@@ -2270,22 +2271,6 @@ static void rps_unpin(struct intel_gt *gt)
atomic_dec(&gt->rps.num_waiters); atomic_dec(&gt->rps.num_waiters);
} }
static void engine_heartbeat_disable(struct intel_engine_cs *engine)
{
engine->props.heartbeat_interval_ms = 0;
intel_engine_pm_get(engine);
intel_engine_park_heartbeat(engine);
}
static void engine_heartbeat_enable(struct intel_engine_cs *engine)
{
intel_engine_pm_put(engine);
engine->props.heartbeat_interval_ms =
engine->defaults.heartbeat_interval_ms;
}
static int perf_request_latency(void *arg) static int perf_request_latency(void *arg)
{ {
struct drm_i915_private *i915 = arg; struct drm_i915_private *i915 = arg;
...@@ -2311,7 +2296,7 @@ static int perf_request_latency(void *arg) ...@@ -2311,7 +2296,7 @@ static int perf_request_latency(void *arg)
goto out; goto out;
} }
engine_heartbeat_disable(engine); st_engine_heartbeat_disable(engine);
rps_pin(engine->gt); rps_pin(engine->gt);
if (err == 0) if (err == 0)
...@@ -2330,7 +2315,7 @@ static int perf_request_latency(void *arg) ...@@ -2330,7 +2315,7 @@ static int perf_request_latency(void *arg)
err = measure_completion(ce); err = measure_completion(ce);
rps_unpin(engine->gt); rps_unpin(engine->gt);
engine_heartbeat_enable(engine); st_engine_heartbeat_enable(engine);
intel_context_unpin(ce); intel_context_unpin(ce);
intel_context_put(ce); intel_context_put(ce);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment