2 * SPDX-License-Identifier: MIT
4 * Copyright © 2018 Intel Corporation
7 #include "../i915_selftest.h"
9 #include "igt_flush_test.h"
10 #include "lib_sw_fence.h"
13 struct i915_active base;
17 static void __live_active_retire(struct i915_active *base)
19 struct live_active *active = container_of(base, typeof(*active), base);
21 active->retired = true;
24 static int __live_active_setup(struct drm_i915_private *i915,
25 struct live_active *active)
27 struct intel_engine_cs *engine;
28 struct i915_sw_fence *submit;
29 enum intel_engine_id id;
30 unsigned int count = 0;
33 submit = heap_fence_create(GFP_KERNEL);
37 i915_active_init(i915, &active->base, __live_active_retire);
38 active->retired = false;
40 if (!i915_active_acquire(&active->base)) {
41 pr_err("First i915_active_acquire should report being idle\n");
46 for_each_engine(engine, i915, id) {
47 struct i915_request *rq;
49 rq = i915_request_create(engine->kernel_context);
55 err = i915_sw_fence_await_sw_fence_gfp(&rq->submit,
59 err = i915_active_ref(&active->base,
60 rq->fence.context, rq);
63 pr_err("Failed to track active ref!\n");
70 i915_active_release(&active->base);
71 if (active->retired && count) {
72 pr_err("i915_active retired before submission!\n");
75 if (active->base.count != count) {
76 pr_err("i915_active not tracking all requests, found %d, expected %d\n",
77 active->base.count, count);
82 i915_sw_fence_commit(submit);
83 heap_fence_put(submit);
88 static int live_active_wait(void *arg)
90 struct drm_i915_private *i915 = arg;
91 struct live_active active;
92 intel_wakeref_t wakeref;
95 /* Check that we get a callback when requests retire upon waiting */
97 mutex_lock(&i915->drm.struct_mutex);
98 wakeref = intel_runtime_pm_get(i915);
100 err = __live_active_setup(i915, &active);
102 i915_active_wait(&active.base);
103 if (!active.retired) {
104 pr_err("i915_active not retired after waiting!\n");
108 i915_active_fini(&active.base);
109 if (igt_flush_test(i915, I915_WAIT_LOCKED))
112 intel_runtime_pm_put(i915, wakeref);
113 mutex_unlock(&i915->drm.struct_mutex);
117 static int live_active_retire(void *arg)
119 struct drm_i915_private *i915 = arg;
120 struct live_active active;
121 intel_wakeref_t wakeref;
124 /* Check that we get a callback when requests are indirectly retired */
126 mutex_lock(&i915->drm.struct_mutex);
127 wakeref = intel_runtime_pm_get(i915);
129 err = __live_active_setup(i915, &active);
131 /* waits for & retires all requests */
132 if (igt_flush_test(i915, I915_WAIT_LOCKED))
135 if (!active.retired) {
136 pr_err("i915_active not retired after flushing!\n");
140 i915_active_fini(&active.base);
141 intel_runtime_pm_put(i915, wakeref);
142 mutex_unlock(&i915->drm.struct_mutex);
146 int i915_active_live_selftests(struct drm_i915_private *i915)
148 static const struct i915_subtest tests[] = {
149 SUBTEST(live_active_wait),
150 SUBTEST(live_active_retire),
153 if (i915_terminally_wedged(i915))
156 return i915_subtests(tests, i915);