| // SPDX-License-Identifier: MIT |
| /* |
| * Copyright �� 2021 Intel Corporation |
| */ |
| |
| #include "selftests/intel_scheduler_helpers.h" |
| |
| static struct i915_request *nop_user_request(struct intel_context *ce, |
| struct i915_request *from) |
| { |
| struct i915_request *rq; |
| int ret; |
| |
| rq = intel_context_create_request(ce); |
| if (IS_ERR(rq)) |
| return rq; |
| |
| if (from) { |
| ret = i915_sw_fence_await_dma_fence(&rq->submit, |
| &from->fence, 0, |
| I915_FENCE_GFP); |
| if (ret < 0) { |
| i915_request_put(rq); |
| return ERR_PTR(ret); |
| } |
| } |
| |
| i915_request_get(rq); |
| i915_request_add(rq); |
| |
| return rq; |
| } |
| |
| static int intel_guc_scrub_ctbs(void *arg) |
| { |
| struct intel_gt *gt = arg; |
| int ret = 0; |
| int i; |
| struct i915_request *last[3] = {NULL, NULL, NULL}, *rq; |
| intel_wakeref_t wakeref; |
| struct intel_engine_cs *engine; |
| struct intel_context *ce; |
| |
| wakeref = intel_runtime_pm_get(gt->uncore->rpm); |
| engine = intel_selftest_find_any_engine(gt); |
| |
| /* Submit requests and inject errors forcing G2H to be dropped */ |
| for (i = 0; i < 3; ++i) { |
| ce = intel_context_create(engine); |
| if (IS_ERR(ce)) { |
| ret = PTR_ERR(ce); |
| pr_err("Failed to create context, %d: %d\n", i, ret); |
| goto err; |
| } |
| |
| switch (i) { |
| case 0: |
| ce->drop_schedule_enable = true; |
| break; |
| case 1: |
| ce->drop_schedule_disable = true; |
| break; |
| case 2: |
| ce->drop_deregister = true; |
| break; |
| } |
| |
| rq = nop_user_request(ce, NULL); |
| intel_context_put(ce); |
| |
| if (IS_ERR(rq)) { |
| ret = PTR_ERR(rq); |
| pr_err("Failed to create request, %d: %d\n", i, ret); |
| goto err; |
| } |
| |
| last[i] = rq; |
| } |
| |
| for (i = 0; i < 3; ++i) { |
| ret = i915_request_wait(last[i], 0, HZ); |
| if (ret < 0) { |
| pr_err("Last request failed to complete: %d\n", ret); |
| goto err; |
| } |
| i915_request_put(last[i]); |
| last[i] = NULL; |
| } |
| |
| /* Force all H2G / G2H to be submitted / processed */ |
| intel_gt_retire_requests(gt); |
| msleep(500); |
| |
| /* Scrub missing G2H */ |
| intel_gt_handle_error(engine->gt, -1, 0, "selftest reset"); |
| |
| /* GT will not idle if G2H are lost */ |
| ret = intel_gt_wait_for_idle(gt, HZ); |
| if (ret < 0) { |
| pr_err("GT failed to idle: %d\n", ret); |
| goto err; |
| } |
| |
| err: |
| for (i = 0; i < 3; ++i) |
| if (last[i]) |
| i915_request_put(last[i]); |
| intel_runtime_pm_put(gt->uncore->rpm, wakeref); |
| |
| return ret; |
| } |
| |
| int intel_guc_live_selftests(struct drm_i915_private *i915) |
| { |
| static const struct i915_subtest tests[] = { |
| SUBTEST(intel_guc_scrub_ctbs), |
| }; |
| struct intel_gt *gt = &i915->gt; |
| |
| if (intel_gt_is_wedged(gt)) |
| return 0; |
| |
| if (!intel_uc_uses_guc_submission(>->uc)) |
| return 0; |
| |
| return intel_gt_live_subtests(tests, gt); |
| } |