2 * SPDX-License-Identifier: GPL-2.0
4 * Copyright © 2018 Intel Corporation
7 #include "i915_selftest.h"
8 #include "selftest_engine.h"
9 #include "selftests/igt_atomic.h"
11 static int live_engine_pm(void *arg
)
13 struct intel_gt
*gt
= arg
;
14 struct intel_engine_cs
*engine
;
15 enum intel_engine_id id
;
18 * Check we can call intel_engine_pm_put from any context. No
19 * failures are reported directly, but if we mess up lockdep should
22 if (intel_gt_pm_wait_for_idle(gt
)) {
23 pr_err("Unable to flush GT pm before test\n");
27 GEM_BUG_ON(intel_gt_pm_is_awake(gt
));
28 for_each_engine(engine
, gt
, id
) {
29 const typeof(*igt_atomic_phases
) *p
;
31 for (p
= igt_atomic_phases
; p
->name
; p
++) {
33 * Acquisition is always synchronous, except if we
34 * know that the engine is already awake, in which
35 * case we should use intel_engine_pm_get_if_awake()
36 * to atomically grab the wakeref.
39 * intel_engine_pm_get();
40 * intel_engine_pm_put();
41 * occurs in one thread, while simultaneously
42 * intel_engine_pm_get_if_awake();
43 * intel_engine_pm_put();
44 * occurs from atomic context in another.
46 GEM_BUG_ON(intel_engine_pm_is_awake(engine
));
47 intel_engine_pm_get(engine
);
49 p
->critical_section_begin();
50 if (!intel_engine_pm_get_if_awake(engine
))
51 pr_err("intel_engine_pm_get_if_awake(%s) failed under %s\n",
52 engine
->name
, p
->name
);
54 intel_engine_pm_put_async(engine
);
55 intel_engine_pm_put_async(engine
);
56 p
->critical_section_end();
58 intel_engine_pm_flush(engine
);
60 if (intel_engine_pm_is_awake(engine
)) {
61 pr_err("%s is still awake after flushing pm\n",
66 /* gt wakeref is async (deferred to workqueue) */
67 if (intel_gt_pm_wait_for_idle(gt
)) {
68 pr_err("GT failed to idle\n");
77 int live_engine_pm_selftests(struct intel_gt
*gt
)
79 static const struct i915_subtest tests
[] = {
80 SUBTEST(live_engine_pm
),
83 return intel_gt_live_subtests(tests
, gt
);