#include "intel_gt_requests.h"
 #include "i915_selftest.h"
+#include "selftest_engine_heartbeat.h"
 
 static int timeline_sync(struct intel_timeline *tl)
 {
        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)
 {
        struct intel_gt *gt = arg;
        /* Check that we can flush the idle barriers */
 
        for_each_engine(engine, gt, id) {
-               unsigned long heartbeat;
-
-               engine_heartbeat_disable(engine, &heartbeat);
+               st_engine_heartbeat_disable(engine);
                err = __live_idle_pulse(engine, intel_engine_flush_barriers);
-               engine_heartbeat_enable(engine, heartbeat);
+               st_engine_heartbeat_enable(engine);
                if (err)
                        break;
        }
        /* Check that heartbeat pulses flush the idle barriers */
 
        for_each_engine(engine, gt, id) {
-               unsigned long heartbeat;
-
-               engine_heartbeat_disable(engine, &heartbeat);
+               st_engine_heartbeat_disable(engine);
                err = __live_idle_pulse(engine, intel_engine_pulse);
-               engine_heartbeat_enable(engine, heartbeat);
+               st_engine_heartbeat_enable(engine);
                if (err && err != -ENODEV)
                        break;
 
        i915_modparams.enable_hangcheck = saved_hangcheck;
        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;
+}
 
--- /dev/null
+/* 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 */
 
 
 #include "i915_selftest.h"
 #include "selftest_engine.h"
+#include "selftest_engine_heartbeat.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)
 {
 int live_engine_pm_selftests(struct intel_gt *gt)
 {
        static const struct i915_subtest tests[] = {
+               SUBTEST(live_engine_busy_stats),
                SUBTEST(live_engine_pm),
        };
 
 
 #include "intel_gt.h"
 #include "intel_engine_heartbeat.h"
 #include "intel_engine_pm.h"
+#include "selftest_engine_heartbeat.h"
 
 #include "i915_selftest.h"
 #include "selftests/i915_random.h"
                          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)
 {
        struct intel_gt *gt = arg;
                reset_engine_count = i915_reset_engine_count(global, engine);
                count = 0;
 
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
                set_bit(I915_RESET_ENGINE + id, >->reset.flags);
                do {
                        int i;
                        }
                } while (time_before(jiffies, end_time));
                clear_bit(I915_RESET_ENGINE + id, >->reset.flags);
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
 
                pr_info("%s(%s): %d resets\n", __func__, engine->name, count);
 
                reset_count = i915_reset_count(global);
                reset_engine_count = i915_reset_engine_count(global, engine);
 
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
                set_bit(I915_RESET_ENGINE + id, >->reset.flags);
                do {
                        if (active) {
                        }
                } while (time_before(jiffies, end_time));
                clear_bit(I915_RESET_ENGINE + id, >->reset.flags);
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
 
                if (err)
                        break;
 
                yield(); /* start all threads before we begin */
 
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
                set_bit(I915_RESET_ENGINE + id, >->reset.flags);
                do {
                        struct i915_request *rq = NULL;
                        }
                } while (time_before(jiffies, end_time));
                clear_bit(I915_RESET_ENGINE + id, >->reset.flags);
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
 
                pr_info("i915_reset_engine(%s:%s): %lu resets\n",
                        engine->name, test_name, count);
 
 #include "gem/i915_gem_pm.h"
 #include "gt/intel_engine_heartbeat.h"
 #include "gt/intel_reset.h"
+#include "gt/selftest_engine_heartbeat.h"
 
 #include "i915_selftest.h"
 #include "selftests/i915_random.h"
        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)
 {
        if (i915_request_is_active(rq))
                        err = -EIO;
                        break;
                }
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
 
                for (n = 0; n < ARRAY_SIZE(ce); n++) {
                        struct intel_context *tmp;
                        intel_context_put(ce[n]);
                }
 
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
                if (igt_live_test_end(&t))
                        err = -EIO;
                if (err)
                        err = -EIO;
                        break;
                }
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
 
                for (n = 0; n < ARRAY_SIZE(ce); n++) {
                        struct intel_context *tmp;
                        intel_context_unpin(ce[n]);
                        intel_context_put(ce[n]);
                }
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
                if (igt_live_test_end(&t))
                        err = -EIO;
                if (err)
                        break;
                }
 
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
 
                rq = igt_spinner_create_request(&spin, ce, MI_ARB_CHECK);
                if (IS_ERR(rq)) {
                i915_request_put(rq);
 
 out:
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
                intel_context_put(ce);
                if (err)
                        break;
                const struct error_phase *p;
                int err = 0;
 
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
 
                for (p = phases; p->error[0] != GOOD; p++) {
                        struct i915_request *client[ARRAY_SIZE(phases->error)];
                        }
                }
 
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
                if (err) {
                        intel_gt_set_wedged(gt);
                        return err;
 
                memset(vaddr, 0, PAGE_SIZE);
 
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
                err = slice_semaphore_queue(engine, vma, 5);
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
                if (err)
                        goto err_pin;
 
                 * Expect execution/evaluation order XZY
                 */
 
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
                timeslice = xchg(&engine->props.timeslice_duration_ms, 1);
 
                slot = memset32(engine->status_page.addr + 1000, 0, 4);
                wmb();
 
                engine->props.timeslice_duration_ms = timeslice;
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
                for (i = 0; i < 3; i++)
                        i915_request_put(rq[i]);
                if (igt_flush_test(gt->i915))
                if (!intel_engine_has_preemption(engine))
                        continue;
 
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
                memset(vaddr, 0, PAGE_SIZE);
 
                /* ELSP[0]: semaphore wait */
 err_rq:
                i915_request_put(rq);
 err_heartbeat:
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
                if (err)
                        break;
        }
                        break;
                }
 
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
                timeslice = xchg(&engine->props.timeslice_duration_ms, 1);
 
                /* Create an unpreemptible spinner */
                igt_spinner_end(&spin);
 out_heartbeat:
                xchg(&engine->props.timeslice_duration_ms, timeslice);
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
                if (err)
                        break;
 
                if (igt_flush_test(gt->i915))
                        goto err_wedged;
 
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
                engine->execlists.preempt_hang.count = 0;
 
                rq_a = spinner_create_request(&a.spin,
                                              MI_NOOP);
                if (IS_ERR(rq_a)) {
                        err = PTR_ERR(rq_a);
-                       engine_heartbeat_enable(engine);
+                       st_engine_heartbeat_enable(engine);
                        goto err_client_b;
                }
 
                i915_request_add(rq_a);
                if (!igt_wait_for_spinner(&a.spin, rq_a)) {
                        pr_err("First client failed to start\n");
-                       engine_heartbeat_enable(engine);
+                       st_engine_heartbeat_enable(engine);
                        goto err_wedged;
                }
 
                                                      MI_NOOP);
                        if (IS_ERR(rq_b)) {
                                err = PTR_ERR(rq_b);
-                               engine_heartbeat_enable(engine);
+                               st_engine_heartbeat_enable(engine);
                                goto err_client_b;
                        }
                        i915_request_add(rq_b);
 
                        if (!igt_wait_for_spinner(&b.spin, rq_b)) {
                                pr_err("Second client failed to start\n");
-                               engine_heartbeat_enable(engine);
+                               st_engine_heartbeat_enable(engine);
                                goto err_wedged;
                        }
 
                               engine->name,
                               engine->execlists.preempt_hang.count,
                               depth);
-                       engine_heartbeat_enable(engine);
+                       st_engine_heartbeat_enable(engine);
                        err = -EINVAL;
                        goto err_client_b;
                }
 
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
                if (igt_flush_test(gt->i915))
                        goto err_wedged;
        }
                if (!intel_engine_can_store_dword(engine))
                        continue;
 
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
 
                for (n = 0; n <= 3; n++) {
                        err = __live_preempt_ring(engine, &spin,
                                break;
                }
 
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
                if (err)
                        break;
        }
        }
 
        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);
        if (IS_ERR(rq)) {
        i915_request_put(rq);
 out_heartbeat:
        for (n = 0; n < nsibling; n++)
-               engine_heartbeat_enable(siblings[n]);
+               st_engine_heartbeat_enable(siblings[n]);
 
        intel_context_put(ve);
 out_spin:
                return PTR_ERR(scratch);
 
        for_each_engine(engine, gt, id) {
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
 
                err = __live_lrc_gpr(engine, scratch, false);
                if (err)
                        goto err;
 
 err:
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
                if (igt_flush_test(gt->i915))
                        err = -EIO;
                if (err)
        for_each_engine(data.engine, gt, id) {
                int i, err = 0;
 
-               engine_heartbeat_disable(data.engine);
+               st_engine_heartbeat_disable(data.engine);
 
                for (i = 0; i < ARRAY_SIZE(data.ce); i++) {
                        struct intel_context *tmp;
                }
 
 err:
-               engine_heartbeat_enable(data.engine);
+               st_engine_heartbeat_enable(data.engine);
                for (i = 0; i < ARRAY_SIZE(data.ce); i++) {
                        if (!data.ce[i])
                                break;
 
 #include "intel_gt_clock_utils.h"
 #include "intel_gt_pm.h"
 #include "intel_rc6.h"
+#include "selftest_engine_heartbeat.h"
 #include "selftest_rps.h"
 #include "selftests/igt_flush_test.h"
 #include "selftests/igt_spinner.h"
 /* 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 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)
 {
 }
                if (!intel_engine_can_store_dword(engine))
                        continue;
 
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
 
                rq = igt_spinner_create_request(&spin,
                                                engine->kernel_context,
                                                MI_NOOP);
                if (IS_ERR(rq)) {
-                       engine_heartbeat_enable(engine);
+                       st_engine_heartbeat_enable(engine);
                        err = PTR_ERR(rq);
                        break;
                }
                        pr_err("%s: RPS spinner did not start\n",
                               engine->name);
                        igt_spinner_end(&spin);
-                       engine_heartbeat_enable(engine);
+                       st_engine_heartbeat_enable(engine);
                        intel_gt_set_wedged(engine->gt);
                        err = -EIO;
                        break;
                intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL);
 
                igt_spinner_end(&spin);
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
 
                if (err == 0) {
                        u64 time = intel_gt_pm_interval_to_ns(gt, cycles);
                if (!intel_engine_can_store_dword(engine))
                        continue;
 
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
 
                rq = igt_spinner_create_request(&spin,
                                                engine->kernel_context,
                        pr_err("%s: RPS spinner did not start\n",
                               engine->name);
                        igt_spinner_end(&spin);
-                       engine_heartbeat_enable(engine);
+                       st_engine_heartbeat_enable(engine);
                        intel_gt_set_wedged(engine->gt);
                        err = -EIO;
                        break;
                        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);
+                       st_engine_heartbeat_enable(engine);
                        show_pstate_limits(rps);
                        err = -EINVAL;
                        break;
                        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);
+                       st_engine_heartbeat_enable(engine);
                        show_pstate_limits(rps);
                        err = -EINVAL;
                        break;
                min_dt = ktime_sub(ktime_get(), min_dt);
 
                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",
                        engine->name,
                        int freq;
                } min, max;
 
-               engine_heartbeat_disable(engine);
+               st_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);
+                       st_engine_heartbeat_enable(engine);
                        break;
                }
 
                i915_vma_unpin(vma);
                i915_vma_put(vma);
 
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
                if (igt_flush_test(gt->i915))
                        err = -EIO;
                if (err)
                        int freq;
                } min, max;
 
-               engine_heartbeat_disable(engine);
+               st_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);
+                       st_engine_heartbeat_enable(engine);
                        break;
                }
 
                i915_vma_unpin(vma);
                i915_vma_put(vma);
 
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
                if (igt_flush_test(gt->i915))
                        err = -EIO;
                if (err)
                        intel_gt_pm_wait_for_idle(engine->gt);
                        GEM_BUG_ON(intel_rps_is_active(rps));
 
-                       engine_heartbeat_disable(engine);
+                       st_engine_heartbeat_disable(engine);
 
                        err = __rps_up_interrupt(rps, engine, &spin);
 
-                       engine_heartbeat_enable(engine);
+                       st_engine_heartbeat_enable(engine);
                        if (err)
                                goto out;
 
 
                /* Keep the engine awake but idle and check for DOWN */
                if (pm_events & GEN6_PM_RP_DOWN_THRESHOLD) {
-                       engine_heartbeat_disable(engine);
+                       st_engine_heartbeat_disable(engine);
                        intel_rc6_disable(>->rc6);
 
                        err = __rps_down_interrupt(rps, engine);
 
                        intel_rc6_enable(>->rc6);
-                       engine_heartbeat_enable(engine);
+                       st_engine_heartbeat_enable(engine);
                        if (err)
                                goto out;
                }
                if (!intel_engine_can_store_dword(engine))
                        continue;
 
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
 
                rq = igt_spinner_create_request(&spin,
                                                engine->kernel_context,
                                                MI_NOOP);
                if (IS_ERR(rq)) {
-                       engine_heartbeat_enable(engine);
+                       st_engine_heartbeat_enable(engine);
                        err = PTR_ERR(rq);
                        break;
                }
                        pr_err("%s: RPS spinner did not start\n",
                               engine->name);
                        igt_spinner_end(&spin);
-                       engine_heartbeat_enable(engine);
+                       st_engine_heartbeat_enable(engine);
                        intel_gt_set_wedged(engine->gt);
                        err = -EIO;
                        break;
                min.power = measure_power_at(rps, &min.freq);
 
                igt_spinner_end(&spin);
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
 
                pr_info("%s: min:%llumW @ %uMHz, max:%llumW @ %uMHz\n",
                        engine->name,
        if (igt_spinner_init(&spin, gt))
                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) {
                struct i915_request *rq;
                struct {
 
 #include "intel_gt.h"
 #include "intel_gt_requests.h"
 #include "intel_ring.h"
+#include "selftest_engine_heartbeat.h"
 
 #include "../selftests/i915_random.h"
 #include "../i915_selftest.h"
        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)
 {
        struct intel_gt *gt = arg;
                struct i915_request *rq[3] = {};
                int i;
 
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
                if (intel_gt_wait_for_idle(gt, HZ / 2)) {
                        err = -EIO;
                        goto out;
 out:
                for (i = 0; i < ARRAY_SIZE(rq); i++)
                        i915_request_put(rq[i]);
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
                if (err)
                        break;
        }
 
 #include "gt/intel_engine_user.h"
 #include "gt/intel_gt.h"
 #include "gt/intel_gt_requests.h"
+#include "gt/selftest_engine_heartbeat.h"
 
 #include "i915_random.h"
 #include "i915_selftest.h"
        atomic_dec(>->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)
 {
        struct drm_i915_private *i915 = arg;
                        goto out;
                }
 
-               engine_heartbeat_disable(engine);
+               st_engine_heartbeat_disable(engine);
                rps_pin(engine->gt);
 
                if (err == 0)
                        err = measure_completion(ce);
 
                rps_unpin(engine->gt);
-               engine_heartbeat_enable(engine);
+               st_engine_heartbeat_enable(engine);
 
                intel_context_unpin(ce);
                intel_context_put(ce);