root/drivers/gpu/drm/i915/selftests/i915_active.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __live_get
  2. __live_free
  3. __live_release
  4. __live_put
  5. __live_active
  6. __live_retire
  7. __live_alloc
  8. __live_active_setup
  9. live_active_wait
  10. live_active_retire
  11. i915_active_live_selftests

   1 /*
   2  * SPDX-License-Identifier: MIT
   3  *
   4  * Copyright © 2018 Intel Corporation
   5  */
   6 
   7 #include <linux/kref.h>
   8 
   9 #include "gem/i915_gem_pm.h"
  10 #include "gt/intel_gt.h"
  11 
  12 #include "i915_selftest.h"
  13 
  14 #include "igt_flush_test.h"
  15 #include "lib_sw_fence.h"
  16 
  17 struct live_active {
  18         struct i915_active base;
  19         struct kref ref;
  20         bool retired;
  21 };
  22 
  23 static void __live_get(struct live_active *active)
  24 {
  25         kref_get(&active->ref);
  26 }
  27 
  28 static void __live_free(struct live_active *active)
  29 {
  30         i915_active_fini(&active->base);
  31         kfree(active);
  32 }
  33 
  34 static void __live_release(struct kref *ref)
  35 {
  36         struct live_active *active = container_of(ref, typeof(*active), ref);
  37 
  38         __live_free(active);
  39 }
  40 
  41 static void __live_put(struct live_active *active)
  42 {
  43         kref_put(&active->ref, __live_release);
  44 }
  45 
  46 static int __live_active(struct i915_active *base)
  47 {
  48         struct live_active *active = container_of(base, typeof(*active), base);
  49 
  50         __live_get(active);
  51         return 0;
  52 }
  53 
  54 static void __live_retire(struct i915_active *base)
  55 {
  56         struct live_active *active = container_of(base, typeof(*active), base);
  57 
  58         active->retired = true;
  59         __live_put(active);
  60 }
  61 
  62 static struct live_active *__live_alloc(struct drm_i915_private *i915)
  63 {
  64         struct live_active *active;
  65 
  66         active = kzalloc(sizeof(*active), GFP_KERNEL);
  67         if (!active)
  68                 return NULL;
  69 
  70         kref_init(&active->ref);
  71         i915_active_init(i915, &active->base, __live_active, __live_retire);
  72 
  73         return active;
  74 }
  75 
  76 static struct live_active *
  77 __live_active_setup(struct drm_i915_private *i915)
  78 {
  79         struct intel_engine_cs *engine;
  80         struct i915_sw_fence *submit;
  81         struct live_active *active;
  82         enum intel_engine_id id;
  83         unsigned int count = 0;
  84         int err = 0;
  85 
  86         active = __live_alloc(i915);
  87         if (!active)
  88                 return ERR_PTR(-ENOMEM);
  89 
  90         submit = heap_fence_create(GFP_KERNEL);
  91         if (!submit) {
  92                 kfree(active);
  93                 return ERR_PTR(-ENOMEM);
  94         }
  95 
  96         err = i915_active_acquire(&active->base);
  97         if (err)
  98                 goto out;
  99 
 100         for_each_engine(engine, i915, id) {
 101                 struct i915_request *rq;
 102 
 103                 rq = i915_request_create(engine->kernel_context);
 104                 if (IS_ERR(rq)) {
 105                         err = PTR_ERR(rq);
 106                         break;
 107                 }
 108 
 109                 err = i915_sw_fence_await_sw_fence_gfp(&rq->submit,
 110                                                        submit,
 111                                                        GFP_KERNEL);
 112                 if (err >= 0)
 113                         err = i915_active_ref(&active->base, rq->timeline, rq);
 114                 i915_request_add(rq);
 115                 if (err) {
 116                         pr_err("Failed to track active ref!\n");
 117                         break;
 118                 }
 119 
 120                 count++;
 121         }
 122 
 123         i915_active_release(&active->base);
 124         if (active->retired && count) {
 125                 pr_err("i915_active retired before submission!\n");
 126                 err = -EINVAL;
 127         }
 128         if (atomic_read(&active->base.count) != count) {
 129                 pr_err("i915_active not tracking all requests, found %d, expected %d\n",
 130                        atomic_read(&active->base.count), count);
 131                 err = -EINVAL;
 132         }
 133 
 134 out:
 135         i915_sw_fence_commit(submit);
 136         heap_fence_put(submit);
 137         if (err) {
 138                 __live_put(active);
 139                 active = ERR_PTR(err);
 140         }
 141 
 142         return active;
 143 }
 144 
 145 static int live_active_wait(void *arg)
 146 {
 147         struct drm_i915_private *i915 = arg;
 148         struct live_active *active;
 149         intel_wakeref_t wakeref;
 150         int err = 0;
 151 
 152         /* Check that we get a callback when requests retire upon waiting */
 153 
 154         mutex_lock(&i915->drm.struct_mutex);
 155         wakeref = intel_runtime_pm_get(&i915->runtime_pm);
 156 
 157         active = __live_active_setup(i915);
 158         if (IS_ERR(active)) {
 159                 err = PTR_ERR(active);
 160                 goto err;
 161         }
 162 
 163         i915_active_wait(&active->base);
 164         if (!active->retired) {
 165                 pr_err("i915_active not retired after waiting!\n");
 166                 err = -EINVAL;
 167         }
 168 
 169         __live_put(active);
 170 
 171         if (igt_flush_test(i915, I915_WAIT_LOCKED))
 172                 err = -EIO;
 173 
 174 err:
 175         intel_runtime_pm_put(&i915->runtime_pm, wakeref);
 176         mutex_unlock(&i915->drm.struct_mutex);
 177 
 178         return err;
 179 }
 180 
 181 static int live_active_retire(void *arg)
 182 {
 183         struct drm_i915_private *i915 = arg;
 184         struct live_active *active;
 185         intel_wakeref_t wakeref;
 186         int err = 0;
 187 
 188         /* Check that we get a callback when requests are indirectly retired */
 189 
 190         mutex_lock(&i915->drm.struct_mutex);
 191         wakeref = intel_runtime_pm_get(&i915->runtime_pm);
 192 
 193         active = __live_active_setup(i915);
 194         if (IS_ERR(active)) {
 195                 err = PTR_ERR(active);
 196                 goto err;
 197         }
 198 
 199         /* waits for & retires all requests */
 200         if (igt_flush_test(i915, I915_WAIT_LOCKED))
 201                 err = -EIO;
 202 
 203         if (!active->retired) {
 204                 pr_err("i915_active not retired after flushing!\n");
 205                 err = -EINVAL;
 206         }
 207 
 208         __live_put(active);
 209 
 210 err:
 211         intel_runtime_pm_put(&i915->runtime_pm, wakeref);
 212         mutex_unlock(&i915->drm.struct_mutex);
 213 
 214         return err;
 215 }
 216 
 217 int i915_active_live_selftests(struct drm_i915_private *i915)
 218 {
 219         static const struct i915_subtest tests[] = {
 220                 SUBTEST(live_active_wait),
 221                 SUBTEST(live_active_retire),
 222         };
 223 
 224         if (intel_gt_is_wedged(&i915->gt))
 225                 return 0;
 226 
 227         return i915_subtests(tests, i915);
 228 }

/* [<][>][^][v][top][bottom][index][help] */