1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * SPDX-License-Identifier: MIT
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright © 2019 Intel Corporation
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include "gem/i915_gem_context.h"
8*4882a593Smuzhiyun #include "gem/i915_gem_pm.h"
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include "i915_drv.h"
11*4882a593Smuzhiyun #include "i915_globals.h"
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #include "intel_context.h"
14*4882a593Smuzhiyun #include "intel_engine.h"
15*4882a593Smuzhiyun #include "intel_engine_pm.h"
16*4882a593Smuzhiyun #include "intel_ring.h"
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun static struct i915_global_context {
19*4882a593Smuzhiyun struct i915_global base;
20*4882a593Smuzhiyun struct kmem_cache *slab_ce;
21*4882a593Smuzhiyun } global;
22*4882a593Smuzhiyun
intel_context_alloc(void)23*4882a593Smuzhiyun static struct intel_context *intel_context_alloc(void)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun return kmem_cache_zalloc(global.slab_ce, GFP_KERNEL);
26*4882a593Smuzhiyun }
27*4882a593Smuzhiyun
rcu_context_free(struct rcu_head * rcu)28*4882a593Smuzhiyun static void rcu_context_free(struct rcu_head *rcu)
29*4882a593Smuzhiyun {
30*4882a593Smuzhiyun struct intel_context *ce = container_of(rcu, typeof(*ce), rcu);
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun kmem_cache_free(global.slab_ce, ce);
33*4882a593Smuzhiyun }
34*4882a593Smuzhiyun
intel_context_free(struct intel_context * ce)35*4882a593Smuzhiyun void intel_context_free(struct intel_context *ce)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun call_rcu(&ce->rcu, rcu_context_free);
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun struct intel_context *
intel_context_create(struct intel_engine_cs * engine)41*4882a593Smuzhiyun intel_context_create(struct intel_engine_cs *engine)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun struct intel_context *ce;
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun ce = intel_context_alloc();
46*4882a593Smuzhiyun if (!ce)
47*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun intel_context_init(ce, engine);
50*4882a593Smuzhiyun return ce;
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun
intel_context_alloc_state(struct intel_context * ce)53*4882a593Smuzhiyun int intel_context_alloc_state(struct intel_context *ce)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun int err = 0;
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun if (mutex_lock_interruptible(&ce->pin_mutex))
58*4882a593Smuzhiyun return -EINTR;
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
61*4882a593Smuzhiyun if (intel_context_is_banned(ce)) {
62*4882a593Smuzhiyun err = -EIO;
63*4882a593Smuzhiyun goto unlock;
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun err = ce->ops->alloc(ce);
67*4882a593Smuzhiyun if (unlikely(err))
68*4882a593Smuzhiyun goto unlock;
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun set_bit(CONTEXT_ALLOC_BIT, &ce->flags);
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun unlock:
74*4882a593Smuzhiyun mutex_unlock(&ce->pin_mutex);
75*4882a593Smuzhiyun return err;
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun
intel_context_active_acquire(struct intel_context * ce)78*4882a593Smuzhiyun static int intel_context_active_acquire(struct intel_context *ce)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun int err;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun __i915_active_acquire(&ce->active);
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun if (intel_context_is_barrier(ce))
85*4882a593Smuzhiyun return 0;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun /* Preallocate tracking nodes */
88*4882a593Smuzhiyun err = i915_active_acquire_preallocate_barrier(&ce->active,
89*4882a593Smuzhiyun ce->engine);
90*4882a593Smuzhiyun if (err)
91*4882a593Smuzhiyun i915_active_release(&ce->active);
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun return err;
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun
intel_context_active_release(struct intel_context * ce)96*4882a593Smuzhiyun static void intel_context_active_release(struct intel_context *ce)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun /* Nodes preallocated in intel_context_active() */
99*4882a593Smuzhiyun i915_active_acquire_barrier(&ce->active);
100*4882a593Smuzhiyun i915_active_release(&ce->active);
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun
__context_pin_state(struct i915_vma * vma,struct i915_gem_ww_ctx * ww)103*4882a593Smuzhiyun static int __context_pin_state(struct i915_vma *vma, struct i915_gem_ww_ctx *ww)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun unsigned int bias = i915_ggtt_pin_bias(vma) | PIN_OFFSET_BIAS;
106*4882a593Smuzhiyun int err;
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun err = i915_ggtt_pin(vma, ww, 0, bias | PIN_HIGH);
109*4882a593Smuzhiyun if (err)
110*4882a593Smuzhiyun return err;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun err = i915_active_acquire(&vma->active);
113*4882a593Smuzhiyun if (err)
114*4882a593Smuzhiyun goto err_unpin;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun /*
117*4882a593Smuzhiyun * And mark it as a globally pinned object to let the shrinker know
118*4882a593Smuzhiyun * it cannot reclaim the object until we release it.
119*4882a593Smuzhiyun */
120*4882a593Smuzhiyun i915_vma_make_unshrinkable(vma);
121*4882a593Smuzhiyun vma->obj->mm.dirty = true;
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun return 0;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun err_unpin:
126*4882a593Smuzhiyun i915_vma_unpin(vma);
127*4882a593Smuzhiyun return err;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
__context_unpin_state(struct i915_vma * vma)130*4882a593Smuzhiyun static void __context_unpin_state(struct i915_vma *vma)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun i915_vma_make_shrinkable(vma);
133*4882a593Smuzhiyun i915_active_release(&vma->active);
134*4882a593Smuzhiyun __i915_vma_unpin(vma);
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun
__ring_active(struct intel_ring * ring,struct i915_gem_ww_ctx * ww)137*4882a593Smuzhiyun static int __ring_active(struct intel_ring *ring,
138*4882a593Smuzhiyun struct i915_gem_ww_ctx *ww)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun int err;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun err = intel_ring_pin(ring, ww);
143*4882a593Smuzhiyun if (err)
144*4882a593Smuzhiyun return err;
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun err = i915_active_acquire(&ring->vma->active);
147*4882a593Smuzhiyun if (err)
148*4882a593Smuzhiyun goto err_pin;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun return 0;
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun err_pin:
153*4882a593Smuzhiyun intel_ring_unpin(ring);
154*4882a593Smuzhiyun return err;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun
__ring_retire(struct intel_ring * ring)157*4882a593Smuzhiyun static void __ring_retire(struct intel_ring *ring)
158*4882a593Smuzhiyun {
159*4882a593Smuzhiyun i915_active_release(&ring->vma->active);
160*4882a593Smuzhiyun intel_ring_unpin(ring);
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun
intel_context_pre_pin(struct intel_context * ce,struct i915_gem_ww_ctx * ww)163*4882a593Smuzhiyun static int intel_context_pre_pin(struct intel_context *ce,
164*4882a593Smuzhiyun struct i915_gem_ww_ctx *ww)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun int err;
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun CE_TRACE(ce, "active\n");
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun err = __ring_active(ce->ring, ww);
171*4882a593Smuzhiyun if (err)
172*4882a593Smuzhiyun return err;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun err = intel_timeline_pin(ce->timeline, ww);
175*4882a593Smuzhiyun if (err)
176*4882a593Smuzhiyun goto err_ring;
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun if (!ce->state)
179*4882a593Smuzhiyun return 0;
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun err = __context_pin_state(ce->state, ww);
182*4882a593Smuzhiyun if (err)
183*4882a593Smuzhiyun goto err_timeline;
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun return 0;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun err_timeline:
189*4882a593Smuzhiyun intel_timeline_unpin(ce->timeline);
190*4882a593Smuzhiyun err_ring:
191*4882a593Smuzhiyun __ring_retire(ce->ring);
192*4882a593Smuzhiyun return err;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun
intel_context_post_unpin(struct intel_context * ce)195*4882a593Smuzhiyun static void intel_context_post_unpin(struct intel_context *ce)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun if (ce->state)
198*4882a593Smuzhiyun __context_unpin_state(ce->state);
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun intel_timeline_unpin(ce->timeline);
201*4882a593Smuzhiyun __ring_retire(ce->ring);
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun
__intel_context_do_pin_ww(struct intel_context * ce,struct i915_gem_ww_ctx * ww)204*4882a593Smuzhiyun int __intel_context_do_pin_ww(struct intel_context *ce,
205*4882a593Smuzhiyun struct i915_gem_ww_ctx *ww)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun bool handoff = false;
208*4882a593Smuzhiyun void *vaddr;
209*4882a593Smuzhiyun int err = 0;
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun if (unlikely(!test_bit(CONTEXT_ALLOC_BIT, &ce->flags))) {
212*4882a593Smuzhiyun err = intel_context_alloc_state(ce);
213*4882a593Smuzhiyun if (err)
214*4882a593Smuzhiyun return err;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun /*
218*4882a593Smuzhiyun * We always pin the context/ring/timeline here, to ensure a pin
219*4882a593Smuzhiyun * refcount for __intel_context_active(), which prevent a lock
220*4882a593Smuzhiyun * inversion of ce->pin_mutex vs dma_resv_lock().
221*4882a593Smuzhiyun */
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun err = i915_gem_object_lock(ce->timeline->hwsp_ggtt->obj, ww);
224*4882a593Smuzhiyun if (!err && ce->ring->vma->obj)
225*4882a593Smuzhiyun err = i915_gem_object_lock(ce->ring->vma->obj, ww);
226*4882a593Smuzhiyun if (!err && ce->state)
227*4882a593Smuzhiyun err = i915_gem_object_lock(ce->state->obj, ww);
228*4882a593Smuzhiyun if (!err)
229*4882a593Smuzhiyun err = intel_context_pre_pin(ce, ww);
230*4882a593Smuzhiyun if (err)
231*4882a593Smuzhiyun return err;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun err = i915_active_acquire(&ce->active);
234*4882a593Smuzhiyun if (err)
235*4882a593Smuzhiyun goto err_ctx_unpin;
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun err = ce->ops->pre_pin(ce, ww, &vaddr);
238*4882a593Smuzhiyun if (err)
239*4882a593Smuzhiyun goto err_release;
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun err = mutex_lock_interruptible(&ce->pin_mutex);
242*4882a593Smuzhiyun if (err)
243*4882a593Smuzhiyun goto err_post_unpin;
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun if (unlikely(intel_context_is_closed(ce))) {
246*4882a593Smuzhiyun err = -ENOENT;
247*4882a593Smuzhiyun goto err_unlock;
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun if (likely(!atomic_add_unless(&ce->pin_count, 1, 0))) {
251*4882a593Smuzhiyun err = intel_context_active_acquire(ce);
252*4882a593Smuzhiyun if (unlikely(err))
253*4882a593Smuzhiyun goto err_unlock;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun err = ce->ops->pin(ce, vaddr);
256*4882a593Smuzhiyun if (err) {
257*4882a593Smuzhiyun intel_context_active_release(ce);
258*4882a593Smuzhiyun goto err_unlock;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun CE_TRACE(ce, "pin ring:{start:%08x, head:%04x, tail:%04x}\n",
262*4882a593Smuzhiyun i915_ggtt_offset(ce->ring->vma),
263*4882a593Smuzhiyun ce->ring->head, ce->ring->tail);
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun handoff = true;
266*4882a593Smuzhiyun smp_mb__before_atomic(); /* flush pin before it is visible */
267*4882a593Smuzhiyun atomic_inc(&ce->pin_count);
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun GEM_BUG_ON(!intel_context_is_pinned(ce)); /* no overflow! */
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun err_unlock:
273*4882a593Smuzhiyun mutex_unlock(&ce->pin_mutex);
274*4882a593Smuzhiyun err_post_unpin:
275*4882a593Smuzhiyun if (!handoff)
276*4882a593Smuzhiyun ce->ops->post_unpin(ce);
277*4882a593Smuzhiyun err_release:
278*4882a593Smuzhiyun i915_active_release(&ce->active);
279*4882a593Smuzhiyun err_ctx_unpin:
280*4882a593Smuzhiyun intel_context_post_unpin(ce);
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun /*
283*4882a593Smuzhiyun * Unlock the hwsp_ggtt object since it's shared.
284*4882a593Smuzhiyun * In principle we can unlock all the global state locked above
285*4882a593Smuzhiyun * since it's pinned and doesn't need fencing, and will
286*4882a593Smuzhiyun * thus remain resident until it is explicitly unpinned.
287*4882a593Smuzhiyun */
288*4882a593Smuzhiyun i915_gem_ww_unlock_single(ce->timeline->hwsp_ggtt->obj);
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun return err;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun
__intel_context_do_pin(struct intel_context * ce)293*4882a593Smuzhiyun int __intel_context_do_pin(struct intel_context *ce)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun struct i915_gem_ww_ctx ww;
296*4882a593Smuzhiyun int err;
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun i915_gem_ww_ctx_init(&ww, true);
299*4882a593Smuzhiyun retry:
300*4882a593Smuzhiyun err = __intel_context_do_pin_ww(ce, &ww);
301*4882a593Smuzhiyun if (err == -EDEADLK) {
302*4882a593Smuzhiyun err = i915_gem_ww_ctx_backoff(&ww);
303*4882a593Smuzhiyun if (!err)
304*4882a593Smuzhiyun goto retry;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun i915_gem_ww_ctx_fini(&ww);
307*4882a593Smuzhiyun return err;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun
intel_context_unpin(struct intel_context * ce)310*4882a593Smuzhiyun void intel_context_unpin(struct intel_context *ce)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun if (!atomic_dec_and_test(&ce->pin_count))
313*4882a593Smuzhiyun return;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun CE_TRACE(ce, "unpin\n");
316*4882a593Smuzhiyun ce->ops->unpin(ce);
317*4882a593Smuzhiyun ce->ops->post_unpin(ce);
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun /*
320*4882a593Smuzhiyun * Once released, we may asynchronously drop the active reference.
321*4882a593Smuzhiyun * As that may be the only reference keeping the context alive,
322*4882a593Smuzhiyun * take an extra now so that it is not freed before we finish
323*4882a593Smuzhiyun * dereferencing it.
324*4882a593Smuzhiyun */
325*4882a593Smuzhiyun intel_context_get(ce);
326*4882a593Smuzhiyun intel_context_active_release(ce);
327*4882a593Smuzhiyun intel_context_put(ce);
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun __i915_active_call
__intel_context_retire(struct i915_active * active)331*4882a593Smuzhiyun static void __intel_context_retire(struct i915_active *active)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun struct intel_context *ce = container_of(active, typeof(*ce), active);
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun CE_TRACE(ce, "retire runtime: { total:%lluns, avg:%lluns }\n",
336*4882a593Smuzhiyun intel_context_get_total_runtime_ns(ce),
337*4882a593Smuzhiyun intel_context_get_avg_runtime_ns(ce));
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun set_bit(CONTEXT_VALID_BIT, &ce->flags);
340*4882a593Smuzhiyun intel_context_post_unpin(ce);
341*4882a593Smuzhiyun intel_context_put(ce);
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
__intel_context_active(struct i915_active * active)344*4882a593Smuzhiyun static int __intel_context_active(struct i915_active *active)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun struct intel_context *ce = container_of(active, typeof(*ce), active);
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun intel_context_get(ce);
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun /* everything should already be activated by intel_context_pre_pin() */
351*4882a593Smuzhiyun GEM_WARN_ON(!i915_active_acquire_if_busy(&ce->ring->vma->active));
352*4882a593Smuzhiyun __intel_ring_pin(ce->ring);
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun __intel_timeline_pin(ce->timeline);
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun if (ce->state) {
357*4882a593Smuzhiyun GEM_WARN_ON(!i915_active_acquire_if_busy(&ce->state->active));
358*4882a593Smuzhiyun __i915_vma_pin(ce->state);
359*4882a593Smuzhiyun i915_vma_make_unshrinkable(ce->state);
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun return 0;
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun void
intel_context_init(struct intel_context * ce,struct intel_engine_cs * engine)366*4882a593Smuzhiyun intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine)
367*4882a593Smuzhiyun {
368*4882a593Smuzhiyun GEM_BUG_ON(!engine->cops);
369*4882a593Smuzhiyun GEM_BUG_ON(!engine->gt->vm);
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun kref_init(&ce->ref);
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun ce->engine = engine;
374*4882a593Smuzhiyun ce->ops = engine->cops;
375*4882a593Smuzhiyun ce->sseu = engine->sseu;
376*4882a593Smuzhiyun ce->ring = __intel_context_ring_size(SZ_4K);
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun ewma_runtime_init(&ce->runtime.avg);
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun ce->vm = i915_vm_get(engine->gt->vm);
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun /* NB ce->signal_link/lock is used under RCU */
383*4882a593Smuzhiyun spin_lock_init(&ce->signal_lock);
384*4882a593Smuzhiyun INIT_LIST_HEAD(&ce->signals);
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun mutex_init(&ce->pin_mutex);
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun i915_active_init(&ce->active,
389*4882a593Smuzhiyun __intel_context_active, __intel_context_retire);
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun
intel_context_fini(struct intel_context * ce)392*4882a593Smuzhiyun void intel_context_fini(struct intel_context *ce)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun if (ce->timeline)
395*4882a593Smuzhiyun intel_timeline_put(ce->timeline);
396*4882a593Smuzhiyun i915_vm_put(ce->vm);
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun mutex_destroy(&ce->pin_mutex);
399*4882a593Smuzhiyun i915_active_fini(&ce->active);
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun
i915_global_context_shrink(void)402*4882a593Smuzhiyun static void i915_global_context_shrink(void)
403*4882a593Smuzhiyun {
404*4882a593Smuzhiyun kmem_cache_shrink(global.slab_ce);
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun
i915_global_context_exit(void)407*4882a593Smuzhiyun static void i915_global_context_exit(void)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun kmem_cache_destroy(global.slab_ce);
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun static struct i915_global_context global = { {
413*4882a593Smuzhiyun .shrink = i915_global_context_shrink,
414*4882a593Smuzhiyun .exit = i915_global_context_exit,
415*4882a593Smuzhiyun } };
416*4882a593Smuzhiyun
i915_global_context_init(void)417*4882a593Smuzhiyun int __init i915_global_context_init(void)
418*4882a593Smuzhiyun {
419*4882a593Smuzhiyun global.slab_ce = KMEM_CACHE(intel_context, SLAB_HWCACHE_ALIGN);
420*4882a593Smuzhiyun if (!global.slab_ce)
421*4882a593Smuzhiyun return -ENOMEM;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun i915_global_register(&global.base);
424*4882a593Smuzhiyun return 0;
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun
intel_context_enter_engine(struct intel_context * ce)427*4882a593Smuzhiyun void intel_context_enter_engine(struct intel_context *ce)
428*4882a593Smuzhiyun {
429*4882a593Smuzhiyun intel_engine_pm_get(ce->engine);
430*4882a593Smuzhiyun intel_timeline_enter(ce->timeline);
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun
intel_context_exit_engine(struct intel_context * ce)433*4882a593Smuzhiyun void intel_context_exit_engine(struct intel_context *ce)
434*4882a593Smuzhiyun {
435*4882a593Smuzhiyun intel_timeline_exit(ce->timeline);
436*4882a593Smuzhiyun intel_engine_pm_put(ce->engine);
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun
intel_context_prepare_remote_request(struct intel_context * ce,struct i915_request * rq)439*4882a593Smuzhiyun int intel_context_prepare_remote_request(struct intel_context *ce,
440*4882a593Smuzhiyun struct i915_request *rq)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun struct intel_timeline *tl = ce->timeline;
443*4882a593Smuzhiyun int err;
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun /* Only suitable for use in remotely modifying this context */
446*4882a593Smuzhiyun GEM_BUG_ON(rq->context == ce);
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun if (rcu_access_pointer(rq->timeline) != tl) { /* timeline sharing! */
449*4882a593Smuzhiyun /* Queue this switch after current activity by this context. */
450*4882a593Smuzhiyun err = i915_active_fence_set(&tl->last_request, rq);
451*4882a593Smuzhiyun if (err)
452*4882a593Smuzhiyun return err;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun /*
456*4882a593Smuzhiyun * Guarantee context image and the timeline remains pinned until the
457*4882a593Smuzhiyun * modifying request is retired by setting the ce activity tracker.
458*4882a593Smuzhiyun *
459*4882a593Smuzhiyun * But we only need to take one pin on the account of it. Or in other
460*4882a593Smuzhiyun * words transfer the pinned ce object to tracked active request.
461*4882a593Smuzhiyun */
462*4882a593Smuzhiyun GEM_BUG_ON(i915_active_is_idle(&ce->active));
463*4882a593Smuzhiyun return i915_active_add_request(&ce->active, rq);
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun
intel_context_create_request(struct intel_context * ce)466*4882a593Smuzhiyun struct i915_request *intel_context_create_request(struct intel_context *ce)
467*4882a593Smuzhiyun {
468*4882a593Smuzhiyun struct i915_gem_ww_ctx ww;
469*4882a593Smuzhiyun struct i915_request *rq;
470*4882a593Smuzhiyun int err;
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun i915_gem_ww_ctx_init(&ww, true);
473*4882a593Smuzhiyun retry:
474*4882a593Smuzhiyun err = intel_context_pin_ww(ce, &ww);
475*4882a593Smuzhiyun if (!err) {
476*4882a593Smuzhiyun rq = i915_request_create(ce);
477*4882a593Smuzhiyun intel_context_unpin(ce);
478*4882a593Smuzhiyun } else if (err == -EDEADLK) {
479*4882a593Smuzhiyun err = i915_gem_ww_ctx_backoff(&ww);
480*4882a593Smuzhiyun if (!err)
481*4882a593Smuzhiyun goto retry;
482*4882a593Smuzhiyun rq = ERR_PTR(err);
483*4882a593Smuzhiyun } else {
484*4882a593Smuzhiyun rq = ERR_PTR(err);
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun i915_gem_ww_ctx_fini(&ww);
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun if (IS_ERR(rq))
490*4882a593Smuzhiyun return rq;
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun /*
493*4882a593Smuzhiyun * timeline->mutex should be the inner lock, but is used as outer lock.
494*4882a593Smuzhiyun * Hack around this to shut up lockdep in selftests..
495*4882a593Smuzhiyun */
496*4882a593Smuzhiyun lockdep_unpin_lock(&ce->timeline->mutex, rq->cookie);
497*4882a593Smuzhiyun mutex_release(&ce->timeline->mutex.dep_map, _RET_IP_);
498*4882a593Smuzhiyun mutex_acquire(&ce->timeline->mutex.dep_map, SINGLE_DEPTH_NESTING, 0, _RET_IP_);
499*4882a593Smuzhiyun rq->cookie = lockdep_pin_lock(&ce->timeline->mutex);
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun return rq;
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
505*4882a593Smuzhiyun #include "selftest_context.c"
506*4882a593Smuzhiyun #endif
507