xref: /openbsd-src/sys/dev/pci/drm/i915/gt/intel_context.c (revision a35b0b997b656f4b852d6265883c726c4f0adfc9)
15ca02815Sjsg // SPDX-License-Identifier: MIT
2c349dbc7Sjsg /*
3c349dbc7Sjsg  * Copyright © 2019 Intel Corporation
4c349dbc7Sjsg  */
5c349dbc7Sjsg 
6c349dbc7Sjsg #include "gem/i915_gem_context.h"
7c349dbc7Sjsg #include "gem/i915_gem_pm.h"
8c349dbc7Sjsg 
9c349dbc7Sjsg #include "i915_drv.h"
105ca02815Sjsg #include "i915_trace.h"
11c349dbc7Sjsg 
12c349dbc7Sjsg #include "intel_context.h"
13c349dbc7Sjsg #include "intel_engine.h"
14c349dbc7Sjsg #include "intel_engine_pm.h"
15c349dbc7Sjsg #include "intel_ring.h"
16c349dbc7Sjsg 
175ca02815Sjsg static struct pool slab_ce;
18c349dbc7Sjsg 
19c349dbc7Sjsg static struct intel_context *intel_context_alloc(void)
20c349dbc7Sjsg {
21c349dbc7Sjsg #ifdef __linux__
225ca02815Sjsg 	return kmem_cache_zalloc(slab_ce, GFP_KERNEL);
23c349dbc7Sjsg #else
245ca02815Sjsg 	return pool_get(&slab_ce, PR_WAITOK | PR_ZERO);
25c349dbc7Sjsg #endif
26c349dbc7Sjsg }
27c349dbc7Sjsg 
28ad8b1aafSjsg static void rcu_context_free(struct rcu_head *rcu)
29c349dbc7Sjsg {
30ad8b1aafSjsg 	struct intel_context *ce = container_of(rcu, typeof(*ce), rcu);
31ad8b1aafSjsg 
325ca02815Sjsg 	trace_intel_context_free(ce);
33c349dbc7Sjsg #ifdef __linux__
345ca02815Sjsg 	kmem_cache_free(slab_ce, ce);
35c349dbc7Sjsg #else
365ca02815Sjsg 	pool_put(&slab_ce, ce);
37c349dbc7Sjsg #endif
38c349dbc7Sjsg }
39c349dbc7Sjsg 
40ad8b1aafSjsg void intel_context_free(struct intel_context *ce)
41ad8b1aafSjsg {
42ad8b1aafSjsg 	call_rcu(&ce->rcu, rcu_context_free);
43ad8b1aafSjsg }
44ad8b1aafSjsg 
45c349dbc7Sjsg struct intel_context *
46c349dbc7Sjsg intel_context_create(struct intel_engine_cs *engine)
47c349dbc7Sjsg {
48c349dbc7Sjsg 	struct intel_context *ce;
49c349dbc7Sjsg 
50c349dbc7Sjsg 	ce = intel_context_alloc();
51c349dbc7Sjsg 	if (!ce)
52c349dbc7Sjsg 		return ERR_PTR(-ENOMEM);
53c349dbc7Sjsg 
54c349dbc7Sjsg 	intel_context_init(ce, engine);
555ca02815Sjsg 	trace_intel_context_create(ce);
56c349dbc7Sjsg 	return ce;
57c349dbc7Sjsg }
58c349dbc7Sjsg 
59c349dbc7Sjsg int intel_context_alloc_state(struct intel_context *ce)
60c349dbc7Sjsg {
61c349dbc7Sjsg 	int err = 0;
62c349dbc7Sjsg 
63c349dbc7Sjsg 	if (mutex_lock_interruptible(&ce->pin_mutex))
64c349dbc7Sjsg 		return -EINTR;
65c349dbc7Sjsg 
66c349dbc7Sjsg 	if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
67c349dbc7Sjsg 		if (intel_context_is_banned(ce)) {
68c349dbc7Sjsg 			err = -EIO;
69c349dbc7Sjsg 			goto unlock;
70c349dbc7Sjsg 		}
71c349dbc7Sjsg 
72c349dbc7Sjsg 		err = ce->ops->alloc(ce);
73c349dbc7Sjsg 		if (unlikely(err))
74c349dbc7Sjsg 			goto unlock;
75c349dbc7Sjsg 
76c349dbc7Sjsg 		set_bit(CONTEXT_ALLOC_BIT, &ce->flags);
77c349dbc7Sjsg 	}
78c349dbc7Sjsg 
79c349dbc7Sjsg unlock:
80c349dbc7Sjsg 	mutex_unlock(&ce->pin_mutex);
81c349dbc7Sjsg 	return err;
82c349dbc7Sjsg }
83c349dbc7Sjsg 
84c349dbc7Sjsg static int intel_context_active_acquire(struct intel_context *ce)
85c349dbc7Sjsg {
86c349dbc7Sjsg 	int err;
87c349dbc7Sjsg 
88c349dbc7Sjsg 	__i915_active_acquire(&ce->active);
89c349dbc7Sjsg 
901bb76ff1Sjsg 	if (intel_context_is_barrier(ce) || intel_engine_uses_guc(ce->engine) ||
911bb76ff1Sjsg 	    intel_context_is_parallel(ce))
92c349dbc7Sjsg 		return 0;
93c349dbc7Sjsg 
94c349dbc7Sjsg 	/* Preallocate tracking nodes */
95c349dbc7Sjsg 	err = i915_active_acquire_preallocate_barrier(&ce->active,
96c349dbc7Sjsg 						      ce->engine);
97c349dbc7Sjsg 	if (err)
98c349dbc7Sjsg 		i915_active_release(&ce->active);
99c349dbc7Sjsg 
100c349dbc7Sjsg 	return err;
101c349dbc7Sjsg }
102c349dbc7Sjsg 
103c349dbc7Sjsg static void intel_context_active_release(struct intel_context *ce)
104c349dbc7Sjsg {
105c349dbc7Sjsg 	/* Nodes preallocated in intel_context_active() */
106c349dbc7Sjsg 	i915_active_acquire_barrier(&ce->active);
107c349dbc7Sjsg 	i915_active_release(&ce->active);
108c349dbc7Sjsg }
109c349dbc7Sjsg 
110ad8b1aafSjsg static int __context_pin_state(struct i915_vma *vma, struct i915_gem_ww_ctx *ww)
111c349dbc7Sjsg {
112c349dbc7Sjsg 	unsigned int bias = i915_ggtt_pin_bias(vma) | PIN_OFFSET_BIAS;
113c349dbc7Sjsg 	int err;
114c349dbc7Sjsg 
115ad8b1aafSjsg 	err = i915_ggtt_pin(vma, ww, 0, bias | PIN_HIGH);
116c349dbc7Sjsg 	if (err)
117c349dbc7Sjsg 		return err;
118c349dbc7Sjsg 
119c349dbc7Sjsg 	err = i915_active_acquire(&vma->active);
120c349dbc7Sjsg 	if (err)
121c349dbc7Sjsg 		goto err_unpin;
122c349dbc7Sjsg 
123c349dbc7Sjsg 	/*
124c349dbc7Sjsg 	 * And mark it as a globally pinned object to let the shrinker know
125c349dbc7Sjsg 	 * it cannot reclaim the object until we release it.
126c349dbc7Sjsg 	 */
127c349dbc7Sjsg 	i915_vma_make_unshrinkable(vma);
128c349dbc7Sjsg 	vma->obj->mm.dirty = true;
129c349dbc7Sjsg 
130c349dbc7Sjsg 	return 0;
131c349dbc7Sjsg 
132c349dbc7Sjsg err_unpin:
133c349dbc7Sjsg 	i915_vma_unpin(vma);
134c349dbc7Sjsg 	return err;
135c349dbc7Sjsg }
136c349dbc7Sjsg 
137c349dbc7Sjsg static void __context_unpin_state(struct i915_vma *vma)
138c349dbc7Sjsg {
139c349dbc7Sjsg 	i915_vma_make_shrinkable(vma);
140c349dbc7Sjsg 	i915_active_release(&vma->active);
141c349dbc7Sjsg 	__i915_vma_unpin(vma);
142c349dbc7Sjsg }
143c349dbc7Sjsg 
144ad8b1aafSjsg static int __ring_active(struct intel_ring *ring,
145ad8b1aafSjsg 			 struct i915_gem_ww_ctx *ww)
146c349dbc7Sjsg {
147c349dbc7Sjsg 	int err;
148c349dbc7Sjsg 
149ad8b1aafSjsg 	err = intel_ring_pin(ring, ww);
150c349dbc7Sjsg 	if (err)
151c349dbc7Sjsg 		return err;
152c349dbc7Sjsg 
15315914761Sjsg 	err = i915_active_acquire(&ring->vma->active);
154c349dbc7Sjsg 	if (err)
15515914761Sjsg 		goto err_pin;
156c349dbc7Sjsg 
157c349dbc7Sjsg 	return 0;
158c349dbc7Sjsg 
15915914761Sjsg err_pin:
16015914761Sjsg 	intel_ring_unpin(ring);
161c349dbc7Sjsg 	return err;
162c349dbc7Sjsg }
163c349dbc7Sjsg 
164c349dbc7Sjsg static void __ring_retire(struct intel_ring *ring)
165c349dbc7Sjsg {
166c349dbc7Sjsg 	i915_active_release(&ring->vma->active);
16715914761Sjsg 	intel_ring_unpin(ring);
168c349dbc7Sjsg }
169c349dbc7Sjsg 
170ad8b1aafSjsg static int intel_context_pre_pin(struct intel_context *ce,
171ad8b1aafSjsg 				 struct i915_gem_ww_ctx *ww)
172ad8b1aafSjsg {
173ad8b1aafSjsg 	int err;
174ad8b1aafSjsg 
175ad8b1aafSjsg 	CE_TRACE(ce, "active\n");
176ad8b1aafSjsg 
177ad8b1aafSjsg 	err = __ring_active(ce->ring, ww);
178ad8b1aafSjsg 	if (err)
179ad8b1aafSjsg 		return err;
180ad8b1aafSjsg 
181ad8b1aafSjsg 	err = intel_timeline_pin(ce->timeline, ww);
182ad8b1aafSjsg 	if (err)
183ad8b1aafSjsg 		goto err_ring;
184ad8b1aafSjsg 
185ad8b1aafSjsg 	if (!ce->state)
186ad8b1aafSjsg 		return 0;
187ad8b1aafSjsg 
188ad8b1aafSjsg 	err = __context_pin_state(ce->state, ww);
189ad8b1aafSjsg 	if (err)
190ad8b1aafSjsg 		goto err_timeline;
191ad8b1aafSjsg 
192ad8b1aafSjsg 
193ad8b1aafSjsg 	return 0;
194ad8b1aafSjsg 
195ad8b1aafSjsg err_timeline:
196ad8b1aafSjsg 	intel_timeline_unpin(ce->timeline);
197ad8b1aafSjsg err_ring:
198ad8b1aafSjsg 	__ring_retire(ce->ring);
199ad8b1aafSjsg 	return err;
200ad8b1aafSjsg }
201ad8b1aafSjsg 
202ad8b1aafSjsg static void intel_context_post_unpin(struct intel_context *ce)
203ad8b1aafSjsg {
204ad8b1aafSjsg 	if (ce->state)
205ad8b1aafSjsg 		__context_unpin_state(ce->state);
206ad8b1aafSjsg 
207ad8b1aafSjsg 	intel_timeline_unpin(ce->timeline);
208ad8b1aafSjsg 	__ring_retire(ce->ring);
209ad8b1aafSjsg }
210ad8b1aafSjsg 
211ad8b1aafSjsg int __intel_context_do_pin_ww(struct intel_context *ce,
212ad8b1aafSjsg 			      struct i915_gem_ww_ctx *ww)
213ad8b1aafSjsg {
214ad8b1aafSjsg 	bool handoff = false;
215ad8b1aafSjsg 	void *vaddr;
216ad8b1aafSjsg 	int err = 0;
217ad8b1aafSjsg 
218ad8b1aafSjsg 	if (unlikely(!test_bit(CONTEXT_ALLOC_BIT, &ce->flags))) {
219ad8b1aafSjsg 		err = intel_context_alloc_state(ce);
220ad8b1aafSjsg 		if (err)
221ad8b1aafSjsg 			return err;
222ad8b1aafSjsg 	}
223ad8b1aafSjsg 
224ad8b1aafSjsg 	/*
225ad8b1aafSjsg 	 * We always pin the context/ring/timeline here, to ensure a pin
226ad8b1aafSjsg 	 * refcount for __intel_context_active(), which prevent a lock
227ad8b1aafSjsg 	 * inversion of ce->pin_mutex vs dma_resv_lock().
228ad8b1aafSjsg 	 */
229ad8b1aafSjsg 
230ad8b1aafSjsg 	err = i915_gem_object_lock(ce->timeline->hwsp_ggtt->obj, ww);
2311bb76ff1Sjsg 	if (!err)
232ad8b1aafSjsg 		err = i915_gem_object_lock(ce->ring->vma->obj, ww);
233ad8b1aafSjsg 	if (!err && ce->state)
234ad8b1aafSjsg 		err = i915_gem_object_lock(ce->state->obj, ww);
235ad8b1aafSjsg 	if (!err)
236ad8b1aafSjsg 		err = intel_context_pre_pin(ce, ww);
237ad8b1aafSjsg 	if (err)
238ad8b1aafSjsg 		return err;
239ad8b1aafSjsg 
2401bb76ff1Sjsg 	err = ce->ops->pre_pin(ce, ww, &vaddr);
241ad8b1aafSjsg 	if (err)
242ad8b1aafSjsg 		goto err_ctx_unpin;
243ad8b1aafSjsg 
2441bb76ff1Sjsg 	err = i915_active_acquire(&ce->active);
245ad8b1aafSjsg 	if (err)
2461bb76ff1Sjsg 		goto err_post_unpin;
247ad8b1aafSjsg 
248ad8b1aafSjsg 	err = mutex_lock_interruptible(&ce->pin_mutex);
249ad8b1aafSjsg 	if (err)
2501bb76ff1Sjsg 		goto err_release;
2511bb76ff1Sjsg 
2521bb76ff1Sjsg 	intel_engine_pm_might_get(ce->engine);
253ad8b1aafSjsg 
254ad8b1aafSjsg 	if (unlikely(intel_context_is_closed(ce))) {
255ad8b1aafSjsg 		err = -ENOENT;
256ad8b1aafSjsg 		goto err_unlock;
257ad8b1aafSjsg 	}
258ad8b1aafSjsg 
259ad8b1aafSjsg 	if (likely(!atomic_add_unless(&ce->pin_count, 1, 0))) {
260ad8b1aafSjsg 		err = intel_context_active_acquire(ce);
261ad8b1aafSjsg 		if (unlikely(err))
262ad8b1aafSjsg 			goto err_unlock;
263ad8b1aafSjsg 
264ad8b1aafSjsg 		err = ce->ops->pin(ce, vaddr);
265ad8b1aafSjsg 		if (err) {
266ad8b1aafSjsg 			intel_context_active_release(ce);
267ad8b1aafSjsg 			goto err_unlock;
268ad8b1aafSjsg 		}
269ad8b1aafSjsg 
270ad8b1aafSjsg 		CE_TRACE(ce, "pin ring:{start:%08x, head:%04x, tail:%04x}\n",
271ad8b1aafSjsg 			 i915_ggtt_offset(ce->ring->vma),
272ad8b1aafSjsg 			 ce->ring->head, ce->ring->tail);
273ad8b1aafSjsg 
274ad8b1aafSjsg 		handoff = true;
275ad8b1aafSjsg 		smp_mb__before_atomic(); /* flush pin before it is visible */
276ad8b1aafSjsg 		atomic_inc(&ce->pin_count);
277ad8b1aafSjsg 	}
278ad8b1aafSjsg 
279ad8b1aafSjsg 	GEM_BUG_ON(!intel_context_is_pinned(ce)); /* no overflow! */
280ad8b1aafSjsg 
2815ca02815Sjsg 	trace_intel_context_do_pin(ce);
2825ca02815Sjsg 
283ad8b1aafSjsg err_unlock:
284ad8b1aafSjsg 	mutex_unlock(&ce->pin_mutex);
2851bb76ff1Sjsg err_release:
2861bb76ff1Sjsg 	i915_active_release(&ce->active);
287ad8b1aafSjsg err_post_unpin:
288ad8b1aafSjsg 	if (!handoff)
289ad8b1aafSjsg 		ce->ops->post_unpin(ce);
290ad8b1aafSjsg err_ctx_unpin:
291ad8b1aafSjsg 	intel_context_post_unpin(ce);
292ad8b1aafSjsg 
293ad8b1aafSjsg 	/*
294ad8b1aafSjsg 	 * Unlock the hwsp_ggtt object since it's shared.
295ad8b1aafSjsg 	 * In principle we can unlock all the global state locked above
296ad8b1aafSjsg 	 * since it's pinned and doesn't need fencing, and will
297ad8b1aafSjsg 	 * thus remain resident until it is explicitly unpinned.
298ad8b1aafSjsg 	 */
299ad8b1aafSjsg 	i915_gem_ww_unlock_single(ce->timeline->hwsp_ggtt->obj);
300ad8b1aafSjsg 
301ad8b1aafSjsg 	return err;
302ad8b1aafSjsg }
303ad8b1aafSjsg 
304ad8b1aafSjsg int __intel_context_do_pin(struct intel_context *ce)
305ad8b1aafSjsg {
306ad8b1aafSjsg 	struct i915_gem_ww_ctx ww;
307ad8b1aafSjsg 	int err;
308ad8b1aafSjsg 
309ad8b1aafSjsg 	i915_gem_ww_ctx_init(&ww, true);
310ad8b1aafSjsg retry:
311ad8b1aafSjsg 	err = __intel_context_do_pin_ww(ce, &ww);
312ad8b1aafSjsg 	if (err == -EDEADLK) {
313ad8b1aafSjsg 		err = i915_gem_ww_ctx_backoff(&ww);
314ad8b1aafSjsg 		if (!err)
315ad8b1aafSjsg 			goto retry;
316ad8b1aafSjsg 	}
317ad8b1aafSjsg 	i915_gem_ww_ctx_fini(&ww);
318ad8b1aafSjsg 	return err;
319ad8b1aafSjsg }
320ad8b1aafSjsg 
3215ca02815Sjsg void __intel_context_do_unpin(struct intel_context *ce, int sub)
322ad8b1aafSjsg {
3235ca02815Sjsg 	if (!atomic_sub_and_test(sub, &ce->pin_count))
324ad8b1aafSjsg 		return;
325ad8b1aafSjsg 
326ad8b1aafSjsg 	CE_TRACE(ce, "unpin\n");
327ad8b1aafSjsg 	ce->ops->unpin(ce);
328ad8b1aafSjsg 	ce->ops->post_unpin(ce);
329ad8b1aafSjsg 
330ad8b1aafSjsg 	/*
331ad8b1aafSjsg 	 * Once released, we may asynchronously drop the active reference.
332ad8b1aafSjsg 	 * As that may be the only reference keeping the context alive,
333ad8b1aafSjsg 	 * take an extra now so that it is not freed before we finish
334ad8b1aafSjsg 	 * dereferencing it.
335ad8b1aafSjsg 	 */
336ad8b1aafSjsg 	intel_context_get(ce);
337ad8b1aafSjsg 	intel_context_active_release(ce);
3385ca02815Sjsg 	trace_intel_context_do_unpin(ce);
339ad8b1aafSjsg 	intel_context_put(ce);
340ad8b1aafSjsg }
341ad8b1aafSjsg 
342c349dbc7Sjsg static void __intel_context_retire(struct i915_active *active)
343c349dbc7Sjsg {
344c349dbc7Sjsg 	struct intel_context *ce = container_of(active, typeof(*ce), active);
345c349dbc7Sjsg 
346c349dbc7Sjsg 	CE_TRACE(ce, "retire runtime: { total:%lluns, avg:%lluns }\n",
347c349dbc7Sjsg 		 intel_context_get_total_runtime_ns(ce),
348c349dbc7Sjsg 		 intel_context_get_avg_runtime_ns(ce));
349c349dbc7Sjsg 
350c349dbc7Sjsg 	set_bit(CONTEXT_VALID_BIT, &ce->flags);
351ad8b1aafSjsg 	intel_context_post_unpin(ce);
352c349dbc7Sjsg 	intel_context_put(ce);
353c349dbc7Sjsg }
354c349dbc7Sjsg 
355c349dbc7Sjsg static int __intel_context_active(struct i915_active *active)
356c349dbc7Sjsg {
357c349dbc7Sjsg 	struct intel_context *ce = container_of(active, typeof(*ce), active);
358c349dbc7Sjsg 
359c349dbc7Sjsg 	intel_context_get(ce);
360c349dbc7Sjsg 
361ad8b1aafSjsg 	/* everything should already be activated by intel_context_pre_pin() */
362ad8b1aafSjsg 	GEM_WARN_ON(!i915_active_acquire_if_busy(&ce->ring->vma->active));
363ad8b1aafSjsg 	__intel_ring_pin(ce->ring);
364c349dbc7Sjsg 
365ad8b1aafSjsg 	__intel_timeline_pin(ce->timeline);
366c349dbc7Sjsg 
367ad8b1aafSjsg 	if (ce->state) {
368ad8b1aafSjsg 		GEM_WARN_ON(!i915_active_acquire_if_busy(&ce->state->active));
369ad8b1aafSjsg 		__i915_vma_pin(ce->state);
370ad8b1aafSjsg 		i915_vma_make_unshrinkable(ce->state);
371ad8b1aafSjsg 	}
372c349dbc7Sjsg 
373c349dbc7Sjsg 	return 0;
374c349dbc7Sjsg }
375c349dbc7Sjsg 
3761bb76ff1Sjsg static int
3775ca02815Sjsg sw_fence_dummy_notify(struct i915_sw_fence *sf,
3785ca02815Sjsg 		      enum i915_sw_fence_notify state)
3795ca02815Sjsg {
3805ca02815Sjsg 	return NOTIFY_DONE;
3815ca02815Sjsg }
3825ca02815Sjsg 
383c349dbc7Sjsg void
384ad8b1aafSjsg intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine)
385c349dbc7Sjsg {
386c349dbc7Sjsg 	GEM_BUG_ON(!engine->cops);
387c349dbc7Sjsg 	GEM_BUG_ON(!engine->gt->vm);
388c349dbc7Sjsg 
389c349dbc7Sjsg 	kref_init(&ce->ref);
390c349dbc7Sjsg 
391c349dbc7Sjsg 	ce->engine = engine;
392c349dbc7Sjsg 	ce->ops = engine->cops;
393c349dbc7Sjsg 	ce->sseu = engine->sseu;
3945ca02815Sjsg 	ce->ring = NULL;
3955ca02815Sjsg 	ce->ring_size = SZ_4K;
396c349dbc7Sjsg 
3971bb76ff1Sjsg 	ewma_runtime_init(&ce->stats.runtime.avg);
398c349dbc7Sjsg 
399c349dbc7Sjsg 	ce->vm = i915_vm_get(engine->gt->vm);
400c349dbc7Sjsg 
401ad8b1aafSjsg 	/* NB ce->signal_link/lock is used under RCU */
402ad8b1aafSjsg 	mtx_init(&ce->signal_lock, IPL_NONE);
403c349dbc7Sjsg 	INIT_LIST_HEAD(&ce->signals);
404c349dbc7Sjsg 
405c349dbc7Sjsg 	rw_init(&ce->pin_mutex, "cepin");
406c349dbc7Sjsg 
407*a35b0b99Sjsg 	mtx_init(&ce->guc_state.lock, IPL_TTY);
4085ca02815Sjsg 	INIT_LIST_HEAD(&ce->guc_state.fences);
4091bb76ff1Sjsg 	INIT_LIST_HEAD(&ce->guc_state.requests);
4105ca02815Sjsg 
4111bb76ff1Sjsg 	ce->guc_id.id = GUC_INVALID_CONTEXT_ID;
4121bb76ff1Sjsg 	INIT_LIST_HEAD(&ce->guc_id.link);
4135ca02815Sjsg 
4141bb76ff1Sjsg 	INIT_LIST_HEAD(&ce->destroyed_link);
4151bb76ff1Sjsg 
4161bb76ff1Sjsg 	INIT_LIST_HEAD(&ce->parallel.child_list);
4175ca02815Sjsg 
4185ca02815Sjsg 	/*
4195ca02815Sjsg 	 * Initialize fence to be complete as this is expected to be complete
4205ca02815Sjsg 	 * unless there is a pending schedule disable outstanding.
4215ca02815Sjsg 	 */
4221bb76ff1Sjsg 	i915_sw_fence_init(&ce->guc_state.blocked,
4231bb76ff1Sjsg 			   sw_fence_dummy_notify);
4241bb76ff1Sjsg 	i915_sw_fence_commit(&ce->guc_state.blocked);
4255ca02815Sjsg 
426c349dbc7Sjsg 	i915_active_init(&ce->active,
4275ca02815Sjsg 			 __intel_context_active, __intel_context_retire, 0);
428c349dbc7Sjsg }
429c349dbc7Sjsg 
430c349dbc7Sjsg void intel_context_fini(struct intel_context *ce)
431c349dbc7Sjsg {
4321bb76ff1Sjsg 	struct intel_context *child, *next;
4331bb76ff1Sjsg 
434c349dbc7Sjsg 	if (ce->timeline)
435c349dbc7Sjsg 		intel_timeline_put(ce->timeline);
436c349dbc7Sjsg 	i915_vm_put(ce->vm);
437c349dbc7Sjsg 
4381bb76ff1Sjsg 	/* Need to put the creation ref for the children */
4391bb76ff1Sjsg 	if (intel_context_is_parent(ce))
4401bb76ff1Sjsg 		for_each_child_safe(ce, child, next)
4411bb76ff1Sjsg 			intel_context_put(child);
4421bb76ff1Sjsg 
443c349dbc7Sjsg 	mutex_destroy(&ce->pin_mutex);
444c349dbc7Sjsg 	i915_active_fini(&ce->active);
4451bb76ff1Sjsg 	i915_sw_fence_fini(&ce->guc_state.blocked);
446c349dbc7Sjsg }
447c349dbc7Sjsg 
4485ca02815Sjsg void i915_context_module_exit(void)
449c349dbc7Sjsg {
450c349dbc7Sjsg #ifdef __linux__
4515ca02815Sjsg 	kmem_cache_destroy(slab_ce);
452c349dbc7Sjsg #else
4535ca02815Sjsg 	pool_destroy(&slab_ce);
454c349dbc7Sjsg #endif
455c349dbc7Sjsg }
456c349dbc7Sjsg 
4575ca02815Sjsg int __init i915_context_module_init(void)
458c349dbc7Sjsg {
459c349dbc7Sjsg #ifdef __linux__
4605ca02815Sjsg 	slab_ce = KMEM_CACHE(intel_context, SLAB_HWCACHE_ALIGN);
4615ca02815Sjsg 	if (!slab_ce)
462c349dbc7Sjsg 		return -ENOMEM;
463c349dbc7Sjsg #else
4645ca02815Sjsg 	pool_init(&slab_ce, sizeof(struct intel_context),
4650f557061Sjsg 	    CACHELINESIZE, IPL_TTY, 0, "ictx", NULL);
466c349dbc7Sjsg #endif
467c349dbc7Sjsg 
468c349dbc7Sjsg 	return 0;
469c349dbc7Sjsg }
470c349dbc7Sjsg 
471c349dbc7Sjsg void intel_context_enter_engine(struct intel_context *ce)
472c349dbc7Sjsg {
473c349dbc7Sjsg 	intel_engine_pm_get(ce->engine);
474c349dbc7Sjsg 	intel_timeline_enter(ce->timeline);
475c349dbc7Sjsg }
476c349dbc7Sjsg 
477c349dbc7Sjsg void intel_context_exit_engine(struct intel_context *ce)
478c349dbc7Sjsg {
479c349dbc7Sjsg 	intel_timeline_exit(ce->timeline);
480c349dbc7Sjsg 	intel_engine_pm_put(ce->engine);
481c349dbc7Sjsg }
482c349dbc7Sjsg 
483c349dbc7Sjsg int intel_context_prepare_remote_request(struct intel_context *ce,
484c349dbc7Sjsg 					 struct i915_request *rq)
485c349dbc7Sjsg {
486c349dbc7Sjsg 	struct intel_timeline *tl = ce->timeline;
487c349dbc7Sjsg 	int err;
488c349dbc7Sjsg 
489c349dbc7Sjsg 	/* Only suitable for use in remotely modifying this context */
490c349dbc7Sjsg 	GEM_BUG_ON(rq->context == ce);
491c349dbc7Sjsg 
492c349dbc7Sjsg 	if (rcu_access_pointer(rq->timeline) != tl) { /* timeline sharing! */
493c349dbc7Sjsg 		/* Queue this switch after current activity by this context. */
494c349dbc7Sjsg 		err = i915_active_fence_set(&tl->last_request, rq);
495c349dbc7Sjsg 		if (err)
496c349dbc7Sjsg 			return err;
497c349dbc7Sjsg 	}
498c349dbc7Sjsg 
499c349dbc7Sjsg 	/*
500c349dbc7Sjsg 	 * Guarantee context image and the timeline remains pinned until the
501c349dbc7Sjsg 	 * modifying request is retired by setting the ce activity tracker.
502c349dbc7Sjsg 	 *
503c349dbc7Sjsg 	 * But we only need to take one pin on the account of it. Or in other
504c349dbc7Sjsg 	 * words transfer the pinned ce object to tracked active request.
505c349dbc7Sjsg 	 */
506c349dbc7Sjsg 	GEM_BUG_ON(i915_active_is_idle(&ce->active));
507c349dbc7Sjsg 	return i915_active_add_request(&ce->active, rq);
508c349dbc7Sjsg }
509c349dbc7Sjsg 
510c349dbc7Sjsg struct i915_request *intel_context_create_request(struct intel_context *ce)
511c349dbc7Sjsg {
512ad8b1aafSjsg 	struct i915_gem_ww_ctx ww;
513c349dbc7Sjsg 	struct i915_request *rq;
514c349dbc7Sjsg 	int err;
515c349dbc7Sjsg 
516ad8b1aafSjsg 	i915_gem_ww_ctx_init(&ww, true);
517ad8b1aafSjsg retry:
518ad8b1aafSjsg 	err = intel_context_pin_ww(ce, &ww);
519ad8b1aafSjsg 	if (!err) {
520c349dbc7Sjsg 		rq = i915_request_create(ce);
521c349dbc7Sjsg 		intel_context_unpin(ce);
522ad8b1aafSjsg 	} else if (err == -EDEADLK) {
523ad8b1aafSjsg 		err = i915_gem_ww_ctx_backoff(&ww);
524ad8b1aafSjsg 		if (!err)
525ad8b1aafSjsg 			goto retry;
526ad8b1aafSjsg 		rq = ERR_PTR(err);
527ad8b1aafSjsg 	} else {
528ad8b1aafSjsg 		rq = ERR_PTR(err);
529ad8b1aafSjsg 	}
530ad8b1aafSjsg 
531ad8b1aafSjsg 	i915_gem_ww_ctx_fini(&ww);
532ad8b1aafSjsg 
533ad8b1aafSjsg 	if (IS_ERR(rq))
534ad8b1aafSjsg 		return rq;
535ad8b1aafSjsg 
536ad8b1aafSjsg 	/*
537ad8b1aafSjsg 	 * timeline->mutex should be the inner lock, but is used as outer lock.
538ad8b1aafSjsg 	 * Hack around this to shut up lockdep in selftests..
539ad8b1aafSjsg 	 */
540ad8b1aafSjsg 	lockdep_unpin_lock(&ce->timeline->mutex, rq->cookie);
541ad8b1aafSjsg 	mutex_release(&ce->timeline->mutex.dep_map, _RET_IP_);
542ad8b1aafSjsg 	mutex_acquire(&ce->timeline->mutex.dep_map, SINGLE_DEPTH_NESTING, 0, _RET_IP_);
543ad8b1aafSjsg 	rq->cookie = lockdep_pin_lock(&ce->timeline->mutex);
544c349dbc7Sjsg 
545c349dbc7Sjsg 	return rq;
546c349dbc7Sjsg }
547c349dbc7Sjsg 
5487c23aa04Sjsg struct i915_request *intel_context_get_active_request(struct intel_context *ce)
5495ca02815Sjsg {
5501bb76ff1Sjsg 	struct intel_context *parent = intel_context_to_parent(ce);
5515ca02815Sjsg 	struct i915_request *rq, *active = NULL;
5525ca02815Sjsg 	unsigned long flags;
5535ca02815Sjsg 
5545ca02815Sjsg 	GEM_BUG_ON(!intel_engine_uses_guc(ce->engine));
5555ca02815Sjsg 
5561bb76ff1Sjsg 	/*
5571bb76ff1Sjsg 	 * We search the parent list to find an active request on the submitted
5581bb76ff1Sjsg 	 * context. The parent list contains the requests for all the contexts
5591bb76ff1Sjsg 	 * in the relationship so we have to do a compare of each request's
5601bb76ff1Sjsg 	 * context.
5611bb76ff1Sjsg 	 */
5621bb76ff1Sjsg 	spin_lock_irqsave(&parent->guc_state.lock, flags);
5631bb76ff1Sjsg 	list_for_each_entry_reverse(rq, &parent->guc_state.requests,
5645ca02815Sjsg 				    sched.link) {
5651bb76ff1Sjsg 		if (rq->context != ce)
5661bb76ff1Sjsg 			continue;
5675ca02815Sjsg 		if (i915_request_completed(rq))
5685ca02815Sjsg 			break;
5695ca02815Sjsg 
5705ca02815Sjsg 		active = rq;
5715ca02815Sjsg 	}
5727c23aa04Sjsg 	if (active)
5737c23aa04Sjsg 		active = i915_request_get_rcu(active);
5741bb76ff1Sjsg 	spin_unlock_irqrestore(&parent->guc_state.lock, flags);
5755ca02815Sjsg 
5765ca02815Sjsg 	return active;
5775ca02815Sjsg }
5785ca02815Sjsg 
5791bb76ff1Sjsg void intel_context_bind_parent_child(struct intel_context *parent,
5801bb76ff1Sjsg 				     struct intel_context *child)
5811bb76ff1Sjsg {
5821bb76ff1Sjsg 	/*
5831bb76ff1Sjsg 	 * Callers responsibility to validate that this function is used
5841bb76ff1Sjsg 	 * correctly but we use GEM_BUG_ON here ensure that they do.
5851bb76ff1Sjsg 	 */
5861bb76ff1Sjsg 	GEM_BUG_ON(intel_context_is_pinned(parent));
5871bb76ff1Sjsg 	GEM_BUG_ON(intel_context_is_child(parent));
5881bb76ff1Sjsg 	GEM_BUG_ON(intel_context_is_pinned(child));
5891bb76ff1Sjsg 	GEM_BUG_ON(intel_context_is_child(child));
5901bb76ff1Sjsg 	GEM_BUG_ON(intel_context_is_parent(child));
5911bb76ff1Sjsg 
5921bb76ff1Sjsg 	parent->parallel.child_index = parent->parallel.number_children++;
5931bb76ff1Sjsg 	list_add_tail(&child->parallel.child_link,
5941bb76ff1Sjsg 		      &parent->parallel.child_list);
5951bb76ff1Sjsg 	child->parallel.parent = parent;
5961bb76ff1Sjsg }
5971bb76ff1Sjsg 
598f005ef32Sjsg u64 intel_context_get_total_runtime_ns(struct intel_context *ce)
5991bb76ff1Sjsg {
6001bb76ff1Sjsg 	u64 total, active;
6011bb76ff1Sjsg 
602f005ef32Sjsg 	if (ce->ops->update_stats)
603f005ef32Sjsg 		ce->ops->update_stats(ce);
604f005ef32Sjsg 
6051bb76ff1Sjsg 	total = ce->stats.runtime.total;
6061bb76ff1Sjsg 	if (ce->ops->flags & COPS_RUNTIME_CYCLES)
6071bb76ff1Sjsg 		total *= ce->engine->gt->clock_period_ns;
6081bb76ff1Sjsg 
6091bb76ff1Sjsg 	active = READ_ONCE(ce->stats.active);
6101bb76ff1Sjsg 	if (active)
6111bb76ff1Sjsg 		active = intel_context_clock() - active;
6121bb76ff1Sjsg 
6131bb76ff1Sjsg 	return total + active;
6141bb76ff1Sjsg }
6151bb76ff1Sjsg 
6161bb76ff1Sjsg u64 intel_context_get_avg_runtime_ns(struct intel_context *ce)
6171bb76ff1Sjsg {
6181bb76ff1Sjsg 	u64 avg = ewma_runtime_read(&ce->stats.runtime.avg);
6191bb76ff1Sjsg 
6201bb76ff1Sjsg 	if (ce->ops->flags & COPS_RUNTIME_CYCLES)
6211bb76ff1Sjsg 		avg *= ce->engine->gt->clock_period_ns;
6221bb76ff1Sjsg 
6231bb76ff1Sjsg 	return avg;
6241bb76ff1Sjsg }
6251bb76ff1Sjsg 
6261bb76ff1Sjsg bool intel_context_ban(struct intel_context *ce, struct i915_request *rq)
6271bb76ff1Sjsg {
6281bb76ff1Sjsg 	bool ret = intel_context_set_banned(ce);
6291bb76ff1Sjsg 
6301bb76ff1Sjsg 	trace_intel_context_ban(ce);
6311bb76ff1Sjsg 
6321bb76ff1Sjsg 	if (ce->ops->revoke)
6331bb76ff1Sjsg 		ce->ops->revoke(ce, rq,
6341bb76ff1Sjsg 				INTEL_CONTEXT_BANNED_PREEMPT_TIMEOUT_MS);
6351bb76ff1Sjsg 
6361bb76ff1Sjsg 	return ret;
6371bb76ff1Sjsg }
6381bb76ff1Sjsg 
6391bb76ff1Sjsg bool intel_context_revoke(struct intel_context *ce)
6401bb76ff1Sjsg {
6411bb76ff1Sjsg 	bool ret = intel_context_set_exiting(ce);
6421bb76ff1Sjsg 
6431bb76ff1Sjsg 	if (ce->ops->revoke)
6441bb76ff1Sjsg 		ce->ops->revoke(ce, NULL, ce->engine->props.preempt_timeout_ms);
6451bb76ff1Sjsg 
6461bb76ff1Sjsg 	return ret;
6471bb76ff1Sjsg }
6481bb76ff1Sjsg 
649c349dbc7Sjsg #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
650c349dbc7Sjsg #include "selftest_context.c"
651c349dbc7Sjsg #endif
652