xref: /dflybsd-src/sys/dev/drm/i915/intel_engine_cs.c (revision a85cb24f18e3804e75ab8bcda7692564d0563317)
187df8fc6SFrançois Tigeot /*
287df8fc6SFrançois Tigeot  * Copyright © 2016 Intel Corporation
387df8fc6SFrançois Tigeot  *
487df8fc6SFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
587df8fc6SFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
687df8fc6SFrançois Tigeot  * to deal in the Software without restriction, including without limitation
787df8fc6SFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
887df8fc6SFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
987df8fc6SFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
1087df8fc6SFrançois Tigeot  *
1187df8fc6SFrançois Tigeot  * The above copyright notice and this permission notice (including the next
1287df8fc6SFrançois Tigeot  * paragraph) shall be included in all copies or substantial portions of the
1387df8fc6SFrançois Tigeot  * Software.
1487df8fc6SFrançois Tigeot  *
1587df8fc6SFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1687df8fc6SFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1787df8fc6SFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1887df8fc6SFrançois Tigeot  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1987df8fc6SFrançois Tigeot  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2087df8fc6SFrançois Tigeot  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2187df8fc6SFrançois Tigeot  * IN THE SOFTWARE.
2287df8fc6SFrançois Tigeot  *
2387df8fc6SFrançois Tigeot  */
2487df8fc6SFrançois Tigeot 
2587df8fc6SFrançois Tigeot #include "i915_drv.h"
2687df8fc6SFrançois Tigeot #include "intel_ringbuffer.h"
2787df8fc6SFrançois Tigeot #include "intel_lrc.h"
2887df8fc6SFrançois Tigeot 
2987df8fc6SFrançois Tigeot static const struct engine_info {
3087df8fc6SFrançois Tigeot 	const char *name;
31*a85cb24fSFrançois Tigeot 	unsigned int exec_id;
32*a85cb24fSFrançois Tigeot 	unsigned int hw_id;
3387df8fc6SFrançois Tigeot 	u32 mmio_base;
3487df8fc6SFrançois Tigeot 	unsigned irq_shift;
3587df8fc6SFrançois Tigeot 	int (*init_legacy)(struct intel_engine_cs *engine);
3687df8fc6SFrançois Tigeot 	int (*init_execlists)(struct intel_engine_cs *engine);
3787df8fc6SFrançois Tigeot } intel_engines[] = {
3887df8fc6SFrançois Tigeot 	[RCS] = {
39*a85cb24fSFrançois Tigeot 		.name = "rcs",
401e12ee3bSFrançois Tigeot 		.hw_id = RCS_HW,
41*a85cb24fSFrançois Tigeot 		.exec_id = I915_EXEC_RENDER,
4287df8fc6SFrançois Tigeot 		.mmio_base = RENDER_RING_BASE,
4387df8fc6SFrançois Tigeot 		.irq_shift = GEN8_RCS_IRQ_SHIFT,
4487df8fc6SFrançois Tigeot 		.init_execlists = logical_render_ring_init,
4587df8fc6SFrançois Tigeot 		.init_legacy = intel_init_render_ring_buffer,
4687df8fc6SFrançois Tigeot 	},
4787df8fc6SFrançois Tigeot 	[BCS] = {
48*a85cb24fSFrançois Tigeot 		.name = "bcs",
491e12ee3bSFrançois Tigeot 		.hw_id = BCS_HW,
50*a85cb24fSFrançois Tigeot 		.exec_id = I915_EXEC_BLT,
5187df8fc6SFrançois Tigeot 		.mmio_base = BLT_RING_BASE,
5287df8fc6SFrançois Tigeot 		.irq_shift = GEN8_BCS_IRQ_SHIFT,
5387df8fc6SFrançois Tigeot 		.init_execlists = logical_xcs_ring_init,
5487df8fc6SFrançois Tigeot 		.init_legacy = intel_init_blt_ring_buffer,
5587df8fc6SFrançois Tigeot 	},
5687df8fc6SFrançois Tigeot 	[VCS] = {
57*a85cb24fSFrançois Tigeot 		.name = "vcs",
581e12ee3bSFrançois Tigeot 		.hw_id = VCS_HW,
59*a85cb24fSFrançois Tigeot 		.exec_id = I915_EXEC_BSD,
6087df8fc6SFrançois Tigeot 		.mmio_base = GEN6_BSD_RING_BASE,
6187df8fc6SFrançois Tigeot 		.irq_shift = GEN8_VCS1_IRQ_SHIFT,
6287df8fc6SFrançois Tigeot 		.init_execlists = logical_xcs_ring_init,
6387df8fc6SFrançois Tigeot 		.init_legacy = intel_init_bsd_ring_buffer,
6487df8fc6SFrançois Tigeot 	},
6587df8fc6SFrançois Tigeot 	[VCS2] = {
66*a85cb24fSFrançois Tigeot 		.name = "vcs2",
671e12ee3bSFrançois Tigeot 		.hw_id = VCS2_HW,
68*a85cb24fSFrançois Tigeot 		.exec_id = I915_EXEC_BSD,
6987df8fc6SFrançois Tigeot 		.mmio_base = GEN8_BSD2_RING_BASE,
7087df8fc6SFrançois Tigeot 		.irq_shift = GEN8_VCS2_IRQ_SHIFT,
7187df8fc6SFrançois Tigeot 		.init_execlists = logical_xcs_ring_init,
7287df8fc6SFrançois Tigeot 		.init_legacy = intel_init_bsd2_ring_buffer,
7387df8fc6SFrançois Tigeot 	},
7487df8fc6SFrançois Tigeot 	[VECS] = {
75*a85cb24fSFrançois Tigeot 		.name = "vecs",
761e12ee3bSFrançois Tigeot 		.hw_id = VECS_HW,
77*a85cb24fSFrançois Tigeot 		.exec_id = I915_EXEC_VEBOX,
7887df8fc6SFrançois Tigeot 		.mmio_base = VEBOX_RING_BASE,
7987df8fc6SFrançois Tigeot 		.irq_shift = GEN8_VECS_IRQ_SHIFT,
8087df8fc6SFrançois Tigeot 		.init_execlists = logical_xcs_ring_init,
8187df8fc6SFrançois Tigeot 		.init_legacy = intel_init_vebox_ring_buffer,
8287df8fc6SFrançois Tigeot 	},
8387df8fc6SFrançois Tigeot };
8487df8fc6SFrançois Tigeot 
851e12ee3bSFrançois Tigeot static int
8687df8fc6SFrançois Tigeot intel_engine_setup(struct drm_i915_private *dev_priv,
8787df8fc6SFrançois Tigeot 		   enum intel_engine_id id)
8887df8fc6SFrançois Tigeot {
8987df8fc6SFrançois Tigeot 	const struct engine_info *info = &intel_engines[id];
901e12ee3bSFrançois Tigeot 	struct intel_engine_cs *engine;
911e12ee3bSFrançois Tigeot 
921e12ee3bSFrançois Tigeot 	GEM_BUG_ON(dev_priv->engine[id]);
931e12ee3bSFrançois Tigeot 	engine = kzalloc(sizeof(*engine), GFP_KERNEL);
941e12ee3bSFrançois Tigeot 	if (!engine)
951e12ee3bSFrançois Tigeot 		return -ENOMEM;
9687df8fc6SFrançois Tigeot 
9787df8fc6SFrançois Tigeot 	engine->id = id;
9887df8fc6SFrançois Tigeot 	engine->i915 = dev_priv;
9987df8fc6SFrançois Tigeot 	engine->name = info->name;
10087df8fc6SFrançois Tigeot 	engine->exec_id = info->exec_id;
1011e12ee3bSFrançois Tigeot 	engine->hw_id = engine->guc_id = info->hw_id;
10287df8fc6SFrançois Tigeot 	engine->mmio_base = info->mmio_base;
10387df8fc6SFrançois Tigeot 	engine->irq_shift = info->irq_shift;
10487df8fc6SFrançois Tigeot 
1054be47400SFrançois Tigeot 	/* Nothing to do here, execute in order of dependencies */
1064be47400SFrançois Tigeot 	engine->schedule = NULL;
1074be47400SFrançois Tigeot 
108*a85cb24fSFrançois Tigeot 	ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier);
109*a85cb24fSFrançois Tigeot 
1101e12ee3bSFrançois Tigeot 	dev_priv->engine[id] = engine;
1111e12ee3bSFrançois Tigeot 	return 0;
11287df8fc6SFrançois Tigeot }
11387df8fc6SFrançois Tigeot 
11487df8fc6SFrançois Tigeot /**
115*a85cb24fSFrançois Tigeot  * intel_engines_init_early() - allocate the Engine Command Streamers
116*a85cb24fSFrançois Tigeot  * @dev_priv: i915 device private
11787df8fc6SFrançois Tigeot  *
11887df8fc6SFrançois Tigeot  * Return: non-zero if the initialization failed.
11987df8fc6SFrançois Tigeot  */
120*a85cb24fSFrançois Tigeot int intel_engines_init_early(struct drm_i915_private *dev_priv)
12187df8fc6SFrançois Tigeot {
1221e12ee3bSFrançois Tigeot 	struct intel_device_info *device_info = mkwrite_device_info(dev_priv);
1231e12ee3bSFrançois Tigeot 	unsigned int ring_mask = INTEL_INFO(dev_priv)->ring_mask;
12487df8fc6SFrançois Tigeot 	unsigned int mask = 0;
1251e12ee3bSFrançois Tigeot 	struct intel_engine_cs *engine;
1261e12ee3bSFrançois Tigeot 	enum intel_engine_id id;
12787df8fc6SFrançois Tigeot 	unsigned int i;
128*a85cb24fSFrançois Tigeot 	int err;
12987df8fc6SFrançois Tigeot 
1301e12ee3bSFrançois Tigeot 	WARN_ON(ring_mask == 0);
1311e12ee3bSFrançois Tigeot 	WARN_ON(ring_mask &
13287df8fc6SFrançois Tigeot 		GENMASK(sizeof(mask) * BITS_PER_BYTE - 1, I915_NUM_ENGINES));
13387df8fc6SFrançois Tigeot 
13487df8fc6SFrançois Tigeot 	for (i = 0; i < ARRAY_SIZE(intel_engines); i++) {
13587df8fc6SFrançois Tigeot 		if (!HAS_ENGINE(dev_priv, i))
13687df8fc6SFrançois Tigeot 			continue;
13787df8fc6SFrançois Tigeot 
138*a85cb24fSFrançois Tigeot 		err = intel_engine_setup(dev_priv, i);
139*a85cb24fSFrançois Tigeot 		if (err)
14087df8fc6SFrançois Tigeot 			goto cleanup;
14187df8fc6SFrançois Tigeot 
14287df8fc6SFrançois Tigeot 		mask |= ENGINE_MASK(i);
14387df8fc6SFrançois Tigeot 	}
14487df8fc6SFrançois Tigeot 
14587df8fc6SFrançois Tigeot 	/*
14687df8fc6SFrançois Tigeot 	 * Catch failures to update intel_engines table when the new engines
14787df8fc6SFrançois Tigeot 	 * are added to the driver by a warning and disabling the forgotten
14887df8fc6SFrançois Tigeot 	 * engines.
14987df8fc6SFrançois Tigeot 	 */
1501e12ee3bSFrançois Tigeot 	if (WARN_ON(mask != ring_mask))
1511e12ee3bSFrançois Tigeot 		device_info->ring_mask = mask;
1521e12ee3bSFrançois Tigeot 
1531e12ee3bSFrançois Tigeot 	device_info->num_rings = hweight32(mask);
15487df8fc6SFrançois Tigeot 
15587df8fc6SFrançois Tigeot 	return 0;
15687df8fc6SFrançois Tigeot 
15787df8fc6SFrançois Tigeot cleanup:
158*a85cb24fSFrançois Tigeot 	for_each_engine(engine, dev_priv, id)
159*a85cb24fSFrançois Tigeot 		kfree(engine);
160*a85cb24fSFrançois Tigeot 	return err;
16187df8fc6SFrançois Tigeot }
16287df8fc6SFrançois Tigeot 
163*a85cb24fSFrançois Tigeot /**
164*a85cb24fSFrançois Tigeot  * intel_engines_init() - allocate, populate and init the Engine Command Streamers
165*a85cb24fSFrançois Tigeot  * @dev_priv: i915 device private
166*a85cb24fSFrançois Tigeot  *
167*a85cb24fSFrançois Tigeot  * Return: non-zero if the initialization failed.
168*a85cb24fSFrançois Tigeot  */
169*a85cb24fSFrançois Tigeot int intel_engines_init(struct drm_i915_private *dev_priv)
170*a85cb24fSFrançois Tigeot {
171*a85cb24fSFrançois Tigeot 	struct intel_device_info *device_info = mkwrite_device_info(dev_priv);
172*a85cb24fSFrançois Tigeot 	struct intel_engine_cs *engine;
173*a85cb24fSFrançois Tigeot 	enum intel_engine_id id, err_id;
174*a85cb24fSFrançois Tigeot 	unsigned int mask = 0;
175*a85cb24fSFrançois Tigeot 	int err = 0;
176*a85cb24fSFrançois Tigeot 
177*a85cb24fSFrançois Tigeot 	for_each_engine(engine, dev_priv, id) {
178*a85cb24fSFrançois Tigeot 		int (*init)(struct intel_engine_cs *engine);
179*a85cb24fSFrançois Tigeot 
180*a85cb24fSFrançois Tigeot 		if (i915.enable_execlists)
181*a85cb24fSFrançois Tigeot 			init = intel_engines[id].init_execlists;
182*a85cb24fSFrançois Tigeot 		else
183*a85cb24fSFrançois Tigeot 			init = intel_engines[id].init_legacy;
184*a85cb24fSFrançois Tigeot 		if (!init) {
185*a85cb24fSFrançois Tigeot 			kfree(engine);
186*a85cb24fSFrançois Tigeot 			dev_priv->engine[id] = NULL;
187*a85cb24fSFrançois Tigeot 			continue;
188*a85cb24fSFrançois Tigeot 		}
189*a85cb24fSFrançois Tigeot 
190*a85cb24fSFrançois Tigeot 		err = init(engine);
191*a85cb24fSFrançois Tigeot 		if (err) {
192*a85cb24fSFrançois Tigeot 			err_id = id;
193*a85cb24fSFrançois Tigeot 			goto cleanup;
194*a85cb24fSFrançois Tigeot 		}
195*a85cb24fSFrançois Tigeot 
196*a85cb24fSFrançois Tigeot 		GEM_BUG_ON(!engine->submit_request);
197*a85cb24fSFrançois Tigeot 		mask |= ENGINE_MASK(id);
198*a85cb24fSFrançois Tigeot 	}
199*a85cb24fSFrançois Tigeot 
200*a85cb24fSFrançois Tigeot 	/*
201*a85cb24fSFrançois Tigeot 	 * Catch failures to update intel_engines table when the new engines
202*a85cb24fSFrançois Tigeot 	 * are added to the driver by a warning and disabling the forgotten
203*a85cb24fSFrançois Tigeot 	 * engines.
204*a85cb24fSFrançois Tigeot 	 */
205*a85cb24fSFrançois Tigeot 	if (WARN_ON(mask != INTEL_INFO(dev_priv)->ring_mask))
206*a85cb24fSFrançois Tigeot 		device_info->ring_mask = mask;
207*a85cb24fSFrançois Tigeot 
208*a85cb24fSFrançois Tigeot 	device_info->num_rings = hweight32(mask);
209*a85cb24fSFrançois Tigeot 
210*a85cb24fSFrançois Tigeot 	return 0;
211*a85cb24fSFrançois Tigeot 
212*a85cb24fSFrançois Tigeot cleanup:
213*a85cb24fSFrançois Tigeot 	for_each_engine(engine, dev_priv, id) {
214*a85cb24fSFrançois Tigeot 		if (id >= err_id)
215*a85cb24fSFrançois Tigeot 			kfree(engine);
216*a85cb24fSFrançois Tigeot 		else
217*a85cb24fSFrançois Tigeot 			dev_priv->gt.cleanup_engine(engine);
218*a85cb24fSFrançois Tigeot 	}
219*a85cb24fSFrançois Tigeot 	return err;
22087df8fc6SFrançois Tigeot }
22187df8fc6SFrançois Tigeot 
2224be47400SFrançois Tigeot void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno)
2231e12ee3bSFrançois Tigeot {
2241e12ee3bSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
2251e12ee3bSFrançois Tigeot 
2261e12ee3bSFrançois Tigeot 	/* Our semaphore implementation is strictly monotonic (i.e. we proceed
2271e12ee3bSFrançois Tigeot 	 * so long as the semaphore value in the register/page is greater
2281e12ee3bSFrançois Tigeot 	 * than the sync value), so whenever we reset the seqno,
2291e12ee3bSFrançois Tigeot 	 * so long as we reset the tracking semaphore value to 0, it will
2301e12ee3bSFrançois Tigeot 	 * always be before the next request's seqno. If we don't reset
2311e12ee3bSFrançois Tigeot 	 * the semaphore value, then when the seqno moves backwards all
2321e12ee3bSFrançois Tigeot 	 * future waits will complete instantly (causing rendering corruption).
2331e12ee3bSFrançois Tigeot 	 */
2341e12ee3bSFrançois Tigeot 	if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) {
2351e12ee3bSFrançois Tigeot 		I915_WRITE(RING_SYNC_0(engine->mmio_base), 0);
2361e12ee3bSFrançois Tigeot 		I915_WRITE(RING_SYNC_1(engine->mmio_base), 0);
2371e12ee3bSFrançois Tigeot 		if (HAS_VEBOX(dev_priv))
2381e12ee3bSFrançois Tigeot 			I915_WRITE(RING_SYNC_2(engine->mmio_base), 0);
2391e12ee3bSFrançois Tigeot 	}
2401e12ee3bSFrançois Tigeot 	if (dev_priv->semaphore) {
2411e12ee3bSFrançois Tigeot 		struct page *page = i915_vma_first_page(dev_priv->semaphore);
2421e12ee3bSFrançois Tigeot 		void *semaphores;
2431e12ee3bSFrançois Tigeot 
2441e12ee3bSFrançois Tigeot 		/* Semaphores are in noncoherent memory, flush to be safe */
245*a85cb24fSFrançois Tigeot 		semaphores = kmap_atomic(page);
2461e12ee3bSFrançois Tigeot 		memset(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0),
2471e12ee3bSFrançois Tigeot 		       0, I915_NUM_ENGINES * gen8_semaphore_seqno_size);
2481e12ee3bSFrançois Tigeot 		drm_clflush_virt_range(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0),
2491e12ee3bSFrançois Tigeot 				       I915_NUM_ENGINES * gen8_semaphore_seqno_size);
250*a85cb24fSFrançois Tigeot 		kunmap_atomic(semaphores);
2511e12ee3bSFrançois Tigeot 	}
2521e12ee3bSFrançois Tigeot 
2531e12ee3bSFrançois Tigeot 	intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);
254*a85cb24fSFrançois Tigeot 	clear_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted);
2554be47400SFrançois Tigeot 
2564be47400SFrançois Tigeot 	GEM_BUG_ON(i915_gem_active_isset(&engine->timeline->last_request));
2571e12ee3bSFrançois Tigeot 	engine->hangcheck.seqno = seqno;
2581e12ee3bSFrançois Tigeot 
2591e12ee3bSFrançois Tigeot 	/* After manually advancing the seqno, fake the interrupt in case
2601e12ee3bSFrançois Tigeot 	 * there are any waiters for that seqno.
2611e12ee3bSFrançois Tigeot 	 */
2621e12ee3bSFrançois Tigeot 	intel_engine_wakeup(engine);
2631e12ee3bSFrançois Tigeot }
2641e12ee3bSFrançois Tigeot 
2654be47400SFrançois Tigeot static void intel_engine_init_timeline(struct intel_engine_cs *engine)
26687df8fc6SFrançois Tigeot {
2674be47400SFrançois Tigeot 	engine->timeline = &engine->i915->gt.global_timeline.engine[engine->id];
26871f41f3eSFrançois Tigeot }
26971f41f3eSFrançois Tigeot 
27087df8fc6SFrançois Tigeot /**
27187df8fc6SFrançois Tigeot  * intel_engines_setup_common - setup engine state not requiring hw access
27287df8fc6SFrançois Tigeot  * @engine: Engine to setup.
27387df8fc6SFrançois Tigeot  *
27487df8fc6SFrançois Tigeot  * Initializes @engine@ structure members shared between legacy and execlists
27587df8fc6SFrançois Tigeot  * submission modes which do not require hardware access.
27687df8fc6SFrançois Tigeot  *
27787df8fc6SFrançois Tigeot  * Typically done early in the submission mode specific engine setup stage.
27887df8fc6SFrançois Tigeot  */
27987df8fc6SFrançois Tigeot void intel_engine_setup_common(struct intel_engine_cs *engine)
28087df8fc6SFrançois Tigeot {
2814be47400SFrançois Tigeot 	engine->execlist_queue = LINUX_RB_ROOT;
2824be47400SFrançois Tigeot 	engine->execlist_first = NULL;
28387df8fc6SFrançois Tigeot 
2844be47400SFrançois Tigeot 	intel_engine_init_timeline(engine);
28587df8fc6SFrançois Tigeot 	intel_engine_init_hangcheck(engine);
28671f41f3eSFrançois Tigeot 	i915_gem_batch_pool_init(engine, &engine->batch_pool);
2871e12ee3bSFrançois Tigeot 
2881e12ee3bSFrançois Tigeot 	intel_engine_init_cmd_parser(engine);
2891e12ee3bSFrançois Tigeot }
2901e12ee3bSFrançois Tigeot 
2911e12ee3bSFrançois Tigeot int intel_engine_create_scratch(struct intel_engine_cs *engine, int size)
2921e12ee3bSFrançois Tigeot {
2931e12ee3bSFrançois Tigeot 	struct drm_i915_gem_object *obj;
2941e12ee3bSFrançois Tigeot 	struct i915_vma *vma;
2951e12ee3bSFrançois Tigeot 	int ret;
2961e12ee3bSFrançois Tigeot 
2971e12ee3bSFrançois Tigeot 	WARN_ON(engine->scratch);
2981e12ee3bSFrançois Tigeot 
299*a85cb24fSFrançois Tigeot 	obj = i915_gem_object_create_stolen(engine->i915, size);
3001e12ee3bSFrançois Tigeot 	if (!obj)
3014be47400SFrançois Tigeot 		obj = i915_gem_object_create_internal(engine->i915, size);
3021e12ee3bSFrançois Tigeot 	if (IS_ERR(obj)) {
3031e12ee3bSFrançois Tigeot 		DRM_ERROR("Failed to allocate scratch page\n");
3041e12ee3bSFrançois Tigeot 		return PTR_ERR(obj);
3051e12ee3bSFrançois Tigeot 	}
3061e12ee3bSFrançois Tigeot 
307*a85cb24fSFrançois Tigeot 	vma = i915_vma_instance(obj, &engine->i915->ggtt.base, NULL);
3081e12ee3bSFrançois Tigeot 	if (IS_ERR(vma)) {
3091e12ee3bSFrançois Tigeot 		ret = PTR_ERR(vma);
3101e12ee3bSFrançois Tigeot 		goto err_unref;
3111e12ee3bSFrançois Tigeot 	}
3121e12ee3bSFrançois Tigeot 
3131e12ee3bSFrançois Tigeot 	ret = i915_vma_pin(vma, 0, 4096, PIN_GLOBAL | PIN_HIGH);
3141e12ee3bSFrançois Tigeot 	if (ret)
3151e12ee3bSFrançois Tigeot 		goto err_unref;
3161e12ee3bSFrançois Tigeot 
3171e12ee3bSFrançois Tigeot 	engine->scratch = vma;
3181e12ee3bSFrançois Tigeot 	DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n",
3191e12ee3bSFrançois Tigeot 			 engine->name, i915_ggtt_offset(vma));
3201e12ee3bSFrançois Tigeot 	return 0;
3211e12ee3bSFrançois Tigeot 
3221e12ee3bSFrançois Tigeot err_unref:
3231e12ee3bSFrançois Tigeot 	i915_gem_object_put(obj);
3241e12ee3bSFrançois Tigeot 	return ret;
3251e12ee3bSFrançois Tigeot }
3261e12ee3bSFrançois Tigeot 
3271e12ee3bSFrançois Tigeot static void intel_engine_cleanup_scratch(struct intel_engine_cs *engine)
3281e12ee3bSFrançois Tigeot {
3291e12ee3bSFrançois Tigeot 	i915_vma_unpin_and_release(&engine->scratch);
33087df8fc6SFrançois Tigeot }
33187df8fc6SFrançois Tigeot 
33287df8fc6SFrançois Tigeot /**
33387df8fc6SFrançois Tigeot  * intel_engines_init_common - initialize cengine state which might require hw access
33487df8fc6SFrançois Tigeot  * @engine: Engine to initialize.
33587df8fc6SFrançois Tigeot  *
33687df8fc6SFrançois Tigeot  * Initializes @engine@ structure members shared between legacy and execlists
33787df8fc6SFrançois Tigeot  * submission modes which do require hardware access.
33887df8fc6SFrançois Tigeot  *
33987df8fc6SFrançois Tigeot  * Typcally done at later stages of submission mode specific engine setup.
34087df8fc6SFrançois Tigeot  *
34187df8fc6SFrançois Tigeot  * Returns zero on success or an error code on failure.
34287df8fc6SFrançois Tigeot  */
34387df8fc6SFrançois Tigeot int intel_engine_init_common(struct intel_engine_cs *engine)
34487df8fc6SFrançois Tigeot {
34587df8fc6SFrançois Tigeot 	int ret;
34687df8fc6SFrançois Tigeot 
347*a85cb24fSFrançois Tigeot 	engine->set_default_submission(engine);
348*a85cb24fSFrançois Tigeot 
349*a85cb24fSFrançois Tigeot 	/* We may need to do things with the shrinker which
350*a85cb24fSFrançois Tigeot 	 * require us to immediately switch back to the default
351*a85cb24fSFrançois Tigeot 	 * context. This can cause a problem as pinning the
352*a85cb24fSFrançois Tigeot 	 * default context also requires GTT space which may not
353*a85cb24fSFrançois Tigeot 	 * be available. To avoid this we always pin the default
354*a85cb24fSFrançois Tigeot 	 * context.
355*a85cb24fSFrançois Tigeot 	 */
356*a85cb24fSFrançois Tigeot 	ret = engine->context_pin(engine, engine->i915->kernel_context);
35787df8fc6SFrançois Tigeot 	if (ret)
35887df8fc6SFrançois Tigeot 		return ret;
35987df8fc6SFrançois Tigeot 
360*a85cb24fSFrançois Tigeot 	ret = intel_engine_init_breadcrumbs(engine);
361*a85cb24fSFrançois Tigeot 	if (ret)
362*a85cb24fSFrançois Tigeot 		goto err_unpin;
363*a85cb24fSFrançois Tigeot 
3644be47400SFrançois Tigeot 	ret = i915_gem_render_state_init(engine);
3654be47400SFrançois Tigeot 	if (ret)
366*a85cb24fSFrançois Tigeot 		goto err_unpin;
3674be47400SFrançois Tigeot 
3681e12ee3bSFrançois Tigeot 	return 0;
369*a85cb24fSFrançois Tigeot 
370*a85cb24fSFrançois Tigeot err_unpin:
371*a85cb24fSFrançois Tigeot 	engine->context_unpin(engine, engine->i915->kernel_context);
372*a85cb24fSFrançois Tigeot 	return ret;
37371f41f3eSFrançois Tigeot }
37471f41f3eSFrançois Tigeot 
37571f41f3eSFrançois Tigeot /**
37671f41f3eSFrançois Tigeot  * intel_engines_cleanup_common - cleans up the engine state created by
37771f41f3eSFrançois Tigeot  *                                the common initiailizers.
37871f41f3eSFrançois Tigeot  * @engine: Engine to cleanup.
37971f41f3eSFrançois Tigeot  *
38071f41f3eSFrançois Tigeot  * This cleans up everything created by the common helpers.
38171f41f3eSFrançois Tigeot  */
38271f41f3eSFrançois Tigeot void intel_engine_cleanup_common(struct intel_engine_cs *engine)
38371f41f3eSFrançois Tigeot {
3841e12ee3bSFrançois Tigeot 	intel_engine_cleanup_scratch(engine);
3851e12ee3bSFrançois Tigeot 
3864be47400SFrançois Tigeot 	i915_gem_render_state_fini(engine);
38771f41f3eSFrançois Tigeot 	intel_engine_fini_breadcrumbs(engine);
3881e12ee3bSFrançois Tigeot 	intel_engine_cleanup_cmd_parser(engine);
38971f41f3eSFrançois Tigeot 	i915_gem_batch_pool_fini(&engine->batch_pool);
390*a85cb24fSFrançois Tigeot 
391*a85cb24fSFrançois Tigeot 	engine->context_unpin(engine, engine->i915->kernel_context);
39287df8fc6SFrançois Tigeot }
3931e12ee3bSFrançois Tigeot 
3941e12ee3bSFrançois Tigeot u64 intel_engine_get_active_head(struct intel_engine_cs *engine)
3951e12ee3bSFrançois Tigeot {
3961e12ee3bSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
3971e12ee3bSFrançois Tigeot 	u64 acthd;
3981e12ee3bSFrançois Tigeot 
3991e12ee3bSFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8)
4001e12ee3bSFrançois Tigeot 		acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base),
4011e12ee3bSFrançois Tigeot 					 RING_ACTHD_UDW(engine->mmio_base));
4021e12ee3bSFrançois Tigeot 	else if (INTEL_GEN(dev_priv) >= 4)
4031e12ee3bSFrançois Tigeot 		acthd = I915_READ(RING_ACTHD(engine->mmio_base));
4041e12ee3bSFrançois Tigeot 	else
4051e12ee3bSFrançois Tigeot 		acthd = I915_READ(ACTHD);
4061e12ee3bSFrançois Tigeot 
4071e12ee3bSFrançois Tigeot 	return acthd;
4081e12ee3bSFrançois Tigeot }
4091e12ee3bSFrançois Tigeot 
4101e12ee3bSFrançois Tigeot u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine)
4111e12ee3bSFrançois Tigeot {
4121e12ee3bSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
4131e12ee3bSFrançois Tigeot 	u64 bbaddr;
4141e12ee3bSFrançois Tigeot 
4151e12ee3bSFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8)
4161e12ee3bSFrançois Tigeot 		bbaddr = I915_READ64_2x32(RING_BBADDR(engine->mmio_base),
4171e12ee3bSFrançois Tigeot 					  RING_BBADDR_UDW(engine->mmio_base));
4181e12ee3bSFrançois Tigeot 	else
4191e12ee3bSFrançois Tigeot 		bbaddr = I915_READ(RING_BBADDR(engine->mmio_base));
4201e12ee3bSFrançois Tigeot 
4211e12ee3bSFrançois Tigeot 	return bbaddr;
4221e12ee3bSFrançois Tigeot }
4231e12ee3bSFrançois Tigeot 
4241e12ee3bSFrançois Tigeot const char *i915_cache_level_str(struct drm_i915_private *i915, int type)
4251e12ee3bSFrançois Tigeot {
4261e12ee3bSFrançois Tigeot 	switch (type) {
4271e12ee3bSFrançois Tigeot 	case I915_CACHE_NONE: return " uncached";
4281e12ee3bSFrançois Tigeot 	case I915_CACHE_LLC: return HAS_LLC(i915) ? " LLC" : " snooped";
4291e12ee3bSFrançois Tigeot 	case I915_CACHE_L3_LLC: return " L3+LLC";
4301e12ee3bSFrançois Tigeot 	case I915_CACHE_WT: return " WT";
4311e12ee3bSFrançois Tigeot 	default: return "";
4321e12ee3bSFrançois Tigeot 	}
4331e12ee3bSFrançois Tigeot }
4341e12ee3bSFrançois Tigeot 
4351e12ee3bSFrançois Tigeot static inline uint32_t
4361e12ee3bSFrançois Tigeot read_subslice_reg(struct drm_i915_private *dev_priv, int slice,
4371e12ee3bSFrançois Tigeot 		  int subslice, i915_reg_t reg)
4381e12ee3bSFrançois Tigeot {
4391e12ee3bSFrançois Tigeot 	uint32_t mcr;
4401e12ee3bSFrançois Tigeot 	uint32_t ret;
4411e12ee3bSFrançois Tigeot 	enum forcewake_domains fw_domains;
4421e12ee3bSFrançois Tigeot 
4431e12ee3bSFrançois Tigeot 	fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg,
4441e12ee3bSFrançois Tigeot 						    FW_REG_READ);
4451e12ee3bSFrançois Tigeot 	fw_domains |= intel_uncore_forcewake_for_reg(dev_priv,
4461e12ee3bSFrançois Tigeot 						     GEN8_MCR_SELECTOR,
4471e12ee3bSFrançois Tigeot 						     FW_REG_READ | FW_REG_WRITE);
4481e12ee3bSFrançois Tigeot 
4491e12ee3bSFrançois Tigeot 	spin_lock_irq(&dev_priv->uncore.lock);
4501e12ee3bSFrançois Tigeot 	intel_uncore_forcewake_get__locked(dev_priv, fw_domains);
4511e12ee3bSFrançois Tigeot 
4521e12ee3bSFrançois Tigeot 	mcr = I915_READ_FW(GEN8_MCR_SELECTOR);
4531e12ee3bSFrançois Tigeot 	/*
4541e12ee3bSFrançois Tigeot 	 * The HW expects the slice and sublice selectors to be reset to 0
4551e12ee3bSFrançois Tigeot 	 * after reading out the registers.
4561e12ee3bSFrançois Tigeot 	 */
4571e12ee3bSFrançois Tigeot 	WARN_ON_ONCE(mcr & (GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK));
4581e12ee3bSFrançois Tigeot 	mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK);
4591e12ee3bSFrançois Tigeot 	mcr |= GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice);
4601e12ee3bSFrançois Tigeot 	I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr);
4611e12ee3bSFrançois Tigeot 
4621e12ee3bSFrançois Tigeot 	ret = I915_READ_FW(reg);
4631e12ee3bSFrançois Tigeot 
4641e12ee3bSFrançois Tigeot 	mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK);
4651e12ee3bSFrançois Tigeot 	I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr);
4661e12ee3bSFrançois Tigeot 
4671e12ee3bSFrançois Tigeot 	intel_uncore_forcewake_put__locked(dev_priv, fw_domains);
4681e12ee3bSFrançois Tigeot 	spin_unlock_irq(&dev_priv->uncore.lock);
4691e12ee3bSFrançois Tigeot 
4701e12ee3bSFrançois Tigeot 	return ret;
4711e12ee3bSFrançois Tigeot }
4721e12ee3bSFrançois Tigeot 
4731e12ee3bSFrançois Tigeot /* NB: please notice the memset */
4741e12ee3bSFrançois Tigeot void intel_engine_get_instdone(struct intel_engine_cs *engine,
4751e12ee3bSFrançois Tigeot 			       struct intel_instdone *instdone)
4761e12ee3bSFrançois Tigeot {
4771e12ee3bSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
4781e12ee3bSFrançois Tigeot 	u32 mmio_base = engine->mmio_base;
4791e12ee3bSFrançois Tigeot 	int slice;
4801e12ee3bSFrançois Tigeot 	int subslice;
4811e12ee3bSFrançois Tigeot 
4821e12ee3bSFrançois Tigeot 	memset(instdone, 0, sizeof(*instdone));
4831e12ee3bSFrançois Tigeot 
4841e12ee3bSFrançois Tigeot 	switch (INTEL_GEN(dev_priv)) {
4851e12ee3bSFrançois Tigeot 	default:
4861e12ee3bSFrançois Tigeot 		instdone->instdone = I915_READ(RING_INSTDONE(mmio_base));
4871e12ee3bSFrançois Tigeot 
4881e12ee3bSFrançois Tigeot 		if (engine->id != RCS)
4891e12ee3bSFrançois Tigeot 			break;
4901e12ee3bSFrançois Tigeot 
4911e12ee3bSFrançois Tigeot 		instdone->slice_common = I915_READ(GEN7_SC_INSTDONE);
4921e12ee3bSFrançois Tigeot 		for_each_instdone_slice_subslice(dev_priv, slice, subslice) {
4931e12ee3bSFrançois Tigeot 			instdone->sampler[slice][subslice] =
4941e12ee3bSFrançois Tigeot 				read_subslice_reg(dev_priv, slice, subslice,
4951e12ee3bSFrançois Tigeot 						  GEN7_SAMPLER_INSTDONE);
4961e12ee3bSFrançois Tigeot 			instdone->row[slice][subslice] =
4971e12ee3bSFrançois Tigeot 				read_subslice_reg(dev_priv, slice, subslice,
4981e12ee3bSFrançois Tigeot 						  GEN7_ROW_INSTDONE);
4991e12ee3bSFrançois Tigeot 		}
5001e12ee3bSFrançois Tigeot 		break;
5011e12ee3bSFrançois Tigeot 	case 7:
5021e12ee3bSFrançois Tigeot 		instdone->instdone = I915_READ(RING_INSTDONE(mmio_base));
5031e12ee3bSFrançois Tigeot 
5041e12ee3bSFrançois Tigeot 		if (engine->id != RCS)
5051e12ee3bSFrançois Tigeot 			break;
5061e12ee3bSFrançois Tigeot 
5071e12ee3bSFrançois Tigeot 		instdone->slice_common = I915_READ(GEN7_SC_INSTDONE);
5081e12ee3bSFrançois Tigeot 		instdone->sampler[0][0] = I915_READ(GEN7_SAMPLER_INSTDONE);
5091e12ee3bSFrançois Tigeot 		instdone->row[0][0] = I915_READ(GEN7_ROW_INSTDONE);
5101e12ee3bSFrançois Tigeot 
5111e12ee3bSFrançois Tigeot 		break;
5121e12ee3bSFrançois Tigeot 	case 6:
5131e12ee3bSFrançois Tigeot 	case 5:
5141e12ee3bSFrançois Tigeot 	case 4:
5151e12ee3bSFrançois Tigeot 		instdone->instdone = I915_READ(RING_INSTDONE(mmio_base));
5161e12ee3bSFrançois Tigeot 
5171e12ee3bSFrançois Tigeot 		if (engine->id == RCS)
5181e12ee3bSFrançois Tigeot 			/* HACK: Using the wrong struct member */
5191e12ee3bSFrançois Tigeot 			instdone->slice_common = I915_READ(GEN4_INSTDONE1);
5201e12ee3bSFrançois Tigeot 		break;
5211e12ee3bSFrançois Tigeot 	case 3:
5221e12ee3bSFrançois Tigeot 	case 2:
5231e12ee3bSFrançois Tigeot 		instdone->instdone = I915_READ(GEN2_INSTDONE);
5241e12ee3bSFrançois Tigeot 		break;
5251e12ee3bSFrançois Tigeot 	}
5261e12ee3bSFrançois Tigeot }
527*a85cb24fSFrançois Tigeot 
528*a85cb24fSFrançois Tigeot static int wa_add(struct drm_i915_private *dev_priv,
529*a85cb24fSFrançois Tigeot 		  i915_reg_t addr,
530*a85cb24fSFrançois Tigeot 		  const u32 mask, const u32 val)
531*a85cb24fSFrançois Tigeot {
532*a85cb24fSFrançois Tigeot 	const u32 idx = dev_priv->workarounds.count;
533*a85cb24fSFrançois Tigeot 
534*a85cb24fSFrançois Tigeot 	if (WARN_ON(idx >= I915_MAX_WA_REGS))
535*a85cb24fSFrançois Tigeot 		return -ENOSPC;
536*a85cb24fSFrançois Tigeot 
537*a85cb24fSFrançois Tigeot 	dev_priv->workarounds.reg[idx].addr = addr;
538*a85cb24fSFrançois Tigeot 	dev_priv->workarounds.reg[idx].value = val;
539*a85cb24fSFrançois Tigeot 	dev_priv->workarounds.reg[idx].mask = mask;
540*a85cb24fSFrançois Tigeot 
541*a85cb24fSFrançois Tigeot 	dev_priv->workarounds.count++;
542*a85cb24fSFrançois Tigeot 
543*a85cb24fSFrançois Tigeot 	return 0;
544*a85cb24fSFrançois Tigeot }
545*a85cb24fSFrançois Tigeot 
546*a85cb24fSFrançois Tigeot #define WA_REG(addr, mask, val) do { \
547*a85cb24fSFrançois Tigeot 		const int r = wa_add(dev_priv, (addr), (mask), (val)); \
548*a85cb24fSFrançois Tigeot 		if (r) \
549*a85cb24fSFrançois Tigeot 			return r; \
550*a85cb24fSFrançois Tigeot 	} while (0)
551*a85cb24fSFrançois Tigeot 
552*a85cb24fSFrançois Tigeot #define WA_SET_BIT_MASKED(addr, mask) \
553*a85cb24fSFrançois Tigeot 	WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask))
554*a85cb24fSFrançois Tigeot 
555*a85cb24fSFrançois Tigeot #define WA_CLR_BIT_MASKED(addr, mask) \
556*a85cb24fSFrançois Tigeot 	WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask))
557*a85cb24fSFrançois Tigeot 
558*a85cb24fSFrançois Tigeot #define WA_SET_FIELD_MASKED(addr, mask, value) \
559*a85cb24fSFrançois Tigeot 	WA_REG(addr, mask, _MASKED_FIELD(mask, value))
560*a85cb24fSFrançois Tigeot 
561*a85cb24fSFrançois Tigeot #define WA_SET_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) | (mask))
562*a85cb24fSFrançois Tigeot #define WA_CLR_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) & ~(mask))
563*a85cb24fSFrançois Tigeot 
564*a85cb24fSFrançois Tigeot #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val)
565*a85cb24fSFrançois Tigeot 
566*a85cb24fSFrançois Tigeot static int wa_ring_whitelist_reg(struct intel_engine_cs *engine,
567*a85cb24fSFrançois Tigeot 				 i915_reg_t reg)
568*a85cb24fSFrançois Tigeot {
569*a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
570*a85cb24fSFrançois Tigeot 	struct i915_workarounds *wa = &dev_priv->workarounds;
571*a85cb24fSFrançois Tigeot 	const uint32_t index = wa->hw_whitelist_count[engine->id];
572*a85cb24fSFrançois Tigeot 
573*a85cb24fSFrançois Tigeot 	if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS))
574*a85cb24fSFrançois Tigeot 		return -EINVAL;
575*a85cb24fSFrançois Tigeot 
576*a85cb24fSFrançois Tigeot 	WA_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index),
577*a85cb24fSFrançois Tigeot 		 i915_mmio_reg_offset(reg));
578*a85cb24fSFrançois Tigeot 	wa->hw_whitelist_count[engine->id]++;
579*a85cb24fSFrançois Tigeot 
580*a85cb24fSFrançois Tigeot 	return 0;
581*a85cb24fSFrançois Tigeot }
582*a85cb24fSFrançois Tigeot 
583*a85cb24fSFrançois Tigeot static int gen8_init_workarounds(struct intel_engine_cs *engine)
584*a85cb24fSFrançois Tigeot {
585*a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
586*a85cb24fSFrançois Tigeot 
587*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING);
588*a85cb24fSFrançois Tigeot 
589*a85cb24fSFrançois Tigeot 	/* WaDisableAsyncFlipPerfMode:bdw,chv */
590*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE);
591*a85cb24fSFrançois Tigeot 
592*a85cb24fSFrançois Tigeot 	/* WaDisablePartialInstShootdown:bdw,chv */
593*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
594*a85cb24fSFrançois Tigeot 			  PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
595*a85cb24fSFrançois Tigeot 
596*a85cb24fSFrançois Tigeot 	/* Use Force Non-Coherent whenever executing a 3D context. This is a
597*a85cb24fSFrançois Tigeot 	 * workaround for for a possible hang in the unlikely event a TLB
598*a85cb24fSFrançois Tigeot 	 * invalidation occurs during a PSD flush.
599*a85cb24fSFrançois Tigeot 	 */
600*a85cb24fSFrançois Tigeot 	/* WaForceEnableNonCoherent:bdw,chv */
601*a85cb24fSFrançois Tigeot 	/* WaHdcDisableFetchWhenMasked:bdw,chv */
602*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
603*a85cb24fSFrançois Tigeot 			  HDC_DONOT_FETCH_MEM_WHEN_MASKED |
604*a85cb24fSFrançois Tigeot 			  HDC_FORCE_NON_COHERENT);
605*a85cb24fSFrançois Tigeot 
606*a85cb24fSFrançois Tigeot 	/* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0:
607*a85cb24fSFrançois Tigeot 	 * "The Hierarchical Z RAW Stall Optimization allows non-overlapping
608*a85cb24fSFrançois Tigeot 	 *  polygons in the same 8x4 pixel/sample area to be processed without
609*a85cb24fSFrançois Tigeot 	 *  stalling waiting for the earlier ones to write to Hierarchical Z
610*a85cb24fSFrançois Tigeot 	 *  buffer."
611*a85cb24fSFrançois Tigeot 	 *
612*a85cb24fSFrançois Tigeot 	 * This optimization is off by default for BDW and CHV; turn it on.
613*a85cb24fSFrançois Tigeot 	 */
614*a85cb24fSFrançois Tigeot 	WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE);
615*a85cb24fSFrançois Tigeot 
616*a85cb24fSFrançois Tigeot 	/* Wa4x4STCOptimizationDisable:bdw,chv */
617*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE);
618*a85cb24fSFrançois Tigeot 
619*a85cb24fSFrançois Tigeot 	/*
620*a85cb24fSFrançois Tigeot 	 * BSpec recommends 8x4 when MSAA is used,
621*a85cb24fSFrançois Tigeot 	 * however in practice 16x4 seems fastest.
622*a85cb24fSFrançois Tigeot 	 *
623*a85cb24fSFrançois Tigeot 	 * Note that PS/WM thread counts depend on the WIZ hashing
624*a85cb24fSFrançois Tigeot 	 * disable bit, which we don't touch here, but it's good
625*a85cb24fSFrançois Tigeot 	 * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
626*a85cb24fSFrançois Tigeot 	 */
627*a85cb24fSFrançois Tigeot 	WA_SET_FIELD_MASKED(GEN7_GT_MODE,
628*a85cb24fSFrançois Tigeot 			    GEN6_WIZ_HASHING_MASK,
629*a85cb24fSFrançois Tigeot 			    GEN6_WIZ_HASHING_16x4);
630*a85cb24fSFrançois Tigeot 
631*a85cb24fSFrançois Tigeot 	return 0;
632*a85cb24fSFrançois Tigeot }
633*a85cb24fSFrançois Tigeot 
634*a85cb24fSFrançois Tigeot static int bdw_init_workarounds(struct intel_engine_cs *engine)
635*a85cb24fSFrançois Tigeot {
636*a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
637*a85cb24fSFrançois Tigeot 	int ret;
638*a85cb24fSFrançois Tigeot 
639*a85cb24fSFrançois Tigeot 	ret = gen8_init_workarounds(engine);
640*a85cb24fSFrançois Tigeot 	if (ret)
641*a85cb24fSFrançois Tigeot 		return ret;
642*a85cb24fSFrançois Tigeot 
643*a85cb24fSFrançois Tigeot 	/* WaDisableThreadStallDopClockGating:bdw (pre-production) */
644*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
645*a85cb24fSFrançois Tigeot 
646*a85cb24fSFrançois Tigeot 	/* WaDisableDopClockGating:bdw
647*a85cb24fSFrançois Tigeot 	 *
648*a85cb24fSFrançois Tigeot 	 * Also see the related UCGTCL1 write in broadwell_init_clock_gating()
649*a85cb24fSFrançois Tigeot 	 * to disable EUTC clock gating.
650*a85cb24fSFrançois Tigeot 	 */
651*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2,
652*a85cb24fSFrançois Tigeot 			  DOP_CLOCK_GATING_DISABLE);
653*a85cb24fSFrançois Tigeot 
654*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
655*a85cb24fSFrançois Tigeot 			  GEN8_SAMPLER_POWER_BYPASS_DIS);
656*a85cb24fSFrançois Tigeot 
657*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
658*a85cb24fSFrançois Tigeot 			  /* WaForceContextSaveRestoreNonCoherent:bdw */
659*a85cb24fSFrançois Tigeot 			  HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
660*a85cb24fSFrançois Tigeot 			  /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */
661*a85cb24fSFrançois Tigeot 			  (IS_BDW_GT3(dev_priv) ? HDC_FENCE_DEST_SLM_DISABLE : 0));
662*a85cb24fSFrançois Tigeot 
663*a85cb24fSFrançois Tigeot 	return 0;
664*a85cb24fSFrançois Tigeot }
665*a85cb24fSFrançois Tigeot 
666*a85cb24fSFrançois Tigeot static int chv_init_workarounds(struct intel_engine_cs *engine)
667*a85cb24fSFrançois Tigeot {
668*a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
669*a85cb24fSFrançois Tigeot 	int ret;
670*a85cb24fSFrançois Tigeot 
671*a85cb24fSFrançois Tigeot 	ret = gen8_init_workarounds(engine);
672*a85cb24fSFrançois Tigeot 	if (ret)
673*a85cb24fSFrançois Tigeot 		return ret;
674*a85cb24fSFrançois Tigeot 
675*a85cb24fSFrançois Tigeot 	/* WaDisableThreadStallDopClockGating:chv */
676*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
677*a85cb24fSFrançois Tigeot 
678*a85cb24fSFrançois Tigeot 	/* Improve HiZ throughput on CHV. */
679*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X);
680*a85cb24fSFrançois Tigeot 
681*a85cb24fSFrançois Tigeot 	return 0;
682*a85cb24fSFrançois Tigeot }
683*a85cb24fSFrançois Tigeot 
684*a85cb24fSFrançois Tigeot static int gen9_init_workarounds(struct intel_engine_cs *engine)
685*a85cb24fSFrançois Tigeot {
686*a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
687*a85cb24fSFrançois Tigeot 	int ret;
688*a85cb24fSFrançois Tigeot 
689*a85cb24fSFrançois Tigeot 	/* WaConextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl,glk */
690*a85cb24fSFrançois Tigeot 	I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE));
691*a85cb24fSFrançois Tigeot 
692*a85cb24fSFrançois Tigeot 	/* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl,glk */
693*a85cb24fSFrançois Tigeot 	I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) |
694*a85cb24fSFrançois Tigeot 		   GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE);
695*a85cb24fSFrançois Tigeot 
696*a85cb24fSFrançois Tigeot 	/* WaDisableKillLogic:bxt,skl,kbl */
697*a85cb24fSFrançois Tigeot 	I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
698*a85cb24fSFrançois Tigeot 		   ECOCHK_DIS_TLB);
699*a85cb24fSFrançois Tigeot 
700*a85cb24fSFrançois Tigeot 	/* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl,glk */
701*a85cb24fSFrançois Tigeot 	/* WaDisablePartialInstShootdown:skl,bxt,kbl,glk */
702*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
703*a85cb24fSFrançois Tigeot 			  FLOW_CONTROL_ENABLE |
704*a85cb24fSFrançois Tigeot 			  PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
705*a85cb24fSFrançois Tigeot 
706*a85cb24fSFrançois Tigeot 	/* Syncing dependencies between camera and graphics:skl,bxt,kbl */
707*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
708*a85cb24fSFrançois Tigeot 			  GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC);
709*a85cb24fSFrançois Tigeot 
710*a85cb24fSFrançois Tigeot 	/* WaDisableDgMirrorFixInHalfSliceChicken5:bxt */
711*a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
712*a85cb24fSFrançois Tigeot 		WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
713*a85cb24fSFrançois Tigeot 				  GEN9_DG_MIRROR_FIX_ENABLE);
714*a85cb24fSFrançois Tigeot 
715*a85cb24fSFrançois Tigeot 	/* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:bxt */
716*a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
717*a85cb24fSFrançois Tigeot 		WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1,
718*a85cb24fSFrançois Tigeot 				  GEN9_RHWO_OPTIMIZATION_DISABLE);
719*a85cb24fSFrançois Tigeot 		/*
720*a85cb24fSFrançois Tigeot 		 * WA also requires GEN9_SLICE_COMMON_ECO_CHICKEN0[14:14] to be set
721*a85cb24fSFrançois Tigeot 		 * but we do that in per ctx batchbuffer as there is an issue
722*a85cb24fSFrançois Tigeot 		 * with this register not getting restored on ctx restore
723*a85cb24fSFrançois Tigeot 		 */
724*a85cb24fSFrançois Tigeot 	}
725*a85cb24fSFrançois Tigeot 
726*a85cb24fSFrançois Tigeot 	/* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl */
727*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7,
728*a85cb24fSFrançois Tigeot 			  GEN9_ENABLE_GPGPU_PREEMPTION);
729*a85cb24fSFrançois Tigeot 
730*a85cb24fSFrançois Tigeot 	/* Wa4x4STCOptimizationDisable:skl,bxt,kbl,glk */
731*a85cb24fSFrançois Tigeot 	/* WaDisablePartialResolveInVc:skl,bxt,kbl */
732*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(CACHE_MODE_1, (GEN8_4x4_STC_OPTIMIZATION_DISABLE |
733*a85cb24fSFrançois Tigeot 					 GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE));
734*a85cb24fSFrançois Tigeot 
735*a85cb24fSFrançois Tigeot 	/* WaCcsTlbPrefetchDisable:skl,bxt,kbl,glk */
736*a85cb24fSFrançois Tigeot 	WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
737*a85cb24fSFrançois Tigeot 			  GEN9_CCS_TLB_PREFETCH_ENABLE);
738*a85cb24fSFrançois Tigeot 
739*a85cb24fSFrançois Tigeot 	/* WaDisableMaskBasedCammingInRCC:bxt */
740*a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
741*a85cb24fSFrançois Tigeot 		WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0,
742*a85cb24fSFrançois Tigeot 				  PIXEL_MASK_CAMMING_DISABLE);
743*a85cb24fSFrançois Tigeot 
744*a85cb24fSFrançois Tigeot 	/* WaForceContextSaveRestoreNonCoherent:skl,bxt,kbl */
745*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
746*a85cb24fSFrançois Tigeot 			  HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
747*a85cb24fSFrançois Tigeot 			  HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE);
748*a85cb24fSFrançois Tigeot 
749*a85cb24fSFrançois Tigeot 	/* WaForceEnableNonCoherent and WaDisableHDCInvalidation are
750*a85cb24fSFrançois Tigeot 	 * both tied to WaForceContextSaveRestoreNonCoherent
751*a85cb24fSFrançois Tigeot 	 * in some hsds for skl. We keep the tie for all gen9. The
752*a85cb24fSFrançois Tigeot 	 * documentation is a bit hazy and so we want to get common behaviour,
753*a85cb24fSFrançois Tigeot 	 * even though there is no clear evidence we would need both on kbl/bxt.
754*a85cb24fSFrançois Tigeot 	 * This area has been source of system hangs so we play it safe
755*a85cb24fSFrançois Tigeot 	 * and mimic the skl regardless of what bspec says.
756*a85cb24fSFrançois Tigeot 	 *
757*a85cb24fSFrançois Tigeot 	 * Use Force Non-Coherent whenever executing a 3D context. This
758*a85cb24fSFrançois Tigeot 	 * is a workaround for a possible hang in the unlikely event
759*a85cb24fSFrançois Tigeot 	 * a TLB invalidation occurs during a PSD flush.
760*a85cb24fSFrançois Tigeot 	 */
761*a85cb24fSFrançois Tigeot 
762*a85cb24fSFrançois Tigeot 	/* WaForceEnableNonCoherent:skl,bxt,kbl */
763*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
764*a85cb24fSFrançois Tigeot 			  HDC_FORCE_NON_COHERENT);
765*a85cb24fSFrançois Tigeot 
766*a85cb24fSFrançois Tigeot 	/* WaDisableHDCInvalidation:skl,bxt,kbl */
767*a85cb24fSFrançois Tigeot 	I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
768*a85cb24fSFrançois Tigeot 		   BDW_DISABLE_HDC_INVALIDATION);
769*a85cb24fSFrançois Tigeot 
770*a85cb24fSFrançois Tigeot 	/* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl */
771*a85cb24fSFrançois Tigeot 	if (IS_SKYLAKE(dev_priv) ||
772*a85cb24fSFrançois Tigeot 	    IS_KABYLAKE(dev_priv) ||
773*a85cb24fSFrançois Tigeot 	    IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0))
774*a85cb24fSFrançois Tigeot 		WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
775*a85cb24fSFrançois Tigeot 				  GEN8_SAMPLER_POWER_BYPASS_DIS);
776*a85cb24fSFrançois Tigeot 
777*a85cb24fSFrançois Tigeot 	/* WaDisableSTUnitPowerOptimization:skl,bxt,kbl,glk */
778*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE);
779*a85cb24fSFrançois Tigeot 
780*a85cb24fSFrançois Tigeot 	/* WaOCLCoherentLineFlush:skl,bxt,kbl */
781*a85cb24fSFrançois Tigeot 	I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) |
782*a85cb24fSFrançois Tigeot 				    GEN8_LQSC_FLUSH_COHERENT_LINES));
783*a85cb24fSFrançois Tigeot 
784*a85cb24fSFrançois Tigeot 	/* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt,glk */
785*a85cb24fSFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG);
786*a85cb24fSFrançois Tigeot 	if (ret)
787*a85cb24fSFrançois Tigeot 		return ret;
788*a85cb24fSFrançois Tigeot 
789*a85cb24fSFrançois Tigeot 	/* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl */
790*a85cb24fSFrançois Tigeot 	ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1);
791*a85cb24fSFrançois Tigeot 	if (ret)
792*a85cb24fSFrançois Tigeot 		return ret;
793*a85cb24fSFrançois Tigeot 
794*a85cb24fSFrançois Tigeot 	/* WaAllowUMDToModifyHDCChicken1:skl,bxt,kbl,glk */
795*a85cb24fSFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN8_HDC_CHICKEN1);
796*a85cb24fSFrançois Tigeot 	if (ret)
797*a85cb24fSFrançois Tigeot 		return ret;
798*a85cb24fSFrançois Tigeot 
799*a85cb24fSFrançois Tigeot 	return 0;
800*a85cb24fSFrançois Tigeot }
801*a85cb24fSFrançois Tigeot 
802*a85cb24fSFrançois Tigeot static int skl_tune_iz_hashing(struct intel_engine_cs *engine)
803*a85cb24fSFrançois Tigeot {
804*a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
805*a85cb24fSFrançois Tigeot 	u8 vals[3] = { 0, 0, 0 };
806*a85cb24fSFrançois Tigeot 	unsigned int i;
807*a85cb24fSFrançois Tigeot 
808*a85cb24fSFrançois Tigeot 	for (i = 0; i < 3; i++) {
809*a85cb24fSFrançois Tigeot 		u8 ss;
810*a85cb24fSFrançois Tigeot 
811*a85cb24fSFrançois Tigeot 		/*
812*a85cb24fSFrançois Tigeot 		 * Only consider slices where one, and only one, subslice has 7
813*a85cb24fSFrançois Tigeot 		 * EUs
814*a85cb24fSFrançois Tigeot 		 */
815*a85cb24fSFrançois Tigeot 		if (!is_power_of_2(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i]))
816*a85cb24fSFrançois Tigeot 			continue;
817*a85cb24fSFrançois Tigeot 
818*a85cb24fSFrançois Tigeot 		/*
819*a85cb24fSFrançois Tigeot 		 * subslice_7eu[i] != 0 (because of the check above) and
820*a85cb24fSFrançois Tigeot 		 * ss_max == 4 (maximum number of subslices possible per slice)
821*a85cb24fSFrançois Tigeot 		 *
822*a85cb24fSFrançois Tigeot 		 * ->    0 <= ss <= 3;
823*a85cb24fSFrançois Tigeot 		 */
824*a85cb24fSFrançois Tigeot 		ss = ffs(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i]) - 1;
825*a85cb24fSFrançois Tigeot 		vals[i] = 3 - ss;
826*a85cb24fSFrançois Tigeot 	}
827*a85cb24fSFrançois Tigeot 
828*a85cb24fSFrançois Tigeot 	if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0)
829*a85cb24fSFrançois Tigeot 		return 0;
830*a85cb24fSFrançois Tigeot 
831*a85cb24fSFrançois Tigeot 	/* Tune IZ hashing. See intel_device_info_runtime_init() */
832*a85cb24fSFrançois Tigeot 	WA_SET_FIELD_MASKED(GEN7_GT_MODE,
833*a85cb24fSFrançois Tigeot 			    GEN9_IZ_HASHING_MASK(2) |
834*a85cb24fSFrançois Tigeot 			    GEN9_IZ_HASHING_MASK(1) |
835*a85cb24fSFrançois Tigeot 			    GEN9_IZ_HASHING_MASK(0),
836*a85cb24fSFrançois Tigeot 			    GEN9_IZ_HASHING(2, vals[2]) |
837*a85cb24fSFrançois Tigeot 			    GEN9_IZ_HASHING(1, vals[1]) |
838*a85cb24fSFrançois Tigeot 			    GEN9_IZ_HASHING(0, vals[0]));
839*a85cb24fSFrançois Tigeot 
840*a85cb24fSFrançois Tigeot 	return 0;
841*a85cb24fSFrançois Tigeot }
842*a85cb24fSFrançois Tigeot 
843*a85cb24fSFrançois Tigeot static int skl_init_workarounds(struct intel_engine_cs *engine)
844*a85cb24fSFrançois Tigeot {
845*a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
846*a85cb24fSFrançois Tigeot 	int ret;
847*a85cb24fSFrançois Tigeot 
848*a85cb24fSFrançois Tigeot 	ret = gen9_init_workarounds(engine);
849*a85cb24fSFrançois Tigeot 	if (ret)
850*a85cb24fSFrançois Tigeot 		return ret;
851*a85cb24fSFrançois Tigeot 
852*a85cb24fSFrançois Tigeot 	/*
853*a85cb24fSFrançois Tigeot 	 * Actual WA is to disable percontext preemption granularity control
854*a85cb24fSFrançois Tigeot 	 * until D0 which is the default case so this is equivalent to
855*a85cb24fSFrançois Tigeot 	 * !WaDisablePerCtxtPreemptionGranularityControl:skl
856*a85cb24fSFrançois Tigeot 	 */
857*a85cb24fSFrançois Tigeot 	I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1,
858*a85cb24fSFrançois Tigeot 		   _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL));
859*a85cb24fSFrançois Tigeot 
860*a85cb24fSFrançois Tigeot 	/* WaEnableGapsTsvCreditFix:skl */
861*a85cb24fSFrançois Tigeot 	I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
862*a85cb24fSFrançois Tigeot 				   GEN9_GAPS_TSV_CREDIT_DISABLE));
863*a85cb24fSFrançois Tigeot 
864*a85cb24fSFrançois Tigeot 	/* WaDisableGafsUnitClkGating:skl */
865*a85cb24fSFrançois Tigeot 	WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
866*a85cb24fSFrançois Tigeot 
867*a85cb24fSFrançois Tigeot 	/* WaInPlaceDecompressionHang:skl */
868*a85cb24fSFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER))
869*a85cb24fSFrançois Tigeot 		WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA,
870*a85cb24fSFrançois Tigeot 			   GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
871*a85cb24fSFrançois Tigeot 
872*a85cb24fSFrançois Tigeot 	/* WaDisableLSQCROPERFforOCL:skl */
873*a85cb24fSFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
874*a85cb24fSFrançois Tigeot 	if (ret)
875*a85cb24fSFrançois Tigeot 		return ret;
876*a85cb24fSFrançois Tigeot 
877*a85cb24fSFrançois Tigeot 	return skl_tune_iz_hashing(engine);
878*a85cb24fSFrançois Tigeot }
879*a85cb24fSFrançois Tigeot 
880*a85cb24fSFrançois Tigeot static int bxt_init_workarounds(struct intel_engine_cs *engine)
881*a85cb24fSFrançois Tigeot {
882*a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
883*a85cb24fSFrançois Tigeot 	int ret;
884*a85cb24fSFrançois Tigeot 
885*a85cb24fSFrançois Tigeot 	ret = gen9_init_workarounds(engine);
886*a85cb24fSFrançois Tigeot 	if (ret)
887*a85cb24fSFrançois Tigeot 		return ret;
888*a85cb24fSFrançois Tigeot 
889*a85cb24fSFrançois Tigeot 	/* WaStoreMultiplePTEenable:bxt */
890*a85cb24fSFrançois Tigeot 	/* This is a requirement according to Hardware specification */
891*a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
892*a85cb24fSFrançois Tigeot 		I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF);
893*a85cb24fSFrançois Tigeot 
894*a85cb24fSFrançois Tigeot 	/* WaSetClckGatingDisableMedia:bxt */
895*a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
896*a85cb24fSFrançois Tigeot 		I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) &
897*a85cb24fSFrançois Tigeot 					    ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE));
898*a85cb24fSFrançois Tigeot 	}
899*a85cb24fSFrançois Tigeot 
900*a85cb24fSFrançois Tigeot 	/* WaDisableThreadStallDopClockGating:bxt */
901*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
902*a85cb24fSFrançois Tigeot 			  STALL_DOP_GATING_DISABLE);
903*a85cb24fSFrançois Tigeot 
904*a85cb24fSFrançois Tigeot 	/* WaDisablePooledEuLoadBalancingFix:bxt */
905*a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) {
906*a85cb24fSFrançois Tigeot 		WA_SET_BIT_MASKED(FF_SLICE_CS_CHICKEN2,
907*a85cb24fSFrançois Tigeot 				  GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE);
908*a85cb24fSFrançois Tigeot 	}
909*a85cb24fSFrançois Tigeot 
910*a85cb24fSFrançois Tigeot 	/* WaDisableSbeCacheDispatchPortSharing:bxt */
911*a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) {
912*a85cb24fSFrançois Tigeot 		WA_SET_BIT_MASKED(
913*a85cb24fSFrançois Tigeot 			GEN7_HALF_SLICE_CHICKEN1,
914*a85cb24fSFrançois Tigeot 			GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
915*a85cb24fSFrançois Tigeot 	}
916*a85cb24fSFrançois Tigeot 
917*a85cb24fSFrançois Tigeot 	/* WaDisableObjectLevelPreemptionForTrifanOrPolygon:bxt */
918*a85cb24fSFrançois Tigeot 	/* WaDisableObjectLevelPreemptionForInstancedDraw:bxt */
919*a85cb24fSFrançois Tigeot 	/* WaDisableObjectLevelPreemtionForInstanceId:bxt */
920*a85cb24fSFrançois Tigeot 	/* WaDisableLSQCROPERFforOCL:bxt */
921*a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
922*a85cb24fSFrançois Tigeot 		ret = wa_ring_whitelist_reg(engine, GEN9_CS_DEBUG_MODE1);
923*a85cb24fSFrançois Tigeot 		if (ret)
924*a85cb24fSFrançois Tigeot 			return ret;
925*a85cb24fSFrançois Tigeot 
926*a85cb24fSFrançois Tigeot 		ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
927*a85cb24fSFrançois Tigeot 		if (ret)
928*a85cb24fSFrançois Tigeot 			return ret;
929*a85cb24fSFrançois Tigeot 	}
930*a85cb24fSFrançois Tigeot 
931*a85cb24fSFrançois Tigeot 	/* WaProgramL3SqcReg1DefaultForPerf:bxt */
932*a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER))
933*a85cb24fSFrançois Tigeot 		I915_WRITE(GEN8_L3SQCREG1, L3_GENERAL_PRIO_CREDITS(62) |
934*a85cb24fSFrançois Tigeot 					   L3_HIGH_PRIO_CREDITS(2));
935*a85cb24fSFrançois Tigeot 
936*a85cb24fSFrançois Tigeot 	/* WaToEnableHwFixForPushConstHWBug:bxt */
937*a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER))
938*a85cb24fSFrançois Tigeot 		WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
939*a85cb24fSFrançois Tigeot 				  GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
940*a85cb24fSFrançois Tigeot 
941*a85cb24fSFrançois Tigeot 	/* WaInPlaceDecompressionHang:bxt */
942*a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER))
943*a85cb24fSFrançois Tigeot 		WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA,
944*a85cb24fSFrançois Tigeot 			   GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
945*a85cb24fSFrançois Tigeot 
946*a85cb24fSFrançois Tigeot 	return 0;
947*a85cb24fSFrançois Tigeot }
948*a85cb24fSFrançois Tigeot 
949*a85cb24fSFrançois Tigeot static int kbl_init_workarounds(struct intel_engine_cs *engine)
950*a85cb24fSFrançois Tigeot {
951*a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
952*a85cb24fSFrançois Tigeot 	int ret;
953*a85cb24fSFrançois Tigeot 
954*a85cb24fSFrançois Tigeot 	ret = gen9_init_workarounds(engine);
955*a85cb24fSFrançois Tigeot 	if (ret)
956*a85cb24fSFrançois Tigeot 		return ret;
957*a85cb24fSFrançois Tigeot 
958*a85cb24fSFrançois Tigeot 	/* WaEnableGapsTsvCreditFix:kbl */
959*a85cb24fSFrançois Tigeot 	I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
960*a85cb24fSFrançois Tigeot 				   GEN9_GAPS_TSV_CREDIT_DISABLE));
961*a85cb24fSFrançois Tigeot 
962*a85cb24fSFrançois Tigeot 	/* WaDisableDynamicCreditSharing:kbl */
963*a85cb24fSFrançois Tigeot 	if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0))
964*a85cb24fSFrançois Tigeot 		WA_SET_BIT(GAMT_CHKN_BIT_REG,
965*a85cb24fSFrançois Tigeot 			   GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING);
966*a85cb24fSFrançois Tigeot 
967*a85cb24fSFrançois Tigeot 	/* WaDisableFenceDestinationToSLM:kbl (pre-prod) */
968*a85cb24fSFrançois Tigeot 	if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_A0))
969*a85cb24fSFrançois Tigeot 		WA_SET_BIT_MASKED(HDC_CHICKEN0,
970*a85cb24fSFrançois Tigeot 				  HDC_FENCE_DEST_SLM_DISABLE);
971*a85cb24fSFrançois Tigeot 
972*a85cb24fSFrançois Tigeot 	/* WaToEnableHwFixForPushConstHWBug:kbl */
973*a85cb24fSFrançois Tigeot 	if (IS_KBL_REVID(dev_priv, KBL_REVID_C0, REVID_FOREVER))
974*a85cb24fSFrançois Tigeot 		WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
975*a85cb24fSFrançois Tigeot 				  GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
976*a85cb24fSFrançois Tigeot 
977*a85cb24fSFrançois Tigeot 	/* WaDisableGafsUnitClkGating:kbl */
978*a85cb24fSFrançois Tigeot 	WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
979*a85cb24fSFrançois Tigeot 
980*a85cb24fSFrançois Tigeot 	/* WaDisableSbeCacheDispatchPortSharing:kbl */
981*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(
982*a85cb24fSFrançois Tigeot 		GEN7_HALF_SLICE_CHICKEN1,
983*a85cb24fSFrançois Tigeot 		GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
984*a85cb24fSFrançois Tigeot 
985*a85cb24fSFrançois Tigeot 	/* WaInPlaceDecompressionHang:kbl */
986*a85cb24fSFrançois Tigeot 	WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA,
987*a85cb24fSFrançois Tigeot 		   GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
988*a85cb24fSFrançois Tigeot 
989*a85cb24fSFrançois Tigeot 	/* WaDisableLSQCROPERFforOCL:kbl */
990*a85cb24fSFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
991*a85cb24fSFrançois Tigeot 	if (ret)
992*a85cb24fSFrançois Tigeot 		return ret;
993*a85cb24fSFrançois Tigeot 
994*a85cb24fSFrançois Tigeot 	return 0;
995*a85cb24fSFrançois Tigeot }
996*a85cb24fSFrançois Tigeot 
997*a85cb24fSFrançois Tigeot static int glk_init_workarounds(struct intel_engine_cs *engine)
998*a85cb24fSFrançois Tigeot {
999*a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1000*a85cb24fSFrançois Tigeot 	int ret;
1001*a85cb24fSFrançois Tigeot 
1002*a85cb24fSFrançois Tigeot 	ret = gen9_init_workarounds(engine);
1003*a85cb24fSFrançois Tigeot 	if (ret)
1004*a85cb24fSFrançois Tigeot 		return ret;
1005*a85cb24fSFrançois Tigeot 
1006*a85cb24fSFrançois Tigeot 	/* WaToEnableHwFixForPushConstHWBug:glk */
1007*a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
1008*a85cb24fSFrançois Tigeot 			  GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
1009*a85cb24fSFrançois Tigeot 
1010*a85cb24fSFrançois Tigeot 	return 0;
1011*a85cb24fSFrançois Tigeot }
1012*a85cb24fSFrançois Tigeot 
1013*a85cb24fSFrançois Tigeot int init_workarounds_ring(struct intel_engine_cs *engine)
1014*a85cb24fSFrançois Tigeot {
1015*a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1016*a85cb24fSFrançois Tigeot 	int err;
1017*a85cb24fSFrançois Tigeot 
1018*a85cb24fSFrançois Tigeot 	WARN_ON(engine->id != RCS);
1019*a85cb24fSFrançois Tigeot 
1020*a85cb24fSFrançois Tigeot 	dev_priv->workarounds.count = 0;
1021*a85cb24fSFrançois Tigeot 	dev_priv->workarounds.hw_whitelist_count[engine->id] = 0;
1022*a85cb24fSFrançois Tigeot 
1023*a85cb24fSFrançois Tigeot 	if (IS_BROADWELL(dev_priv))
1024*a85cb24fSFrançois Tigeot 		err = bdw_init_workarounds(engine);
1025*a85cb24fSFrançois Tigeot 	else if (IS_CHERRYVIEW(dev_priv))
1026*a85cb24fSFrançois Tigeot 		err = chv_init_workarounds(engine);
1027*a85cb24fSFrançois Tigeot 	else if (IS_SKYLAKE(dev_priv))
1028*a85cb24fSFrançois Tigeot 		err =  skl_init_workarounds(engine);
1029*a85cb24fSFrançois Tigeot 	else if (IS_BROXTON(dev_priv))
1030*a85cb24fSFrançois Tigeot 		err = bxt_init_workarounds(engine);
1031*a85cb24fSFrançois Tigeot 	else if (IS_KABYLAKE(dev_priv))
1032*a85cb24fSFrançois Tigeot 		err = kbl_init_workarounds(engine);
1033*a85cb24fSFrançois Tigeot 	else if (IS_GEMINILAKE(dev_priv))
1034*a85cb24fSFrançois Tigeot 		err =  glk_init_workarounds(engine);
1035*a85cb24fSFrançois Tigeot 	else
1036*a85cb24fSFrançois Tigeot 		err = 0;
1037*a85cb24fSFrançois Tigeot 	if (err)
1038*a85cb24fSFrançois Tigeot 		return err;
1039*a85cb24fSFrançois Tigeot 
1040*a85cb24fSFrançois Tigeot 	DRM_DEBUG_DRIVER("%s: Number of context specific w/a: %d\n",
1041*a85cb24fSFrançois Tigeot 			 engine->name, dev_priv->workarounds.count);
1042*a85cb24fSFrançois Tigeot 	return 0;
1043*a85cb24fSFrançois Tigeot }
1044*a85cb24fSFrançois Tigeot 
1045*a85cb24fSFrançois Tigeot int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
1046*a85cb24fSFrançois Tigeot {
1047*a85cb24fSFrançois Tigeot 	struct i915_workarounds *w = &req->i915->workarounds;
1048*a85cb24fSFrançois Tigeot 	u32 *cs;
1049*a85cb24fSFrançois Tigeot 	int ret, i;
1050*a85cb24fSFrançois Tigeot 
1051*a85cb24fSFrançois Tigeot 	if (w->count == 0)
1052*a85cb24fSFrançois Tigeot 		return 0;
1053*a85cb24fSFrançois Tigeot 
1054*a85cb24fSFrançois Tigeot 	ret = req->engine->emit_flush(req, EMIT_BARRIER);
1055*a85cb24fSFrançois Tigeot 	if (ret)
1056*a85cb24fSFrançois Tigeot 		return ret;
1057*a85cb24fSFrançois Tigeot 
1058*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, (w->count * 2 + 2));
1059*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
1060*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
1061*a85cb24fSFrançois Tigeot 
1062*a85cb24fSFrançois Tigeot 	*cs++ = MI_LOAD_REGISTER_IMM(w->count);
1063*a85cb24fSFrançois Tigeot 	for (i = 0; i < w->count; i++) {
1064*a85cb24fSFrançois Tigeot 		*cs++ = i915_mmio_reg_offset(w->reg[i].addr);
1065*a85cb24fSFrançois Tigeot 		*cs++ = w->reg[i].value;
1066*a85cb24fSFrançois Tigeot 	}
1067*a85cb24fSFrançois Tigeot 	*cs++ = MI_NOOP;
1068*a85cb24fSFrançois Tigeot 
1069*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
1070*a85cb24fSFrançois Tigeot 
1071*a85cb24fSFrançois Tigeot 	ret = req->engine->emit_flush(req, EMIT_BARRIER);
1072*a85cb24fSFrançois Tigeot 	if (ret)
1073*a85cb24fSFrançois Tigeot 		return ret;
1074*a85cb24fSFrançois Tigeot 
1075*a85cb24fSFrançois Tigeot 	return 0;
1076*a85cb24fSFrançois Tigeot }
1077*a85cb24fSFrançois Tigeot 
1078*a85cb24fSFrançois Tigeot static bool ring_is_idle(struct intel_engine_cs *engine)
1079*a85cb24fSFrançois Tigeot {
1080*a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1081*a85cb24fSFrançois Tigeot 	bool idle = true;
1082*a85cb24fSFrançois Tigeot 
1083*a85cb24fSFrançois Tigeot 	intel_runtime_pm_get(dev_priv);
1084*a85cb24fSFrançois Tigeot 
1085*a85cb24fSFrançois Tigeot 	/* No bit for gen2, so assume the CS parser is idle */
1086*a85cb24fSFrançois Tigeot 	if (INTEL_GEN(dev_priv) > 2 && !(I915_READ_MODE(engine) & MODE_IDLE))
1087*a85cb24fSFrançois Tigeot 		idle = false;
1088*a85cb24fSFrançois Tigeot 
1089*a85cb24fSFrançois Tigeot 	intel_runtime_pm_put(dev_priv);
1090*a85cb24fSFrançois Tigeot 
1091*a85cb24fSFrançois Tigeot 	return idle;
1092*a85cb24fSFrançois Tigeot }
1093*a85cb24fSFrançois Tigeot 
1094*a85cb24fSFrançois Tigeot /**
1095*a85cb24fSFrançois Tigeot  * intel_engine_is_idle() - Report if the engine has finished process all work
1096*a85cb24fSFrançois Tigeot  * @engine: the intel_engine_cs
1097*a85cb24fSFrançois Tigeot  *
1098*a85cb24fSFrançois Tigeot  * Return true if there are no requests pending, nothing left to be submitted
1099*a85cb24fSFrançois Tigeot  * to hardware, and that the engine is idle.
1100*a85cb24fSFrançois Tigeot  */
1101*a85cb24fSFrançois Tigeot bool intel_engine_is_idle(struct intel_engine_cs *engine)
1102*a85cb24fSFrançois Tigeot {
1103*a85cb24fSFrançois Tigeot 	/* Any inflight/incomplete requests? */
1104*a85cb24fSFrançois Tigeot 	if (!i915_seqno_passed(intel_engine_get_seqno(engine),
1105*a85cb24fSFrançois Tigeot 			       intel_engine_last_submit(engine)))
1106*a85cb24fSFrançois Tigeot 		return false;
1107*a85cb24fSFrançois Tigeot 
1108*a85cb24fSFrançois Tigeot 	/* Interrupt/tasklet pending? */
1109*a85cb24fSFrançois Tigeot 	if (test_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted))
1110*a85cb24fSFrançois Tigeot 		return false;
1111*a85cb24fSFrançois Tigeot 
1112*a85cb24fSFrançois Tigeot 	/* Both ports drained, no more ELSP submission? */
1113*a85cb24fSFrançois Tigeot 	if (engine->execlist_port[0].request)
1114*a85cb24fSFrançois Tigeot 		return false;
1115*a85cb24fSFrançois Tigeot 
1116*a85cb24fSFrançois Tigeot 	/* Ring stopped? */
1117*a85cb24fSFrançois Tigeot 	if (!ring_is_idle(engine))
1118*a85cb24fSFrançois Tigeot 		return false;
1119*a85cb24fSFrançois Tigeot 
1120*a85cb24fSFrançois Tigeot 	return true;
1121*a85cb24fSFrançois Tigeot }
1122*a85cb24fSFrançois Tigeot 
1123*a85cb24fSFrançois Tigeot bool intel_engines_are_idle(struct drm_i915_private *dev_priv)
1124*a85cb24fSFrançois Tigeot {
1125*a85cb24fSFrançois Tigeot 	struct intel_engine_cs *engine;
1126*a85cb24fSFrançois Tigeot 	enum intel_engine_id id;
1127*a85cb24fSFrançois Tigeot 
1128*a85cb24fSFrançois Tigeot 	if (READ_ONCE(dev_priv->gt.active_requests))
1129*a85cb24fSFrançois Tigeot 		return false;
1130*a85cb24fSFrançois Tigeot 
1131*a85cb24fSFrançois Tigeot 	/* If the driver is wedged, HW state may be very inconsistent and
1132*a85cb24fSFrançois Tigeot 	 * report that it is still busy, even though we have stopped using it.
1133*a85cb24fSFrançois Tigeot 	 */
1134*a85cb24fSFrançois Tigeot 	if (i915_terminally_wedged(&dev_priv->gpu_error))
1135*a85cb24fSFrançois Tigeot 		return true;
1136*a85cb24fSFrançois Tigeot 
1137*a85cb24fSFrançois Tigeot 	for_each_engine(engine, dev_priv, id) {
1138*a85cb24fSFrançois Tigeot 		if (!intel_engine_is_idle(engine))
1139*a85cb24fSFrançois Tigeot 			return false;
1140*a85cb24fSFrançois Tigeot 	}
1141*a85cb24fSFrançois Tigeot 
1142*a85cb24fSFrançois Tigeot 	return true;
1143*a85cb24fSFrançois Tigeot }
1144*a85cb24fSFrançois Tigeot 
1145*a85cb24fSFrançois Tigeot void intel_engines_reset_default_submission(struct drm_i915_private *i915)
1146*a85cb24fSFrançois Tigeot {
1147*a85cb24fSFrançois Tigeot 	struct intel_engine_cs *engine;
1148*a85cb24fSFrançois Tigeot 	enum intel_engine_id id;
1149*a85cb24fSFrançois Tigeot 
1150*a85cb24fSFrançois Tigeot 	for_each_engine(engine, i915, id)
1151*a85cb24fSFrançois Tigeot 		engine->set_default_submission(engine);
1152*a85cb24fSFrançois Tigeot }
1153*a85cb24fSFrançois Tigeot 
1154*a85cb24fSFrançois Tigeot #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
1155*a85cb24fSFrançois Tigeot #include "selftests/mock_engine.c"
1156*a85cb24fSFrançois Tigeot #endif
1157