Branch data Line data Source code
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 : : #include "intel_ring.h" 17 : : 18 : : static struct i915_global_context { 19 : : struct i915_global base; 20 : : struct kmem_cache *slab_ce; 21 : : } global; 22 : : 23 : 0 : static struct intel_context *intel_context_alloc(void) 24 : : { 25 : 0 : return kmem_cache_zalloc(global.slab_ce, GFP_KERNEL); 26 : : } 27 : : 28 : 0 : void intel_context_free(struct intel_context *ce) 29 : : { 30 : 0 : kmem_cache_free(global.slab_ce, ce); 31 : 0 : } 32 : : 33 : : struct intel_context * 34 : 0 : intel_context_create(struct intel_engine_cs *engine) 35 : : { 36 : 0 : struct intel_context *ce; 37 : : 38 : 0 : ce = intel_context_alloc(); 39 [ # # ]: 0 : if (!ce) 40 : : return ERR_PTR(-ENOMEM); 41 : : 42 : 0 : intel_context_init(ce, engine); 43 : 0 : return ce; 44 : : } 45 : : 46 : 0 : int intel_context_alloc_state(struct intel_context *ce) 47 : : { 48 : 0 : int err = 0; 49 : : 50 [ # # ]: 0 : if (mutex_lock_interruptible(&ce->pin_mutex)) 51 : : return -EINTR; 52 : : 53 [ # # ]: 0 : if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) { 54 : 0 : err = ce->ops->alloc(ce); 55 [ # # ]: 0 : if (unlikely(err)) 56 : 0 : goto unlock; 57 : : 58 : 0 : set_bit(CONTEXT_ALLOC_BIT, &ce->flags); 59 : : } 60 : : 61 : 0 : unlock: 62 : 0 : mutex_unlock(&ce->pin_mutex); 63 : 0 : return err; 64 : : } 65 : : 66 : 0 : static int intel_context_active_acquire(struct intel_context *ce) 67 : : { 68 : 0 : int err; 69 : : 70 : 0 : __i915_active_acquire(&ce->active); 71 : : 72 [ # # ]: 0 : if (intel_context_is_barrier(ce)) 73 : : return 0; 74 : : 75 : : /* Preallocate tracking nodes */ 76 : 0 : err = i915_active_acquire_preallocate_barrier(&ce->active, 77 : : ce->engine); 78 [ # # ]: 0 : if (err) 79 : 0 : i915_active_release(&ce->active); 80 : : 81 : : return err; 82 : : } 83 : : 84 : 0 : static void intel_context_active_release(struct intel_context *ce) 85 : : { 86 : : /* Nodes preallocated in intel_context_active() */ 87 : 0 : i915_active_acquire_barrier(&ce->active); 88 : 0 : i915_active_release(&ce->active); 89 : 0 : } 90 : : 91 : 0 : int __intel_context_do_pin(struct intel_context *ce) 92 : : { 93 : 0 : int err; 94 : : 95 [ # # ]: 0 : if (unlikely(!test_bit(CONTEXT_ALLOC_BIT, &ce->flags))) { 96 : 0 : err = intel_context_alloc_state(ce); 97 [ # # ]: 0 : if (err) 98 : : return err; 99 : : } 100 : : 101 : 0 : err = i915_active_acquire(&ce->active); 102 [ # # ]: 0 : if (err) 103 : : return err; 104 : : 105 [ # # ]: 0 : if (mutex_lock_interruptible(&ce->pin_mutex)) { 106 : 0 : err = -EINTR; 107 : 0 : goto out_release; 108 : : } 109 : : 110 [ # # ]: 0 : if (likely(!atomic_add_unless(&ce->pin_count, 1, 0))) { 111 : 0 : err = intel_context_active_acquire(ce); 112 [ # # ]: 0 : if (unlikely(err)) 113 : 0 : goto out_unlock; 114 : : 115 : 0 : err = ce->ops->pin(ce); 116 [ # # ]: 0 : if (unlikely(err)) 117 : 0 : goto err_active; 118 : : 119 : 0 : CE_TRACE(ce, "pin ring:{head:%04x, tail:%04x}\n", 120 : : ce->ring->head, ce->ring->tail); 121 : : 122 : 0 : smp_mb__before_atomic(); /* flush pin before it is visible */ 123 : 0 : atomic_inc(&ce->pin_count); 124 : : } 125 : : 126 : 0 : GEM_BUG_ON(!intel_context_is_pinned(ce)); /* no overflow! */ 127 : 0 : GEM_BUG_ON(i915_active_is_idle(&ce->active)); 128 : 0 : goto out_unlock; 129 : : 130 : : err_active: 131 : 0 : intel_context_active_release(ce); 132 : 0 : out_unlock: 133 : 0 : mutex_unlock(&ce->pin_mutex); 134 : 0 : out_release: 135 : 0 : i915_active_release(&ce->active); 136 : 0 : return err; 137 : : } 138 : : 139 : 0 : void intel_context_unpin(struct intel_context *ce) 140 : : { 141 [ # # ]: 0 : if (!atomic_dec_and_test(&ce->pin_count)) 142 : : return; 143 : : 144 : 0 : CE_TRACE(ce, "unpin\n"); 145 : 0 : ce->ops->unpin(ce); 146 : : 147 : : /* 148 : : * Once released, we may asynchronously drop the active reference. 149 : : * As that may be the only reference keeping the context alive, 150 : : * take an extra now so that it is not freed before we finish 151 : : * dereferencing it. 152 : : */ 153 : 0 : intel_context_get(ce); 154 : 0 : intel_context_active_release(ce); 155 : 0 : intel_context_put(ce); 156 : : } 157 : : 158 : 0 : static int __context_pin_state(struct i915_vma *vma) 159 : : { 160 : 0 : unsigned int bias = i915_ggtt_pin_bias(vma) | PIN_OFFSET_BIAS; 161 : 0 : int err; 162 : : 163 : 0 : err = i915_ggtt_pin(vma, 0, bias | PIN_HIGH); 164 [ # # ]: 0 : if (err) 165 : : return err; 166 : : 167 : 0 : err = i915_active_acquire(&vma->active); 168 [ # # ]: 0 : if (err) 169 : 0 : goto err_unpin; 170 : : 171 : : /* 172 : : * And mark it as a globally pinned object to let the shrinker know 173 : : * it cannot reclaim the object until we release it. 174 : : */ 175 : 0 : i915_vma_make_unshrinkable(vma); 176 : 0 : vma->obj->mm.dirty = true; 177 : : 178 : 0 : return 0; 179 : : 180 : : err_unpin: 181 : 0 : i915_vma_unpin(vma); 182 : 0 : return err; 183 : : } 184 : : 185 : 0 : static void __context_unpin_state(struct i915_vma *vma) 186 : : { 187 : 0 : i915_vma_make_shrinkable(vma); 188 : 0 : i915_active_release(&vma->active); 189 : 0 : __i915_vma_unpin(vma); 190 : 0 : } 191 : : 192 : 0 : static int __ring_active(struct intel_ring *ring) 193 : : { 194 : 0 : int err; 195 : : 196 : 0 : err = i915_active_acquire(&ring->vma->active); 197 [ # # ]: 0 : if (err) 198 : : return err; 199 : : 200 : 0 : err = intel_ring_pin(ring); 201 [ # # ]: 0 : if (err) 202 : 0 : goto err_active; 203 : : 204 : : return 0; 205 : : 206 : : err_active: 207 : 0 : i915_active_release(&ring->vma->active); 208 : 0 : return err; 209 : : } 210 : : 211 : 0 : static void __ring_retire(struct intel_ring *ring) 212 : : { 213 : 0 : intel_ring_unpin(ring); 214 : 0 : i915_active_release(&ring->vma->active); 215 : 0 : } 216 : : 217 : : __i915_active_call 218 : 0 : static void __intel_context_retire(struct i915_active *active) 219 : : { 220 : 0 : struct intel_context *ce = container_of(active, typeof(*ce), active); 221 : : 222 : 0 : CE_TRACE(ce, "retire\n"); 223 : : 224 : 0 : set_bit(CONTEXT_VALID_BIT, &ce->flags); 225 [ # # ]: 0 : if (ce->state) 226 : 0 : __context_unpin_state(ce->state); 227 : : 228 : 0 : intel_timeline_unpin(ce->timeline); 229 : 0 : __ring_retire(ce->ring); 230 : : 231 : 0 : intel_context_put(ce); 232 : 0 : } 233 : : 234 : 0 : static int __intel_context_active(struct i915_active *active) 235 : : { 236 : 0 : struct intel_context *ce = container_of(active, typeof(*ce), active); 237 : 0 : int err; 238 : : 239 : 0 : CE_TRACE(ce, "active\n"); 240 : : 241 : 0 : intel_context_get(ce); 242 : : 243 : 0 : err = __ring_active(ce->ring); 244 [ # # ]: 0 : if (err) 245 : 0 : goto err_put; 246 : : 247 : 0 : err = intel_timeline_pin(ce->timeline); 248 [ # # ]: 0 : if (err) 249 : 0 : goto err_ring; 250 : : 251 [ # # ]: 0 : if (!ce->state) 252 : : return 0; 253 : : 254 : 0 : err = __context_pin_state(ce->state); 255 [ # # ]: 0 : if (err) 256 : 0 : goto err_timeline; 257 : : 258 : : return 0; 259 : : 260 : : err_timeline: 261 : 0 : intel_timeline_unpin(ce->timeline); 262 : 0 : err_ring: 263 : 0 : __ring_retire(ce->ring); 264 : 0 : err_put: 265 : 0 : intel_context_put(ce); 266 : 0 : return err; 267 : : } 268 : : 269 : : void 270 : 0 : intel_context_init(struct intel_context *ce, 271 : : struct intel_engine_cs *engine) 272 : : { 273 : 0 : GEM_BUG_ON(!engine->cops); 274 : 0 : GEM_BUG_ON(!engine->gt->vm); 275 : : 276 : 0 : kref_init(&ce->ref); 277 : : 278 : 0 : ce->engine = engine; 279 : 0 : ce->ops = engine->cops; 280 : 0 : ce->sseu = engine->sseu; 281 : 0 : ce->ring = __intel_context_ring_size(SZ_4K); 282 : : 283 : 0 : ce->vm = i915_vm_get(engine->gt->vm); 284 : : 285 : 0 : INIT_LIST_HEAD(&ce->signal_link); 286 : 0 : INIT_LIST_HEAD(&ce->signals); 287 : : 288 : 0 : mutex_init(&ce->pin_mutex); 289 : : 290 : 0 : i915_active_init(&ce->active, 291 : : __intel_context_active, __intel_context_retire); 292 : 0 : } 293 : : 294 : 0 : void intel_context_fini(struct intel_context *ce) 295 : : { 296 [ # # ]: 0 : if (ce->timeline) 297 : 0 : intel_timeline_put(ce->timeline); 298 : 0 : i915_vm_put(ce->vm); 299 : : 300 : 0 : mutex_destroy(&ce->pin_mutex); 301 : 0 : i915_active_fini(&ce->active); 302 : 0 : } 303 : : 304 : 0 : static void i915_global_context_shrink(void) 305 : : { 306 : 0 : kmem_cache_shrink(global.slab_ce); 307 : 0 : } 308 : : 309 : 0 : static void i915_global_context_exit(void) 310 : : { 311 : 0 : kmem_cache_destroy(global.slab_ce); 312 : 0 : } 313 : : 314 : : static struct i915_global_context global = { { 315 : : .shrink = i915_global_context_shrink, 316 : : .exit = i915_global_context_exit, 317 : : } }; 318 : : 319 : 13 : int __init i915_global_context_init(void) 320 : : { 321 : 13 : global.slab_ce = KMEM_CACHE(intel_context, SLAB_HWCACHE_ALIGN); 322 [ + - ]: 13 : if (!global.slab_ce) 323 : : return -ENOMEM; 324 : : 325 : 13 : i915_global_register(&global.base); 326 : 13 : return 0; 327 : : } 328 : : 329 : 0 : void intel_context_enter_engine(struct intel_context *ce) 330 : : { 331 : 0 : intel_engine_pm_get(ce->engine); 332 : 0 : intel_timeline_enter(ce->timeline); 333 : 0 : } 334 : : 335 : 0 : void intel_context_exit_engine(struct intel_context *ce) 336 : : { 337 : 0 : intel_timeline_exit(ce->timeline); 338 : 0 : intel_engine_pm_put(ce->engine); 339 : 0 : } 340 : : 341 : 0 : int intel_context_prepare_remote_request(struct intel_context *ce, 342 : : struct i915_request *rq) 343 : : { 344 : 0 : struct intel_timeline *tl = ce->timeline; 345 : 0 : int err; 346 : : 347 : : /* Only suitable for use in remotely modifying this context */ 348 : 0 : GEM_BUG_ON(rq->context == ce); 349 : : 350 [ # # ]: 0 : if (rcu_access_pointer(rq->timeline) != tl) { /* timeline sharing! */ 351 : : /* Queue this switch after current activity by this context. */ 352 : 0 : err = i915_active_fence_set(&tl->last_request, rq); 353 [ # # ]: 0 : if (err) 354 : : return err; 355 : : } 356 : : 357 : : /* 358 : : * Guarantee context image and the timeline remains pinned until the 359 : : * modifying request is retired by setting the ce activity tracker. 360 : : * 361 : : * But we only need to take one pin on the account of it. Or in other 362 : : * words transfer the pinned ce object to tracked active request. 363 : : */ 364 : 0 : GEM_BUG_ON(i915_active_is_idle(&ce->active)); 365 : 0 : return i915_active_add_request(&ce->active, rq); 366 : : } 367 : : 368 : 0 : struct i915_request *intel_context_create_request(struct intel_context *ce) 369 : : { 370 : 0 : struct i915_request *rq; 371 : 0 : int err; 372 : : 373 : 0 : err = intel_context_pin(ce); 374 [ # # ]: 0 : if (unlikely(err)) 375 : 0 : return ERR_PTR(err); 376 : : 377 : 0 : rq = i915_request_create(ce); 378 : 0 : intel_context_unpin(ce); 379 : : 380 : 0 : return rq; 381 : : } 382 : : 383 : : #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) 384 : : #include "selftest_context.c" 385 : : #endif