root/drivers/gpu/drm/i915/gt/intel_context.c

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

DEFINITIONS

This source file includes following definitions.
  1. intel_context_alloc
  2. intel_context_free
  3. intel_context_create
  4. __intel_context_do_pin
  5. intel_context_unpin
  6. __context_pin_state
  7. __context_unpin_state
  8. __intel_context_retire
  9. __intel_context_active
  10. intel_context_active_acquire
  11. intel_context_active_release
  12. intel_context_init
  13. intel_context_fini
  14. i915_global_context_shrink
  15. i915_global_context_exit
  16. i915_global_context_init
  17. intel_context_enter_engine
  18. intel_context_exit_engine
  19. intel_context_prepare_remote_request
  20. intel_context_create_request

   1 /*
   2  * SPDX-License-Identifier: MIT
   3  *
   4  * Copyright © 2019 Intel Corporation
   5  */
   6 
   7 #include "gem/i915_gem_context.h"
   8 #include "gem/i915_gem_pm.h"
   9 
  10 #include "i915_drv.h"
  11 #include "i915_globals.h"
  12 
  13 #include "intel_context.h"
  14 #include "intel_engine.h"
  15 #include "intel_engine_pm.h"
  16 
  17 static struct i915_global_context {
  18         struct i915_global base;
  19         struct kmem_cache *slab_ce;
  20 } global;
  21 
  22 static struct intel_context *intel_context_alloc(void)
  23 {
  24         return kmem_cache_zalloc(global.slab_ce, GFP_KERNEL);
  25 }
  26 
  27 void intel_context_free(struct intel_context *ce)
  28 {
  29         kmem_cache_free(global.slab_ce, ce);
  30 }
  31 
  32 struct intel_context *
  33 intel_context_create(struct i915_gem_context *ctx,
  34                      struct intel_engine_cs *engine)
  35 {
  36         struct intel_context *ce;
  37 
  38         ce = intel_context_alloc();
  39         if (!ce)
  40                 return ERR_PTR(-ENOMEM);
  41 
  42         intel_context_init(ce, ctx, engine);
  43         return ce;
  44 }
  45 
  46 int __intel_context_do_pin(struct intel_context *ce)
  47 {
  48         int err;
  49 
  50         if (mutex_lock_interruptible(&ce->pin_mutex))
  51                 return -EINTR;
  52 
  53         if (likely(!atomic_read(&ce->pin_count))) {
  54                 intel_wakeref_t wakeref;
  55 
  56                 if (unlikely(!test_bit(CONTEXT_ALLOC_BIT, &ce->flags))) {
  57                         err = ce->ops->alloc(ce);
  58                         if (unlikely(err))
  59                                 goto err;
  60 
  61                         __set_bit(CONTEXT_ALLOC_BIT, &ce->flags);
  62                 }
  63 
  64                 err = 0;
  65                 with_intel_runtime_pm(&ce->engine->i915->runtime_pm, wakeref)
  66                         err = ce->ops->pin(ce);
  67                 if (err)
  68                         goto err;
  69 
  70                 GEM_TRACE("%s context:%llx pin ring:{head:%04x, tail:%04x}\n",
  71                           ce->engine->name, ce->timeline->fence_context,
  72                           ce->ring->head, ce->ring->tail);
  73 
  74                 i915_gem_context_get(ce->gem_context); /* for ctx->ppgtt */
  75 
  76                 smp_mb__before_atomic(); /* flush pin before it is visible */
  77         }
  78 
  79         atomic_inc(&ce->pin_count);
  80         GEM_BUG_ON(!intel_context_is_pinned(ce)); /* no overflow! */
  81 
  82         mutex_unlock(&ce->pin_mutex);
  83         return 0;
  84 
  85 err:
  86         mutex_unlock(&ce->pin_mutex);
  87         return err;
  88 }
  89 
  90 void intel_context_unpin(struct intel_context *ce)
  91 {
  92         if (likely(atomic_add_unless(&ce->pin_count, -1, 1)))
  93                 return;
  94 
  95         /* We may be called from inside intel_context_pin() to evict another */
  96         intel_context_get(ce);
  97         mutex_lock_nested(&ce->pin_mutex, SINGLE_DEPTH_NESTING);
  98 
  99         if (likely(atomic_dec_and_test(&ce->pin_count))) {
 100                 GEM_TRACE("%s context:%llx retire\n",
 101                           ce->engine->name, ce->timeline->fence_context);
 102 
 103                 ce->ops->unpin(ce);
 104 
 105                 i915_gem_context_put(ce->gem_context);
 106                 intel_context_active_release(ce);
 107         }
 108 
 109         mutex_unlock(&ce->pin_mutex);
 110         intel_context_put(ce);
 111 }
 112 
 113 static int __context_pin_state(struct i915_vma *vma)
 114 {
 115         u64 flags;
 116         int err;
 117 
 118         flags = i915_ggtt_pin_bias(vma) | PIN_OFFSET_BIAS;
 119         flags |= PIN_HIGH | PIN_GLOBAL;
 120 
 121         err = i915_vma_pin(vma, 0, 0, flags);
 122         if (err)
 123                 return err;
 124 
 125         /*
 126          * And mark it as a globally pinned object to let the shrinker know
 127          * it cannot reclaim the object until we release it.
 128          */
 129         i915_vma_make_unshrinkable(vma);
 130         vma->obj->mm.dirty = true;
 131 
 132         return 0;
 133 }
 134 
 135 static void __context_unpin_state(struct i915_vma *vma)
 136 {
 137         __i915_vma_unpin(vma);
 138         i915_vma_make_shrinkable(vma);
 139 }
 140 
 141 static void __intel_context_retire(struct i915_active *active)
 142 {
 143         struct intel_context *ce = container_of(active, typeof(*ce), active);
 144 
 145         GEM_TRACE("%s context:%llx retire\n",
 146                   ce->engine->name, ce->timeline->fence_context);
 147 
 148         if (ce->state)
 149                 __context_unpin_state(ce->state);
 150 
 151         intel_timeline_unpin(ce->timeline);
 152         intel_ring_unpin(ce->ring);
 153         intel_context_put(ce);
 154 }
 155 
 156 static int __intel_context_active(struct i915_active *active)
 157 {
 158         struct intel_context *ce = container_of(active, typeof(*ce), active);
 159         int err;
 160 
 161         intel_context_get(ce);
 162 
 163         err = intel_ring_pin(ce->ring);
 164         if (err)
 165                 goto err_put;
 166 
 167         err = intel_timeline_pin(ce->timeline);
 168         if (err)
 169                 goto err_ring;
 170 
 171         if (!ce->state)
 172                 return 0;
 173 
 174         err = __context_pin_state(ce->state);
 175         if (err)
 176                 goto err_timeline;
 177 
 178         return 0;
 179 
 180 err_timeline:
 181         intel_timeline_unpin(ce->timeline);
 182 err_ring:
 183         intel_ring_unpin(ce->ring);
 184 err_put:
 185         intel_context_put(ce);
 186         return err;
 187 }
 188 
 189 int intel_context_active_acquire(struct intel_context *ce)
 190 {
 191         int err;
 192 
 193         err = i915_active_acquire(&ce->active);
 194         if (err)
 195                 return err;
 196 
 197         /* Preallocate tracking nodes */
 198         if (!i915_gem_context_is_kernel(ce->gem_context)) {
 199                 err = i915_active_acquire_preallocate_barrier(&ce->active,
 200                                                               ce->engine);
 201                 if (err) {
 202                         i915_active_release(&ce->active);
 203                         return err;
 204                 }
 205         }
 206 
 207         return 0;
 208 }
 209 
 210 void intel_context_active_release(struct intel_context *ce)
 211 {
 212         /* Nodes preallocated in intel_context_active() */
 213         i915_active_acquire_barrier(&ce->active);
 214         i915_active_release(&ce->active);
 215 }
 216 
 217 void
 218 intel_context_init(struct intel_context *ce,
 219                    struct i915_gem_context *ctx,
 220                    struct intel_engine_cs *engine)
 221 {
 222         GEM_BUG_ON(!engine->cops);
 223 
 224         kref_init(&ce->ref);
 225 
 226         ce->gem_context = ctx;
 227         ce->vm = i915_vm_get(ctx->vm ?: &engine->gt->ggtt->vm);
 228         if (ctx->timeline)
 229                 ce->timeline = intel_timeline_get(ctx->timeline);
 230 
 231         ce->engine = engine;
 232         ce->ops = engine->cops;
 233         ce->sseu = engine->sseu;
 234         ce->ring = __intel_context_ring_size(SZ_16K);
 235 
 236         INIT_LIST_HEAD(&ce->signal_link);
 237         INIT_LIST_HEAD(&ce->signals);
 238 
 239         mutex_init(&ce->pin_mutex);
 240 
 241         i915_active_init(ctx->i915, &ce->active,
 242                          __intel_context_active, __intel_context_retire);
 243 }
 244 
 245 void intel_context_fini(struct intel_context *ce)
 246 {
 247         if (ce->timeline)
 248                 intel_timeline_put(ce->timeline);
 249         i915_vm_put(ce->vm);
 250 
 251         mutex_destroy(&ce->pin_mutex);
 252         i915_active_fini(&ce->active);
 253 }
 254 
 255 static void i915_global_context_shrink(void)
 256 {
 257         kmem_cache_shrink(global.slab_ce);
 258 }
 259 
 260 static void i915_global_context_exit(void)
 261 {
 262         kmem_cache_destroy(global.slab_ce);
 263 }
 264 
 265 static struct i915_global_context global = { {
 266         .shrink = i915_global_context_shrink,
 267         .exit = i915_global_context_exit,
 268 } };
 269 
 270 int __init i915_global_context_init(void)
 271 {
 272         global.slab_ce = KMEM_CACHE(intel_context, SLAB_HWCACHE_ALIGN);
 273         if (!global.slab_ce)
 274                 return -ENOMEM;
 275 
 276         i915_global_register(&global.base);
 277         return 0;
 278 }
 279 
 280 void intel_context_enter_engine(struct intel_context *ce)
 281 {
 282         intel_engine_pm_get(ce->engine);
 283         intel_timeline_enter(ce->timeline);
 284 }
 285 
 286 void intel_context_exit_engine(struct intel_context *ce)
 287 {
 288         intel_timeline_exit(ce->timeline);
 289         intel_engine_pm_put(ce->engine);
 290 }
 291 
 292 int intel_context_prepare_remote_request(struct intel_context *ce,
 293                                          struct i915_request *rq)
 294 {
 295         struct intel_timeline *tl = ce->timeline;
 296         int err;
 297 
 298         /* Only suitable for use in remotely modifying this context */
 299         GEM_BUG_ON(rq->hw_context == ce);
 300 
 301         if (rq->timeline != tl) { /* beware timeline sharing */
 302                 err = mutex_lock_interruptible_nested(&tl->mutex,
 303                                                       SINGLE_DEPTH_NESTING);
 304                 if (err)
 305                         return err;
 306 
 307                 /* Queue this switch after current activity by this context. */
 308                 err = i915_active_request_set(&tl->last_request, rq);
 309                 mutex_unlock(&tl->mutex);
 310                 if (err)
 311                         return err;
 312         }
 313 
 314         /*
 315          * Guarantee context image and the timeline remains pinned until the
 316          * modifying request is retired by setting the ce activity tracker.
 317          *
 318          * But we only need to take one pin on the account of it. Or in other
 319          * words transfer the pinned ce object to tracked active request.
 320          */
 321         GEM_BUG_ON(i915_active_is_idle(&ce->active));
 322         return i915_active_ref(&ce->active, rq->timeline, rq);
 323 }
 324 
 325 struct i915_request *intel_context_create_request(struct intel_context *ce)
 326 {
 327         struct i915_request *rq;
 328         int err;
 329 
 330         err = intel_context_pin(ce);
 331         if (unlikely(err))
 332                 return ERR_PTR(err);
 333 
 334         rq = i915_request_create(ce);
 335         intel_context_unpin(ce);
 336 
 337         return rq;
 338 }
 339 
 340 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 341 #include "selftest_context.c"
 342 #endif

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