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