xref: /openbsd-src/sys/dev/pci/drm/i915/gt/mock_engine.c (revision 1bb76ff151c0aba8e3312a604e4cd2e5195cf4b7)
15ca02815Sjsg // SPDX-License-Identifier: MIT
2c349dbc7Sjsg /*
3c349dbc7Sjsg  * Copyright © 2016 Intel Corporation
4c349dbc7Sjsg  */
5c349dbc7Sjsg 
6c349dbc7Sjsg #include "gem/i915_gem_context.h"
7c349dbc7Sjsg #include "gt/intel_ring.h"
8c349dbc7Sjsg 
9c349dbc7Sjsg #include "i915_drv.h"
10c349dbc7Sjsg #include "intel_context.h"
11c349dbc7Sjsg #include "intel_engine_pm.h"
12c349dbc7Sjsg 
13c349dbc7Sjsg #include "mock_engine.h"
14c349dbc7Sjsg #include "selftests/mock_request.h"
15c349dbc7Sjsg 
mock_timeline_pin(struct intel_timeline * tl)165ca02815Sjsg static int mock_timeline_pin(struct intel_timeline *tl)
17c349dbc7Sjsg {
185ca02815Sjsg 	int err;
195ca02815Sjsg 
20*1bb76ff1Sjsg 	if (WARN_ON(!i915_gem_object_trylock(tl->hwsp_ggtt->obj, NULL)))
215ca02815Sjsg 		return -EBUSY;
225ca02815Sjsg 
235ca02815Sjsg 	err = intel_timeline_pin_map(tl);
245ca02815Sjsg 	i915_gem_object_unlock(tl->hwsp_ggtt->obj);
255ca02815Sjsg 	if (err)
265ca02815Sjsg 		return err;
275ca02815Sjsg 
28c349dbc7Sjsg 	atomic_inc(&tl->pin_count);
295ca02815Sjsg 	return 0;
30c349dbc7Sjsg }
31c349dbc7Sjsg 
mock_timeline_unpin(struct intel_timeline * tl)32c349dbc7Sjsg static void mock_timeline_unpin(struct intel_timeline *tl)
33c349dbc7Sjsg {
34c349dbc7Sjsg 	GEM_BUG_ON(!atomic_read(&tl->pin_count));
35c349dbc7Sjsg 	atomic_dec(&tl->pin_count);
36c349dbc7Sjsg }
37c349dbc7Sjsg 
create_ring_vma(struct i915_ggtt * ggtt,int size)38*1bb76ff1Sjsg static struct i915_vma *create_ring_vma(struct i915_ggtt *ggtt, int size)
39*1bb76ff1Sjsg {
40*1bb76ff1Sjsg 	struct i915_address_space *vm = &ggtt->vm;
41*1bb76ff1Sjsg 	struct drm_i915_private *i915 = vm->i915;
42*1bb76ff1Sjsg 	struct drm_i915_gem_object *obj;
43*1bb76ff1Sjsg 	struct i915_vma *vma;
44*1bb76ff1Sjsg 
45*1bb76ff1Sjsg 	obj = i915_gem_object_create_internal(i915, size);
46*1bb76ff1Sjsg 	if (IS_ERR(obj))
47*1bb76ff1Sjsg 		return ERR_CAST(obj);
48*1bb76ff1Sjsg 
49*1bb76ff1Sjsg 	vma = i915_vma_instance(obj, vm, NULL);
50*1bb76ff1Sjsg 	if (IS_ERR(vma))
51*1bb76ff1Sjsg 		goto err;
52*1bb76ff1Sjsg 
53*1bb76ff1Sjsg 	return vma;
54*1bb76ff1Sjsg 
55*1bb76ff1Sjsg err:
56*1bb76ff1Sjsg 	i915_gem_object_put(obj);
57*1bb76ff1Sjsg 	return vma;
58*1bb76ff1Sjsg }
59*1bb76ff1Sjsg 
mock_ring(struct intel_engine_cs * engine)60c349dbc7Sjsg static struct intel_ring *mock_ring(struct intel_engine_cs *engine)
61c349dbc7Sjsg {
62*1bb76ff1Sjsg 	const unsigned long sz = PAGE_SIZE;
63c349dbc7Sjsg 	struct intel_ring *ring;
64c349dbc7Sjsg 
65c349dbc7Sjsg 	ring = kzalloc(sizeof(*ring) + sz, GFP_KERNEL);
66c349dbc7Sjsg 	if (!ring)
67c349dbc7Sjsg 		return NULL;
68c349dbc7Sjsg 
69c349dbc7Sjsg 	kref_init(&ring->ref);
70c349dbc7Sjsg 	ring->size = sz;
71c349dbc7Sjsg 	ring->effective_size = sz;
72c349dbc7Sjsg 	ring->vaddr = (void *)(ring + 1);
73c349dbc7Sjsg 	atomic_set(&ring->pin_count, 1);
74c349dbc7Sjsg 
75*1bb76ff1Sjsg 	ring->vma = create_ring_vma(engine->gt->ggtt, PAGE_SIZE);
76*1bb76ff1Sjsg 	if (IS_ERR(ring->vma)) {
77c349dbc7Sjsg 		kfree(ring);
78c349dbc7Sjsg 		return NULL;
79c349dbc7Sjsg 	}
80c349dbc7Sjsg 
81c349dbc7Sjsg 	intel_ring_update_space(ring);
82c349dbc7Sjsg 
83c349dbc7Sjsg 	return ring;
84c349dbc7Sjsg }
85c349dbc7Sjsg 
mock_ring_free(struct intel_ring * ring)86c349dbc7Sjsg static void mock_ring_free(struct intel_ring *ring)
87c349dbc7Sjsg {
88*1bb76ff1Sjsg 	i915_vma_put(ring->vma);
89c349dbc7Sjsg 
90c349dbc7Sjsg 	kfree(ring);
91c349dbc7Sjsg }
92c349dbc7Sjsg 
first_request(struct mock_engine * engine)93c349dbc7Sjsg static struct i915_request *first_request(struct mock_engine *engine)
94c349dbc7Sjsg {
95c349dbc7Sjsg 	return list_first_entry_or_null(&engine->hw_queue,
96c349dbc7Sjsg 					struct i915_request,
97c349dbc7Sjsg 					mock.link);
98c349dbc7Sjsg }
99c349dbc7Sjsg 
advance(struct i915_request * request)100c349dbc7Sjsg static void advance(struct i915_request *request)
101c349dbc7Sjsg {
102c349dbc7Sjsg 	list_del_init(&request->mock.link);
103c349dbc7Sjsg 	i915_request_mark_complete(request);
104c349dbc7Sjsg 	GEM_BUG_ON(!i915_request_completed(request));
105c349dbc7Sjsg 
106c349dbc7Sjsg 	intel_engine_signal_breadcrumbs(request->engine);
107c349dbc7Sjsg }
108c349dbc7Sjsg 
hw_delay_complete(struct timer_list * t)109c349dbc7Sjsg static void hw_delay_complete(struct timer_list *t)
110c349dbc7Sjsg {
111c349dbc7Sjsg 	struct mock_engine *engine = from_timer(engine, t, hw_delay);
112c349dbc7Sjsg 	struct i915_request *request;
113c349dbc7Sjsg 	unsigned long flags;
114c349dbc7Sjsg 
115c349dbc7Sjsg 	spin_lock_irqsave(&engine->hw_lock, flags);
116c349dbc7Sjsg 
117c349dbc7Sjsg 	/* Timer fired, first request is complete */
118c349dbc7Sjsg 	request = first_request(engine);
119c349dbc7Sjsg 	if (request)
120c349dbc7Sjsg 		advance(request);
121c349dbc7Sjsg 
122c349dbc7Sjsg 	/*
123c349dbc7Sjsg 	 * Also immediately signal any subsequent 0-delay requests, but
124c349dbc7Sjsg 	 * requeue the timer for the next delayed request.
125c349dbc7Sjsg 	 */
126c349dbc7Sjsg 	while ((request = first_request(engine))) {
127c349dbc7Sjsg 		if (request->mock.delay) {
128c349dbc7Sjsg 			mod_timer(&engine->hw_delay,
129c349dbc7Sjsg 				  jiffies + request->mock.delay);
130c349dbc7Sjsg 			break;
131c349dbc7Sjsg 		}
132c349dbc7Sjsg 
133c349dbc7Sjsg 		advance(request);
134c349dbc7Sjsg 	}
135c349dbc7Sjsg 
136c349dbc7Sjsg 	spin_unlock_irqrestore(&engine->hw_lock, flags);
137c349dbc7Sjsg }
138c349dbc7Sjsg 
mock_context_unpin(struct intel_context * ce)139c349dbc7Sjsg static void mock_context_unpin(struct intel_context *ce)
140c349dbc7Sjsg {
141c349dbc7Sjsg }
142c349dbc7Sjsg 
mock_context_post_unpin(struct intel_context * ce)143ad8b1aafSjsg static void mock_context_post_unpin(struct intel_context *ce)
144ad8b1aafSjsg {
145*1bb76ff1Sjsg 	i915_vma_unpin(ce->ring->vma);
146ad8b1aafSjsg }
147ad8b1aafSjsg 
mock_context_destroy(struct kref * ref)148c349dbc7Sjsg static void mock_context_destroy(struct kref *ref)
149c349dbc7Sjsg {
150c349dbc7Sjsg 	struct intel_context *ce = container_of(ref, typeof(*ce), ref);
151c349dbc7Sjsg 
152c349dbc7Sjsg 	GEM_BUG_ON(intel_context_is_pinned(ce));
153c349dbc7Sjsg 
154c349dbc7Sjsg 	if (test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
155c349dbc7Sjsg 		mock_ring_free(ce->ring);
156c349dbc7Sjsg 		mock_timeline_unpin(ce->timeline);
157c349dbc7Sjsg 	}
158c349dbc7Sjsg 
159c349dbc7Sjsg 	intel_context_fini(ce);
160c349dbc7Sjsg 	intel_context_free(ce);
161c349dbc7Sjsg }
162c349dbc7Sjsg 
mock_context_alloc(struct intel_context * ce)163c349dbc7Sjsg static int mock_context_alloc(struct intel_context *ce)
164c349dbc7Sjsg {
1655ca02815Sjsg 	int err;
1665ca02815Sjsg 
167c349dbc7Sjsg 	ce->ring = mock_ring(ce->engine);
168c349dbc7Sjsg 	if (!ce->ring)
169c349dbc7Sjsg 		return -ENOMEM;
170c349dbc7Sjsg 
171ad8b1aafSjsg 	ce->timeline = intel_timeline_create(ce->engine->gt);
172c349dbc7Sjsg 	if (IS_ERR(ce->timeline)) {
173c349dbc7Sjsg 		kfree(ce->engine);
174c349dbc7Sjsg 		return PTR_ERR(ce->timeline);
175c349dbc7Sjsg 	}
176c349dbc7Sjsg 
1775ca02815Sjsg 	err = mock_timeline_pin(ce->timeline);
1785ca02815Sjsg 	if (err) {
1795ca02815Sjsg 		intel_timeline_put(ce->timeline);
1805ca02815Sjsg 		ce->timeline = NULL;
1815ca02815Sjsg 		return err;
1825ca02815Sjsg 	}
183c349dbc7Sjsg 
184c349dbc7Sjsg 	return 0;
185c349dbc7Sjsg }
186c349dbc7Sjsg 
mock_context_pre_pin(struct intel_context * ce,struct i915_gem_ww_ctx * ww,void ** unused)187ad8b1aafSjsg static int mock_context_pre_pin(struct intel_context *ce,
188ad8b1aafSjsg 				struct i915_gem_ww_ctx *ww, void **unused)
189ad8b1aafSjsg {
190*1bb76ff1Sjsg 	return i915_vma_pin_ww(ce->ring->vma, ww, 0, 0, PIN_GLOBAL | PIN_HIGH);
191ad8b1aafSjsg }
192ad8b1aafSjsg 
mock_context_pin(struct intel_context * ce,void * unused)193ad8b1aafSjsg static int mock_context_pin(struct intel_context *ce, void *unused)
194c349dbc7Sjsg {
195c349dbc7Sjsg 	return 0;
196c349dbc7Sjsg }
197c349dbc7Sjsg 
mock_context_reset(struct intel_context * ce)198c349dbc7Sjsg static void mock_context_reset(struct intel_context *ce)
199c349dbc7Sjsg {
200c349dbc7Sjsg }
201c349dbc7Sjsg 
202c349dbc7Sjsg static const struct intel_context_ops mock_context_ops = {
203c349dbc7Sjsg 	.alloc = mock_context_alloc,
204c349dbc7Sjsg 
205ad8b1aafSjsg 	.pre_pin = mock_context_pre_pin,
206c349dbc7Sjsg 	.pin = mock_context_pin,
207c349dbc7Sjsg 	.unpin = mock_context_unpin,
208ad8b1aafSjsg 	.post_unpin = mock_context_post_unpin,
209c349dbc7Sjsg 
210c349dbc7Sjsg 	.enter = intel_context_enter_engine,
211c349dbc7Sjsg 	.exit = intel_context_exit_engine,
212c349dbc7Sjsg 
213c349dbc7Sjsg 	.reset = mock_context_reset,
214c349dbc7Sjsg 	.destroy = mock_context_destroy,
215c349dbc7Sjsg };
216c349dbc7Sjsg 
mock_request_alloc(struct i915_request * request)217c349dbc7Sjsg static int mock_request_alloc(struct i915_request *request)
218c349dbc7Sjsg {
219c349dbc7Sjsg 	INIT_LIST_HEAD(&request->mock.link);
220c349dbc7Sjsg 	request->mock.delay = 0;
221c349dbc7Sjsg 
222c349dbc7Sjsg 	return 0;
223c349dbc7Sjsg }
224c349dbc7Sjsg 
mock_emit_flush(struct i915_request * request,unsigned int flags)225c349dbc7Sjsg static int mock_emit_flush(struct i915_request *request,
226c349dbc7Sjsg 			   unsigned int flags)
227c349dbc7Sjsg {
228c349dbc7Sjsg 	return 0;
229c349dbc7Sjsg }
230c349dbc7Sjsg 
mock_emit_breadcrumb(struct i915_request * request,u32 * cs)231c349dbc7Sjsg static u32 *mock_emit_breadcrumb(struct i915_request *request, u32 *cs)
232c349dbc7Sjsg {
233c349dbc7Sjsg 	return cs;
234c349dbc7Sjsg }
235c349dbc7Sjsg 
mock_submit_request(struct i915_request * request)236c349dbc7Sjsg static void mock_submit_request(struct i915_request *request)
237c349dbc7Sjsg {
238c349dbc7Sjsg 	struct mock_engine *engine =
239c349dbc7Sjsg 		container_of(request->engine, typeof(*engine), base);
240c349dbc7Sjsg 	unsigned long flags;
241c349dbc7Sjsg 
242c349dbc7Sjsg 	i915_request_submit(request);
243c349dbc7Sjsg 
244c349dbc7Sjsg 	spin_lock_irqsave(&engine->hw_lock, flags);
245c349dbc7Sjsg 	list_add_tail(&request->mock.link, &engine->hw_queue);
246c349dbc7Sjsg 	if (list_is_first(&request->mock.link, &engine->hw_queue)) {
247c349dbc7Sjsg 		if (request->mock.delay)
248c349dbc7Sjsg 			mod_timer(&engine->hw_delay,
249c349dbc7Sjsg 				  jiffies + request->mock.delay);
250c349dbc7Sjsg 		else
251c349dbc7Sjsg 			advance(request);
252c349dbc7Sjsg 	}
253c349dbc7Sjsg 	spin_unlock_irqrestore(&engine->hw_lock, flags);
254c349dbc7Sjsg }
255c349dbc7Sjsg 
mock_add_to_engine(struct i915_request * rq)2565ca02815Sjsg static void mock_add_to_engine(struct i915_request *rq)
2575ca02815Sjsg {
2585ca02815Sjsg 	lockdep_assert_held(&rq->engine->sched_engine->lock);
2595ca02815Sjsg 	list_move_tail(&rq->sched.link, &rq->engine->sched_engine->requests);
2605ca02815Sjsg }
2615ca02815Sjsg 
mock_remove_from_engine(struct i915_request * rq)2625ca02815Sjsg static void mock_remove_from_engine(struct i915_request *rq)
2635ca02815Sjsg {
2645ca02815Sjsg 	struct intel_engine_cs *engine, *locked;
2655ca02815Sjsg 
2665ca02815Sjsg 	/*
2675ca02815Sjsg 	 * Virtual engines complicate acquiring the engine timeline lock,
2685ca02815Sjsg 	 * as their rq->engine pointer is not stable until under that
2695ca02815Sjsg 	 * engine lock. The simple ploy we use is to take the lock then
2705ca02815Sjsg 	 * check that the rq still belongs to the newly locked engine.
2715ca02815Sjsg 	 */
2725ca02815Sjsg 
2735ca02815Sjsg 	locked = READ_ONCE(rq->engine);
2745ca02815Sjsg 	spin_lock_irq(&locked->sched_engine->lock);
2755ca02815Sjsg 	while (unlikely(locked != (engine = READ_ONCE(rq->engine)))) {
2765ca02815Sjsg 		spin_unlock(&locked->sched_engine->lock);
2775ca02815Sjsg 		spin_lock(&engine->sched_engine->lock);
2785ca02815Sjsg 		locked = engine;
2795ca02815Sjsg 	}
2805ca02815Sjsg 	list_del_init(&rq->sched.link);
2815ca02815Sjsg 	spin_unlock_irq(&locked->sched_engine->lock);
2825ca02815Sjsg }
2835ca02815Sjsg 
mock_reset_prepare(struct intel_engine_cs * engine)284c349dbc7Sjsg static void mock_reset_prepare(struct intel_engine_cs *engine)
285c349dbc7Sjsg {
286c349dbc7Sjsg }
287c349dbc7Sjsg 
mock_reset_rewind(struct intel_engine_cs * engine,bool stalled)288c349dbc7Sjsg static void mock_reset_rewind(struct intel_engine_cs *engine, bool stalled)
289c349dbc7Sjsg {
290c349dbc7Sjsg 	GEM_BUG_ON(stalled);
291c349dbc7Sjsg }
292c349dbc7Sjsg 
mock_reset_cancel(struct intel_engine_cs * engine)293c349dbc7Sjsg static void mock_reset_cancel(struct intel_engine_cs *engine)
294c349dbc7Sjsg {
2955ca02815Sjsg 	struct mock_engine *mock =
2965ca02815Sjsg 		container_of(engine, typeof(*mock), base);
2975ca02815Sjsg 	struct i915_request *rq;
298c349dbc7Sjsg 	unsigned long flags;
299c349dbc7Sjsg 
3005ca02815Sjsg 	del_timer_sync(&mock->hw_delay);
3015ca02815Sjsg 
3025ca02815Sjsg 	spin_lock_irqsave(&engine->sched_engine->lock, flags);
303c349dbc7Sjsg 
304c349dbc7Sjsg 	/* Mark all submitted requests as skipped. */
3055ca02815Sjsg 	list_for_each_entry(rq, &engine->sched_engine->requests, sched.link)
3065ca02815Sjsg 		i915_request_put(i915_request_mark_eio(rq));
3075ca02815Sjsg 	intel_engine_signal_breadcrumbs(engine);
308c349dbc7Sjsg 
3095ca02815Sjsg 	/* Cancel and submit all pending requests. */
3105ca02815Sjsg 	list_for_each_entry(rq, &mock->hw_queue, mock.link) {
3115ca02815Sjsg 		if (i915_request_mark_eio(rq)) {
3125ca02815Sjsg 			__i915_request_submit(rq);
3135ca02815Sjsg 			i915_request_put(rq);
3145ca02815Sjsg 		}
3155ca02815Sjsg 	}
3165ca02815Sjsg 	INIT_LIST_HEAD(&mock->hw_queue);
3175ca02815Sjsg 
3185ca02815Sjsg 	spin_unlock_irqrestore(&engine->sched_engine->lock, flags);
319c349dbc7Sjsg }
320c349dbc7Sjsg 
mock_reset_finish(struct intel_engine_cs * engine)321c349dbc7Sjsg static void mock_reset_finish(struct intel_engine_cs *engine)
322c349dbc7Sjsg {
323c349dbc7Sjsg }
324c349dbc7Sjsg 
mock_engine_release(struct intel_engine_cs * engine)325c349dbc7Sjsg static void mock_engine_release(struct intel_engine_cs *engine)
326c349dbc7Sjsg {
327c349dbc7Sjsg 	struct mock_engine *mock =
328c349dbc7Sjsg 		container_of(engine, typeof(*mock), base);
329c349dbc7Sjsg 
330c349dbc7Sjsg 	GEM_BUG_ON(timer_pending(&mock->hw_delay));
331c349dbc7Sjsg 
3325ca02815Sjsg 	i915_sched_engine_put(engine->sched_engine);
3335ca02815Sjsg 	intel_breadcrumbs_put(engine->breadcrumbs);
334ad8b1aafSjsg 
335c349dbc7Sjsg 	intel_context_unpin(engine->kernel_context);
336c349dbc7Sjsg 	intel_context_put(engine->kernel_context);
337c349dbc7Sjsg 
338c349dbc7Sjsg 	intel_engine_fini_retire(engine);
339c349dbc7Sjsg }
340c349dbc7Sjsg 
mock_engine(struct drm_i915_private * i915,const char * name,int id)341c349dbc7Sjsg struct intel_engine_cs *mock_engine(struct drm_i915_private *i915,
342c349dbc7Sjsg 				    const char *name,
343c349dbc7Sjsg 				    int id)
344c349dbc7Sjsg {
345c349dbc7Sjsg 	struct mock_engine *engine;
346c349dbc7Sjsg 
347c349dbc7Sjsg 	GEM_BUG_ON(id >= I915_NUM_ENGINES);
348*1bb76ff1Sjsg 	GEM_BUG_ON(!to_gt(i915)->uncore);
349c349dbc7Sjsg 
350c349dbc7Sjsg 	engine = kzalloc(sizeof(*engine) + PAGE_SIZE, GFP_KERNEL);
351c349dbc7Sjsg 	if (!engine)
352c349dbc7Sjsg 		return NULL;
353c349dbc7Sjsg 
354c349dbc7Sjsg 	/* minimal engine setup for requests */
355c349dbc7Sjsg 	engine->base.i915 = i915;
356*1bb76ff1Sjsg 	engine->base.gt = to_gt(i915);
357*1bb76ff1Sjsg 	engine->base.uncore = to_gt(i915)->uncore;
358c349dbc7Sjsg 	snprintf(engine->base.name, sizeof(engine->base.name), "%s", name);
359c349dbc7Sjsg 	engine->base.id = id;
360c349dbc7Sjsg 	engine->base.mask = BIT(id);
361c349dbc7Sjsg 	engine->base.legacy_idx = INVALID_ENGINE;
362c349dbc7Sjsg 	engine->base.instance = id;
363c349dbc7Sjsg 	engine->base.status_page.addr = (void *)(engine + 1);
364c349dbc7Sjsg 
365c349dbc7Sjsg 	engine->base.cops = &mock_context_ops;
366c349dbc7Sjsg 	engine->base.request_alloc = mock_request_alloc;
367c349dbc7Sjsg 	engine->base.emit_flush = mock_emit_flush;
368c349dbc7Sjsg 	engine->base.emit_fini_breadcrumb = mock_emit_breadcrumb;
369c349dbc7Sjsg 	engine->base.submit_request = mock_submit_request;
3705ca02815Sjsg 	engine->base.add_active_request = mock_add_to_engine;
3715ca02815Sjsg 	engine->base.remove_active_request = mock_remove_from_engine;
372c349dbc7Sjsg 
373c349dbc7Sjsg 	engine->base.reset.prepare = mock_reset_prepare;
374c349dbc7Sjsg 	engine->base.reset.rewind = mock_reset_rewind;
375c349dbc7Sjsg 	engine->base.reset.cancel = mock_reset_cancel;
376c349dbc7Sjsg 	engine->base.reset.finish = mock_reset_finish;
377c349dbc7Sjsg 
378c349dbc7Sjsg 	engine->base.release = mock_engine_release;
379c349dbc7Sjsg 
380*1bb76ff1Sjsg 	to_gt(i915)->engine[id] = &engine->base;
381*1bb76ff1Sjsg 	to_gt(i915)->engine_class[0][id] = &engine->base;
382c349dbc7Sjsg 
383c349dbc7Sjsg 	/* fake hw queue */
384c349dbc7Sjsg 	mtx_init(&engine->hw_lock, IPL_TTY);
385c349dbc7Sjsg 	timer_setup(&engine->hw_delay, hw_delay_complete, 0);
386c349dbc7Sjsg 	INIT_LIST_HEAD(&engine->hw_queue);
387c349dbc7Sjsg 
388c349dbc7Sjsg 	intel_engine_add_user(&engine->base);
389c349dbc7Sjsg 
390c349dbc7Sjsg 	return &engine->base;
391c349dbc7Sjsg }
392c349dbc7Sjsg 
mock_engine_init(struct intel_engine_cs * engine)393c349dbc7Sjsg int mock_engine_init(struct intel_engine_cs *engine)
394c349dbc7Sjsg {
395c349dbc7Sjsg 	struct intel_context *ce;
396c349dbc7Sjsg 
3973f069f93Sjsg 	INIT_LIST_HEAD(&engine->pinned_contexts_list);
3983f069f93Sjsg 
3995ca02815Sjsg 	engine->sched_engine = i915_sched_engine_create(ENGINE_MOCK);
4005ca02815Sjsg 	if (!engine->sched_engine)
4015ca02815Sjsg 		return -ENOMEM;
4025ca02815Sjsg 	engine->sched_engine->private_data = engine;
4035ca02815Sjsg 
404c349dbc7Sjsg 	intel_engine_init_execlists(engine);
405c349dbc7Sjsg 	intel_engine_init__pm(engine);
406c349dbc7Sjsg 	intel_engine_init_retire(engine);
407ad8b1aafSjsg 
408ad8b1aafSjsg 	engine->breadcrumbs = intel_breadcrumbs_create(NULL);
409ad8b1aafSjsg 	if (!engine->breadcrumbs)
4105ca02815Sjsg 		goto err_schedule;
411c349dbc7Sjsg 
412c349dbc7Sjsg 	ce = create_kernel_context(engine);
413c349dbc7Sjsg 	if (IS_ERR(ce))
414c349dbc7Sjsg 		goto err_breadcrumbs;
415c349dbc7Sjsg 
416ad8b1aafSjsg 	/* We insist the kernel context is using the status_page */
417ad8b1aafSjsg 	engine->status_page.vma = ce->timeline->hwsp_ggtt;
418ad8b1aafSjsg 
419c349dbc7Sjsg 	engine->kernel_context = ce;
420c349dbc7Sjsg 	return 0;
421c349dbc7Sjsg 
422c349dbc7Sjsg err_breadcrumbs:
4235ca02815Sjsg 	intel_breadcrumbs_put(engine->breadcrumbs);
4245ca02815Sjsg err_schedule:
4255ca02815Sjsg 	i915_sched_engine_put(engine->sched_engine);
426c349dbc7Sjsg 	return -ENOMEM;
427c349dbc7Sjsg }
428c349dbc7Sjsg 
mock_engine_flush(struct intel_engine_cs * engine)429c349dbc7Sjsg void mock_engine_flush(struct intel_engine_cs *engine)
430c349dbc7Sjsg {
431c349dbc7Sjsg 	struct mock_engine *mock =
432c349dbc7Sjsg 		container_of(engine, typeof(*mock), base);
433c349dbc7Sjsg 	struct i915_request *request, *rn;
434c349dbc7Sjsg 
435c349dbc7Sjsg 	del_timer_sync(&mock->hw_delay);
436c349dbc7Sjsg 
437c349dbc7Sjsg 	spin_lock_irq(&mock->hw_lock);
438c349dbc7Sjsg 	list_for_each_entry_safe(request, rn, &mock->hw_queue, mock.link)
439c349dbc7Sjsg 		advance(request);
440c349dbc7Sjsg 	spin_unlock_irq(&mock->hw_lock);
441c349dbc7Sjsg }
442c349dbc7Sjsg 
mock_engine_reset(struct intel_engine_cs * engine)443c349dbc7Sjsg void mock_engine_reset(struct intel_engine_cs *engine)
444c349dbc7Sjsg {
445c349dbc7Sjsg }
446