18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * SPDX-License-Identifier: MIT 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright © 2019 Intel Corporation 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include "gem/i915_gem_context.h" 88c2ecf20Sopenharmony_ci#include "gem/i915_gem_pm.h" 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include "i915_drv.h" 118c2ecf20Sopenharmony_ci#include "i915_globals.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include "intel_context.h" 148c2ecf20Sopenharmony_ci#include "intel_engine.h" 158c2ecf20Sopenharmony_ci#include "intel_engine_pm.h" 168c2ecf20Sopenharmony_ci#include "intel_ring.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistatic struct i915_global_context { 198c2ecf20Sopenharmony_ci struct i915_global base; 208c2ecf20Sopenharmony_ci struct kmem_cache *slab_ce; 218c2ecf20Sopenharmony_ci} global; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic struct intel_context *intel_context_alloc(void) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci return kmem_cache_zalloc(global.slab_ce, GFP_KERNEL); 268c2ecf20Sopenharmony_ci} 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic void rcu_context_free(struct rcu_head *rcu) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci struct intel_context *ce = container_of(rcu, typeof(*ce), rcu); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci kmem_cache_free(global.slab_ce, ce); 338c2ecf20Sopenharmony_ci} 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_civoid intel_context_free(struct intel_context *ce) 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci call_rcu(&ce->rcu, rcu_context_free); 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistruct intel_context * 418c2ecf20Sopenharmony_ciintel_context_create(struct intel_engine_cs *engine) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci struct intel_context *ce; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci ce = intel_context_alloc(); 468c2ecf20Sopenharmony_ci if (!ce) 478c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci intel_context_init(ce, engine); 508c2ecf20Sopenharmony_ci return ce; 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ciint intel_context_alloc_state(struct intel_context *ce) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci int err = 0; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&ce->pin_mutex)) 588c2ecf20Sopenharmony_ci return -EINTR; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) { 618c2ecf20Sopenharmony_ci if (intel_context_is_banned(ce)) { 628c2ecf20Sopenharmony_ci err = -EIO; 638c2ecf20Sopenharmony_ci goto unlock; 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci err = ce->ops->alloc(ce); 678c2ecf20Sopenharmony_ci if (unlikely(err)) 688c2ecf20Sopenharmony_ci goto unlock; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci set_bit(CONTEXT_ALLOC_BIT, &ce->flags); 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ciunlock: 748c2ecf20Sopenharmony_ci mutex_unlock(&ce->pin_mutex); 758c2ecf20Sopenharmony_ci return err; 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic int intel_context_active_acquire(struct intel_context *ce) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci int err; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci __i915_active_acquire(&ce->active); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci if (intel_context_is_barrier(ce)) 858c2ecf20Sopenharmony_ci return 0; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci /* Preallocate tracking nodes */ 888c2ecf20Sopenharmony_ci err = i915_active_acquire_preallocate_barrier(&ce->active, 898c2ecf20Sopenharmony_ci ce->engine); 908c2ecf20Sopenharmony_ci if (err) 918c2ecf20Sopenharmony_ci i915_active_release(&ce->active); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci return err; 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic void intel_context_active_release(struct intel_context *ce) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci /* Nodes preallocated in intel_context_active() */ 998c2ecf20Sopenharmony_ci i915_active_acquire_barrier(&ce->active); 1008c2ecf20Sopenharmony_ci i915_active_release(&ce->active); 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic int __context_pin_state(struct i915_vma *vma, struct i915_gem_ww_ctx *ww) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci unsigned int bias = i915_ggtt_pin_bias(vma) | PIN_OFFSET_BIAS; 1068c2ecf20Sopenharmony_ci int err; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci err = i915_ggtt_pin(vma, ww, 0, bias | PIN_HIGH); 1098c2ecf20Sopenharmony_ci if (err) 1108c2ecf20Sopenharmony_ci return err; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci err = i915_active_acquire(&vma->active); 1138c2ecf20Sopenharmony_ci if (err) 1148c2ecf20Sopenharmony_ci goto err_unpin; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci /* 1178c2ecf20Sopenharmony_ci * And mark it as a globally pinned object to let the shrinker know 1188c2ecf20Sopenharmony_ci * it cannot reclaim the object until we release it. 1198c2ecf20Sopenharmony_ci */ 1208c2ecf20Sopenharmony_ci i915_vma_make_unshrinkable(vma); 1218c2ecf20Sopenharmony_ci vma->obj->mm.dirty = true; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci return 0; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cierr_unpin: 1268c2ecf20Sopenharmony_ci i915_vma_unpin(vma); 1278c2ecf20Sopenharmony_ci return err; 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_cistatic void __context_unpin_state(struct i915_vma *vma) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci i915_vma_make_shrinkable(vma); 1338c2ecf20Sopenharmony_ci i915_active_release(&vma->active); 1348c2ecf20Sopenharmony_ci __i915_vma_unpin(vma); 1358c2ecf20Sopenharmony_ci} 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_cistatic int __ring_active(struct intel_ring *ring, 1388c2ecf20Sopenharmony_ci struct i915_gem_ww_ctx *ww) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci int err; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci err = intel_ring_pin(ring, ww); 1438c2ecf20Sopenharmony_ci if (err) 1448c2ecf20Sopenharmony_ci return err; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci err = i915_active_acquire(&ring->vma->active); 1478c2ecf20Sopenharmony_ci if (err) 1488c2ecf20Sopenharmony_ci goto err_pin; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci return 0; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cierr_pin: 1538c2ecf20Sopenharmony_ci intel_ring_unpin(ring); 1548c2ecf20Sopenharmony_ci return err; 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic void __ring_retire(struct intel_ring *ring) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci i915_active_release(&ring->vma->active); 1608c2ecf20Sopenharmony_ci intel_ring_unpin(ring); 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cistatic int intel_context_pre_pin(struct intel_context *ce, 1648c2ecf20Sopenharmony_ci struct i915_gem_ww_ctx *ww) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci int err; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci CE_TRACE(ce, "active\n"); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci err = __ring_active(ce->ring, ww); 1718c2ecf20Sopenharmony_ci if (err) 1728c2ecf20Sopenharmony_ci return err; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci err = intel_timeline_pin(ce->timeline, ww); 1758c2ecf20Sopenharmony_ci if (err) 1768c2ecf20Sopenharmony_ci goto err_ring; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci if (!ce->state) 1798c2ecf20Sopenharmony_ci return 0; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci err = __context_pin_state(ce->state, ww); 1828c2ecf20Sopenharmony_ci if (err) 1838c2ecf20Sopenharmony_ci goto err_timeline; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci return 0; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cierr_timeline: 1898c2ecf20Sopenharmony_ci intel_timeline_unpin(ce->timeline); 1908c2ecf20Sopenharmony_cierr_ring: 1918c2ecf20Sopenharmony_ci __ring_retire(ce->ring); 1928c2ecf20Sopenharmony_ci return err; 1938c2ecf20Sopenharmony_ci} 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_cistatic void intel_context_post_unpin(struct intel_context *ce) 1968c2ecf20Sopenharmony_ci{ 1978c2ecf20Sopenharmony_ci if (ce->state) 1988c2ecf20Sopenharmony_ci __context_unpin_state(ce->state); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci intel_timeline_unpin(ce->timeline); 2018c2ecf20Sopenharmony_ci __ring_retire(ce->ring); 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ciint __intel_context_do_pin_ww(struct intel_context *ce, 2058c2ecf20Sopenharmony_ci struct i915_gem_ww_ctx *ww) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci bool handoff = false; 2088c2ecf20Sopenharmony_ci void *vaddr; 2098c2ecf20Sopenharmony_ci int err = 0; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci if (unlikely(!test_bit(CONTEXT_ALLOC_BIT, &ce->flags))) { 2128c2ecf20Sopenharmony_ci err = intel_context_alloc_state(ce); 2138c2ecf20Sopenharmony_ci if (err) 2148c2ecf20Sopenharmony_ci return err; 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci /* 2188c2ecf20Sopenharmony_ci * We always pin the context/ring/timeline here, to ensure a pin 2198c2ecf20Sopenharmony_ci * refcount for __intel_context_active(), which prevent a lock 2208c2ecf20Sopenharmony_ci * inversion of ce->pin_mutex vs dma_resv_lock(). 2218c2ecf20Sopenharmony_ci */ 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci err = i915_gem_object_lock(ce->timeline->hwsp_ggtt->obj, ww); 2248c2ecf20Sopenharmony_ci if (!err && ce->ring->vma->obj) 2258c2ecf20Sopenharmony_ci err = i915_gem_object_lock(ce->ring->vma->obj, ww); 2268c2ecf20Sopenharmony_ci if (!err && ce->state) 2278c2ecf20Sopenharmony_ci err = i915_gem_object_lock(ce->state->obj, ww); 2288c2ecf20Sopenharmony_ci if (!err) 2298c2ecf20Sopenharmony_ci err = intel_context_pre_pin(ce, ww); 2308c2ecf20Sopenharmony_ci if (err) 2318c2ecf20Sopenharmony_ci return err; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci err = i915_active_acquire(&ce->active); 2348c2ecf20Sopenharmony_ci if (err) 2358c2ecf20Sopenharmony_ci goto err_ctx_unpin; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci err = ce->ops->pre_pin(ce, ww, &vaddr); 2388c2ecf20Sopenharmony_ci if (err) 2398c2ecf20Sopenharmony_ci goto err_release; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci err = mutex_lock_interruptible(&ce->pin_mutex); 2428c2ecf20Sopenharmony_ci if (err) 2438c2ecf20Sopenharmony_ci goto err_post_unpin; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci if (unlikely(intel_context_is_closed(ce))) { 2468c2ecf20Sopenharmony_ci err = -ENOENT; 2478c2ecf20Sopenharmony_ci goto err_unlock; 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci if (likely(!atomic_add_unless(&ce->pin_count, 1, 0))) { 2518c2ecf20Sopenharmony_ci err = intel_context_active_acquire(ce); 2528c2ecf20Sopenharmony_ci if (unlikely(err)) 2538c2ecf20Sopenharmony_ci goto err_unlock; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci err = ce->ops->pin(ce, vaddr); 2568c2ecf20Sopenharmony_ci if (err) { 2578c2ecf20Sopenharmony_ci intel_context_active_release(ce); 2588c2ecf20Sopenharmony_ci goto err_unlock; 2598c2ecf20Sopenharmony_ci } 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci CE_TRACE(ce, "pin ring:{start:%08x, head:%04x, tail:%04x}\n", 2628c2ecf20Sopenharmony_ci i915_ggtt_offset(ce->ring->vma), 2638c2ecf20Sopenharmony_ci ce->ring->head, ce->ring->tail); 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci handoff = true; 2668c2ecf20Sopenharmony_ci smp_mb__before_atomic(); /* flush pin before it is visible */ 2678c2ecf20Sopenharmony_ci atomic_inc(&ce->pin_count); 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci GEM_BUG_ON(!intel_context_is_pinned(ce)); /* no overflow! */ 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_cierr_unlock: 2738c2ecf20Sopenharmony_ci mutex_unlock(&ce->pin_mutex); 2748c2ecf20Sopenharmony_cierr_post_unpin: 2758c2ecf20Sopenharmony_ci if (!handoff) 2768c2ecf20Sopenharmony_ci ce->ops->post_unpin(ce); 2778c2ecf20Sopenharmony_cierr_release: 2788c2ecf20Sopenharmony_ci i915_active_release(&ce->active); 2798c2ecf20Sopenharmony_cierr_ctx_unpin: 2808c2ecf20Sopenharmony_ci intel_context_post_unpin(ce); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci /* 2838c2ecf20Sopenharmony_ci * Unlock the hwsp_ggtt object since it's shared. 2848c2ecf20Sopenharmony_ci * In principle we can unlock all the global state locked above 2858c2ecf20Sopenharmony_ci * since it's pinned and doesn't need fencing, and will 2868c2ecf20Sopenharmony_ci * thus remain resident until it is explicitly unpinned. 2878c2ecf20Sopenharmony_ci */ 2888c2ecf20Sopenharmony_ci i915_gem_ww_unlock_single(ce->timeline->hwsp_ggtt->obj); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci return err; 2918c2ecf20Sopenharmony_ci} 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ciint __intel_context_do_pin(struct intel_context *ce) 2948c2ecf20Sopenharmony_ci{ 2958c2ecf20Sopenharmony_ci struct i915_gem_ww_ctx ww; 2968c2ecf20Sopenharmony_ci int err; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci i915_gem_ww_ctx_init(&ww, true); 2998c2ecf20Sopenharmony_ciretry: 3008c2ecf20Sopenharmony_ci err = __intel_context_do_pin_ww(ce, &ww); 3018c2ecf20Sopenharmony_ci if (err == -EDEADLK) { 3028c2ecf20Sopenharmony_ci err = i915_gem_ww_ctx_backoff(&ww); 3038c2ecf20Sopenharmony_ci if (!err) 3048c2ecf20Sopenharmony_ci goto retry; 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci i915_gem_ww_ctx_fini(&ww); 3078c2ecf20Sopenharmony_ci return err; 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_civoid intel_context_unpin(struct intel_context *ce) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci if (!atomic_dec_and_test(&ce->pin_count)) 3138c2ecf20Sopenharmony_ci return; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci CE_TRACE(ce, "unpin\n"); 3168c2ecf20Sopenharmony_ci ce->ops->unpin(ce); 3178c2ecf20Sopenharmony_ci ce->ops->post_unpin(ce); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci /* 3208c2ecf20Sopenharmony_ci * Once released, we may asynchronously drop the active reference. 3218c2ecf20Sopenharmony_ci * As that may be the only reference keeping the context alive, 3228c2ecf20Sopenharmony_ci * take an extra now so that it is not freed before we finish 3238c2ecf20Sopenharmony_ci * dereferencing it. 3248c2ecf20Sopenharmony_ci */ 3258c2ecf20Sopenharmony_ci intel_context_get(ce); 3268c2ecf20Sopenharmony_ci intel_context_active_release(ce); 3278c2ecf20Sopenharmony_ci intel_context_put(ce); 3288c2ecf20Sopenharmony_ci} 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci__i915_active_call 3318c2ecf20Sopenharmony_cistatic void __intel_context_retire(struct i915_active *active) 3328c2ecf20Sopenharmony_ci{ 3338c2ecf20Sopenharmony_ci struct intel_context *ce = container_of(active, typeof(*ce), active); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci CE_TRACE(ce, "retire runtime: { total:%lluns, avg:%lluns }\n", 3368c2ecf20Sopenharmony_ci intel_context_get_total_runtime_ns(ce), 3378c2ecf20Sopenharmony_ci intel_context_get_avg_runtime_ns(ce)); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci set_bit(CONTEXT_VALID_BIT, &ce->flags); 3408c2ecf20Sopenharmony_ci intel_context_post_unpin(ce); 3418c2ecf20Sopenharmony_ci intel_context_put(ce); 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_cistatic int __intel_context_active(struct i915_active *active) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci struct intel_context *ce = container_of(active, typeof(*ce), active); 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci intel_context_get(ce); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci /* everything should already be activated by intel_context_pre_pin() */ 3518c2ecf20Sopenharmony_ci GEM_WARN_ON(!i915_active_acquire_if_busy(&ce->ring->vma->active)); 3528c2ecf20Sopenharmony_ci __intel_ring_pin(ce->ring); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci __intel_timeline_pin(ce->timeline); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci if (ce->state) { 3578c2ecf20Sopenharmony_ci GEM_WARN_ON(!i915_active_acquire_if_busy(&ce->state->active)); 3588c2ecf20Sopenharmony_ci __i915_vma_pin(ce->state); 3598c2ecf20Sopenharmony_ci i915_vma_make_unshrinkable(ce->state); 3608c2ecf20Sopenharmony_ci } 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci return 0; 3638c2ecf20Sopenharmony_ci} 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_civoid 3668c2ecf20Sopenharmony_ciintel_context_init(struct intel_context *ce, struct intel_engine_cs *engine) 3678c2ecf20Sopenharmony_ci{ 3688c2ecf20Sopenharmony_ci GEM_BUG_ON(!engine->cops); 3698c2ecf20Sopenharmony_ci GEM_BUG_ON(!engine->gt->vm); 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci kref_init(&ce->ref); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci ce->engine = engine; 3748c2ecf20Sopenharmony_ci ce->ops = engine->cops; 3758c2ecf20Sopenharmony_ci ce->sseu = engine->sseu; 3768c2ecf20Sopenharmony_ci ce->ring = __intel_context_ring_size(SZ_4K); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci ewma_runtime_init(&ce->runtime.avg); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci ce->vm = i915_vm_get(engine->gt->vm); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci /* NB ce->signal_link/lock is used under RCU */ 3838c2ecf20Sopenharmony_ci spin_lock_init(&ce->signal_lock); 3848c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ce->signals); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci mutex_init(&ce->pin_mutex); 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci i915_active_init(&ce->active, 3898c2ecf20Sopenharmony_ci __intel_context_active, __intel_context_retire); 3908c2ecf20Sopenharmony_ci} 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_civoid intel_context_fini(struct intel_context *ce) 3938c2ecf20Sopenharmony_ci{ 3948c2ecf20Sopenharmony_ci if (ce->timeline) 3958c2ecf20Sopenharmony_ci intel_timeline_put(ce->timeline); 3968c2ecf20Sopenharmony_ci i915_vm_put(ce->vm); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci mutex_destroy(&ce->pin_mutex); 3998c2ecf20Sopenharmony_ci i915_active_fini(&ce->active); 4008c2ecf20Sopenharmony_ci} 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_cistatic void i915_global_context_shrink(void) 4038c2ecf20Sopenharmony_ci{ 4048c2ecf20Sopenharmony_ci kmem_cache_shrink(global.slab_ce); 4058c2ecf20Sopenharmony_ci} 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_cistatic void i915_global_context_exit(void) 4088c2ecf20Sopenharmony_ci{ 4098c2ecf20Sopenharmony_ci kmem_cache_destroy(global.slab_ce); 4108c2ecf20Sopenharmony_ci} 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_cistatic struct i915_global_context global = { { 4138c2ecf20Sopenharmony_ci .shrink = i915_global_context_shrink, 4148c2ecf20Sopenharmony_ci .exit = i915_global_context_exit, 4158c2ecf20Sopenharmony_ci} }; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ciint __init i915_global_context_init(void) 4188c2ecf20Sopenharmony_ci{ 4198c2ecf20Sopenharmony_ci global.slab_ce = KMEM_CACHE(intel_context, SLAB_HWCACHE_ALIGN); 4208c2ecf20Sopenharmony_ci if (!global.slab_ce) 4218c2ecf20Sopenharmony_ci return -ENOMEM; 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci i915_global_register(&global.base); 4248c2ecf20Sopenharmony_ci return 0; 4258c2ecf20Sopenharmony_ci} 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_civoid intel_context_enter_engine(struct intel_context *ce) 4288c2ecf20Sopenharmony_ci{ 4298c2ecf20Sopenharmony_ci intel_engine_pm_get(ce->engine); 4308c2ecf20Sopenharmony_ci intel_timeline_enter(ce->timeline); 4318c2ecf20Sopenharmony_ci} 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_civoid intel_context_exit_engine(struct intel_context *ce) 4348c2ecf20Sopenharmony_ci{ 4358c2ecf20Sopenharmony_ci intel_timeline_exit(ce->timeline); 4368c2ecf20Sopenharmony_ci intel_engine_pm_put(ce->engine); 4378c2ecf20Sopenharmony_ci} 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ciint intel_context_prepare_remote_request(struct intel_context *ce, 4408c2ecf20Sopenharmony_ci struct i915_request *rq) 4418c2ecf20Sopenharmony_ci{ 4428c2ecf20Sopenharmony_ci struct intel_timeline *tl = ce->timeline; 4438c2ecf20Sopenharmony_ci int err; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci /* Only suitable for use in remotely modifying this context */ 4468c2ecf20Sopenharmony_ci GEM_BUG_ON(rq->context == ce); 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci if (rcu_access_pointer(rq->timeline) != tl) { /* timeline sharing! */ 4498c2ecf20Sopenharmony_ci /* Queue this switch after current activity by this context. */ 4508c2ecf20Sopenharmony_ci err = i915_active_fence_set(&tl->last_request, rq); 4518c2ecf20Sopenharmony_ci if (err) 4528c2ecf20Sopenharmony_ci return err; 4538c2ecf20Sopenharmony_ci } 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci /* 4568c2ecf20Sopenharmony_ci * Guarantee context image and the timeline remains pinned until the 4578c2ecf20Sopenharmony_ci * modifying request is retired by setting the ce activity tracker. 4588c2ecf20Sopenharmony_ci * 4598c2ecf20Sopenharmony_ci * But we only need to take one pin on the account of it. Or in other 4608c2ecf20Sopenharmony_ci * words transfer the pinned ce object to tracked active request. 4618c2ecf20Sopenharmony_ci */ 4628c2ecf20Sopenharmony_ci GEM_BUG_ON(i915_active_is_idle(&ce->active)); 4638c2ecf20Sopenharmony_ci return i915_active_add_request(&ce->active, rq); 4648c2ecf20Sopenharmony_ci} 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_cistruct i915_request *intel_context_create_request(struct intel_context *ce) 4678c2ecf20Sopenharmony_ci{ 4688c2ecf20Sopenharmony_ci struct i915_gem_ww_ctx ww; 4698c2ecf20Sopenharmony_ci struct i915_request *rq; 4708c2ecf20Sopenharmony_ci int err; 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci i915_gem_ww_ctx_init(&ww, true); 4738c2ecf20Sopenharmony_ciretry: 4748c2ecf20Sopenharmony_ci err = intel_context_pin_ww(ce, &ww); 4758c2ecf20Sopenharmony_ci if (!err) { 4768c2ecf20Sopenharmony_ci rq = i915_request_create(ce); 4778c2ecf20Sopenharmony_ci intel_context_unpin(ce); 4788c2ecf20Sopenharmony_ci } else if (err == -EDEADLK) { 4798c2ecf20Sopenharmony_ci err = i915_gem_ww_ctx_backoff(&ww); 4808c2ecf20Sopenharmony_ci if (!err) 4818c2ecf20Sopenharmony_ci goto retry; 4828c2ecf20Sopenharmony_ci rq = ERR_PTR(err); 4838c2ecf20Sopenharmony_ci } else { 4848c2ecf20Sopenharmony_ci rq = ERR_PTR(err); 4858c2ecf20Sopenharmony_ci } 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci i915_gem_ww_ctx_fini(&ww); 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci if (IS_ERR(rq)) 4908c2ecf20Sopenharmony_ci return rq; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci /* 4938c2ecf20Sopenharmony_ci * timeline->mutex should be the inner lock, but is used as outer lock. 4948c2ecf20Sopenharmony_ci * Hack around this to shut up lockdep in selftests.. 4958c2ecf20Sopenharmony_ci */ 4968c2ecf20Sopenharmony_ci lockdep_unpin_lock(&ce->timeline->mutex, rq->cookie); 4978c2ecf20Sopenharmony_ci mutex_release(&ce->timeline->mutex.dep_map, _RET_IP_); 4988c2ecf20Sopenharmony_ci mutex_acquire(&ce->timeline->mutex.dep_map, SINGLE_DEPTH_NESTING, 0, _RET_IP_); 4998c2ecf20Sopenharmony_ci rq->cookie = lockdep_pin_lock(&ce->timeline->mutex); 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci return rq; 5028c2ecf20Sopenharmony_ci} 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) 5058c2ecf20Sopenharmony_ci#include "selftest_context.c" 5068c2ecf20Sopenharmony_ci#endif 507