Once again extract the context in/out accounting for use elsewhere, and
add a selftest to check that the busy-stats are being reported
correctly. Other than keep userspace informed, the busy-stats are a
funamental building block for activity tracking such as RPS.

Signed-off-by: Chris Wilson <[email protected]>
---
 drivers/gpu/drm/i915/gt/intel_engine_stats.h | 49 +++++++++++
 drivers/gpu/drm/i915/gt/intel_lrc.c          | 34 +-------
 drivers/gpu/drm/i915/gt/selftest_engine_pm.c | 91 ++++++++++++++++++++
 drivers/gpu/drm/i915/gt/selftest_rps.c       |  5 ++
 4 files changed, 146 insertions(+), 33 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gt/intel_engine_stats.h

diff --git a/drivers/gpu/drm/i915/gt/intel_engine_stats.h 
b/drivers/gpu/drm/i915/gt/intel_engine_stats.h
new file mode 100644
index 000000000000..58491eae3482
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/intel_engine_stats.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#ifndef __INTEL_ENGINE_STATS_H__
+#define __INTEL_ENGINE_STATS_H__
+
+#include <linux/atomic.h>
+#include <linux/ktime.h>
+#include <linux/seqlock.h>
+
+#include "i915_gem.h" /* GEM_BUG_ON */
+#include "intel_engine.h"
+
+static inline void intel_engine_context_in(struct intel_engine_cs *engine)
+{
+       unsigned long flags;
+
+       if (atomic_add_unless(&engine->stats.active, 1, 0))
+               return;
+
+       write_seqlock_irqsave(&engine->stats.lock, flags);
+       if (!atomic_add_unless(&engine->stats.active, 1, 0)) {
+               engine->stats.start = ktime_get();
+               atomic_inc(&engine->stats.active);
+       }
+       write_sequnlock_irqrestore(&engine->stats.lock, flags);
+}
+
+static inline void intel_engine_context_out(struct intel_engine_cs *engine)
+{
+       unsigned long flags;
+
+       GEM_BUG_ON(!atomic_read(&engine->stats.active));
+
+       if (atomic_add_unless(&engine->stats.active, -1, 1))
+               return;
+
+       write_seqlock_irqsave(&engine->stats.lock, flags);
+       if (atomic_dec_and_test(&engine->stats.active)) {
+               engine->stats.total =
+                       ktime_add(engine->stats.total,
+                                 ktime_sub(ktime_get(), engine->stats.start));
+       }
+       write_sequnlock_irqrestore(&engine->stats.lock, flags);
+}
+
+#endif /* __INTEL_ENGINE_STATS_H__ */
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c 
b/drivers/gpu/drm/i915/gt/intel_lrc.c
index d55a5e0466e5..36e2ce4ac2fa 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -139,6 +139,7 @@
 #include "i915_vgpu.h"
 #include "intel_context.h"
 #include "intel_engine_pm.h"
+#include "intel_engine_stats.h"
 #include "intel_gt.h"
 #include "intel_gt_pm.h"
 #include "intel_gt_requests.h"
@@ -1187,39 +1188,6 @@ execlists_context_status_change(struct i915_request *rq, 
unsigned long status)
                                   status, rq);
 }
 
-static void intel_engine_context_in(struct intel_engine_cs *engine)
-{
-       unsigned long flags;
-
-       if (atomic_add_unless(&engine->stats.active, 1, 0))
-               return;
-
-       write_seqlock_irqsave(&engine->stats.lock, flags);
-       if (!atomic_add_unless(&engine->stats.active, 1, 0)) {
-               engine->stats.start = ktime_get();
-               atomic_inc(&engine->stats.active);
-       }
-       write_sequnlock_irqrestore(&engine->stats.lock, flags);
-}
-
-static void intel_engine_context_out(struct intel_engine_cs *engine)
-{
-       unsigned long flags;
-
-       GEM_BUG_ON(!atomic_read(&engine->stats.active));
-
-       if (atomic_add_unless(&engine->stats.active, -1, 1))
-               return;
-
-       write_seqlock_irqsave(&engine->stats.lock, flags);
-       if (atomic_dec_and_test(&engine->stats.active)) {
-               engine->stats.total =
-                       ktime_add(engine->stats.total,
-                                 ktime_sub(ktime_get(), engine->stats.start));
-       }
-       write_sequnlock_irqrestore(&engine->stats.lock, flags);
-}
-
 static void
 execlists_check_context(const struct intel_context *ce,
                        const struct intel_engine_cs *engine)
diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_pm.c 
b/drivers/gpu/drm/i915/gt/selftest_engine_pm.c
index cbf6b0735272..a35737958735 100644
--- a/drivers/gpu/drm/i915/gt/selftest_engine_pm.c
+++ b/drivers/gpu/drm/i915/gt/selftest_engine_pm.c
@@ -7,6 +7,96 @@
 #include "i915_selftest.h"
 #include "selftest_engine.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 dt, de;
+
+               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;
+               }
+
+               preempt_disable();
+               dt = ktime_get();
+               de = intel_engine_get_busy_time(engine);
+               udelay(100);
+               dt = ktime_sub(ktime_get(), dt);
+               de = ktime_sub(intel_engine_get_busy_time(engine), de);
+               preempt_enable();
+               if (de > 10) {
+                       pr_err("%s: reported %lldns [%d%%] busyness while 
sleeping [for %lldns]\n",
+                              engine->name,
+                              de, (int)div64_u64(100 * de, dt), dt);
+                       err = -EINVAL;
+                       break;
+               }
+
+               rq = igt_spinner_create_request(&spin,
+                                               engine->kernel_context,
+                                               MI_NOOP);
+               if (IS_ERR(rq)) {
+                       err = PTR_ERR(rq);
+                       break;
+               }
+               i915_request_add(rq);
+
+               if (!igt_wait_for_spinner(&spin, rq)) {
+                       intel_gt_set_wedged(engine->gt);
+                       err = -ETIME;
+                       break;
+               }
+
+               preempt_disable();
+               dt = ktime_get();
+               de = intel_engine_get_busy_time(engine);
+               udelay(100);
+               dt = ktime_sub(ktime_get(), dt);
+               de = ktime_sub(intel_engine_get_busy_time(engine), de);
+               preempt_enable();
+               if (100 * de < 95 * dt) {
+                       pr_err("%s: reported only %lldns [%d%%] busyness while 
spinning [for %lldns]\n",
+                              engine->name,
+                              de, (int)div64_u64(100 * de, dt), dt);
+                       GEM_TRACE_DUMP();
+                       err = -EINVAL;
+                       break;
+               }
+
+               igt_spinner_end(&spin);
+               if (igt_flush_test(gt->i915)) {
+                       err = -EIO;
+                       break;
+               }
+       }
+
+       igt_spinner_fini(&spin);
+       return err;
+}
 
 static int live_engine_pm(void *arg)
 {
@@ -77,6 +167,7 @@ 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),
        };
 
diff --git a/drivers/gpu/drm/i915/gt/selftest_rps.c 
b/drivers/gpu/drm/i915/gt/selftest_rps.c
index 5049c3dd08a6..5e364fb31aea 100644
--- a/drivers/gpu/drm/i915/gt/selftest_rps.c
+++ b/drivers/gpu/drm/i915/gt/selftest_rps.c
@@ -1252,6 +1252,11 @@ int live_rps_dynamic(void *arg)
        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 {
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to