linux/drivers/gpu/drm/i915/gt/uc/selftest_guc_multi_lrc.c
<<
>>
Prefs
   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
  12static 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
  29static struct intel_context *
  30multi_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
  53static 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
  64static 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
  75static struct i915_request *
  76multi_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
 104child_error:
 105        i915_request_put(rq);
 106
 107        return ERR_PTR(-ENOMEM);
 108}
 109
 110static 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
 144out:
 145        multi_lrc_context_unpin(parent);
 146        multi_lrc_context_put(parent);
 147        return ret;
 148}
 149
 150static 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                /* We don't support breadcrumb handshake on these classes */
 158                if (class == COMPUTE_CLASS || class == RENDER_CLASS)
 159                        continue;
 160
 161                ret = __intel_guc_multi_lrc_basic(gt, class);
 162                if (ret)
 163                        return ret;
 164        }
 165
 166        return 0;
 167}
 168
 169int intel_guc_multi_lrc_live_selftests(struct drm_i915_private *i915)
 170{
 171        static const struct i915_subtest tests[] = {
 172                SUBTEST(intel_guc_multi_lrc_basic),
 173        };
 174        struct intel_gt *gt = to_gt(i915);
 175
 176        if (intel_gt_is_wedged(gt))
 177                return 0;
 178
 179        if (!intel_uc_uses_guc_submission(&gt->uc))
 180                return 0;
 181
 182        return intel_gt_live_subtests(tests, gt);
 183}
 184