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, 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_async(engine); 55 intel_engine_pm_put_async(engine); 56 p->critical_section_end(); 57 58 intel_engine_pm_flush(engine); 59 60 if (intel_engine_pm_is_awake(engine)) { 61 pr_err("%s is still awake after flushing pm\n", 62 engine->name); 63 return -EINVAL; 64 } 65 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"); 69 return -EINVAL; 70 } 71 } 72 } 73 74 return 0; 75 } 76 77 int live_engine_pm_selftests(struct intel_gt *gt) 78 { 79 static const struct i915_subtest tests[] = { 80 SUBTEST(live_engine_pm), 81 }; 82 83 return intel_gt_live_subtests(tests, gt); 84 } 85