1 /* 2 * SPDX-License-Identifier: GPL-2.0 3 * 4 * Copyright © 2018 Intel Corporation 5 */ 6 7 #include "i915_selftest.h" 8 #include "selftest_engine.h" 9 #include "selftests/igt_atomic.h" 10 11 static int live_engine_pm(void *arg) 12 { 13 struct intel_gt *gt = arg; 14 struct intel_engine_cs *engine; 15 enum intel_engine_id id; 16 17 /* 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 20 * tell us. 21 */ 22 if (intel_gt_pm_wait_for_idle(gt)) { 23 pr_err("Unable to flush GT pm before test\n"); 24 return -EBUSY; 25 } 26 27 GEM_BUG_ON(intel_gt_pm_is_awake(gt)); 28 for_each_engine(engine, gt->i915, id) { 29 const typeof(*igt_atomic_phases) *p; 30 31 for (p = igt_atomic_phases; p->name; p++) { 32 /* 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. 37 * 38 * In practice, 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. 45 */ 46 GEM_BUG_ON(intel_engine_pm_is_awake(engine)); 47 intel_engine_pm_get(engine); 48 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); 53 else 54 intel_engine_pm_put(engine); 55 intel_engine_pm_put(engine); 56 p->critical_section_end(); 57 58 /* engine wakeref is sync (instant) */ 59 if (intel_engine_pm_is_awake(engine)) { 60 pr_err("%s is still awake after flushing pm\n", 61 engine->name); 62 return -EINVAL; 63 } 64 65 /* gt wakeref is async (deferred to workqueue) */ 66 if (intel_gt_pm_wait_for_idle(gt)) { 67 pr_err("GT failed to idle\n"); 68 return -EINVAL; 69 } 70 } 71 } 72 73 return 0; 74 } 75 76 int live_engine_pm_selftests(struct intel_gt *gt) 77 { 78 static const struct i915_subtest tests[] = { 79 SUBTEST(live_engine_pm), 80 }; 81 82 return intel_gt_live_subtests(tests, gt); 83 } 84