xref: /dflybsd-src/sys/dev/drm/i915/intel_engine_cs.c (revision 3f2dd94a569761201b5b0a18b2f697f97fe1b9dc)
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 
25*3f2dd94aSFrançois Tigeot #include <drm/drm_print.h>
26*3f2dd94aSFrançois Tigeot 
2787df8fc6SFrançois Tigeot #include "i915_drv.h"
28*3f2dd94aSFrançois Tigeot #include "i915_vgpu.h"
2987df8fc6SFrançois Tigeot #include "intel_ringbuffer.h"
3087df8fc6SFrançois Tigeot #include "intel_lrc.h"
3187df8fc6SFrançois Tigeot 
32*3f2dd94aSFrançois Tigeot /* Haswell does have the CXT_SIZE register however it does not appear to be
33*3f2dd94aSFrançois Tigeot  * valid. Now, docs explain in dwords what is in the context object. The full
34*3f2dd94aSFrançois Tigeot  * size is 70720 bytes, however, the power context and execlist context will
35*3f2dd94aSFrançois Tigeot  * never be saved (power context is stored elsewhere, and execlists don't work
36*3f2dd94aSFrançois Tigeot  * on HSW) - so the final size, including the extra state required for the
37*3f2dd94aSFrançois Tigeot  * Resource Streamer, is 66944 bytes, which rounds to 17 pages.
38*3f2dd94aSFrançois Tigeot  */
39*3f2dd94aSFrançois Tigeot #define HSW_CXT_TOTAL_SIZE		(17 * PAGE_SIZE)
40*3f2dd94aSFrançois Tigeot /* Same as Haswell, but 72064 bytes now. */
41*3f2dd94aSFrançois Tigeot #define GEN8_CXT_TOTAL_SIZE		(18 * PAGE_SIZE)
42*3f2dd94aSFrançois Tigeot 
43*3f2dd94aSFrançois Tigeot #define GEN8_LR_CONTEXT_RENDER_SIZE	(20 * PAGE_SIZE)
44*3f2dd94aSFrançois Tigeot #define GEN9_LR_CONTEXT_RENDER_SIZE	(22 * PAGE_SIZE)
45*3f2dd94aSFrançois Tigeot #define GEN10_LR_CONTEXT_RENDER_SIZE	(18 * PAGE_SIZE)
46*3f2dd94aSFrançois Tigeot 
47*3f2dd94aSFrançois Tigeot #define GEN8_LR_CONTEXT_OTHER_SIZE	( 2 * PAGE_SIZE)
48*3f2dd94aSFrançois Tigeot 
49*3f2dd94aSFrançois Tigeot struct engine_class_info {
5087df8fc6SFrançois Tigeot 	const char *name;
5187df8fc6SFrançois Tigeot 	int (*init_legacy)(struct intel_engine_cs *engine);
5287df8fc6SFrançois Tigeot 	int (*init_execlists)(struct intel_engine_cs *engine);
53*3f2dd94aSFrançois Tigeot };
54*3f2dd94aSFrançois Tigeot 
55*3f2dd94aSFrançois Tigeot static const struct engine_class_info intel_engine_classes[] = {
56*3f2dd94aSFrançois Tigeot 	[RENDER_CLASS] = {
57a85cb24fSFrançois Tigeot 		.name = "rcs",
5887df8fc6SFrançois Tigeot 		.init_execlists = logical_render_ring_init,
5987df8fc6SFrançois Tigeot 		.init_legacy = intel_init_render_ring_buffer,
6087df8fc6SFrançois Tigeot 	},
61*3f2dd94aSFrançois Tigeot 	[COPY_ENGINE_CLASS] = {
62a85cb24fSFrançois Tigeot 		.name = "bcs",
6387df8fc6SFrançois Tigeot 		.init_execlists = logical_xcs_ring_init,
6487df8fc6SFrançois Tigeot 		.init_legacy = intel_init_blt_ring_buffer,
6587df8fc6SFrançois Tigeot 	},
66*3f2dd94aSFrançois Tigeot 	[VIDEO_DECODE_CLASS] = {
67a85cb24fSFrançois Tigeot 		.name = "vcs",
6887df8fc6SFrançois Tigeot 		.init_execlists = logical_xcs_ring_init,
6987df8fc6SFrançois Tigeot 		.init_legacy = intel_init_bsd_ring_buffer,
7087df8fc6SFrançois Tigeot 	},
71*3f2dd94aSFrançois Tigeot 	[VIDEO_ENHANCEMENT_CLASS] = {
72a85cb24fSFrançois Tigeot 		.name = "vecs",
7387df8fc6SFrançois Tigeot 		.init_execlists = logical_xcs_ring_init,
7487df8fc6SFrançois Tigeot 		.init_legacy = intel_init_vebox_ring_buffer,
7587df8fc6SFrançois Tigeot 	},
7687df8fc6SFrançois Tigeot };
7787df8fc6SFrançois Tigeot 
78*3f2dd94aSFrançois Tigeot struct engine_info {
79*3f2dd94aSFrançois Tigeot 	unsigned int hw_id;
80*3f2dd94aSFrançois Tigeot 	unsigned int uabi_id;
81*3f2dd94aSFrançois Tigeot 	u8 class;
82*3f2dd94aSFrançois Tigeot 	u8 instance;
83*3f2dd94aSFrançois Tigeot 	u32 mmio_base;
84*3f2dd94aSFrançois Tigeot 	unsigned irq_shift;
85*3f2dd94aSFrançois Tigeot };
86*3f2dd94aSFrançois Tigeot 
87*3f2dd94aSFrançois Tigeot static const struct engine_info intel_engines[] = {
88*3f2dd94aSFrançois Tigeot 	[RCS] = {
89*3f2dd94aSFrançois Tigeot 		.hw_id = RCS_HW,
90*3f2dd94aSFrançois Tigeot 		.uabi_id = I915_EXEC_RENDER,
91*3f2dd94aSFrançois Tigeot 		.class = RENDER_CLASS,
92*3f2dd94aSFrançois Tigeot 		.instance = 0,
93*3f2dd94aSFrançois Tigeot 		.mmio_base = RENDER_RING_BASE,
94*3f2dd94aSFrançois Tigeot 		.irq_shift = GEN8_RCS_IRQ_SHIFT,
95*3f2dd94aSFrançois Tigeot 	},
96*3f2dd94aSFrançois Tigeot 	[BCS] = {
97*3f2dd94aSFrançois Tigeot 		.hw_id = BCS_HW,
98*3f2dd94aSFrançois Tigeot 		.uabi_id = I915_EXEC_BLT,
99*3f2dd94aSFrançois Tigeot 		.class = COPY_ENGINE_CLASS,
100*3f2dd94aSFrançois Tigeot 		.instance = 0,
101*3f2dd94aSFrançois Tigeot 		.mmio_base = BLT_RING_BASE,
102*3f2dd94aSFrançois Tigeot 		.irq_shift = GEN8_BCS_IRQ_SHIFT,
103*3f2dd94aSFrançois Tigeot 	},
104*3f2dd94aSFrançois Tigeot 	[VCS] = {
105*3f2dd94aSFrançois Tigeot 		.hw_id = VCS_HW,
106*3f2dd94aSFrançois Tigeot 		.uabi_id = I915_EXEC_BSD,
107*3f2dd94aSFrançois Tigeot 		.class = VIDEO_DECODE_CLASS,
108*3f2dd94aSFrançois Tigeot 		.instance = 0,
109*3f2dd94aSFrançois Tigeot 		.mmio_base = GEN6_BSD_RING_BASE,
110*3f2dd94aSFrançois Tigeot 		.irq_shift = GEN8_VCS1_IRQ_SHIFT,
111*3f2dd94aSFrançois Tigeot 	},
112*3f2dd94aSFrançois Tigeot 	[VCS2] = {
113*3f2dd94aSFrançois Tigeot 		.hw_id = VCS2_HW,
114*3f2dd94aSFrançois Tigeot 		.uabi_id = I915_EXEC_BSD,
115*3f2dd94aSFrançois Tigeot 		.class = VIDEO_DECODE_CLASS,
116*3f2dd94aSFrançois Tigeot 		.instance = 1,
117*3f2dd94aSFrançois Tigeot 		.mmio_base = GEN8_BSD2_RING_BASE,
118*3f2dd94aSFrançois Tigeot 		.irq_shift = GEN8_VCS2_IRQ_SHIFT,
119*3f2dd94aSFrançois Tigeot 	},
120*3f2dd94aSFrançois Tigeot 	[VECS] = {
121*3f2dd94aSFrançois Tigeot 		.hw_id = VECS_HW,
122*3f2dd94aSFrançois Tigeot 		.uabi_id = I915_EXEC_VEBOX,
123*3f2dd94aSFrançois Tigeot 		.class = VIDEO_ENHANCEMENT_CLASS,
124*3f2dd94aSFrançois Tigeot 		.instance = 0,
125*3f2dd94aSFrançois Tigeot 		.mmio_base = VEBOX_RING_BASE,
126*3f2dd94aSFrançois Tigeot 		.irq_shift = GEN8_VECS_IRQ_SHIFT,
127*3f2dd94aSFrançois Tigeot 	},
128*3f2dd94aSFrançois Tigeot };
129*3f2dd94aSFrançois Tigeot 
130*3f2dd94aSFrançois Tigeot /**
131*3f2dd94aSFrançois Tigeot  * ___intel_engine_context_size() - return the size of the context for an engine
132*3f2dd94aSFrançois Tigeot  * @dev_priv: i915 device private
133*3f2dd94aSFrançois Tigeot  * @class: engine class
134*3f2dd94aSFrançois Tigeot  *
135*3f2dd94aSFrançois Tigeot  * Each engine class may require a different amount of space for a context
136*3f2dd94aSFrançois Tigeot  * image.
137*3f2dd94aSFrançois Tigeot  *
138*3f2dd94aSFrançois Tigeot  * Return: size (in bytes) of an engine class specific context image
139*3f2dd94aSFrançois Tigeot  *
140*3f2dd94aSFrançois Tigeot  * Note: this size includes the HWSP, which is part of the context image
141*3f2dd94aSFrançois Tigeot  * in LRC mode, but does not include the "shared data page" used with
142*3f2dd94aSFrançois Tigeot  * GuC submission. The caller should account for this if using the GuC.
143*3f2dd94aSFrançois Tigeot  */
144*3f2dd94aSFrançois Tigeot static u32
__intel_engine_context_size(struct drm_i915_private * dev_priv,u8 class)145*3f2dd94aSFrançois Tigeot __intel_engine_context_size(struct drm_i915_private *dev_priv, u8 class)
146*3f2dd94aSFrançois Tigeot {
147*3f2dd94aSFrançois Tigeot 	u32 cxt_size;
148*3f2dd94aSFrançois Tigeot 
149*3f2dd94aSFrançois Tigeot 	BUILD_BUG_ON(I915_GTT_PAGE_SIZE != PAGE_SIZE);
150*3f2dd94aSFrançois Tigeot 
151*3f2dd94aSFrançois Tigeot 	switch (class) {
152*3f2dd94aSFrançois Tigeot 	case RENDER_CLASS:
153*3f2dd94aSFrançois Tigeot 		switch (INTEL_GEN(dev_priv)) {
154*3f2dd94aSFrançois Tigeot 		default:
155*3f2dd94aSFrançois Tigeot 			MISSING_CASE(INTEL_GEN(dev_priv));
156*3f2dd94aSFrançois Tigeot 		case 10:
157*3f2dd94aSFrançois Tigeot 			return GEN10_LR_CONTEXT_RENDER_SIZE;
158*3f2dd94aSFrançois Tigeot 		case 9:
159*3f2dd94aSFrançois Tigeot 			return GEN9_LR_CONTEXT_RENDER_SIZE;
160*3f2dd94aSFrançois Tigeot 		case 8:
161*3f2dd94aSFrançois Tigeot 			return i915_modparams.enable_execlists ?
162*3f2dd94aSFrançois Tigeot 			       GEN8_LR_CONTEXT_RENDER_SIZE :
163*3f2dd94aSFrançois Tigeot 			       GEN8_CXT_TOTAL_SIZE;
164*3f2dd94aSFrançois Tigeot 		case 7:
165*3f2dd94aSFrançois Tigeot 			if (IS_HASWELL(dev_priv))
166*3f2dd94aSFrançois Tigeot 				return HSW_CXT_TOTAL_SIZE;
167*3f2dd94aSFrançois Tigeot 
168*3f2dd94aSFrançois Tigeot 			cxt_size = I915_READ(GEN7_CXT_SIZE);
169*3f2dd94aSFrançois Tigeot 			return round_up(GEN7_CXT_TOTAL_SIZE(cxt_size) * 64,
170*3f2dd94aSFrançois Tigeot 					PAGE_SIZE);
171*3f2dd94aSFrançois Tigeot 		case 6:
172*3f2dd94aSFrançois Tigeot 			cxt_size = I915_READ(CXT_SIZE);
173*3f2dd94aSFrançois Tigeot 			return round_up(GEN6_CXT_TOTAL_SIZE(cxt_size) * 64,
174*3f2dd94aSFrançois Tigeot 					PAGE_SIZE);
175*3f2dd94aSFrançois Tigeot 		case 5:
176*3f2dd94aSFrançois Tigeot 		case 4:
177*3f2dd94aSFrançois Tigeot 		case 3:
178*3f2dd94aSFrançois Tigeot 		case 2:
179*3f2dd94aSFrançois Tigeot 		/* For the special day when i810 gets merged. */
180*3f2dd94aSFrançois Tigeot 		case 1:
181*3f2dd94aSFrançois Tigeot 			return 0;
182*3f2dd94aSFrançois Tigeot 		}
183*3f2dd94aSFrançois Tigeot 		break;
184*3f2dd94aSFrançois Tigeot 	default:
185*3f2dd94aSFrançois Tigeot 		MISSING_CASE(class);
186*3f2dd94aSFrançois Tigeot 	case VIDEO_DECODE_CLASS:
187*3f2dd94aSFrançois Tigeot 	case VIDEO_ENHANCEMENT_CLASS:
188*3f2dd94aSFrançois Tigeot 	case COPY_ENGINE_CLASS:
189*3f2dd94aSFrançois Tigeot 		if (INTEL_GEN(dev_priv) < 8)
190*3f2dd94aSFrançois Tigeot 			return 0;
191*3f2dd94aSFrançois Tigeot 		return GEN8_LR_CONTEXT_OTHER_SIZE;
192*3f2dd94aSFrançois Tigeot 	}
193*3f2dd94aSFrançois Tigeot }
194*3f2dd94aSFrançois Tigeot 
1951e12ee3bSFrançois Tigeot static int
intel_engine_setup(struct drm_i915_private * dev_priv,enum intel_engine_id id)19687df8fc6SFrançois Tigeot intel_engine_setup(struct drm_i915_private *dev_priv,
19787df8fc6SFrançois Tigeot 		   enum intel_engine_id id)
19887df8fc6SFrançois Tigeot {
19987df8fc6SFrançois Tigeot 	const struct engine_info *info = &intel_engines[id];
200*3f2dd94aSFrançois Tigeot 	const struct engine_class_info *class_info;
2011e12ee3bSFrançois Tigeot 	struct intel_engine_cs *engine;
2021e12ee3bSFrançois Tigeot 
203*3f2dd94aSFrançois Tigeot 	GEM_BUG_ON(info->class >= ARRAY_SIZE(intel_engine_classes));
204*3f2dd94aSFrançois Tigeot 	class_info = &intel_engine_classes[info->class];
205*3f2dd94aSFrançois Tigeot 
2061e12ee3bSFrançois Tigeot 	GEM_BUG_ON(dev_priv->engine[id]);
2071e12ee3bSFrançois Tigeot 	engine = kzalloc(sizeof(*engine), GFP_KERNEL);
2081e12ee3bSFrançois Tigeot 	if (!engine)
2091e12ee3bSFrançois Tigeot 		return -ENOMEM;
21087df8fc6SFrançois Tigeot 
21187df8fc6SFrançois Tigeot 	engine->id = id;
21287df8fc6SFrançois Tigeot 	engine->i915 = dev_priv;
213*3f2dd94aSFrançois Tigeot 	WARN_ON(snprintf(engine->name, sizeof(engine->name), "%s%u",
214*3f2dd94aSFrançois Tigeot 			 class_info->name, info->instance) >=
215*3f2dd94aSFrançois Tigeot 		sizeof(engine->name));
216*3f2dd94aSFrançois Tigeot 	engine->uabi_id = info->uabi_id;
2171e12ee3bSFrançois Tigeot 	engine->hw_id = engine->guc_id = info->hw_id;
21887df8fc6SFrançois Tigeot 	engine->mmio_base = info->mmio_base;
21987df8fc6SFrançois Tigeot 	engine->irq_shift = info->irq_shift;
220*3f2dd94aSFrançois Tigeot 	engine->class = info->class;
221*3f2dd94aSFrançois Tigeot 	engine->instance = info->instance;
222*3f2dd94aSFrançois Tigeot 
223*3f2dd94aSFrançois Tigeot 	engine->context_size = __intel_engine_context_size(dev_priv,
224*3f2dd94aSFrançois Tigeot 							   engine->class);
225*3f2dd94aSFrançois Tigeot 	if (WARN_ON(engine->context_size > BIT(20)))
226*3f2dd94aSFrançois Tigeot 		engine->context_size = 0;
22787df8fc6SFrançois Tigeot 
2284be47400SFrançois Tigeot 	/* Nothing to do here, execute in order of dependencies */
2294be47400SFrançois Tigeot 	engine->schedule = NULL;
2304be47400SFrançois Tigeot 
231a85cb24fSFrançois Tigeot 	ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier);
232a85cb24fSFrançois Tigeot 
2331e12ee3bSFrançois Tigeot 	dev_priv->engine[id] = engine;
2341e12ee3bSFrançois Tigeot 	return 0;
23587df8fc6SFrançois Tigeot }
23687df8fc6SFrançois Tigeot 
23787df8fc6SFrançois Tigeot /**
238*3f2dd94aSFrançois Tigeot  * intel_engines_init_mmio() - allocate and prepare the Engine Command Streamers
239a85cb24fSFrançois Tigeot  * @dev_priv: i915 device private
24087df8fc6SFrançois Tigeot  *
24187df8fc6SFrançois Tigeot  * Return: non-zero if the initialization failed.
24287df8fc6SFrançois Tigeot  */
intel_engines_init_mmio(struct drm_i915_private * dev_priv)243*3f2dd94aSFrançois Tigeot int intel_engines_init_mmio(struct drm_i915_private *dev_priv)
24487df8fc6SFrançois Tigeot {
2451e12ee3bSFrançois Tigeot 	struct intel_device_info *device_info = mkwrite_device_info(dev_priv);
246*3f2dd94aSFrançois Tigeot 	const unsigned int ring_mask = INTEL_INFO(dev_priv)->ring_mask;
2471e12ee3bSFrançois Tigeot 	struct intel_engine_cs *engine;
2481e12ee3bSFrançois Tigeot 	enum intel_engine_id id;
249*3f2dd94aSFrançois Tigeot 	unsigned int mask = 0;
25087df8fc6SFrançois Tigeot 	unsigned int i;
251a85cb24fSFrançois Tigeot 	int err;
25287df8fc6SFrançois Tigeot 
2531e12ee3bSFrançois Tigeot 	WARN_ON(ring_mask == 0);
2541e12ee3bSFrançois Tigeot 	WARN_ON(ring_mask &
25587df8fc6SFrançois Tigeot 		GENMASK(sizeof(mask) * BITS_PER_BYTE - 1, I915_NUM_ENGINES));
25687df8fc6SFrançois Tigeot 
25787df8fc6SFrançois Tigeot 	for (i = 0; i < ARRAY_SIZE(intel_engines); i++) {
25887df8fc6SFrançois Tigeot 		if (!HAS_ENGINE(dev_priv, i))
25987df8fc6SFrançois Tigeot 			continue;
26087df8fc6SFrançois Tigeot 
261a85cb24fSFrançois Tigeot 		err = intel_engine_setup(dev_priv, i);
262a85cb24fSFrançois Tigeot 		if (err)
26387df8fc6SFrançois Tigeot 			goto cleanup;
26487df8fc6SFrançois Tigeot 
26587df8fc6SFrançois Tigeot 		mask |= ENGINE_MASK(i);
26687df8fc6SFrançois Tigeot 	}
26787df8fc6SFrançois Tigeot 
26887df8fc6SFrançois Tigeot 	/*
26987df8fc6SFrançois Tigeot 	 * Catch failures to update intel_engines table when the new engines
27087df8fc6SFrançois Tigeot 	 * are added to the driver by a warning and disabling the forgotten
27187df8fc6SFrançois Tigeot 	 * engines.
27287df8fc6SFrançois Tigeot 	 */
2731e12ee3bSFrançois Tigeot 	if (WARN_ON(mask != ring_mask))
2741e12ee3bSFrançois Tigeot 		device_info->ring_mask = mask;
2751e12ee3bSFrançois Tigeot 
276*3f2dd94aSFrançois Tigeot 	/* We always presume we have at least RCS available for later probing */
277*3f2dd94aSFrançois Tigeot 	if (WARN_ON(!HAS_ENGINE(dev_priv, RCS))) {
278*3f2dd94aSFrançois Tigeot 		err = -ENODEV;
279*3f2dd94aSFrançois Tigeot 		goto cleanup;
280*3f2dd94aSFrançois Tigeot 	}
281*3f2dd94aSFrançois Tigeot 
2821e12ee3bSFrançois Tigeot 	device_info->num_rings = hweight32(mask);
28387df8fc6SFrançois Tigeot 
28487df8fc6SFrançois Tigeot 	return 0;
28587df8fc6SFrançois Tigeot 
28687df8fc6SFrançois Tigeot cleanup:
287a85cb24fSFrançois Tigeot 	for_each_engine(engine, dev_priv, id)
288a85cb24fSFrançois Tigeot 		kfree(engine);
289a85cb24fSFrançois Tigeot 	return err;
29087df8fc6SFrançois Tigeot }
29187df8fc6SFrançois Tigeot 
292a85cb24fSFrançois Tigeot /**
293*3f2dd94aSFrançois Tigeot  * intel_engines_init() - init the Engine Command Streamers
294a85cb24fSFrançois Tigeot  * @dev_priv: i915 device private
295a85cb24fSFrançois Tigeot  *
296a85cb24fSFrançois Tigeot  * Return: non-zero if the initialization failed.
297a85cb24fSFrançois Tigeot  */
intel_engines_init(struct drm_i915_private * dev_priv)298a85cb24fSFrançois Tigeot int intel_engines_init(struct drm_i915_private *dev_priv)
299a85cb24fSFrançois Tigeot {
300a85cb24fSFrançois Tigeot 	struct intel_engine_cs *engine;
301a85cb24fSFrançois Tigeot 	enum intel_engine_id id, err_id;
302*3f2dd94aSFrançois Tigeot 	int err;
303a85cb24fSFrançois Tigeot 
304a85cb24fSFrançois Tigeot 	for_each_engine(engine, dev_priv, id) {
305*3f2dd94aSFrançois Tigeot 		const struct engine_class_info *class_info =
306*3f2dd94aSFrançois Tigeot 			&intel_engine_classes[engine->class];
307a85cb24fSFrançois Tigeot 		int (*init)(struct intel_engine_cs *engine);
308a85cb24fSFrançois Tigeot 
309*3f2dd94aSFrançois Tigeot 		if (i915_modparams.enable_execlists)
310*3f2dd94aSFrançois Tigeot 			init = class_info->init_execlists;
311a85cb24fSFrançois Tigeot 		else
312*3f2dd94aSFrançois Tigeot 			init = class_info->init_legacy;
313*3f2dd94aSFrançois Tigeot 
314*3f2dd94aSFrançois Tigeot 		err = -EINVAL;
315*3f2dd94aSFrançois Tigeot 		err_id = id;
316*3f2dd94aSFrançois Tigeot 
317*3f2dd94aSFrançois Tigeot 		if (GEM_WARN_ON(!init))
318*3f2dd94aSFrançois Tigeot 			goto cleanup;
319a85cb24fSFrançois Tigeot 
320a85cb24fSFrançois Tigeot 		err = init(engine);
321*3f2dd94aSFrançois Tigeot 		if (err)
322a85cb24fSFrançois Tigeot 			goto cleanup;
323a85cb24fSFrançois Tigeot 
324a85cb24fSFrançois Tigeot 		GEM_BUG_ON(!engine->submit_request);
325a85cb24fSFrançois Tigeot 	}
326a85cb24fSFrançois Tigeot 
327a85cb24fSFrançois Tigeot 	return 0;
328a85cb24fSFrançois Tigeot 
329a85cb24fSFrançois Tigeot cleanup:
330a85cb24fSFrançois Tigeot 	for_each_engine(engine, dev_priv, id) {
331*3f2dd94aSFrançois Tigeot 		if (id >= err_id) {
332a85cb24fSFrançois Tigeot 			kfree(engine);
333*3f2dd94aSFrançois Tigeot 			dev_priv->engine[id] = NULL;
334*3f2dd94aSFrançois Tigeot 		} else {
335a85cb24fSFrançois Tigeot 			dev_priv->gt.cleanup_engine(engine);
336a85cb24fSFrançois Tigeot 		}
337*3f2dd94aSFrançois Tigeot 	}
338a85cb24fSFrançois Tigeot 	return err;
33987df8fc6SFrançois Tigeot }
34087df8fc6SFrançois Tigeot 
intel_engine_init_global_seqno(struct intel_engine_cs * engine,u32 seqno)3414be47400SFrançois Tigeot void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno)
3421e12ee3bSFrançois Tigeot {
3431e12ee3bSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
3441e12ee3bSFrançois Tigeot 
3451e12ee3bSFrançois Tigeot 	/* Our semaphore implementation is strictly monotonic (i.e. we proceed
3461e12ee3bSFrançois Tigeot 	 * so long as the semaphore value in the register/page is greater
3471e12ee3bSFrançois Tigeot 	 * than the sync value), so whenever we reset the seqno,
3481e12ee3bSFrançois Tigeot 	 * so long as we reset the tracking semaphore value to 0, it will
3491e12ee3bSFrançois Tigeot 	 * always be before the next request's seqno. If we don't reset
3501e12ee3bSFrançois Tigeot 	 * the semaphore value, then when the seqno moves backwards all
3511e12ee3bSFrançois Tigeot 	 * future waits will complete instantly (causing rendering corruption).
3521e12ee3bSFrançois Tigeot 	 */
3531e12ee3bSFrançois Tigeot 	if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) {
3541e12ee3bSFrançois Tigeot 		I915_WRITE(RING_SYNC_0(engine->mmio_base), 0);
3551e12ee3bSFrançois Tigeot 		I915_WRITE(RING_SYNC_1(engine->mmio_base), 0);
3561e12ee3bSFrançois Tigeot 		if (HAS_VEBOX(dev_priv))
3571e12ee3bSFrançois Tigeot 			I915_WRITE(RING_SYNC_2(engine->mmio_base), 0);
3581e12ee3bSFrançois Tigeot 	}
3591e12ee3bSFrançois Tigeot 	if (dev_priv->semaphore) {
3601e12ee3bSFrançois Tigeot 		struct page *page = i915_vma_first_page(dev_priv->semaphore);
3611e12ee3bSFrançois Tigeot 		void *semaphores;
3621e12ee3bSFrançois Tigeot 
3631e12ee3bSFrançois Tigeot 		/* Semaphores are in noncoherent memory, flush to be safe */
364a85cb24fSFrançois Tigeot 		semaphores = kmap_atomic(page);
3651e12ee3bSFrançois Tigeot 		memset(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0),
3661e12ee3bSFrançois Tigeot 		       0, I915_NUM_ENGINES * gen8_semaphore_seqno_size);
3671e12ee3bSFrançois Tigeot 		drm_clflush_virt_range(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0),
3681e12ee3bSFrançois Tigeot 				       I915_NUM_ENGINES * gen8_semaphore_seqno_size);
369a85cb24fSFrançois Tigeot 		kunmap_atomic(semaphores);
3701e12ee3bSFrançois Tigeot 	}
3711e12ee3bSFrançois Tigeot 
3721e12ee3bSFrançois Tigeot 	intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);
373a85cb24fSFrançois Tigeot 	clear_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted);
3744be47400SFrançois Tigeot 
3751e12ee3bSFrançois Tigeot 	/* After manually advancing the seqno, fake the interrupt in case
3761e12ee3bSFrançois Tigeot 	 * there are any waiters for that seqno.
3771e12ee3bSFrançois Tigeot 	 */
3781e12ee3bSFrançois Tigeot 	intel_engine_wakeup(engine);
379*3f2dd94aSFrançois Tigeot 
380*3f2dd94aSFrançois Tigeot 	GEM_BUG_ON(intel_engine_get_seqno(engine) != seqno);
3811e12ee3bSFrançois Tigeot }
3821e12ee3bSFrançois Tigeot 
intel_engine_init_timeline(struct intel_engine_cs * engine)3834be47400SFrançois Tigeot static void intel_engine_init_timeline(struct intel_engine_cs *engine)
38487df8fc6SFrançois Tigeot {
3854be47400SFrançois Tigeot 	engine->timeline = &engine->i915->gt.global_timeline.engine[engine->id];
38671f41f3eSFrançois Tigeot }
38771f41f3eSFrançois Tigeot 
csb_force_mmio(struct drm_i915_private * i915)388*3f2dd94aSFrançois Tigeot static bool csb_force_mmio(struct drm_i915_private *i915)
389*3f2dd94aSFrançois Tigeot {
390*3f2dd94aSFrançois Tigeot 	/*
391*3f2dd94aSFrançois Tigeot 	 * IOMMU adds unpredictable latency causing the CSB write (from the
392*3f2dd94aSFrançois Tigeot 	 * GPU into the HWSP) to only be visible some time after the interrupt
393*3f2dd94aSFrançois Tigeot 	 * (missed breadcrumb syndrome).
394*3f2dd94aSFrançois Tigeot 	 */
395*3f2dd94aSFrançois Tigeot 	if (intel_vtd_active())
396*3f2dd94aSFrançois Tigeot 		return true;
397*3f2dd94aSFrançois Tigeot 
398*3f2dd94aSFrançois Tigeot 	/* Older GVT emulation depends upon intercepting CSB mmio */
399*3f2dd94aSFrançois Tigeot 	if (intel_vgpu_active(i915) && !intel_vgpu_has_hwsp_emulation(i915))
400*3f2dd94aSFrançois Tigeot 		return true;
401*3f2dd94aSFrançois Tigeot 
402*3f2dd94aSFrançois Tigeot 	return false;
403*3f2dd94aSFrançois Tigeot }
404*3f2dd94aSFrançois Tigeot 
intel_engine_init_execlist(struct intel_engine_cs * engine)405*3f2dd94aSFrançois Tigeot static void intel_engine_init_execlist(struct intel_engine_cs *engine)
406*3f2dd94aSFrançois Tigeot {
407*3f2dd94aSFrançois Tigeot 	struct intel_engine_execlists * const execlists = &engine->execlists;
408*3f2dd94aSFrançois Tigeot 
409*3f2dd94aSFrançois Tigeot 	execlists->csb_use_mmio = csb_force_mmio(engine->i915);
410*3f2dd94aSFrançois Tigeot 
411*3f2dd94aSFrançois Tigeot 	execlists->port_mask = 1;
412*3f2dd94aSFrançois Tigeot 	GEM_BUG_ON(!is_power_of_2(execlists_num_ports(execlists)));	/* From Linux 5.0 */
413*3f2dd94aSFrançois Tigeot 	GEM_BUG_ON(execlists_num_ports(execlists) > EXECLIST_MAX_PORTS);
414*3f2dd94aSFrançois Tigeot 
415*3f2dd94aSFrançois Tigeot 	execlists->queue = LINUX_RB_ROOT;
416*3f2dd94aSFrançois Tigeot 	execlists->first = NULL;
417*3f2dd94aSFrançois Tigeot }
418*3f2dd94aSFrançois Tigeot 
41987df8fc6SFrançois Tigeot /**
42087df8fc6SFrançois Tigeot  * intel_engines_setup_common - setup engine state not requiring hw access
42187df8fc6SFrançois Tigeot  * @engine: Engine to setup.
42287df8fc6SFrançois Tigeot  *
42387df8fc6SFrançois Tigeot  * Initializes @engine@ structure members shared between legacy and execlists
42487df8fc6SFrançois Tigeot  * submission modes which do not require hardware access.
42587df8fc6SFrançois Tigeot  *
42687df8fc6SFrançois Tigeot  * Typically done early in the submission mode specific engine setup stage.
42787df8fc6SFrançois Tigeot  */
intel_engine_setup_common(struct intel_engine_cs * engine)42887df8fc6SFrançois Tigeot void intel_engine_setup_common(struct intel_engine_cs *engine)
42987df8fc6SFrançois Tigeot {
430*3f2dd94aSFrançois Tigeot 	intel_engine_init_execlist(engine);
43187df8fc6SFrançois Tigeot 
4324be47400SFrançois Tigeot 	intel_engine_init_timeline(engine);
43387df8fc6SFrançois Tigeot 	intel_engine_init_hangcheck(engine);
43471f41f3eSFrançois Tigeot 	i915_gem_batch_pool_init(engine, &engine->batch_pool);
4351e12ee3bSFrançois Tigeot 
4361e12ee3bSFrançois Tigeot 	intel_engine_init_cmd_parser(engine);
4371e12ee3bSFrançois Tigeot }
4381e12ee3bSFrançois Tigeot 
intel_engine_create_scratch(struct intel_engine_cs * engine,int size)4391e12ee3bSFrançois Tigeot int intel_engine_create_scratch(struct intel_engine_cs *engine, int size)
4401e12ee3bSFrançois Tigeot {
4411e12ee3bSFrançois Tigeot 	struct drm_i915_gem_object *obj;
4421e12ee3bSFrançois Tigeot 	struct i915_vma *vma;
4431e12ee3bSFrançois Tigeot 	int ret;
4441e12ee3bSFrançois Tigeot 
4451e12ee3bSFrançois Tigeot 	WARN_ON(engine->scratch);
4461e12ee3bSFrançois Tigeot 
447a85cb24fSFrançois Tigeot 	obj = i915_gem_object_create_stolen(engine->i915, size);
4481e12ee3bSFrançois Tigeot 	if (!obj)
4494be47400SFrançois Tigeot 		obj = i915_gem_object_create_internal(engine->i915, size);
4501e12ee3bSFrançois Tigeot 	if (IS_ERR(obj)) {
4511e12ee3bSFrançois Tigeot 		DRM_ERROR("Failed to allocate scratch page\n");
4521e12ee3bSFrançois Tigeot 		return PTR_ERR(obj);
4531e12ee3bSFrançois Tigeot 	}
4541e12ee3bSFrançois Tigeot 
455a85cb24fSFrançois Tigeot 	vma = i915_vma_instance(obj, &engine->i915->ggtt.base, NULL);
4561e12ee3bSFrançois Tigeot 	if (IS_ERR(vma)) {
4571e12ee3bSFrançois Tigeot 		ret = PTR_ERR(vma);
4581e12ee3bSFrançois Tigeot 		goto err_unref;
4591e12ee3bSFrançois Tigeot 	}
4601e12ee3bSFrançois Tigeot 
4611e12ee3bSFrançois Tigeot 	ret = i915_vma_pin(vma, 0, 4096, PIN_GLOBAL | PIN_HIGH);
4621e12ee3bSFrançois Tigeot 	if (ret)
4631e12ee3bSFrançois Tigeot 		goto err_unref;
4641e12ee3bSFrançois Tigeot 
4651e12ee3bSFrançois Tigeot 	engine->scratch = vma;
4661e12ee3bSFrançois Tigeot 	DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n",
4671e12ee3bSFrançois Tigeot 			 engine->name, i915_ggtt_offset(vma));
4681e12ee3bSFrançois Tigeot 	return 0;
4691e12ee3bSFrançois Tigeot 
4701e12ee3bSFrançois Tigeot err_unref:
4711e12ee3bSFrançois Tigeot 	i915_gem_object_put(obj);
4721e12ee3bSFrançois Tigeot 	return ret;
4731e12ee3bSFrançois Tigeot }
4741e12ee3bSFrançois Tigeot 
intel_engine_cleanup_scratch(struct intel_engine_cs * engine)4751e12ee3bSFrançois Tigeot static void intel_engine_cleanup_scratch(struct intel_engine_cs *engine)
4761e12ee3bSFrançois Tigeot {
4771e12ee3bSFrançois Tigeot 	i915_vma_unpin_and_release(&engine->scratch);
47887df8fc6SFrançois Tigeot }
47987df8fc6SFrançois Tigeot 
cleanup_phys_status_page(struct intel_engine_cs * engine)480*3f2dd94aSFrançois Tigeot static void cleanup_phys_status_page(struct intel_engine_cs *engine)
481*3f2dd94aSFrançois Tigeot {
482*3f2dd94aSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
483*3f2dd94aSFrançois Tigeot 
484*3f2dd94aSFrançois Tigeot 	if (!dev_priv->status_page_dmah)
485*3f2dd94aSFrançois Tigeot 		return;
486*3f2dd94aSFrançois Tigeot 
487*3f2dd94aSFrançois Tigeot 	drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah);
488*3f2dd94aSFrançois Tigeot 	engine->status_page.page_addr = NULL;
489*3f2dd94aSFrançois Tigeot }
490*3f2dd94aSFrançois Tigeot 
cleanup_status_page(struct intel_engine_cs * engine)491*3f2dd94aSFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *engine)
492*3f2dd94aSFrançois Tigeot {
493*3f2dd94aSFrançois Tigeot 	struct i915_vma *vma;
494*3f2dd94aSFrançois Tigeot 	struct drm_i915_gem_object *obj;
495*3f2dd94aSFrançois Tigeot 
496*3f2dd94aSFrançois Tigeot 	vma = fetch_and_zero(&engine->status_page.vma);
497*3f2dd94aSFrançois Tigeot 	if (!vma)
498*3f2dd94aSFrançois Tigeot 		return;
499*3f2dd94aSFrançois Tigeot 
500*3f2dd94aSFrançois Tigeot 	obj = vma->obj;
501*3f2dd94aSFrançois Tigeot 
502*3f2dd94aSFrançois Tigeot 	i915_vma_unpin(vma);
503*3f2dd94aSFrançois Tigeot 	i915_vma_close(vma);
504*3f2dd94aSFrançois Tigeot 
505*3f2dd94aSFrançois Tigeot 	i915_gem_object_unpin_map(obj);
506*3f2dd94aSFrançois Tigeot 	__i915_gem_object_release_unless_active(obj);
507*3f2dd94aSFrançois Tigeot }
508*3f2dd94aSFrançois Tigeot 
init_status_page(struct intel_engine_cs * engine)509*3f2dd94aSFrançois Tigeot static int init_status_page(struct intel_engine_cs *engine)
510*3f2dd94aSFrançois Tigeot {
511*3f2dd94aSFrançois Tigeot 	struct drm_i915_gem_object *obj;
512*3f2dd94aSFrançois Tigeot 	struct i915_vma *vma;
513*3f2dd94aSFrançois Tigeot 	unsigned int flags;
514*3f2dd94aSFrançois Tigeot 	void *vaddr;
515*3f2dd94aSFrançois Tigeot 	int ret;
516*3f2dd94aSFrançois Tigeot 
517*3f2dd94aSFrançois Tigeot 	obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE);
518*3f2dd94aSFrançois Tigeot 	if (IS_ERR(obj)) {
519*3f2dd94aSFrançois Tigeot 		DRM_ERROR("Failed to allocate status page\n");
520*3f2dd94aSFrançois Tigeot 		return PTR_ERR(obj);
521*3f2dd94aSFrançois Tigeot 	}
522*3f2dd94aSFrançois Tigeot 
523*3f2dd94aSFrançois Tigeot 	ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
524*3f2dd94aSFrançois Tigeot 	if (ret)
525*3f2dd94aSFrançois Tigeot 		goto err;
526*3f2dd94aSFrançois Tigeot 
527*3f2dd94aSFrançois Tigeot 	vma = i915_vma_instance(obj, &engine->i915->ggtt.base, NULL);
528*3f2dd94aSFrançois Tigeot 	if (IS_ERR(vma)) {
529*3f2dd94aSFrançois Tigeot 		ret = PTR_ERR(vma);
530*3f2dd94aSFrançois Tigeot 		goto err;
531*3f2dd94aSFrançois Tigeot 	}
532*3f2dd94aSFrançois Tigeot 
533*3f2dd94aSFrançois Tigeot 	flags = PIN_GLOBAL;
534*3f2dd94aSFrançois Tigeot 	if (!HAS_LLC(engine->i915))
535*3f2dd94aSFrançois Tigeot 		/* On g33, we cannot place HWS above 256MiB, so
536*3f2dd94aSFrançois Tigeot 		 * restrict its pinning to the low mappable arena.
537*3f2dd94aSFrançois Tigeot 		 * Though this restriction is not documented for
538*3f2dd94aSFrançois Tigeot 		 * gen4, gen5, or byt, they also behave similarly
539*3f2dd94aSFrançois Tigeot 		 * and hang if the HWS is placed at the top of the
540*3f2dd94aSFrançois Tigeot 		 * GTT. To generalise, it appears that all !llc
541*3f2dd94aSFrançois Tigeot 		 * platforms have issues with us placing the HWS
542*3f2dd94aSFrançois Tigeot 		 * above the mappable region (even though we never
543*3f2dd94aSFrançois Tigeot 		 * actually map it).
544*3f2dd94aSFrançois Tigeot 		 */
545*3f2dd94aSFrançois Tigeot 		flags |= PIN_MAPPABLE;
546*3f2dd94aSFrançois Tigeot 	else
547*3f2dd94aSFrançois Tigeot 		flags |= PIN_HIGH;
548*3f2dd94aSFrançois Tigeot 	ret = i915_vma_pin(vma, 0, 4096, flags);
549*3f2dd94aSFrançois Tigeot 	if (ret)
550*3f2dd94aSFrançois Tigeot 		goto err;
551*3f2dd94aSFrançois Tigeot 
552*3f2dd94aSFrançois Tigeot 	vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB);
553*3f2dd94aSFrançois Tigeot 	if (IS_ERR(vaddr)) {
554*3f2dd94aSFrançois Tigeot 		ret = PTR_ERR(vaddr);
555*3f2dd94aSFrançois Tigeot 		goto err_unpin;
556*3f2dd94aSFrançois Tigeot 	}
557*3f2dd94aSFrançois Tigeot 
558*3f2dd94aSFrançois Tigeot 	engine->status_page.vma = vma;
559*3f2dd94aSFrançois Tigeot 	engine->status_page.ggtt_offset = i915_ggtt_offset(vma);
560*3f2dd94aSFrançois Tigeot 	engine->status_page.page_addr = memset(vaddr, 0, PAGE_SIZE);
561*3f2dd94aSFrançois Tigeot 
562*3f2dd94aSFrançois Tigeot 	DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
563*3f2dd94aSFrançois Tigeot 			 engine->name, i915_ggtt_offset(vma));
564*3f2dd94aSFrançois Tigeot 	return 0;
565*3f2dd94aSFrançois Tigeot 
566*3f2dd94aSFrançois Tigeot err_unpin:
567*3f2dd94aSFrançois Tigeot 	i915_vma_unpin(vma);
568*3f2dd94aSFrançois Tigeot err:
569*3f2dd94aSFrançois Tigeot 	i915_gem_object_put(obj);
570*3f2dd94aSFrançois Tigeot 	return ret;
571*3f2dd94aSFrançois Tigeot }
572*3f2dd94aSFrançois Tigeot 
init_phys_status_page(struct intel_engine_cs * engine)573*3f2dd94aSFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *engine)
574*3f2dd94aSFrançois Tigeot {
575*3f2dd94aSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
576*3f2dd94aSFrançois Tigeot 
577*3f2dd94aSFrançois Tigeot 	GEM_BUG_ON(engine->id != RCS);
578*3f2dd94aSFrançois Tigeot 
579*3f2dd94aSFrançois Tigeot 	dev_priv->status_page_dmah =
580*3f2dd94aSFrançois Tigeot 		drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE);
581*3f2dd94aSFrançois Tigeot 	if (!dev_priv->status_page_dmah)
582*3f2dd94aSFrançois Tigeot 		return -ENOMEM;
583*3f2dd94aSFrançois Tigeot 
584*3f2dd94aSFrançois Tigeot 	engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
585*3f2dd94aSFrançois Tigeot 	memset(engine->status_page.page_addr, 0, PAGE_SIZE);
586*3f2dd94aSFrançois Tigeot 
587*3f2dd94aSFrançois Tigeot 	return 0;
588*3f2dd94aSFrançois Tigeot }
589*3f2dd94aSFrançois Tigeot 
59087df8fc6SFrançois Tigeot /**
59187df8fc6SFrançois Tigeot  * intel_engines_init_common - initialize cengine state which might require hw access
59287df8fc6SFrançois Tigeot  * @engine: Engine to initialize.
59387df8fc6SFrançois Tigeot  *
59487df8fc6SFrançois Tigeot  * Initializes @engine@ structure members shared between legacy and execlists
59587df8fc6SFrançois Tigeot  * submission modes which do require hardware access.
59687df8fc6SFrançois Tigeot  *
59787df8fc6SFrançois Tigeot  * Typcally done at later stages of submission mode specific engine setup.
59887df8fc6SFrançois Tigeot  *
59987df8fc6SFrançois Tigeot  * Returns zero on success or an error code on failure.
60087df8fc6SFrançois Tigeot  */
intel_engine_init_common(struct intel_engine_cs * engine)60187df8fc6SFrançois Tigeot int intel_engine_init_common(struct intel_engine_cs *engine)
60287df8fc6SFrançois Tigeot {
603*3f2dd94aSFrançois Tigeot 	struct intel_ring *ring;
60487df8fc6SFrançois Tigeot 	int ret;
60587df8fc6SFrançois Tigeot 
606a85cb24fSFrançois Tigeot 	engine->set_default_submission(engine);
607a85cb24fSFrançois Tigeot 
608a85cb24fSFrançois Tigeot 	/* We may need to do things with the shrinker which
609a85cb24fSFrançois Tigeot 	 * require us to immediately switch back to the default
610a85cb24fSFrançois Tigeot 	 * context. This can cause a problem as pinning the
611a85cb24fSFrançois Tigeot 	 * default context also requires GTT space which may not
612a85cb24fSFrançois Tigeot 	 * be available. To avoid this we always pin the default
613a85cb24fSFrançois Tigeot 	 * context.
614a85cb24fSFrançois Tigeot 	 */
615*3f2dd94aSFrançois Tigeot 	ring = engine->context_pin(engine, engine->i915->kernel_context);
616*3f2dd94aSFrançois Tigeot 	if (IS_ERR(ring))
617*3f2dd94aSFrançois Tigeot 		return PTR_ERR(ring);
618*3f2dd94aSFrançois Tigeot 
619*3f2dd94aSFrançois Tigeot 	/*
620*3f2dd94aSFrançois Tigeot 	 * Similarly the preempt context must always be available so that
621*3f2dd94aSFrançois Tigeot 	 * we can interrupt the engine at any time.
622*3f2dd94aSFrançois Tigeot 	 */
623*3f2dd94aSFrançois Tigeot 	if (INTEL_INFO(engine->i915)->has_logical_ring_preemption) {
624*3f2dd94aSFrançois Tigeot 		ring = engine->context_pin(engine,
625*3f2dd94aSFrançois Tigeot 					   engine->i915->preempt_context);
626*3f2dd94aSFrançois Tigeot 		if (IS_ERR(ring)) {
627*3f2dd94aSFrançois Tigeot 			ret = PTR_ERR(ring);
628*3f2dd94aSFrançois Tigeot 			goto err_unpin_kernel;
629*3f2dd94aSFrançois Tigeot 		}
630*3f2dd94aSFrançois Tigeot 	}
63187df8fc6SFrançois Tigeot 
632a85cb24fSFrançois Tigeot 	ret = intel_engine_init_breadcrumbs(engine);
633a85cb24fSFrançois Tigeot 	if (ret)
634*3f2dd94aSFrançois Tigeot 		goto err_unpin_preempt;
635a85cb24fSFrançois Tigeot 
6364be47400SFrançois Tigeot 	ret = i915_gem_render_state_init(engine);
6374be47400SFrançois Tigeot 	if (ret)
638*3f2dd94aSFrançois Tigeot 		goto err_breadcrumbs;
639*3f2dd94aSFrançois Tigeot 
640*3f2dd94aSFrançois Tigeot 	if (HWS_NEEDS_PHYSICAL(engine->i915))
641*3f2dd94aSFrançois Tigeot 		ret = init_phys_status_page(engine);
642*3f2dd94aSFrançois Tigeot 	else
643*3f2dd94aSFrançois Tigeot 		ret = init_status_page(engine);
644*3f2dd94aSFrançois Tigeot 	if (ret)
645*3f2dd94aSFrançois Tigeot 		goto err_rs_fini;
6464be47400SFrançois Tigeot 
6471e12ee3bSFrançois Tigeot 	return 0;
648a85cb24fSFrançois Tigeot 
649*3f2dd94aSFrançois Tigeot err_rs_fini:
650*3f2dd94aSFrançois Tigeot 	i915_gem_render_state_fini(engine);
651*3f2dd94aSFrançois Tigeot err_breadcrumbs:
652*3f2dd94aSFrançois Tigeot 	intel_engine_fini_breadcrumbs(engine);
653*3f2dd94aSFrançois Tigeot err_unpin_preempt:
654*3f2dd94aSFrançois Tigeot 	if (INTEL_INFO(engine->i915)->has_logical_ring_preemption)
655*3f2dd94aSFrançois Tigeot 		engine->context_unpin(engine, engine->i915->preempt_context);
656*3f2dd94aSFrançois Tigeot err_unpin_kernel:
657a85cb24fSFrançois Tigeot 	engine->context_unpin(engine, engine->i915->kernel_context);
658a85cb24fSFrançois Tigeot 	return ret;
65971f41f3eSFrançois Tigeot }
66071f41f3eSFrançois Tigeot 
66171f41f3eSFrançois Tigeot /**
66271f41f3eSFrançois Tigeot  * intel_engines_cleanup_common - cleans up the engine state created by
66371f41f3eSFrançois Tigeot  *                                the common initiailizers.
66471f41f3eSFrançois Tigeot  * @engine: Engine to cleanup.
66571f41f3eSFrançois Tigeot  *
66671f41f3eSFrançois Tigeot  * This cleans up everything created by the common helpers.
66771f41f3eSFrançois Tigeot  */
intel_engine_cleanup_common(struct intel_engine_cs * engine)66871f41f3eSFrançois Tigeot void intel_engine_cleanup_common(struct intel_engine_cs *engine)
66971f41f3eSFrançois Tigeot {
6701e12ee3bSFrançois Tigeot 	intel_engine_cleanup_scratch(engine);
6711e12ee3bSFrançois Tigeot 
672*3f2dd94aSFrançois Tigeot 	if (HWS_NEEDS_PHYSICAL(engine->i915))
673*3f2dd94aSFrançois Tigeot 		cleanup_phys_status_page(engine);
674*3f2dd94aSFrançois Tigeot 	else
675*3f2dd94aSFrançois Tigeot 		cleanup_status_page(engine);
676*3f2dd94aSFrançois Tigeot 
6774be47400SFrançois Tigeot 	i915_gem_render_state_fini(engine);
67871f41f3eSFrançois Tigeot 	intel_engine_fini_breadcrumbs(engine);
6791e12ee3bSFrançois Tigeot 	intel_engine_cleanup_cmd_parser(engine);
68071f41f3eSFrançois Tigeot 	i915_gem_batch_pool_fini(&engine->batch_pool);
681a85cb24fSFrançois Tigeot 
682*3f2dd94aSFrançois Tigeot 	if (INTEL_INFO(engine->i915)->has_logical_ring_preemption)
683*3f2dd94aSFrançois Tigeot 		engine->context_unpin(engine, engine->i915->preempt_context);
684a85cb24fSFrançois Tigeot 	engine->context_unpin(engine, engine->i915->kernel_context);
68587df8fc6SFrançois Tigeot }
6861e12ee3bSFrançois Tigeot 
intel_engine_get_active_head(struct intel_engine_cs * engine)6871e12ee3bSFrançois Tigeot u64 intel_engine_get_active_head(struct intel_engine_cs *engine)
6881e12ee3bSFrançois Tigeot {
6891e12ee3bSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
6901e12ee3bSFrançois Tigeot 	u64 acthd;
6911e12ee3bSFrançois Tigeot 
6921e12ee3bSFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8)
6931e12ee3bSFrançois Tigeot 		acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base),
6941e12ee3bSFrançois Tigeot 					 RING_ACTHD_UDW(engine->mmio_base));
6951e12ee3bSFrançois Tigeot 	else if (INTEL_GEN(dev_priv) >= 4)
6961e12ee3bSFrançois Tigeot 		acthd = I915_READ(RING_ACTHD(engine->mmio_base));
6971e12ee3bSFrançois Tigeot 	else
6981e12ee3bSFrançois Tigeot 		acthd = I915_READ(ACTHD);
6991e12ee3bSFrançois Tigeot 
7001e12ee3bSFrançois Tigeot 	return acthd;
7011e12ee3bSFrançois Tigeot }
7021e12ee3bSFrançois Tigeot 
intel_engine_get_last_batch_head(struct intel_engine_cs * engine)7031e12ee3bSFrançois Tigeot u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine)
7041e12ee3bSFrançois Tigeot {
7051e12ee3bSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
7061e12ee3bSFrançois Tigeot 	u64 bbaddr;
7071e12ee3bSFrançois Tigeot 
7081e12ee3bSFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8)
7091e12ee3bSFrançois Tigeot 		bbaddr = I915_READ64_2x32(RING_BBADDR(engine->mmio_base),
7101e12ee3bSFrançois Tigeot 					  RING_BBADDR_UDW(engine->mmio_base));
7111e12ee3bSFrançois Tigeot 	else
7121e12ee3bSFrançois Tigeot 		bbaddr = I915_READ(RING_BBADDR(engine->mmio_base));
7131e12ee3bSFrançois Tigeot 
7141e12ee3bSFrançois Tigeot 	return bbaddr;
7151e12ee3bSFrançois Tigeot }
7161e12ee3bSFrançois Tigeot 
i915_cache_level_str(struct drm_i915_private * i915,int type)7171e12ee3bSFrançois Tigeot const char *i915_cache_level_str(struct drm_i915_private *i915, int type)
7181e12ee3bSFrançois Tigeot {
7191e12ee3bSFrançois Tigeot 	switch (type) {
7201e12ee3bSFrançois Tigeot 	case I915_CACHE_NONE: return " uncached";
7211e12ee3bSFrançois Tigeot 	case I915_CACHE_LLC: return HAS_LLC(i915) ? " LLC" : " snooped";
7221e12ee3bSFrançois Tigeot 	case I915_CACHE_L3_LLC: return " L3+LLC";
7231e12ee3bSFrançois Tigeot 	case I915_CACHE_WT: return " WT";
7241e12ee3bSFrançois Tigeot 	default: return "";
7251e12ee3bSFrançois Tigeot 	}
7261e12ee3bSFrançois Tigeot }
7271e12ee3bSFrançois Tigeot 
7281e12ee3bSFrançois Tigeot static inline uint32_t
read_subslice_reg(struct drm_i915_private * dev_priv,int slice,int subslice,i915_reg_t reg)7291e12ee3bSFrançois Tigeot read_subslice_reg(struct drm_i915_private *dev_priv, int slice,
7301e12ee3bSFrançois Tigeot 		  int subslice, i915_reg_t reg)
7311e12ee3bSFrançois Tigeot {
7321e12ee3bSFrançois Tigeot 	uint32_t mcr;
7331e12ee3bSFrançois Tigeot 	uint32_t ret;
7341e12ee3bSFrançois Tigeot 	enum forcewake_domains fw_domains;
7351e12ee3bSFrançois Tigeot 
7361e12ee3bSFrançois Tigeot 	fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg,
7371e12ee3bSFrançois Tigeot 						    FW_REG_READ);
7381e12ee3bSFrançois Tigeot 	fw_domains |= intel_uncore_forcewake_for_reg(dev_priv,
7391e12ee3bSFrançois Tigeot 						     GEN8_MCR_SELECTOR,
7401e12ee3bSFrançois Tigeot 						     FW_REG_READ | FW_REG_WRITE);
7411e12ee3bSFrançois Tigeot 
7421e12ee3bSFrançois Tigeot 	spin_lock_irq(&dev_priv->uncore.lock);
7431e12ee3bSFrançois Tigeot 	intel_uncore_forcewake_get__locked(dev_priv, fw_domains);
7441e12ee3bSFrançois Tigeot 
7451e12ee3bSFrançois Tigeot 	mcr = I915_READ_FW(GEN8_MCR_SELECTOR);
7461e12ee3bSFrançois Tigeot 	/*
7471e12ee3bSFrançois Tigeot 	 * The HW expects the slice and sublice selectors to be reset to 0
7481e12ee3bSFrançois Tigeot 	 * after reading out the registers.
7491e12ee3bSFrançois Tigeot 	 */
7501e12ee3bSFrançois Tigeot 	WARN_ON_ONCE(mcr & (GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK));
7511e12ee3bSFrançois Tigeot 	mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK);
7521e12ee3bSFrançois Tigeot 	mcr |= GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice);
7531e12ee3bSFrançois Tigeot 	I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr);
7541e12ee3bSFrançois Tigeot 
7551e12ee3bSFrançois Tigeot 	ret = I915_READ_FW(reg);
7561e12ee3bSFrançois Tigeot 
7571e12ee3bSFrançois Tigeot 	mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK);
7581e12ee3bSFrançois Tigeot 	I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr);
7591e12ee3bSFrançois Tigeot 
7601e12ee3bSFrançois Tigeot 	intel_uncore_forcewake_put__locked(dev_priv, fw_domains);
7611e12ee3bSFrançois Tigeot 	spin_unlock_irq(&dev_priv->uncore.lock);
7621e12ee3bSFrançois Tigeot 
7631e12ee3bSFrançois Tigeot 	return ret;
7641e12ee3bSFrançois Tigeot }
7651e12ee3bSFrançois Tigeot 
7661e12ee3bSFrançois Tigeot /* NB: please notice the memset */
intel_engine_get_instdone(struct intel_engine_cs * engine,struct intel_instdone * instdone)7671e12ee3bSFrançois Tigeot void intel_engine_get_instdone(struct intel_engine_cs *engine,
7681e12ee3bSFrançois Tigeot 			       struct intel_instdone *instdone)
7691e12ee3bSFrançois Tigeot {
7701e12ee3bSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
7711e12ee3bSFrançois Tigeot 	u32 mmio_base = engine->mmio_base;
7721e12ee3bSFrançois Tigeot 	int slice;
7731e12ee3bSFrançois Tigeot 	int subslice;
7741e12ee3bSFrançois Tigeot 
7751e12ee3bSFrançois Tigeot 	memset(instdone, 0, sizeof(*instdone));
7761e12ee3bSFrançois Tigeot 
7771e12ee3bSFrançois Tigeot 	switch (INTEL_GEN(dev_priv)) {
7781e12ee3bSFrançois Tigeot 	default:
7791e12ee3bSFrançois Tigeot 		instdone->instdone = I915_READ(RING_INSTDONE(mmio_base));
7801e12ee3bSFrançois Tigeot 
7811e12ee3bSFrançois Tigeot 		if (engine->id != RCS)
7821e12ee3bSFrançois Tigeot 			break;
7831e12ee3bSFrançois Tigeot 
7841e12ee3bSFrançois Tigeot 		instdone->slice_common = I915_READ(GEN7_SC_INSTDONE);
7851e12ee3bSFrançois Tigeot 		for_each_instdone_slice_subslice(dev_priv, slice, subslice) {
7861e12ee3bSFrançois Tigeot 			instdone->sampler[slice][subslice] =
7871e12ee3bSFrançois Tigeot 				read_subslice_reg(dev_priv, slice, subslice,
7881e12ee3bSFrançois Tigeot 						  GEN7_SAMPLER_INSTDONE);
7891e12ee3bSFrançois Tigeot 			instdone->row[slice][subslice] =
7901e12ee3bSFrançois Tigeot 				read_subslice_reg(dev_priv, slice, subslice,
7911e12ee3bSFrançois Tigeot 						  GEN7_ROW_INSTDONE);
7921e12ee3bSFrançois Tigeot 		}
7931e12ee3bSFrançois Tigeot 		break;
7941e12ee3bSFrançois Tigeot 	case 7:
7951e12ee3bSFrançois Tigeot 		instdone->instdone = I915_READ(RING_INSTDONE(mmio_base));
7961e12ee3bSFrançois Tigeot 
7971e12ee3bSFrançois Tigeot 		if (engine->id != RCS)
7981e12ee3bSFrançois Tigeot 			break;
7991e12ee3bSFrançois Tigeot 
8001e12ee3bSFrançois Tigeot 		instdone->slice_common = I915_READ(GEN7_SC_INSTDONE);
8011e12ee3bSFrançois Tigeot 		instdone->sampler[0][0] = I915_READ(GEN7_SAMPLER_INSTDONE);
8021e12ee3bSFrançois Tigeot 		instdone->row[0][0] = I915_READ(GEN7_ROW_INSTDONE);
8031e12ee3bSFrançois Tigeot 
8041e12ee3bSFrançois Tigeot 		break;
8051e12ee3bSFrançois Tigeot 	case 6:
8061e12ee3bSFrançois Tigeot 	case 5:
8071e12ee3bSFrançois Tigeot 	case 4:
8081e12ee3bSFrançois Tigeot 		instdone->instdone = I915_READ(RING_INSTDONE(mmio_base));
8091e12ee3bSFrançois Tigeot 
8101e12ee3bSFrançois Tigeot 		if (engine->id == RCS)
8111e12ee3bSFrançois Tigeot 			/* HACK: Using the wrong struct member */
8121e12ee3bSFrançois Tigeot 			instdone->slice_common = I915_READ(GEN4_INSTDONE1);
8131e12ee3bSFrançois Tigeot 		break;
8141e12ee3bSFrançois Tigeot 	case 3:
8151e12ee3bSFrançois Tigeot 	case 2:
8161e12ee3bSFrançois Tigeot 		instdone->instdone = I915_READ(GEN2_INSTDONE);
8171e12ee3bSFrançois Tigeot 		break;
8181e12ee3bSFrançois Tigeot 	}
8191e12ee3bSFrançois Tigeot }
820a85cb24fSFrançois Tigeot 
wa_add(struct drm_i915_private * dev_priv,i915_reg_t addr,const u32 mask,const u32 val)821a85cb24fSFrançois Tigeot static int wa_add(struct drm_i915_private *dev_priv,
822a85cb24fSFrançois Tigeot 		  i915_reg_t addr,
823a85cb24fSFrançois Tigeot 		  const u32 mask, const u32 val)
824a85cb24fSFrançois Tigeot {
825a85cb24fSFrançois Tigeot 	const u32 idx = dev_priv->workarounds.count;
826a85cb24fSFrançois Tigeot 
827a85cb24fSFrançois Tigeot 	if (WARN_ON(idx >= I915_MAX_WA_REGS))
828a85cb24fSFrançois Tigeot 		return -ENOSPC;
829a85cb24fSFrançois Tigeot 
830a85cb24fSFrançois Tigeot 	dev_priv->workarounds.reg[idx].addr = addr;
831a85cb24fSFrançois Tigeot 	dev_priv->workarounds.reg[idx].value = val;
832a85cb24fSFrançois Tigeot 	dev_priv->workarounds.reg[idx].mask = mask;
833a85cb24fSFrançois Tigeot 
834a85cb24fSFrançois Tigeot 	dev_priv->workarounds.count++;
835a85cb24fSFrançois Tigeot 
836a85cb24fSFrançois Tigeot 	return 0;
837a85cb24fSFrançois Tigeot }
838a85cb24fSFrançois Tigeot 
839a85cb24fSFrançois Tigeot #define WA_REG(addr, mask, val) do { \
840a85cb24fSFrançois Tigeot 		const int r = wa_add(dev_priv, (addr), (mask), (val)); \
841a85cb24fSFrançois Tigeot 		if (r) \
842a85cb24fSFrançois Tigeot 			return r; \
843a85cb24fSFrançois Tigeot 	} while (0)
844a85cb24fSFrançois Tigeot 
845a85cb24fSFrançois Tigeot #define WA_SET_BIT_MASKED(addr, mask) \
846a85cb24fSFrançois Tigeot 	WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask))
847a85cb24fSFrançois Tigeot 
848a85cb24fSFrançois Tigeot #define WA_CLR_BIT_MASKED(addr, mask) \
849a85cb24fSFrançois Tigeot 	WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask))
850a85cb24fSFrançois Tigeot 
851a85cb24fSFrançois Tigeot #define WA_SET_FIELD_MASKED(addr, mask, value) \
852a85cb24fSFrançois Tigeot 	WA_REG(addr, mask, _MASKED_FIELD(mask, value))
853a85cb24fSFrançois Tigeot 
wa_ring_whitelist_reg(struct intel_engine_cs * engine,i915_reg_t reg)854a85cb24fSFrançois Tigeot static int wa_ring_whitelist_reg(struct intel_engine_cs *engine,
855a85cb24fSFrançois Tigeot 				 i915_reg_t reg)
856a85cb24fSFrançois Tigeot {
857a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
858a85cb24fSFrançois Tigeot 	struct i915_workarounds *wa = &dev_priv->workarounds;
859a85cb24fSFrançois Tigeot 	const uint32_t index = wa->hw_whitelist_count[engine->id];
860a85cb24fSFrançois Tigeot 
861a85cb24fSFrançois Tigeot 	if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS))
862a85cb24fSFrançois Tigeot 		return -EINVAL;
863a85cb24fSFrançois Tigeot 
864*3f2dd94aSFrançois Tigeot 	I915_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index),
865a85cb24fSFrançois Tigeot 		   i915_mmio_reg_offset(reg));
866a85cb24fSFrançois Tigeot 	wa->hw_whitelist_count[engine->id]++;
867a85cb24fSFrançois Tigeot 
868a85cb24fSFrançois Tigeot 	return 0;
869a85cb24fSFrançois Tigeot }
870a85cb24fSFrançois Tigeot 
gen8_init_workarounds(struct intel_engine_cs * engine)871a85cb24fSFrançois Tigeot static int gen8_init_workarounds(struct intel_engine_cs *engine)
872a85cb24fSFrançois Tigeot {
873a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
874a85cb24fSFrançois Tigeot 
875a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING);
876a85cb24fSFrançois Tigeot 
877a85cb24fSFrançois Tigeot 	/* WaDisableAsyncFlipPerfMode:bdw,chv */
878a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE);
879a85cb24fSFrançois Tigeot 
880a85cb24fSFrançois Tigeot 	/* WaDisablePartialInstShootdown:bdw,chv */
881a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
882a85cb24fSFrançois Tigeot 			  PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
883a85cb24fSFrançois Tigeot 
884a85cb24fSFrançois Tigeot 	/* Use Force Non-Coherent whenever executing a 3D context. This is a
885a85cb24fSFrançois Tigeot 	 * workaround for for a possible hang in the unlikely event a TLB
886a85cb24fSFrançois Tigeot 	 * invalidation occurs during a PSD flush.
887a85cb24fSFrançois Tigeot 	 */
888a85cb24fSFrançois Tigeot 	/* WaForceEnableNonCoherent:bdw,chv */
889a85cb24fSFrançois Tigeot 	/* WaHdcDisableFetchWhenMasked:bdw,chv */
890a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
891a85cb24fSFrançois Tigeot 			  HDC_DONOT_FETCH_MEM_WHEN_MASKED |
892a85cb24fSFrançois Tigeot 			  HDC_FORCE_NON_COHERENT);
893a85cb24fSFrançois Tigeot 
894a85cb24fSFrançois Tigeot 	/* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0:
895a85cb24fSFrançois Tigeot 	 * "The Hierarchical Z RAW Stall Optimization allows non-overlapping
896a85cb24fSFrançois Tigeot 	 *  polygons in the same 8x4 pixel/sample area to be processed without
897a85cb24fSFrançois Tigeot 	 *  stalling waiting for the earlier ones to write to Hierarchical Z
898a85cb24fSFrançois Tigeot 	 *  buffer."
899a85cb24fSFrançois Tigeot 	 *
900a85cb24fSFrançois Tigeot 	 * This optimization is off by default for BDW and CHV; turn it on.
901a85cb24fSFrançois Tigeot 	 */
902a85cb24fSFrançois Tigeot 	WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE);
903a85cb24fSFrançois Tigeot 
904a85cb24fSFrançois Tigeot 	/* Wa4x4STCOptimizationDisable:bdw,chv */
905a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE);
906a85cb24fSFrançois Tigeot 
907a85cb24fSFrançois Tigeot 	/*
908a85cb24fSFrançois Tigeot 	 * BSpec recommends 8x4 when MSAA is used,
909a85cb24fSFrançois Tigeot 	 * however in practice 16x4 seems fastest.
910a85cb24fSFrançois Tigeot 	 *
911a85cb24fSFrançois Tigeot 	 * Note that PS/WM thread counts depend on the WIZ hashing
912a85cb24fSFrançois Tigeot 	 * disable bit, which we don't touch here, but it's good
913a85cb24fSFrançois Tigeot 	 * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
914a85cb24fSFrançois Tigeot 	 */
915a85cb24fSFrançois Tigeot 	WA_SET_FIELD_MASKED(GEN7_GT_MODE,
916a85cb24fSFrançois Tigeot 			    GEN6_WIZ_HASHING_MASK,
917a85cb24fSFrançois Tigeot 			    GEN6_WIZ_HASHING_16x4);
918a85cb24fSFrançois Tigeot 
919a85cb24fSFrançois Tigeot 	return 0;
920a85cb24fSFrançois Tigeot }
921a85cb24fSFrançois Tigeot 
bdw_init_workarounds(struct intel_engine_cs * engine)922a85cb24fSFrançois Tigeot static int bdw_init_workarounds(struct intel_engine_cs *engine)
923a85cb24fSFrançois Tigeot {
924a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
925a85cb24fSFrançois Tigeot 	int ret;
926a85cb24fSFrançois Tigeot 
927a85cb24fSFrançois Tigeot 	ret = gen8_init_workarounds(engine);
928a85cb24fSFrançois Tigeot 	if (ret)
929a85cb24fSFrançois Tigeot 		return ret;
930a85cb24fSFrançois Tigeot 
931a85cb24fSFrançois Tigeot 	/* WaDisableThreadStallDopClockGating:bdw (pre-production) */
932a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
933a85cb24fSFrançois Tigeot 
934a85cb24fSFrançois Tigeot 	/* WaDisableDopClockGating:bdw
935a85cb24fSFrançois Tigeot 	 *
936a85cb24fSFrançois Tigeot 	 * Also see the related UCGTCL1 write in broadwell_init_clock_gating()
937a85cb24fSFrançois Tigeot 	 * to disable EUTC clock gating.
938a85cb24fSFrançois Tigeot 	 */
939a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2,
940a85cb24fSFrançois Tigeot 			  DOP_CLOCK_GATING_DISABLE);
941a85cb24fSFrançois Tigeot 
942a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
943a85cb24fSFrançois Tigeot 			  GEN8_SAMPLER_POWER_BYPASS_DIS);
944a85cb24fSFrançois Tigeot 
945a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
946a85cb24fSFrançois Tigeot 			  /* WaForceContextSaveRestoreNonCoherent:bdw */
947a85cb24fSFrançois Tigeot 			  HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
948a85cb24fSFrançois Tigeot 			  /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */
949a85cb24fSFrançois Tigeot 			  (IS_BDW_GT3(dev_priv) ? HDC_FENCE_DEST_SLM_DISABLE : 0));
950a85cb24fSFrançois Tigeot 
951a85cb24fSFrançois Tigeot 	return 0;
952a85cb24fSFrançois Tigeot }
953a85cb24fSFrançois Tigeot 
chv_init_workarounds(struct intel_engine_cs * engine)954a85cb24fSFrançois Tigeot static int chv_init_workarounds(struct intel_engine_cs *engine)
955a85cb24fSFrançois Tigeot {
956a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
957a85cb24fSFrançois Tigeot 	int ret;
958a85cb24fSFrançois Tigeot 
959a85cb24fSFrançois Tigeot 	ret = gen8_init_workarounds(engine);
960a85cb24fSFrançois Tigeot 	if (ret)
961a85cb24fSFrançois Tigeot 		return ret;
962a85cb24fSFrançois Tigeot 
963a85cb24fSFrançois Tigeot 	/* WaDisableThreadStallDopClockGating:chv */
964a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
965a85cb24fSFrançois Tigeot 
966a85cb24fSFrançois Tigeot 	/* Improve HiZ throughput on CHV. */
967a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X);
968a85cb24fSFrançois Tigeot 
969a85cb24fSFrançois Tigeot 	return 0;
970a85cb24fSFrançois Tigeot }
971a85cb24fSFrançois Tigeot 
gen9_init_workarounds(struct intel_engine_cs * engine)972a85cb24fSFrançois Tigeot static int gen9_init_workarounds(struct intel_engine_cs *engine)
973a85cb24fSFrançois Tigeot {
974a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
975a85cb24fSFrançois Tigeot 	int ret;
976a85cb24fSFrançois Tigeot 
977*3f2dd94aSFrançois Tigeot 	/* WaConextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl,glk,cfl */
978a85cb24fSFrançois Tigeot 	I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE));
979a85cb24fSFrançois Tigeot 
980*3f2dd94aSFrançois Tigeot 	/* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl,glk,cfl */
981a85cb24fSFrançois Tigeot 	I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) |
982a85cb24fSFrançois Tigeot 		   GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE);
983a85cb24fSFrançois Tigeot 
984a85cb24fSFrançois Tigeot 	/* WaDisableKillLogic:bxt,skl,kbl */
985*3f2dd94aSFrançois Tigeot 	if (!IS_COFFEELAKE(dev_priv))
986a85cb24fSFrançois Tigeot 		I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
987a85cb24fSFrançois Tigeot 			   ECOCHK_DIS_TLB);
988a85cb24fSFrançois Tigeot 
989*3f2dd94aSFrançois Tigeot 	if (HAS_LLC(dev_priv)) {
990*3f2dd94aSFrançois Tigeot 		/* WaCompressedResourceSamplerPbeMediaNewHashMode:skl,kbl
991*3f2dd94aSFrançois Tigeot 		 *
992*3f2dd94aSFrançois Tigeot 		 * Must match Display Engine. See
993*3f2dd94aSFrançois Tigeot 		 * WaCompressedResourceDisplayNewHashMode.
994*3f2dd94aSFrançois Tigeot 		 */
995*3f2dd94aSFrançois Tigeot 		WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
996*3f2dd94aSFrançois Tigeot 				  GEN9_PBE_COMPRESSED_HASH_SELECTION);
997*3f2dd94aSFrançois Tigeot 		WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7,
998*3f2dd94aSFrançois Tigeot 				  GEN9_SAMPLER_HASH_COMPRESSED_READ_ADDR);
999*3f2dd94aSFrançois Tigeot 
1000*3f2dd94aSFrançois Tigeot 		I915_WRITE(MMCD_MISC_CTRL,
1001*3f2dd94aSFrançois Tigeot 			   I915_READ(MMCD_MISC_CTRL) |
1002*3f2dd94aSFrançois Tigeot 			   MMCD_PCLA |
1003*3f2dd94aSFrançois Tigeot 			   MMCD_HOTSPOT_EN);
1004*3f2dd94aSFrançois Tigeot 	}
1005*3f2dd94aSFrançois Tigeot 
1006*3f2dd94aSFrançois Tigeot 	/* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl,glk,cfl */
1007*3f2dd94aSFrançois Tigeot 	/* WaDisablePartialInstShootdown:skl,bxt,kbl,glk,cfl */
1008a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
1009a85cb24fSFrançois Tigeot 			  FLOW_CONTROL_ENABLE |
1010a85cb24fSFrançois Tigeot 			  PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
1011a85cb24fSFrançois Tigeot 
1012a85cb24fSFrançois Tigeot 	/* Syncing dependencies between camera and graphics:skl,bxt,kbl */
1013*3f2dd94aSFrançois Tigeot 	if (!IS_COFFEELAKE(dev_priv))
1014a85cb24fSFrançois Tigeot 		WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
1015a85cb24fSFrançois Tigeot 				  GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC);
1016a85cb24fSFrançois Tigeot 
1017a85cb24fSFrançois Tigeot 	/* WaDisableDgMirrorFixInHalfSliceChicken5:bxt */
1018a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
1019a85cb24fSFrançois Tigeot 		WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
1020a85cb24fSFrançois Tigeot 				  GEN9_DG_MIRROR_FIX_ENABLE);
1021a85cb24fSFrançois Tigeot 
1022a85cb24fSFrançois Tigeot 	/* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:bxt */
1023a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
1024a85cb24fSFrançois Tigeot 		WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1,
1025a85cb24fSFrançois Tigeot 				  GEN9_RHWO_OPTIMIZATION_DISABLE);
1026a85cb24fSFrançois Tigeot 		/*
1027a85cb24fSFrançois Tigeot 		 * WA also requires GEN9_SLICE_COMMON_ECO_CHICKEN0[14:14] to be set
1028a85cb24fSFrançois Tigeot 		 * but we do that in per ctx batchbuffer as there is an issue
1029a85cb24fSFrançois Tigeot 		 * with this register not getting restored on ctx restore
1030a85cb24fSFrançois Tigeot 		 */
1031a85cb24fSFrançois Tigeot 	}
1032a85cb24fSFrançois Tigeot 
1033*3f2dd94aSFrançois Tigeot 	/* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl,glk,cfl */
1034*3f2dd94aSFrançois Tigeot 	/* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl,cfl */
1035a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7,
1036*3f2dd94aSFrançois Tigeot 			  GEN9_ENABLE_YV12_BUGFIX |
1037a85cb24fSFrançois Tigeot 			  GEN9_ENABLE_GPGPU_PREEMPTION);
1038a85cb24fSFrançois Tigeot 
1039*3f2dd94aSFrançois Tigeot 	/* Wa4x4STCOptimizationDisable:skl,bxt,kbl,glk,cfl */
1040*3f2dd94aSFrançois Tigeot 	/* WaDisablePartialResolveInVc:skl,bxt,kbl,cfl */
1041a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(CACHE_MODE_1, (GEN8_4x4_STC_OPTIMIZATION_DISABLE |
1042a85cb24fSFrançois Tigeot 					 GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE));
1043a85cb24fSFrançois Tigeot 
1044*3f2dd94aSFrançois Tigeot 	/* WaCcsTlbPrefetchDisable:skl,bxt,kbl,glk,cfl */
1045a85cb24fSFrançois Tigeot 	WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
1046a85cb24fSFrançois Tigeot 			  GEN9_CCS_TLB_PREFETCH_ENABLE);
1047a85cb24fSFrançois Tigeot 
1048a85cb24fSFrançois Tigeot 	/* WaDisableMaskBasedCammingInRCC:bxt */
1049a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
1050a85cb24fSFrançois Tigeot 		WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0,
1051a85cb24fSFrançois Tigeot 				  PIXEL_MASK_CAMMING_DISABLE);
1052a85cb24fSFrançois Tigeot 
1053*3f2dd94aSFrançois Tigeot 	/* WaForceContextSaveRestoreNonCoherent:skl,bxt,kbl,cfl */
1054a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
1055a85cb24fSFrançois Tigeot 			  HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
1056a85cb24fSFrançois Tigeot 			  HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE);
1057a85cb24fSFrançois Tigeot 
1058a85cb24fSFrançois Tigeot 	/* WaForceEnableNonCoherent and WaDisableHDCInvalidation are
1059a85cb24fSFrançois Tigeot 	 * both tied to WaForceContextSaveRestoreNonCoherent
1060a85cb24fSFrançois Tigeot 	 * in some hsds for skl. We keep the tie for all gen9. The
1061a85cb24fSFrançois Tigeot 	 * documentation is a bit hazy and so we want to get common behaviour,
1062a85cb24fSFrançois Tigeot 	 * even though there is no clear evidence we would need both on kbl/bxt.
1063a85cb24fSFrançois Tigeot 	 * This area has been source of system hangs so we play it safe
1064a85cb24fSFrançois Tigeot 	 * and mimic the skl regardless of what bspec says.
1065a85cb24fSFrançois Tigeot 	 *
1066a85cb24fSFrançois Tigeot 	 * Use Force Non-Coherent whenever executing a 3D context. This
1067a85cb24fSFrançois Tigeot 	 * is a workaround for a possible hang in the unlikely event
1068a85cb24fSFrançois Tigeot 	 * a TLB invalidation occurs during a PSD flush.
1069a85cb24fSFrançois Tigeot 	 */
1070a85cb24fSFrançois Tigeot 
1071*3f2dd94aSFrançois Tigeot 	/* WaForceEnableNonCoherent:skl,bxt,kbl,cfl */
1072a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
1073a85cb24fSFrançois Tigeot 			  HDC_FORCE_NON_COHERENT);
1074a85cb24fSFrançois Tigeot 
1075*3f2dd94aSFrançois Tigeot 	/* WaDisableHDCInvalidation:skl,bxt,kbl,cfl */
1076a85cb24fSFrançois Tigeot 	I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
1077a85cb24fSFrançois Tigeot 		   BDW_DISABLE_HDC_INVALIDATION);
1078a85cb24fSFrançois Tigeot 
1079*3f2dd94aSFrançois Tigeot 	/* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl,cfl */
1080a85cb24fSFrançois Tigeot 	if (IS_SKYLAKE(dev_priv) ||
1081a85cb24fSFrançois Tigeot 	    IS_KABYLAKE(dev_priv) ||
1082*3f2dd94aSFrançois Tigeot 	    IS_COFFEELAKE(dev_priv) ||
1083a85cb24fSFrançois Tigeot 	    IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0))
1084a85cb24fSFrançois Tigeot 		WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
1085a85cb24fSFrançois Tigeot 				  GEN8_SAMPLER_POWER_BYPASS_DIS);
1086a85cb24fSFrançois Tigeot 
1087*3f2dd94aSFrançois Tigeot 	/* WaDisableSTUnitPowerOptimization:skl,bxt,kbl,glk,cfl */
1088a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE);
1089a85cb24fSFrançois Tigeot 
1090*3f2dd94aSFrançois Tigeot 	/* WaOCLCoherentLineFlush:skl,bxt,kbl,cfl */
1091a85cb24fSFrançois Tigeot 	I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) |
1092a85cb24fSFrançois Tigeot 				    GEN8_LQSC_FLUSH_COHERENT_LINES));
1093a85cb24fSFrançois Tigeot 
1094*3f2dd94aSFrançois Tigeot 	/*
1095*3f2dd94aSFrançois Tigeot 	 * Supporting preemption with fine-granularity requires changes in the
1096*3f2dd94aSFrançois Tigeot 	 * batch buffer programming. Since we can't break old userspace, we
1097*3f2dd94aSFrançois Tigeot 	 * need to set our default preemption level to safe value. Userspace is
1098*3f2dd94aSFrançois Tigeot 	 * still able to use more fine-grained preemption levels, since in
1099*3f2dd94aSFrançois Tigeot 	 * WaEnablePreemptionGranularityControlByUMD we're whitelisting the
1100*3f2dd94aSFrançois Tigeot 	 * per-ctx register. As such, WaDisable{3D,GPGPU}MidCmdPreemption are
1101*3f2dd94aSFrançois Tigeot 	 * not real HW workarounds, but merely a way to start using preemption
1102*3f2dd94aSFrançois Tigeot 	 * while maintaining old contract with userspace.
1103*3f2dd94aSFrançois Tigeot 	 */
1104*3f2dd94aSFrançois Tigeot 
1105*3f2dd94aSFrançois Tigeot 	/* WaDisable3DMidCmdPreemption:skl,bxt,glk,cfl,[cnl] */
1106*3f2dd94aSFrançois Tigeot 	WA_CLR_BIT_MASKED(GEN8_CS_CHICKEN1, GEN9_PREEMPT_3D_OBJECT_LEVEL);
1107*3f2dd94aSFrançois Tigeot 
1108*3f2dd94aSFrançois Tigeot 	/* WaDisableGPGPUMidCmdPreemption:skl,bxt,blk,cfl,[cnl] */
1109*3f2dd94aSFrançois Tigeot 	WA_SET_FIELD_MASKED(GEN8_CS_CHICKEN1, GEN9_PREEMPT_GPGPU_LEVEL_MASK,
1110*3f2dd94aSFrançois Tigeot 			    GEN9_PREEMPT_GPGPU_COMMAND_LEVEL);
1111*3f2dd94aSFrançois Tigeot 
1112*3f2dd94aSFrançois Tigeot 	/* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt,glk,cfl */
1113a85cb24fSFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG);
1114a85cb24fSFrançois Tigeot 	if (ret)
1115a85cb24fSFrançois Tigeot 		return ret;
1116a85cb24fSFrançois Tigeot 
1117*3f2dd94aSFrançois Tigeot 	/* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl,cfl,[cnl] */
1118*3f2dd94aSFrançois Tigeot 	I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1,
1119*3f2dd94aSFrançois Tigeot 		   _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL));
1120a85cb24fSFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1);
1121a85cb24fSFrançois Tigeot 	if (ret)
1122a85cb24fSFrançois Tigeot 		return ret;
1123a85cb24fSFrançois Tigeot 
1124*3f2dd94aSFrançois Tigeot 	/* WaAllowUMDToModifyHDCChicken1:skl,bxt,kbl,glk,cfl */
1125a85cb24fSFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN8_HDC_CHICKEN1);
1126a85cb24fSFrançois Tigeot 	if (ret)
1127a85cb24fSFrançois Tigeot 		return ret;
1128a85cb24fSFrançois Tigeot 
1129a85cb24fSFrançois Tigeot 	return 0;
1130a85cb24fSFrançois Tigeot }
1131a85cb24fSFrançois Tigeot 
skl_tune_iz_hashing(struct intel_engine_cs * engine)1132a85cb24fSFrançois Tigeot static int skl_tune_iz_hashing(struct intel_engine_cs *engine)
1133a85cb24fSFrançois Tigeot {
1134a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1135a85cb24fSFrançois Tigeot 	u8 vals[3] = { 0, 0, 0 };
1136a85cb24fSFrançois Tigeot 	unsigned int i;
1137a85cb24fSFrançois Tigeot 
1138a85cb24fSFrançois Tigeot 	for (i = 0; i < 3; i++) {
1139a85cb24fSFrançois Tigeot 		u8 ss;
1140a85cb24fSFrançois Tigeot 
1141a85cb24fSFrançois Tigeot 		/*
1142a85cb24fSFrançois Tigeot 		 * Only consider slices where one, and only one, subslice has 7
1143a85cb24fSFrançois Tigeot 		 * EUs
1144a85cb24fSFrançois Tigeot 		 */
1145a85cb24fSFrançois Tigeot 		if (!is_power_of_2(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i]))
1146a85cb24fSFrançois Tigeot 			continue;
1147a85cb24fSFrançois Tigeot 
1148a85cb24fSFrançois Tigeot 		/*
1149a85cb24fSFrançois Tigeot 		 * subslice_7eu[i] != 0 (because of the check above) and
1150a85cb24fSFrançois Tigeot 		 * ss_max == 4 (maximum number of subslices possible per slice)
1151a85cb24fSFrançois Tigeot 		 *
1152a85cb24fSFrançois Tigeot 		 * ->    0 <= ss <= 3;
1153a85cb24fSFrançois Tigeot 		 */
1154a85cb24fSFrançois Tigeot 		ss = ffs(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i]) - 1;
1155a85cb24fSFrançois Tigeot 		vals[i] = 3 - ss;
1156a85cb24fSFrançois Tigeot 	}
1157a85cb24fSFrançois Tigeot 
1158a85cb24fSFrançois Tigeot 	if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0)
1159a85cb24fSFrançois Tigeot 		return 0;
1160a85cb24fSFrançois Tigeot 
1161a85cb24fSFrançois Tigeot 	/* Tune IZ hashing. See intel_device_info_runtime_init() */
1162a85cb24fSFrançois Tigeot 	WA_SET_FIELD_MASKED(GEN7_GT_MODE,
1163a85cb24fSFrançois Tigeot 			    GEN9_IZ_HASHING_MASK(2) |
1164a85cb24fSFrançois Tigeot 			    GEN9_IZ_HASHING_MASK(1) |
1165a85cb24fSFrançois Tigeot 			    GEN9_IZ_HASHING_MASK(0),
1166a85cb24fSFrançois Tigeot 			    GEN9_IZ_HASHING(2, vals[2]) |
1167a85cb24fSFrançois Tigeot 			    GEN9_IZ_HASHING(1, vals[1]) |
1168a85cb24fSFrançois Tigeot 			    GEN9_IZ_HASHING(0, vals[0]));
1169a85cb24fSFrançois Tigeot 
1170a85cb24fSFrançois Tigeot 	return 0;
1171a85cb24fSFrançois Tigeot }
1172a85cb24fSFrançois Tigeot 
skl_init_workarounds(struct intel_engine_cs * engine)1173a85cb24fSFrançois Tigeot static int skl_init_workarounds(struct intel_engine_cs *engine)
1174a85cb24fSFrançois Tigeot {
1175a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1176a85cb24fSFrançois Tigeot 	int ret;
1177a85cb24fSFrançois Tigeot 
1178a85cb24fSFrançois Tigeot 	ret = gen9_init_workarounds(engine);
1179a85cb24fSFrançois Tigeot 	if (ret)
1180a85cb24fSFrançois Tigeot 		return ret;
1181a85cb24fSFrançois Tigeot 
1182a85cb24fSFrançois Tigeot 	/* WaEnableGapsTsvCreditFix:skl */
1183a85cb24fSFrançois Tigeot 	I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
1184a85cb24fSFrançois Tigeot 				   GEN9_GAPS_TSV_CREDIT_DISABLE));
1185a85cb24fSFrançois Tigeot 
1186a85cb24fSFrançois Tigeot 	/* WaDisableGafsUnitClkGating:skl */
1187*3f2dd94aSFrançois Tigeot 	I915_WRITE(GEN7_UCGCTL4, (I915_READ(GEN7_UCGCTL4) |
1188*3f2dd94aSFrançois Tigeot 				  GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE));
1189a85cb24fSFrançois Tigeot 
1190a85cb24fSFrançois Tigeot 	/* WaInPlaceDecompressionHang:skl */
1191a85cb24fSFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER))
1192*3f2dd94aSFrançois Tigeot 		I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA,
1193*3f2dd94aSFrançois Tigeot 			   (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) |
1194*3f2dd94aSFrançois Tigeot 			    GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS));
1195a85cb24fSFrançois Tigeot 
1196a85cb24fSFrançois Tigeot 	/* WaDisableLSQCROPERFforOCL:skl */
1197a85cb24fSFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
1198a85cb24fSFrançois Tigeot 	if (ret)
1199a85cb24fSFrançois Tigeot 		return ret;
1200a85cb24fSFrançois Tigeot 
1201a85cb24fSFrançois Tigeot 	return skl_tune_iz_hashing(engine);
1202a85cb24fSFrançois Tigeot }
1203a85cb24fSFrançois Tigeot 
bxt_init_workarounds(struct intel_engine_cs * engine)1204a85cb24fSFrançois Tigeot static int bxt_init_workarounds(struct intel_engine_cs *engine)
1205a85cb24fSFrançois Tigeot {
1206a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1207a85cb24fSFrançois Tigeot 	int ret;
1208a85cb24fSFrançois Tigeot 
1209a85cb24fSFrançois Tigeot 	ret = gen9_init_workarounds(engine);
1210a85cb24fSFrançois Tigeot 	if (ret)
1211a85cb24fSFrançois Tigeot 		return ret;
1212a85cb24fSFrançois Tigeot 
1213a85cb24fSFrançois Tigeot 	/* WaStoreMultiplePTEenable:bxt */
1214a85cb24fSFrançois Tigeot 	/* This is a requirement according to Hardware specification */
1215a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
1216a85cb24fSFrançois Tigeot 		I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF);
1217a85cb24fSFrançois Tigeot 
1218a85cb24fSFrançois Tigeot 	/* WaSetClckGatingDisableMedia:bxt */
1219a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
1220a85cb24fSFrançois Tigeot 		I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) &
1221a85cb24fSFrançois Tigeot 					    ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE));
1222a85cb24fSFrançois Tigeot 	}
1223a85cb24fSFrançois Tigeot 
1224a85cb24fSFrançois Tigeot 	/* WaDisableThreadStallDopClockGating:bxt */
1225a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
1226a85cb24fSFrançois Tigeot 			  STALL_DOP_GATING_DISABLE);
1227a85cb24fSFrançois Tigeot 
1228a85cb24fSFrançois Tigeot 	/* WaDisablePooledEuLoadBalancingFix:bxt */
1229a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) {
1230*3f2dd94aSFrançois Tigeot 		I915_WRITE(FF_SLICE_CS_CHICKEN2,
1231*3f2dd94aSFrançois Tigeot 			   _MASKED_BIT_ENABLE(GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE));
1232a85cb24fSFrançois Tigeot 	}
1233a85cb24fSFrançois Tigeot 
1234a85cb24fSFrançois Tigeot 	/* WaDisableSbeCacheDispatchPortSharing:bxt */
1235a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) {
1236a85cb24fSFrançois Tigeot 		WA_SET_BIT_MASKED(
1237a85cb24fSFrançois Tigeot 			GEN7_HALF_SLICE_CHICKEN1,
1238a85cb24fSFrançois Tigeot 			GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
1239a85cb24fSFrançois Tigeot 	}
1240a85cb24fSFrançois Tigeot 
1241a85cb24fSFrançois Tigeot 	/* WaDisableObjectLevelPreemptionForTrifanOrPolygon:bxt */
1242a85cb24fSFrançois Tigeot 	/* WaDisableObjectLevelPreemptionForInstancedDraw:bxt */
1243a85cb24fSFrançois Tigeot 	/* WaDisableObjectLevelPreemtionForInstanceId:bxt */
1244a85cb24fSFrançois Tigeot 	/* WaDisableLSQCROPERFforOCL:bxt */
1245a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
1246a85cb24fSFrançois Tigeot 		ret = wa_ring_whitelist_reg(engine, GEN9_CS_DEBUG_MODE1);
1247a85cb24fSFrançois Tigeot 		if (ret)
1248a85cb24fSFrançois Tigeot 			return ret;
1249a85cb24fSFrançois Tigeot 
1250a85cb24fSFrançois Tigeot 		ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
1251a85cb24fSFrançois Tigeot 		if (ret)
1252a85cb24fSFrançois Tigeot 			return ret;
1253a85cb24fSFrançois Tigeot 	}
1254a85cb24fSFrançois Tigeot 
1255a85cb24fSFrançois Tigeot 	/* WaProgramL3SqcReg1DefaultForPerf:bxt */
1256*3f2dd94aSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) {
1257*3f2dd94aSFrançois Tigeot 		u32 val = I915_READ(GEN8_L3SQCREG1);
1258*3f2dd94aSFrançois Tigeot 		val &= ~L3_PRIO_CREDITS_MASK;
1259*3f2dd94aSFrançois Tigeot 		val |= L3_GENERAL_PRIO_CREDITS(62) | L3_HIGH_PRIO_CREDITS(2);
1260*3f2dd94aSFrançois Tigeot 		I915_WRITE(GEN8_L3SQCREG1, val);
1261*3f2dd94aSFrançois Tigeot 	}
1262a85cb24fSFrançois Tigeot 
1263a85cb24fSFrançois Tigeot 	/* WaToEnableHwFixForPushConstHWBug:bxt */
1264a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER))
1265a85cb24fSFrançois Tigeot 		WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
1266a85cb24fSFrançois Tigeot 				  GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
1267a85cb24fSFrançois Tigeot 
1268a85cb24fSFrançois Tigeot 	/* WaInPlaceDecompressionHang:bxt */
1269a85cb24fSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER))
1270*3f2dd94aSFrançois Tigeot 		I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA,
1271*3f2dd94aSFrançois Tigeot 			   (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) |
1272*3f2dd94aSFrançois Tigeot 			    GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS));
1273*3f2dd94aSFrançois Tigeot 
1274*3f2dd94aSFrançois Tigeot 	return 0;
1275*3f2dd94aSFrançois Tigeot }
1276*3f2dd94aSFrançois Tigeot 
cnl_init_workarounds(struct intel_engine_cs * engine)1277*3f2dd94aSFrançois Tigeot static int cnl_init_workarounds(struct intel_engine_cs *engine)
1278*3f2dd94aSFrançois Tigeot {
1279*3f2dd94aSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1280*3f2dd94aSFrançois Tigeot 	int ret;
1281*3f2dd94aSFrançois Tigeot 
1282*3f2dd94aSFrançois Tigeot 	/* WaDisableI2mCycleOnWRPort:cnl (pre-prod) */
1283*3f2dd94aSFrançois Tigeot 	if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0))
1284*3f2dd94aSFrançois Tigeot 		I915_WRITE(GAMT_CHKN_BIT_REG,
1285*3f2dd94aSFrançois Tigeot 			   (I915_READ(GAMT_CHKN_BIT_REG) |
1286*3f2dd94aSFrançois Tigeot 			    GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT));
1287*3f2dd94aSFrançois Tigeot 
1288*3f2dd94aSFrançois Tigeot 	/* WaForceContextSaveRestoreNonCoherent:cnl */
1289*3f2dd94aSFrançois Tigeot 	WA_SET_BIT_MASKED(CNL_HDC_CHICKEN0,
1290*3f2dd94aSFrançois Tigeot 			  HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT);
1291*3f2dd94aSFrançois Tigeot 
1292*3f2dd94aSFrançois Tigeot 	/* WaThrottleEUPerfToAvoidTDBackPressure:cnl(pre-prod) */
1293*3f2dd94aSFrançois Tigeot 	if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0))
1294*3f2dd94aSFrançois Tigeot 		WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, THROTTLE_12_5);
1295*3f2dd94aSFrançois Tigeot 
1296*3f2dd94aSFrançois Tigeot 	/* WaDisableReplayBufferBankArbitrationOptimization:cnl */
1297*3f2dd94aSFrançois Tigeot 	WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
1298*3f2dd94aSFrançois Tigeot 			  GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
1299*3f2dd94aSFrançois Tigeot 
1300*3f2dd94aSFrançois Tigeot 	/* WaDisableEnhancedSBEVertexCaching:cnl (pre-prod) */
1301*3f2dd94aSFrançois Tigeot 	if (IS_CNL_REVID(dev_priv, 0, CNL_REVID_B0))
1302*3f2dd94aSFrançois Tigeot 		WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
1303*3f2dd94aSFrançois Tigeot 				  GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE);
1304*3f2dd94aSFrançois Tigeot 
1305*3f2dd94aSFrançois Tigeot 	/* WaInPlaceDecompressionHang:cnl */
1306*3f2dd94aSFrançois Tigeot 	I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA,
1307*3f2dd94aSFrançois Tigeot 		   (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) |
1308*3f2dd94aSFrançois Tigeot 		    GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS));
1309*3f2dd94aSFrançois Tigeot 
1310*3f2dd94aSFrançois Tigeot 	/* WaPushConstantDereferenceHoldDisable:cnl */
1311*3f2dd94aSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, PUSH_CONSTANT_DEREF_DISABLE);
1312*3f2dd94aSFrançois Tigeot 
1313*3f2dd94aSFrançois Tigeot 	/* FtrEnableFastAnisoL1BankingFix: cnl */
1314*3f2dd94aSFrançois Tigeot 	WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, CNL_FAST_ANISO_L1_BANKING_FIX);
1315*3f2dd94aSFrançois Tigeot 
1316*3f2dd94aSFrançois Tigeot 	/* WaDisable3DMidCmdPreemption:cnl */
1317*3f2dd94aSFrançois Tigeot 	WA_CLR_BIT_MASKED(GEN8_CS_CHICKEN1, GEN9_PREEMPT_3D_OBJECT_LEVEL);
1318*3f2dd94aSFrançois Tigeot 
1319*3f2dd94aSFrançois Tigeot 	/* WaDisableGPGPUMidCmdPreemption:cnl */
1320*3f2dd94aSFrançois Tigeot 	WA_SET_FIELD_MASKED(GEN8_CS_CHICKEN1, GEN9_PREEMPT_GPGPU_LEVEL_MASK,
1321*3f2dd94aSFrançois Tigeot 			    GEN9_PREEMPT_GPGPU_COMMAND_LEVEL);
1322*3f2dd94aSFrançois Tigeot 
1323*3f2dd94aSFrançois Tigeot 	/* WaEnablePreemptionGranularityControlByUMD:cnl */
1324*3f2dd94aSFrançois Tigeot 	I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1,
1325*3f2dd94aSFrançois Tigeot 		   _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL));
1326*3f2dd94aSFrançois Tigeot 	ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1);
1327*3f2dd94aSFrançois Tigeot 	if (ret)
1328*3f2dd94aSFrançois Tigeot 		return ret;
1329a85cb24fSFrançois Tigeot 
1330a85cb24fSFrançois Tigeot 	return 0;
1331a85cb24fSFrançois Tigeot }
1332a85cb24fSFrançois Tigeot 
kbl_init_workarounds(struct intel_engine_cs * engine)1333a85cb24fSFrançois Tigeot static int kbl_init_workarounds(struct intel_engine_cs *engine)
1334a85cb24fSFrançois Tigeot {
1335a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1336a85cb24fSFrançois Tigeot 	int ret;
1337a85cb24fSFrançois Tigeot 
1338a85cb24fSFrançois Tigeot 	ret = gen9_init_workarounds(engine);
1339a85cb24fSFrançois Tigeot 	if (ret)
1340a85cb24fSFrançois Tigeot 		return ret;
1341a85cb24fSFrançois Tigeot 
1342a85cb24fSFrançois Tigeot 	/* WaEnableGapsTsvCreditFix:kbl */
1343a85cb24fSFrançois Tigeot 	I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
1344a85cb24fSFrançois Tigeot 				   GEN9_GAPS_TSV_CREDIT_DISABLE));
1345a85cb24fSFrançois Tigeot 
1346a85cb24fSFrançois Tigeot 	/* WaDisableDynamicCreditSharing:kbl */
1347a85cb24fSFrançois Tigeot 	if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0))
1348*3f2dd94aSFrançois Tigeot 		I915_WRITE(GAMT_CHKN_BIT_REG,
1349*3f2dd94aSFrançois Tigeot 			   (I915_READ(GAMT_CHKN_BIT_REG) |
1350*3f2dd94aSFrançois Tigeot 			    GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING));
1351a85cb24fSFrançois Tigeot 
1352a85cb24fSFrançois Tigeot 	/* WaDisableFenceDestinationToSLM:kbl (pre-prod) */
1353a85cb24fSFrançois Tigeot 	if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_A0))
1354a85cb24fSFrançois Tigeot 		WA_SET_BIT_MASKED(HDC_CHICKEN0,
1355a85cb24fSFrançois Tigeot 				  HDC_FENCE_DEST_SLM_DISABLE);
1356a85cb24fSFrançois Tigeot 
1357a85cb24fSFrançois Tigeot 	/* WaToEnableHwFixForPushConstHWBug:kbl */
1358a85cb24fSFrançois Tigeot 	if (IS_KBL_REVID(dev_priv, KBL_REVID_C0, REVID_FOREVER))
1359a85cb24fSFrançois Tigeot 		WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
1360a85cb24fSFrançois Tigeot 				  GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
1361a85cb24fSFrançois Tigeot 
1362a85cb24fSFrançois Tigeot 	/* WaDisableGafsUnitClkGating:kbl */
1363*3f2dd94aSFrançois Tigeot 	I915_WRITE(GEN7_UCGCTL4, (I915_READ(GEN7_UCGCTL4) |
1364*3f2dd94aSFrançois Tigeot 				  GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE));
1365a85cb24fSFrançois Tigeot 
1366a85cb24fSFrançois Tigeot 	/* WaDisableSbeCacheDispatchPortSharing:kbl */
1367a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(
1368a85cb24fSFrançois Tigeot 		GEN7_HALF_SLICE_CHICKEN1,
1369a85cb24fSFrançois Tigeot 		GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
1370a85cb24fSFrançois Tigeot 
1371a85cb24fSFrançois Tigeot 	/* WaInPlaceDecompressionHang:kbl */
1372*3f2dd94aSFrançois Tigeot 	I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA,
1373*3f2dd94aSFrançois Tigeot 		   (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) |
1374*3f2dd94aSFrançois Tigeot 		    GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS));
1375a85cb24fSFrançois Tigeot 
1376a85cb24fSFrançois Tigeot 	/* WaDisableLSQCROPERFforOCL:kbl */
1377a85cb24fSFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
1378a85cb24fSFrançois Tigeot 	if (ret)
1379a85cb24fSFrançois Tigeot 		return ret;
1380a85cb24fSFrançois Tigeot 
1381a85cb24fSFrançois Tigeot 	return 0;
1382a85cb24fSFrançois Tigeot }
1383a85cb24fSFrançois Tigeot 
glk_init_workarounds(struct intel_engine_cs * engine)1384a85cb24fSFrançois Tigeot static int glk_init_workarounds(struct intel_engine_cs *engine)
1385a85cb24fSFrançois Tigeot {
1386a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1387a85cb24fSFrançois Tigeot 	int ret;
1388a85cb24fSFrançois Tigeot 
1389a85cb24fSFrançois Tigeot 	ret = gen9_init_workarounds(engine);
1390a85cb24fSFrançois Tigeot 	if (ret)
1391a85cb24fSFrançois Tigeot 		return ret;
1392a85cb24fSFrançois Tigeot 
1393*3f2dd94aSFrançois Tigeot 	/* WA #0862: Userspace has to set "Barrier Mode" to avoid hangs. */
1394*3f2dd94aSFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN9_SLICE_COMMON_ECO_CHICKEN1);
1395*3f2dd94aSFrançois Tigeot 	if (ret)
1396*3f2dd94aSFrançois Tigeot 		return ret;
1397*3f2dd94aSFrançois Tigeot 
1398a85cb24fSFrançois Tigeot 	/* WaToEnableHwFixForPushConstHWBug:glk */
1399a85cb24fSFrançois Tigeot 	WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
1400a85cb24fSFrançois Tigeot 			  GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
1401a85cb24fSFrançois Tigeot 
1402a85cb24fSFrançois Tigeot 	return 0;
1403a85cb24fSFrançois Tigeot }
1404a85cb24fSFrançois Tigeot 
cfl_init_workarounds(struct intel_engine_cs * engine)1405*3f2dd94aSFrançois Tigeot static int cfl_init_workarounds(struct intel_engine_cs *engine)
1406*3f2dd94aSFrançois Tigeot {
1407*3f2dd94aSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1408*3f2dd94aSFrançois Tigeot 	int ret;
1409*3f2dd94aSFrançois Tigeot 
1410*3f2dd94aSFrançois Tigeot 	ret = gen9_init_workarounds(engine);
1411*3f2dd94aSFrançois Tigeot 	if (ret)
1412*3f2dd94aSFrançois Tigeot 		return ret;
1413*3f2dd94aSFrançois Tigeot 
1414*3f2dd94aSFrançois Tigeot 	/* WaEnableGapsTsvCreditFix:cfl */
1415*3f2dd94aSFrançois Tigeot 	I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
1416*3f2dd94aSFrançois Tigeot 				   GEN9_GAPS_TSV_CREDIT_DISABLE));
1417*3f2dd94aSFrançois Tigeot 
1418*3f2dd94aSFrançois Tigeot 	/* WaToEnableHwFixForPushConstHWBug:cfl */
1419*3f2dd94aSFrançois Tigeot 	WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
1420*3f2dd94aSFrançois Tigeot 			  GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
1421*3f2dd94aSFrançois Tigeot 
1422*3f2dd94aSFrançois Tigeot 	/* WaDisableGafsUnitClkGating:cfl */
1423*3f2dd94aSFrançois Tigeot 	I915_WRITE(GEN7_UCGCTL4, (I915_READ(GEN7_UCGCTL4) |
1424*3f2dd94aSFrançois Tigeot 				  GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE));
1425*3f2dd94aSFrançois Tigeot 
1426*3f2dd94aSFrançois Tigeot 	/* WaDisableSbeCacheDispatchPortSharing:cfl */
1427*3f2dd94aSFrançois Tigeot 	WA_SET_BIT_MASKED(
1428*3f2dd94aSFrançois Tigeot 		GEN7_HALF_SLICE_CHICKEN1,
1429*3f2dd94aSFrançois Tigeot 		GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
1430*3f2dd94aSFrançois Tigeot 
1431*3f2dd94aSFrançois Tigeot 	/* WaInPlaceDecompressionHang:cfl */
1432*3f2dd94aSFrançois Tigeot 	I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA,
1433*3f2dd94aSFrançois Tigeot 		   (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) |
1434*3f2dd94aSFrançois Tigeot 		    GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS));
1435*3f2dd94aSFrançois Tigeot 
1436*3f2dd94aSFrançois Tigeot 	return 0;
1437*3f2dd94aSFrançois Tigeot }
1438*3f2dd94aSFrançois Tigeot 
init_workarounds_ring(struct intel_engine_cs * engine)1439a85cb24fSFrançois Tigeot int init_workarounds_ring(struct intel_engine_cs *engine)
1440a85cb24fSFrançois Tigeot {
1441a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1442a85cb24fSFrançois Tigeot 	int err;
1443a85cb24fSFrançois Tigeot 
1444a85cb24fSFrançois Tigeot 	WARN_ON(engine->id != RCS);
1445a85cb24fSFrançois Tigeot 
1446a85cb24fSFrançois Tigeot 	dev_priv->workarounds.count = 0;
1447a85cb24fSFrançois Tigeot 	dev_priv->workarounds.hw_whitelist_count[engine->id] = 0;
1448a85cb24fSFrançois Tigeot 
1449a85cb24fSFrançois Tigeot 	if (IS_BROADWELL(dev_priv))
1450a85cb24fSFrançois Tigeot 		err = bdw_init_workarounds(engine);
1451a85cb24fSFrançois Tigeot 	else if (IS_CHERRYVIEW(dev_priv))
1452a85cb24fSFrançois Tigeot 		err = chv_init_workarounds(engine);
1453a85cb24fSFrançois Tigeot 	else if (IS_SKYLAKE(dev_priv))
1454a85cb24fSFrançois Tigeot 		err =  skl_init_workarounds(engine);
1455a85cb24fSFrançois Tigeot 	else if (IS_BROXTON(dev_priv))
1456a85cb24fSFrançois Tigeot 		err = bxt_init_workarounds(engine);
1457a85cb24fSFrançois Tigeot 	else if (IS_KABYLAKE(dev_priv))
1458a85cb24fSFrançois Tigeot 		err = kbl_init_workarounds(engine);
1459a85cb24fSFrançois Tigeot 	else if (IS_GEMINILAKE(dev_priv))
1460a85cb24fSFrançois Tigeot 		err =  glk_init_workarounds(engine);
1461*3f2dd94aSFrançois Tigeot 	else if (IS_COFFEELAKE(dev_priv))
1462*3f2dd94aSFrançois Tigeot 		err = cfl_init_workarounds(engine);
1463*3f2dd94aSFrançois Tigeot 	else if (IS_CANNONLAKE(dev_priv))
1464*3f2dd94aSFrançois Tigeot 		err = cnl_init_workarounds(engine);
1465a85cb24fSFrançois Tigeot 	else
1466a85cb24fSFrançois Tigeot 		err = 0;
1467a85cb24fSFrançois Tigeot 	if (err)
1468a85cb24fSFrançois Tigeot 		return err;
1469a85cb24fSFrançois Tigeot 
1470a85cb24fSFrançois Tigeot 	DRM_DEBUG_DRIVER("%s: Number of context specific w/a: %d\n",
1471a85cb24fSFrançois Tigeot 			 engine->name, dev_priv->workarounds.count);
1472a85cb24fSFrançois Tigeot 	return 0;
1473a85cb24fSFrançois Tigeot }
1474a85cb24fSFrançois Tigeot 
intel_ring_workarounds_emit(struct drm_i915_gem_request * req)1475a85cb24fSFrançois Tigeot int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
1476a85cb24fSFrançois Tigeot {
1477a85cb24fSFrançois Tigeot 	struct i915_workarounds *w = &req->i915->workarounds;
1478a85cb24fSFrançois Tigeot 	u32 *cs;
1479a85cb24fSFrançois Tigeot 	int ret, i;
1480a85cb24fSFrançois Tigeot 
1481a85cb24fSFrançois Tigeot 	if (w->count == 0)
1482a85cb24fSFrançois Tigeot 		return 0;
1483a85cb24fSFrançois Tigeot 
1484a85cb24fSFrançois Tigeot 	ret = req->engine->emit_flush(req, EMIT_BARRIER);
1485a85cb24fSFrançois Tigeot 	if (ret)
1486a85cb24fSFrançois Tigeot 		return ret;
1487a85cb24fSFrançois Tigeot 
1488a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, (w->count * 2 + 2));
1489a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
1490a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
1491a85cb24fSFrançois Tigeot 
1492a85cb24fSFrançois Tigeot 	*cs++ = MI_LOAD_REGISTER_IMM(w->count);
1493a85cb24fSFrançois Tigeot 	for (i = 0; i < w->count; i++) {
1494a85cb24fSFrançois Tigeot 		*cs++ = i915_mmio_reg_offset(w->reg[i].addr);
1495a85cb24fSFrançois Tigeot 		*cs++ = w->reg[i].value;
1496a85cb24fSFrançois Tigeot 	}
1497a85cb24fSFrançois Tigeot 	*cs++ = MI_NOOP;
1498a85cb24fSFrançois Tigeot 
1499a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
1500a85cb24fSFrançois Tigeot 
1501a85cb24fSFrançois Tigeot 	ret = req->engine->emit_flush(req, EMIT_BARRIER);
1502a85cb24fSFrançois Tigeot 	if (ret)
1503a85cb24fSFrançois Tigeot 		return ret;
1504a85cb24fSFrançois Tigeot 
1505a85cb24fSFrançois Tigeot 	return 0;
1506a85cb24fSFrançois Tigeot }
1507a85cb24fSFrançois Tigeot 
ring_is_idle(struct intel_engine_cs * engine)1508a85cb24fSFrançois Tigeot static bool ring_is_idle(struct intel_engine_cs *engine)
1509a85cb24fSFrançois Tigeot {
1510a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1511a85cb24fSFrançois Tigeot 	bool idle = true;
1512a85cb24fSFrançois Tigeot 
1513a85cb24fSFrançois Tigeot 	intel_runtime_pm_get(dev_priv);
1514a85cb24fSFrançois Tigeot 
1515*3f2dd94aSFrançois Tigeot 	/* First check that no commands are left in the ring */
1516*3f2dd94aSFrançois Tigeot 	if ((I915_READ_HEAD(engine) & HEAD_ADDR) !=
1517*3f2dd94aSFrançois Tigeot 	    (I915_READ_TAIL(engine) & TAIL_ADDR))
1518*3f2dd94aSFrançois Tigeot 		idle = false;
1519*3f2dd94aSFrançois Tigeot 
1520a85cb24fSFrançois Tigeot 	/* No bit for gen2, so assume the CS parser is idle */
1521a85cb24fSFrançois Tigeot 	if (INTEL_GEN(dev_priv) > 2 && !(I915_READ_MODE(engine) & MODE_IDLE))
1522a85cb24fSFrançois Tigeot 		idle = false;
1523a85cb24fSFrançois Tigeot 
1524a85cb24fSFrançois Tigeot 	intel_runtime_pm_put(dev_priv);
1525a85cb24fSFrançois Tigeot 
1526a85cb24fSFrançois Tigeot 	return idle;
1527a85cb24fSFrançois Tigeot }
1528a85cb24fSFrançois Tigeot 
1529a85cb24fSFrançois Tigeot /**
1530a85cb24fSFrançois Tigeot  * intel_engine_is_idle() - Report if the engine has finished process all work
1531a85cb24fSFrançois Tigeot  * @engine: the intel_engine_cs
1532a85cb24fSFrançois Tigeot  *
1533a85cb24fSFrançois Tigeot  * Return true if there are no requests pending, nothing left to be submitted
1534a85cb24fSFrançois Tigeot  * to hardware, and that the engine is idle.
1535a85cb24fSFrançois Tigeot  */
intel_engine_is_idle(struct intel_engine_cs * engine)1536a85cb24fSFrançois Tigeot bool intel_engine_is_idle(struct intel_engine_cs *engine)
1537a85cb24fSFrançois Tigeot {
1538*3f2dd94aSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1539*3f2dd94aSFrançois Tigeot 
1540*3f2dd94aSFrançois Tigeot 	/* More white lies, if wedged, hw state is inconsistent */
1541*3f2dd94aSFrançois Tigeot 	if (i915_terminally_wedged(&dev_priv->gpu_error))
1542*3f2dd94aSFrançois Tigeot 		return true;
1543*3f2dd94aSFrançois Tigeot 
1544a85cb24fSFrançois Tigeot 	/* Any inflight/incomplete requests? */
1545a85cb24fSFrançois Tigeot 	if (!i915_seqno_passed(intel_engine_get_seqno(engine),
1546a85cb24fSFrançois Tigeot 			       intel_engine_last_submit(engine)))
1547a85cb24fSFrançois Tigeot 		return false;
1548a85cb24fSFrançois Tigeot 
1549*3f2dd94aSFrançois Tigeot 	if (I915_SELFTEST_ONLY(engine->breadcrumbs.mock))
1550*3f2dd94aSFrançois Tigeot 		return true;
1551*3f2dd94aSFrançois Tigeot 
1552a85cb24fSFrançois Tigeot 	/* Interrupt/tasklet pending? */
1553a85cb24fSFrançois Tigeot 	if (test_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted))
1554a85cb24fSFrançois Tigeot 		return false;
1555a85cb24fSFrançois Tigeot 
1556*3f2dd94aSFrançois Tigeot 	/* Waiting to drain ELSP? */
1557*3f2dd94aSFrançois Tigeot 	if (READ_ONCE(engine->execlists.active))
1558*3f2dd94aSFrançois Tigeot 		return false;
1559*3f2dd94aSFrançois Tigeot 
1560*3f2dd94aSFrançois Tigeot 	/* ELSP is empty, but there are ready requests? */
1561*3f2dd94aSFrançois Tigeot 	if (READ_ONCE(engine->execlists.first))
1562a85cb24fSFrançois Tigeot 		return false;
1563a85cb24fSFrançois Tigeot 
1564a85cb24fSFrançois Tigeot 	/* Ring stopped? */
1565a85cb24fSFrançois Tigeot 	if (!ring_is_idle(engine))
1566a85cb24fSFrançois Tigeot 		return false;
1567a85cb24fSFrançois Tigeot 
1568a85cb24fSFrançois Tigeot 	return true;
1569a85cb24fSFrançois Tigeot }
1570a85cb24fSFrançois Tigeot 
intel_engines_are_idle(struct drm_i915_private * dev_priv)1571a85cb24fSFrançois Tigeot bool intel_engines_are_idle(struct drm_i915_private *dev_priv)
1572a85cb24fSFrançois Tigeot {
1573a85cb24fSFrançois Tigeot 	struct intel_engine_cs *engine;
1574a85cb24fSFrançois Tigeot 	enum intel_engine_id id;
1575a85cb24fSFrançois Tigeot 
1576a85cb24fSFrançois Tigeot 	if (READ_ONCE(dev_priv->gt.active_requests))
1577a85cb24fSFrançois Tigeot 		return false;
1578a85cb24fSFrançois Tigeot 
1579a85cb24fSFrançois Tigeot 	/* If the driver is wedged, HW state may be very inconsistent and
1580a85cb24fSFrançois Tigeot 	 * report that it is still busy, even though we have stopped using it.
1581a85cb24fSFrançois Tigeot 	 */
1582a85cb24fSFrançois Tigeot 	if (i915_terminally_wedged(&dev_priv->gpu_error))
1583a85cb24fSFrançois Tigeot 		return true;
1584a85cb24fSFrançois Tigeot 
1585a85cb24fSFrançois Tigeot 	for_each_engine(engine, dev_priv, id) {
1586a85cb24fSFrançois Tigeot 		if (!intel_engine_is_idle(engine))
1587a85cb24fSFrançois Tigeot 			return false;
1588a85cb24fSFrançois Tigeot 	}
1589a85cb24fSFrançois Tigeot 
1590a85cb24fSFrançois Tigeot 	return true;
1591a85cb24fSFrançois Tigeot }
1592a85cb24fSFrançois Tigeot 
intel_engines_reset_default_submission(struct drm_i915_private * i915)1593a85cb24fSFrançois Tigeot void intel_engines_reset_default_submission(struct drm_i915_private *i915)
1594a85cb24fSFrançois Tigeot {
1595a85cb24fSFrançois Tigeot 	struct intel_engine_cs *engine;
1596a85cb24fSFrançois Tigeot 	enum intel_engine_id id;
1597a85cb24fSFrançois Tigeot 
1598a85cb24fSFrançois Tigeot 	for_each_engine(engine, i915, id)
1599a85cb24fSFrançois Tigeot 		engine->set_default_submission(engine);
1600a85cb24fSFrançois Tigeot }
1601a85cb24fSFrançois Tigeot 
intel_engines_mark_idle(struct drm_i915_private * i915)1602*3f2dd94aSFrançois Tigeot void intel_engines_mark_idle(struct drm_i915_private *i915)
1603*3f2dd94aSFrançois Tigeot {
1604*3f2dd94aSFrançois Tigeot 	struct intel_engine_cs *engine;
1605*3f2dd94aSFrançois Tigeot 	enum intel_engine_id id;
1606*3f2dd94aSFrançois Tigeot 
1607*3f2dd94aSFrançois Tigeot 	for_each_engine(engine, i915, id) {
1608*3f2dd94aSFrançois Tigeot 		intel_engine_disarm_breadcrumbs(engine);
1609*3f2dd94aSFrançois Tigeot 		i915_gem_batch_pool_fini(&engine->batch_pool);
1610*3f2dd94aSFrançois Tigeot 		tasklet_kill(&engine->execlists.irq_tasklet);
1611*3f2dd94aSFrançois Tigeot 		engine->execlists.no_priolist = false;
1612*3f2dd94aSFrançois Tigeot 	}
1613*3f2dd94aSFrançois Tigeot }
1614*3f2dd94aSFrançois Tigeot 
intel_engine_can_store_dword(struct intel_engine_cs * engine)1615*3f2dd94aSFrançois Tigeot bool intel_engine_can_store_dword(struct intel_engine_cs *engine)
1616*3f2dd94aSFrançois Tigeot {
1617*3f2dd94aSFrançois Tigeot 	switch (INTEL_GEN(engine->i915)) {
1618*3f2dd94aSFrançois Tigeot 	case 2:
1619*3f2dd94aSFrançois Tigeot 		return false; /* uses physical not virtual addresses */
1620*3f2dd94aSFrançois Tigeot 	case 3:
1621*3f2dd94aSFrançois Tigeot 		/* maybe only uses physical not virtual addresses */
1622*3f2dd94aSFrançois Tigeot 		return !(IS_I915G(engine->i915) || IS_I915GM(engine->i915));
1623*3f2dd94aSFrançois Tigeot 	case 6:
1624*3f2dd94aSFrançois Tigeot 		return engine->class != VIDEO_DECODE_CLASS; /* b0rked */
1625*3f2dd94aSFrançois Tigeot 	default:
1626*3f2dd94aSFrançois Tigeot 		return true;
1627*3f2dd94aSFrançois Tigeot 	}
1628*3f2dd94aSFrançois Tigeot }
1629*3f2dd94aSFrançois Tigeot 
print_request(struct drm_printer * m,struct drm_i915_gem_request * rq,const char * prefix)1630*3f2dd94aSFrançois Tigeot static void print_request(struct drm_printer *m,
1631*3f2dd94aSFrançois Tigeot 			  struct drm_i915_gem_request *rq,
1632*3f2dd94aSFrançois Tigeot 			  const char *prefix)
1633*3f2dd94aSFrançois Tigeot {
1634*3f2dd94aSFrançois Tigeot 	drm_printf(m, "%s%x%s [%x:%x] prio=%d @ %ldms: %s\n", prefix,
1635*3f2dd94aSFrançois Tigeot 		   rq->global_seqno,
1636*3f2dd94aSFrançois Tigeot 		   i915_gem_request_completed(rq) ? "!" : "",
1637*3f2dd94aSFrançois Tigeot 		   rq->ctx->hw_id, rq->fence.seqno,
1638*3f2dd94aSFrançois Tigeot 		   rq->priotree.priority,
1639*3f2dd94aSFrançois Tigeot 		   jiffies_to_msecs(jiffies - rq->emitted_jiffies),
1640*3f2dd94aSFrançois Tigeot 		   rq->timeline->common->name);
1641*3f2dd94aSFrançois Tigeot }
1642*3f2dd94aSFrançois Tigeot 
intel_engine_dump(struct intel_engine_cs * engine,struct drm_printer * m)1643*3f2dd94aSFrançois Tigeot void intel_engine_dump(struct intel_engine_cs *engine, struct drm_printer *m)
1644*3f2dd94aSFrançois Tigeot {
1645*3f2dd94aSFrançois Tigeot 	struct intel_breadcrumbs * const b = &engine->breadcrumbs;
1646*3f2dd94aSFrançois Tigeot 	const struct intel_engine_execlists * const execlists = &engine->execlists;
1647*3f2dd94aSFrançois Tigeot 	struct i915_gpu_error * const error = &engine->i915->gpu_error;
1648*3f2dd94aSFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1649*3f2dd94aSFrançois Tigeot 	struct drm_i915_gem_request *rq;
1650*3f2dd94aSFrançois Tigeot 	struct rb_node *rb;
1651*3f2dd94aSFrançois Tigeot 	u64 addr;
1652*3f2dd94aSFrançois Tigeot 
1653*3f2dd94aSFrançois Tigeot 	drm_printf(m, "%s\n", engine->name);
1654*3f2dd94aSFrançois Tigeot 	drm_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [%ld ms], inflight %d\n",
1655*3f2dd94aSFrançois Tigeot 		   intel_engine_get_seqno(engine),
1656*3f2dd94aSFrançois Tigeot 		   intel_engine_last_submit(engine),
1657*3f2dd94aSFrançois Tigeot 		   engine->hangcheck.seqno,
1658*3f2dd94aSFrançois Tigeot 		   jiffies_to_msecs(jiffies - engine->hangcheck.action_timestamp),
1659*3f2dd94aSFrançois Tigeot 		   engine->timeline->inflight_seqnos);
1660*3f2dd94aSFrançois Tigeot 	drm_printf(m, "\tReset count: %d\n",
1661*3f2dd94aSFrançois Tigeot 		   i915_reset_engine_count(error, engine));
1662*3f2dd94aSFrançois Tigeot 
1663*3f2dd94aSFrançois Tigeot 	rcu_read_lock();
1664*3f2dd94aSFrançois Tigeot 
1665*3f2dd94aSFrançois Tigeot 	drm_printf(m, "\tRequests:\n");
1666*3f2dd94aSFrançois Tigeot 
1667*3f2dd94aSFrançois Tigeot 	rq = list_first_entry(&engine->timeline->requests,
1668*3f2dd94aSFrançois Tigeot 			      struct drm_i915_gem_request, link);
1669*3f2dd94aSFrançois Tigeot 	if (&rq->link != &engine->timeline->requests)
1670*3f2dd94aSFrançois Tigeot 		print_request(m, rq, "\t\tfirst  ");
1671*3f2dd94aSFrançois Tigeot 
1672*3f2dd94aSFrançois Tigeot 	rq = list_last_entry(&engine->timeline->requests,
1673*3f2dd94aSFrançois Tigeot 			     struct drm_i915_gem_request, link);
1674*3f2dd94aSFrançois Tigeot 	if (&rq->link != &engine->timeline->requests)
1675*3f2dd94aSFrançois Tigeot 		print_request(m, rq, "\t\tlast   ");
1676*3f2dd94aSFrançois Tigeot 
1677*3f2dd94aSFrançois Tigeot 	rq = i915_gem_find_active_request(engine);
1678*3f2dd94aSFrançois Tigeot 	if (rq) {
1679*3f2dd94aSFrançois Tigeot 		print_request(m, rq, "\t\tactive ");
1680*3f2dd94aSFrançois Tigeot 		drm_printf(m,
1681*3f2dd94aSFrançois Tigeot 			   "\t\t[head %04x, postfix %04x, tail %04x, batch 0x%08x_%08x]\n",
1682*3f2dd94aSFrançois Tigeot 			   rq->head, rq->postfix, rq->tail,
1683*3f2dd94aSFrançois Tigeot 			   rq->batch ? upper_32_bits(rq->batch->node.start) : ~0u,
1684*3f2dd94aSFrançois Tigeot 			   rq->batch ? lower_32_bits(rq->batch->node.start) : ~0u);
1685*3f2dd94aSFrançois Tigeot 	}
1686*3f2dd94aSFrançois Tigeot 
1687*3f2dd94aSFrançois Tigeot 	drm_printf(m, "\tRING_START: 0x%08x [0x%08x]\n",
1688*3f2dd94aSFrançois Tigeot 		   I915_READ(RING_START(engine->mmio_base)),
1689*3f2dd94aSFrançois Tigeot 		   rq ? i915_ggtt_offset(rq->ring->vma) : 0);
1690*3f2dd94aSFrançois Tigeot 	drm_printf(m, "\tRING_HEAD:  0x%08x [0x%08x]\n",
1691*3f2dd94aSFrançois Tigeot 		   I915_READ(RING_HEAD(engine->mmio_base)) & HEAD_ADDR,
1692*3f2dd94aSFrançois Tigeot 		   rq ? rq->ring->head : 0);
1693*3f2dd94aSFrançois Tigeot 	drm_printf(m, "\tRING_TAIL:  0x%08x [0x%08x]\n",
1694*3f2dd94aSFrançois Tigeot 		   I915_READ(RING_TAIL(engine->mmio_base)) & TAIL_ADDR,
1695*3f2dd94aSFrançois Tigeot 		   rq ? rq->ring->tail : 0);
1696*3f2dd94aSFrançois Tigeot 	drm_printf(m, "\tRING_CTL:   0x%08x [%s]\n",
1697*3f2dd94aSFrançois Tigeot 		   I915_READ(RING_CTL(engine->mmio_base)),
1698*3f2dd94aSFrançois Tigeot 		   I915_READ(RING_CTL(engine->mmio_base)) & (RING_WAIT | RING_WAIT_SEMAPHORE) ? "waiting" : "");
1699*3f2dd94aSFrançois Tigeot 
1700*3f2dd94aSFrançois Tigeot 	rcu_read_unlock();
1701*3f2dd94aSFrançois Tigeot 
1702*3f2dd94aSFrançois Tigeot 	addr = intel_engine_get_active_head(engine);
1703*3f2dd94aSFrançois Tigeot 	drm_printf(m, "\tACTHD:  0x%08x_%08x\n",
1704*3f2dd94aSFrançois Tigeot 		   upper_32_bits(addr), lower_32_bits(addr));
1705*3f2dd94aSFrançois Tigeot 	addr = intel_engine_get_last_batch_head(engine);
1706*3f2dd94aSFrançois Tigeot 	drm_printf(m, "\tBBADDR: 0x%08x_%08x\n",
1707*3f2dd94aSFrançois Tigeot 		   upper_32_bits(addr), lower_32_bits(addr));
1708*3f2dd94aSFrançois Tigeot 
1709*3f2dd94aSFrançois Tigeot 	if (i915_modparams.enable_execlists) {
1710*3f2dd94aSFrançois Tigeot 		const u32 *hws = &engine->status_page.page_addr[I915_HWS_CSB_BUF0_INDEX];
1711*3f2dd94aSFrançois Tigeot 		u32 ptr, read, write;
1712*3f2dd94aSFrançois Tigeot 		unsigned int idx;
1713*3f2dd94aSFrançois Tigeot 
1714*3f2dd94aSFrançois Tigeot 		drm_printf(m, "\tExeclist status: 0x%08x %08x\n",
1715*3f2dd94aSFrançois Tigeot 			   I915_READ(RING_EXECLIST_STATUS_LO(engine)),
1716*3f2dd94aSFrançois Tigeot 			   I915_READ(RING_EXECLIST_STATUS_HI(engine)));
1717*3f2dd94aSFrançois Tigeot 
1718*3f2dd94aSFrançois Tigeot 		ptr = I915_READ(RING_CONTEXT_STATUS_PTR(engine));
1719*3f2dd94aSFrançois Tigeot 		read = GEN8_CSB_READ_PTR(ptr);
1720*3f2dd94aSFrançois Tigeot 		write = GEN8_CSB_WRITE_PTR(ptr);
1721*3f2dd94aSFrançois Tigeot 		drm_printf(m, "\tExeclist CSB read %d [%d cached], write %d [%d from hws], interrupt posted? %s\n",
1722*3f2dd94aSFrançois Tigeot 			   read, execlists->csb_head,
1723*3f2dd94aSFrançois Tigeot 			   write,
1724*3f2dd94aSFrançois Tigeot 			   intel_read_status_page(engine, intel_hws_csb_write_index(engine->i915)),
1725*3f2dd94aSFrançois Tigeot 			   yesno(test_bit(ENGINE_IRQ_EXECLIST,
1726*3f2dd94aSFrançois Tigeot 					  &engine->irq_posted)));
1727*3f2dd94aSFrançois Tigeot 		if (read >= GEN8_CSB_ENTRIES)
1728*3f2dd94aSFrançois Tigeot 			read = 0;
1729*3f2dd94aSFrançois Tigeot 		if (write >= GEN8_CSB_ENTRIES)
1730*3f2dd94aSFrançois Tigeot 			write = 0;
1731*3f2dd94aSFrançois Tigeot 		if (read > write)
1732*3f2dd94aSFrançois Tigeot 			write += GEN8_CSB_ENTRIES;
1733*3f2dd94aSFrançois Tigeot 		while (read < write) {
1734*3f2dd94aSFrançois Tigeot 			idx = ++read % GEN8_CSB_ENTRIES;
1735*3f2dd94aSFrançois Tigeot 			drm_printf(m, "\tExeclist CSB[%d]: 0x%08x [0x%08x in hwsp], context: %d [%d in hwsp]\n",
1736*3f2dd94aSFrançois Tigeot 				   idx,
1737*3f2dd94aSFrançois Tigeot 				   I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, idx)),
1738*3f2dd94aSFrançois Tigeot 				   hws[idx * 2],
1739*3f2dd94aSFrançois Tigeot 				   I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, idx)),
1740*3f2dd94aSFrançois Tigeot 				   hws[idx * 2 + 1]);
1741*3f2dd94aSFrançois Tigeot 		}
1742*3f2dd94aSFrançois Tigeot 
1743*3f2dd94aSFrançois Tigeot 		rcu_read_lock();
1744*3f2dd94aSFrançois Tigeot 		for (idx = 0; idx < execlists_num_ports(execlists); idx++) {
1745*3f2dd94aSFrançois Tigeot 			unsigned int count;
1746*3f2dd94aSFrançois Tigeot 
1747*3f2dd94aSFrançois Tigeot 			rq = port_unpack(&execlists->port[idx], &count);
1748*3f2dd94aSFrançois Tigeot 			if (rq) {
1749*3f2dd94aSFrançois Tigeot 				drm_printf(m, "\t\tELSP[%d] count=%d, ",
1750*3f2dd94aSFrançois Tigeot 					   idx, count);
1751*3f2dd94aSFrançois Tigeot 				print_request(m, rq, "rq: ");
1752*3f2dd94aSFrançois Tigeot 			} else {
1753*3f2dd94aSFrançois Tigeot 				drm_printf(m, "\t\tELSP[%d] idle\n",
1754*3f2dd94aSFrançois Tigeot 					   idx);
1755*3f2dd94aSFrançois Tigeot 			}
1756*3f2dd94aSFrançois Tigeot 		}
1757*3f2dd94aSFrançois Tigeot 		drm_printf(m, "\t\tHW active? 0x%x\n", execlists->active);
1758*3f2dd94aSFrançois Tigeot 		rcu_read_unlock();
1759*3f2dd94aSFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) > 6) {
1760*3f2dd94aSFrançois Tigeot 		drm_printf(m, "\tPP_DIR_BASE: 0x%08x\n",
1761*3f2dd94aSFrançois Tigeot 			   I915_READ(RING_PP_DIR_BASE(engine)));
1762*3f2dd94aSFrançois Tigeot 		drm_printf(m, "\tPP_DIR_BASE_READ: 0x%08x\n",
1763*3f2dd94aSFrançois Tigeot 			   I915_READ(RING_PP_DIR_BASE_READ(engine)));
1764*3f2dd94aSFrançois Tigeot 		drm_printf(m, "\tPP_DIR_DCLV: 0x%08x\n",
1765*3f2dd94aSFrançois Tigeot 			   I915_READ(RING_PP_DIR_DCLV(engine)));
1766*3f2dd94aSFrançois Tigeot 	}
1767*3f2dd94aSFrançois Tigeot 
1768*3f2dd94aSFrançois Tigeot 	spin_lock_irq(&engine->timeline->lock);
1769*3f2dd94aSFrançois Tigeot 	list_for_each_entry(rq, &engine->timeline->requests, link)
1770*3f2dd94aSFrançois Tigeot 		print_request(m, rq, "\t\tE ");
1771*3f2dd94aSFrançois Tigeot 	for (rb = execlists->first; rb; rb = rb_next(rb)) {
1772*3f2dd94aSFrançois Tigeot 		struct i915_priolist *p =
1773*3f2dd94aSFrançois Tigeot 			rb_entry(rb, typeof(*p), node);
1774*3f2dd94aSFrançois Tigeot 
1775*3f2dd94aSFrançois Tigeot 		list_for_each_entry(rq, &p->requests, priotree.link)
1776*3f2dd94aSFrançois Tigeot 			print_request(m, rq, "\t\tQ ");
1777*3f2dd94aSFrançois Tigeot 	}
1778*3f2dd94aSFrançois Tigeot 	spin_unlock_irq(&engine->timeline->lock);
1779*3f2dd94aSFrançois Tigeot 
1780*3f2dd94aSFrançois Tigeot 	spin_lock_irq(&b->rb_lock);
1781*3f2dd94aSFrançois Tigeot 	for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) {
1782*3f2dd94aSFrançois Tigeot 		struct intel_wait *w = rb_entry(rb, typeof(*w), node);
1783*3f2dd94aSFrançois Tigeot 
1784*3f2dd94aSFrançois Tigeot 		drm_printf(m, "\t%s [%d] waiting for %x\n",
1785*3f2dd94aSFrançois Tigeot 			   w->tsk->comm, w->tsk->pid, w->seqno);
1786*3f2dd94aSFrançois Tigeot 	}
1787*3f2dd94aSFrançois Tigeot 	spin_unlock_irq(&b->rb_lock);
1788*3f2dd94aSFrançois Tigeot 
1789*3f2dd94aSFrançois Tigeot 	drm_printf(m, "\n");
1790*3f2dd94aSFrançois Tigeot }
1791*3f2dd94aSFrançois Tigeot 
1792a85cb24fSFrançois Tigeot #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
1793a85cb24fSFrançois Tigeot #include "selftests/mock_engine.c"
1794a85cb24fSFrançois Tigeot #endif
1795