1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright �� 2019 Intel Corporation 4 */ 5 6 #include "selftests/igt_spinner.h" 7 #include "selftests/igt_reset.h" 8 #include "selftests/intel_scheduler_helpers.h" 9 #include "gt/intel_engine_heartbeat.h" 10 #include "gem/selftests/mock_context.h" 11 12 static void logical_sort(struct intel_engine_cs **engines, int num_engines) 13 { 14 struct intel_engine_cs *sorted[MAX_ENGINE_INSTANCE + 1]; 15 int i, j; 16 17 for (i = 0; i < num_engines; ++i) 18 for (j = 0; j < MAX_ENGINE_INSTANCE + 1; ++j) { 19 if (engines[j]->logical_mask & BIT(i)) { 20 sorted[i] = engines[j]; 21 break; 22 } 23 } 24 25 memcpy(*engines, *sorted, 26 sizeof(struct intel_engine_cs *) * num_engines); 27 } 28 29 static struct intel_context * 30 multi_lrc_create_parent(struct intel_gt *gt, u8 class, 31 unsigned long flags) 32 { 33 struct intel_engine_cs *siblings[MAX_ENGINE_INSTANCE + 1]; 34 struct intel_engine_cs *engine; 35 enum intel_engine_id id; 36 int i = 0; 37 38 for_each_engine(engine, gt, id) { 39 if (engine->class != class) 40 continue; 41 42 siblings[i++] = engine; 43 } 44 45 if (i <= 1) 46 return ERR_PTR(0); 47 48 logical_sort(siblings, i); 49 50 return intel_engine_create_parallel(siblings, 1, i); 51 } 52 53 static void multi_lrc_context_unpin(struct intel_context *ce) 54 { 55 struct intel_context *child; 56 57 GEM_BUG_ON(!intel_context_is_parent(ce)); 58 59 for_each_child(ce, child) 60 intel_context_unpin(child); 61 intel_context_unpin(ce); 62 } 63 64 static void multi_lrc_context_put(struct intel_context *ce) 65 { 66 GEM_BUG_ON(!intel_context_is_parent(ce)); 67 68 /* 69 * Only the parent gets the creation ref put in the uAPI, the parent 70 * itself is responsible for creation ref put on the children. 71 */ 72 intel_context_put(ce); 73 } 74 75 static struct i915_request * 76 multi_lrc_nop_request(struct intel_context *ce) 77 { 78 struct intel_context *child; 79 struct i915_request *rq, *child_rq; 80 int i = 0; 81 82 GEM_BUG_ON(!intel_context_is_parent(ce)); 83 84 rq = intel_context_create_request(ce); 85 if (IS_ERR(rq)) 86 return rq; 87 88 i915_request_get(rq); 89 i915_request_add(rq); 90 91 for_each_child(ce, child) { 92 child_rq = intel_context_create_request(child); 93 if (IS_ERR(child_rq)) 94 goto child_error; 95 96 if (++i == ce->parallel.number_children) 97 set_bit(I915_FENCE_FLAG_SUBMIT_PARALLEL, 98 &child_rq->fence.flags); 99 i915_request_add(child_rq); 100 } 101 102 return rq; 103 104 child_error: 105 i915_request_put(rq); 106 107 return ERR_PTR(-ENOMEM); 108 } 109 110 static int __intel_guc_multi_lrc_basic(struct intel_gt *gt, unsigned int class) 111 { 112 struct intel_context *parent; 113 struct i915_request *rq; 114 int ret; 115 116 parent = multi_lrc_create_parent(gt, class, 0); 117 if (IS_ERR(parent)) { 118 pr_err("Failed creating contexts: %ld", PTR_ERR(parent)); 119 return PTR_ERR(parent); 120 } else if (!parent) { 121 pr_debug("Not enough engines in class: %d", class); 122 return 0; 123 } 124 125 rq = multi_lrc_nop_request(parent); 126 if (IS_ERR(rq)) { 127 ret = PTR_ERR(rq); 128 pr_err("Failed creating requests: %d", ret); 129 goto out; 130 } 131 132 ret = intel_selftest_wait_for_rq(rq); 133 if (ret) 134 pr_err("Failed waiting on request: %d", ret); 135 136 i915_request_put(rq); 137 138 if (ret >= 0) { 139 ret = intel_gt_wait_for_idle(gt, HZ * 5); 140 if (ret < 0) 141 pr_err("GT failed to idle: %d\n", ret); 142 } 143 144 out: 145 multi_lrc_context_unpin(parent); 146 multi_lrc_context_put(parent); 147 return ret; 148 } 149 150 static int intel_guc_multi_lrc_basic(void *arg) 151 { 152 struct intel_gt *gt = arg; 153 unsigned int class; 154 int ret; 155 156 for (class = 0; class < MAX_ENGINE_CLASS + 1; ++class) { 157 ret = __intel_guc_multi_lrc_basic(gt, class); 158 if (ret) 159 return ret; 160 } 161 162 return 0; 163 } 164 165 int intel_guc_multi_lrc_live_selftests(struct drm_i915_private *i915) 166 { 167 static const struct i915_subtest tests[] = { 168 SUBTEST(intel_guc_multi_lrc_basic), 169 }; 170 struct intel_gt *gt = &i915->gt; 171 172 if (intel_gt_is_wedged(gt)) 173 return 0; 174 175 if (!intel_uc_uses_guc_submission(>->uc)) 176 return 0; 177 178 return intel_gt_live_subtests(tests, gt); 179 } 180