blob: 020e4c6c0192542071fd24579bdb303460a5e49c [file] [log] [blame]
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +01001/*
2 * Copyright © 2016 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 */
24
25#include "i915_drv.h"
26#include "intel_ringbuffer.h"
27#include "intel_lrc.h"
28
Joonas Lahtinen63ffbcd2017-04-28 10:53:36 +030029/* Haswell does have the CXT_SIZE register however it does not appear to be
30 * valid. Now, docs explain in dwords what is in the context object. The full
31 * size is 70720 bytes, however, the power context and execlist context will
32 * never be saved (power context is stored elsewhere, and execlists don't work
33 * on HSW) - so the final size, including the extra state required for the
34 * Resource Streamer, is 66944 bytes, which rounds to 17 pages.
35 */
36#define HSW_CXT_TOTAL_SIZE (17 * PAGE_SIZE)
37/* Same as Haswell, but 72064 bytes now. */
38#define GEN8_CXT_TOTAL_SIZE (18 * PAGE_SIZE)
39
40#define GEN8_LR_CONTEXT_RENDER_SIZE (20 * PAGE_SIZE)
41#define GEN9_LR_CONTEXT_RENDER_SIZE (22 * PAGE_SIZE)
Oscar Mateo7fd0b1a2017-09-21 16:19:49 -070042#define GEN10_LR_CONTEXT_RENDER_SIZE (19 * PAGE_SIZE)
Joonas Lahtinen63ffbcd2017-04-28 10:53:36 +030043
44#define GEN8_LR_CONTEXT_OTHER_SIZE ( 2 * PAGE_SIZE)
45
Oscar Mateob8400f02017-04-10 07:34:32 -070046struct engine_class_info {
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +010047 const char *name;
Oscar Mateob8400f02017-04-10 07:34:32 -070048 int (*init_legacy)(struct intel_engine_cs *engine);
49 int (*init_execlists)(struct intel_engine_cs *engine);
50};
51
52static const struct engine_class_info intel_engine_classes[] = {
53 [RENDER_CLASS] = {
54 .name = "rcs",
55 .init_execlists = logical_render_ring_init,
56 .init_legacy = intel_init_render_ring_buffer,
57 },
58 [COPY_ENGINE_CLASS] = {
59 .name = "bcs",
60 .init_execlists = logical_xcs_ring_init,
61 .init_legacy = intel_init_blt_ring_buffer,
62 },
63 [VIDEO_DECODE_CLASS] = {
64 .name = "vcs",
65 .init_execlists = logical_xcs_ring_init,
66 .init_legacy = intel_init_bsd_ring_buffer,
67 },
68 [VIDEO_ENHANCEMENT_CLASS] = {
69 .name = "vecs",
70 .init_execlists = logical_xcs_ring_init,
71 .init_legacy = intel_init_vebox_ring_buffer,
72 },
73};
74
75struct engine_info {
Michal Wajdeczko237ae7c2017-03-01 20:26:15 +000076 unsigned int hw_id;
Chris Wilson1d39f282017-04-11 13:43:06 +010077 unsigned int uabi_id;
Daniele Ceraolo Spurio09081802017-04-10 07:34:29 -070078 u8 class;
79 u8 instance;
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +010080 u32 mmio_base;
81 unsigned irq_shift;
Oscar Mateob8400f02017-04-10 07:34:32 -070082};
83
84static const struct engine_info intel_engines[] = {
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +010085 [RCS] = {
Tvrtko Ursulin5ec2cf72016-08-16 17:04:20 +010086 .hw_id = RCS_HW,
Chris Wilson1d39f282017-04-11 13:43:06 +010087 .uabi_id = I915_EXEC_RENDER,
Daniele Ceraolo Spurio09081802017-04-10 07:34:29 -070088 .class = RENDER_CLASS,
89 .instance = 0,
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +010090 .mmio_base = RENDER_RING_BASE,
91 .irq_shift = GEN8_RCS_IRQ_SHIFT,
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +010092 },
93 [BCS] = {
Tvrtko Ursulin5ec2cf72016-08-16 17:04:20 +010094 .hw_id = BCS_HW,
Chris Wilson1d39f282017-04-11 13:43:06 +010095 .uabi_id = I915_EXEC_BLT,
Daniele Ceraolo Spurio09081802017-04-10 07:34:29 -070096 .class = COPY_ENGINE_CLASS,
97 .instance = 0,
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +010098 .mmio_base = BLT_RING_BASE,
99 .irq_shift = GEN8_BCS_IRQ_SHIFT,
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100100 },
101 [VCS] = {
Tvrtko Ursulin5ec2cf72016-08-16 17:04:20 +0100102 .hw_id = VCS_HW,
Chris Wilson1d39f282017-04-11 13:43:06 +0100103 .uabi_id = I915_EXEC_BSD,
Daniele Ceraolo Spurio09081802017-04-10 07:34:29 -0700104 .class = VIDEO_DECODE_CLASS,
105 .instance = 0,
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100106 .mmio_base = GEN6_BSD_RING_BASE,
107 .irq_shift = GEN8_VCS1_IRQ_SHIFT,
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100108 },
109 [VCS2] = {
Tvrtko Ursulin5ec2cf72016-08-16 17:04:20 +0100110 .hw_id = VCS2_HW,
Chris Wilson1d39f282017-04-11 13:43:06 +0100111 .uabi_id = I915_EXEC_BSD,
Daniele Ceraolo Spurio09081802017-04-10 07:34:29 -0700112 .class = VIDEO_DECODE_CLASS,
113 .instance = 1,
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100114 .mmio_base = GEN8_BSD2_RING_BASE,
115 .irq_shift = GEN8_VCS2_IRQ_SHIFT,
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100116 },
117 [VECS] = {
Tvrtko Ursulin5ec2cf72016-08-16 17:04:20 +0100118 .hw_id = VECS_HW,
Chris Wilson1d39f282017-04-11 13:43:06 +0100119 .uabi_id = I915_EXEC_VEBOX,
Daniele Ceraolo Spurio09081802017-04-10 07:34:29 -0700120 .class = VIDEO_ENHANCEMENT_CLASS,
121 .instance = 0,
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100122 .mmio_base = VEBOX_RING_BASE,
123 .irq_shift = GEN8_VECS_IRQ_SHIFT,
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100124 },
125};
126
Joonas Lahtinen63ffbcd2017-04-28 10:53:36 +0300127/**
128 * ___intel_engine_context_size() - return the size of the context for an engine
129 * @dev_priv: i915 device private
130 * @class: engine class
131 *
132 * Each engine class may require a different amount of space for a context
133 * image.
134 *
135 * Return: size (in bytes) of an engine class specific context image
136 *
137 * Note: this size includes the HWSP, which is part of the context image
138 * in LRC mode, but does not include the "shared data page" used with
139 * GuC submission. The caller should account for this if using the GuC.
140 */
141static u32
142__intel_engine_context_size(struct drm_i915_private *dev_priv, u8 class)
143{
144 u32 cxt_size;
145
146 BUILD_BUG_ON(I915_GTT_PAGE_SIZE != PAGE_SIZE);
147
148 switch (class) {
149 case RENDER_CLASS:
150 switch (INTEL_GEN(dev_priv)) {
151 default:
152 MISSING_CASE(INTEL_GEN(dev_priv));
Rodrigo Vivif65f8412017-07-06 14:06:24 -0700153 case 10:
Oscar Mateo7fd0b1a2017-09-21 16:19:49 -0700154 return GEN10_LR_CONTEXT_RENDER_SIZE;
Joonas Lahtinen63ffbcd2017-04-28 10:53:36 +0300155 case 9:
156 return GEN9_LR_CONTEXT_RENDER_SIZE;
157 case 8:
Michal Wajdeczko4f044a82017-09-19 19:38:44 +0000158 return i915_modparams.enable_execlists ?
Joonas Lahtinen63ffbcd2017-04-28 10:53:36 +0300159 GEN8_LR_CONTEXT_RENDER_SIZE :
160 GEN8_CXT_TOTAL_SIZE;
161 case 7:
162 if (IS_HASWELL(dev_priv))
163 return HSW_CXT_TOTAL_SIZE;
164
165 cxt_size = I915_READ(GEN7_CXT_SIZE);
166 return round_up(GEN7_CXT_TOTAL_SIZE(cxt_size) * 64,
167 PAGE_SIZE);
168 case 6:
169 cxt_size = I915_READ(CXT_SIZE);
170 return round_up(GEN6_CXT_TOTAL_SIZE(cxt_size) * 64,
171 PAGE_SIZE);
172 case 5:
173 case 4:
174 case 3:
175 case 2:
176 /* For the special day when i810 gets merged. */
177 case 1:
178 return 0;
179 }
180 break;
181 default:
182 MISSING_CASE(class);
183 case VIDEO_DECODE_CLASS:
184 case VIDEO_ENHANCEMENT_CLASS:
185 case COPY_ENGINE_CLASS:
186 if (INTEL_GEN(dev_priv) < 8)
187 return 0;
188 return GEN8_LR_CONTEXT_OTHER_SIZE;
189 }
190}
191
Akash Goel3b3f1652016-10-13 22:44:48 +0530192static int
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100193intel_engine_setup(struct drm_i915_private *dev_priv,
194 enum intel_engine_id id)
195{
196 const struct engine_info *info = &intel_engines[id];
Oscar Mateob8400f02017-04-10 07:34:32 -0700197 const struct engine_class_info *class_info;
Akash Goel3b3f1652016-10-13 22:44:48 +0530198 struct intel_engine_cs *engine;
199
Oscar Mateob8400f02017-04-10 07:34:32 -0700200 GEM_BUG_ON(info->class >= ARRAY_SIZE(intel_engine_classes));
201 class_info = &intel_engine_classes[info->class];
202
Akash Goel3b3f1652016-10-13 22:44:48 +0530203 GEM_BUG_ON(dev_priv->engine[id]);
204 engine = kzalloc(sizeof(*engine), GFP_KERNEL);
205 if (!engine)
206 return -ENOMEM;
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100207
208 engine->id = id;
209 engine->i915 = dev_priv;
Oscar Mateo6e516142017-04-10 07:34:31 -0700210 WARN_ON(snprintf(engine->name, sizeof(engine->name), "%s%u",
Oscar Mateob8400f02017-04-10 07:34:32 -0700211 class_info->name, info->instance) >=
212 sizeof(engine->name));
Chris Wilson1d39f282017-04-11 13:43:06 +0100213 engine->uabi_id = info->uabi_id;
Tvrtko Ursulin5ec2cf72016-08-16 17:04:20 +0100214 engine->hw_id = engine->guc_id = info->hw_id;
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100215 engine->mmio_base = info->mmio_base;
216 engine->irq_shift = info->irq_shift;
Daniele Ceraolo Spurio09081802017-04-10 07:34:29 -0700217 engine->class = info->class;
218 engine->instance = info->instance;
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100219
Joonas Lahtinen63ffbcd2017-04-28 10:53:36 +0300220 engine->context_size = __intel_engine_context_size(dev_priv,
221 engine->class);
222 if (WARN_ON(engine->context_size > BIT(20)))
223 engine->context_size = 0;
224
Chris Wilson0de91362016-11-14 20:41:01 +0000225 /* Nothing to do here, execute in order of dependencies */
226 engine->schedule = NULL;
227
Changbin Du3fc03062017-03-13 10:47:11 +0800228 ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier);
229
Akash Goel3b3f1652016-10-13 22:44:48 +0530230 dev_priv->engine[id] = engine;
231 return 0;
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100232}
233
234/**
Joonas Lahtinen63ffbcd2017-04-28 10:53:36 +0300235 * intel_engines_init_mmio() - allocate and prepare the Engine Command Streamers
Tvrtko Ursulinbf9e8422016-12-01 14:16:38 +0000236 * @dev_priv: i915 device private
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100237 *
238 * Return: non-zero if the initialization failed.
239 */
Joonas Lahtinen63ffbcd2017-04-28 10:53:36 +0300240int intel_engines_init_mmio(struct drm_i915_private *dev_priv)
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100241{
Tvrtko Ursulinc1bb1142016-08-10 16:22:10 +0100242 struct intel_device_info *device_info = mkwrite_device_info(dev_priv);
Chris Wilson5f9be052017-04-11 17:56:58 +0100243 const unsigned int ring_mask = INTEL_INFO(dev_priv)->ring_mask;
Akash Goel3b3f1652016-10-13 22:44:48 +0530244 struct intel_engine_cs *engine;
245 enum intel_engine_id id;
Chris Wilson5f9be052017-04-11 17:56:58 +0100246 unsigned int mask = 0;
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100247 unsigned int i;
Chris Wilsonbb8f0f52017-01-24 11:01:34 +0000248 int err;
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100249
Tvrtko Ursulin70006ad2016-10-13 11:02:56 +0100250 WARN_ON(ring_mask == 0);
251 WARN_ON(ring_mask &
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100252 GENMASK(sizeof(mask) * BITS_PER_BYTE - 1, I915_NUM_ENGINES));
253
254 for (i = 0; i < ARRAY_SIZE(intel_engines); i++) {
255 if (!HAS_ENGINE(dev_priv, i))
256 continue;
257
Chris Wilsonbb8f0f52017-01-24 11:01:34 +0000258 err = intel_engine_setup(dev_priv, i);
259 if (err)
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100260 goto cleanup;
261
262 mask |= ENGINE_MASK(i);
263 }
264
265 /*
266 * Catch failures to update intel_engines table when the new engines
267 * are added to the driver by a warning and disabling the forgotten
268 * engines.
269 */
Tvrtko Ursulin70006ad2016-10-13 11:02:56 +0100270 if (WARN_ON(mask != ring_mask))
Tvrtko Ursulinc1bb1142016-08-10 16:22:10 +0100271 device_info->ring_mask = mask;
272
Chris Wilson5f9be052017-04-11 17:56:58 +0100273 /* We always presume we have at least RCS available for later probing */
274 if (WARN_ON(!HAS_ENGINE(dev_priv, RCS))) {
275 err = -ENODEV;
276 goto cleanup;
277 }
278
Tvrtko Ursulinc1bb1142016-08-10 16:22:10 +0100279 device_info->num_rings = hweight32(mask);
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100280
281 return 0;
282
283cleanup:
Chris Wilsonbb8f0f52017-01-24 11:01:34 +0000284 for_each_engine(engine, dev_priv, id)
285 kfree(engine);
286 return err;
287}
288
289/**
Joonas Lahtinen63ffbcd2017-04-28 10:53:36 +0300290 * intel_engines_init() - init the Engine Command Streamers
Chris Wilsonbb8f0f52017-01-24 11:01:34 +0000291 * @dev_priv: i915 device private
292 *
293 * Return: non-zero if the initialization failed.
294 */
295int intel_engines_init(struct drm_i915_private *dev_priv)
296{
Chris Wilsonbb8f0f52017-01-24 11:01:34 +0000297 struct intel_engine_cs *engine;
298 enum intel_engine_id id, err_id;
Tvrtko Ursulin33def1f2017-06-16 14:03:38 +0100299 int err;
Chris Wilsonbb8f0f52017-01-24 11:01:34 +0000300
Akash Goel3b3f1652016-10-13 22:44:48 +0530301 for_each_engine(engine, dev_priv, id) {
Oscar Mateob8400f02017-04-10 07:34:32 -0700302 const struct engine_class_info *class_info =
303 &intel_engine_classes[engine->class];
Chris Wilsonbb8f0f52017-01-24 11:01:34 +0000304 int (*init)(struct intel_engine_cs *engine);
305
Michal Wajdeczko4f044a82017-09-19 19:38:44 +0000306 if (i915_modparams.enable_execlists)
Oscar Mateob8400f02017-04-10 07:34:32 -0700307 init = class_info->init_execlists;
Chris Wilsonbb8f0f52017-01-24 11:01:34 +0000308 else
Oscar Mateob8400f02017-04-10 07:34:32 -0700309 init = class_info->init_legacy;
Tvrtko Ursulin33def1f2017-06-16 14:03:38 +0100310
311 err = -EINVAL;
312 err_id = id;
313
314 if (GEM_WARN_ON(!init))
315 goto cleanup;
Chris Wilsonbb8f0f52017-01-24 11:01:34 +0000316
317 err = init(engine);
Tvrtko Ursulin33def1f2017-06-16 14:03:38 +0100318 if (err)
Chris Wilsonbb8f0f52017-01-24 11:01:34 +0000319 goto cleanup;
Chris Wilsonbb8f0f52017-01-24 11:01:34 +0000320
Chris Wilsonff44ad52017-03-16 17:13:03 +0000321 GEM_BUG_ON(!engine->submit_request);
Chris Wilsonbb8f0f52017-01-24 11:01:34 +0000322 }
323
Chris Wilsonbb8f0f52017-01-24 11:01:34 +0000324 return 0;
325
326cleanup:
327 for_each_engine(engine, dev_priv, id) {
Tvrtko Ursulin33def1f2017-06-16 14:03:38 +0100328 if (id >= err_id) {
Chris Wilsonbb8f0f52017-01-24 11:01:34 +0000329 kfree(engine);
Tvrtko Ursulin33def1f2017-06-16 14:03:38 +0100330 dev_priv->engine[id] = NULL;
331 } else {
Tvrtko Ursulin8ee7c6e2017-02-16 12:23:22 +0000332 dev_priv->gt.cleanup_engine(engine);
Tvrtko Ursulin33def1f2017-06-16 14:03:38 +0100333 }
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100334 }
Chris Wilsonbb8f0f52017-01-24 11:01:34 +0000335 return err;
Tvrtko Ursulin88d2ba22016-07-13 16:03:40 +0100336}
337
Chris Wilson73cb9702016-10-28 13:58:46 +0100338void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno)
Chris Wilson57f275a2016-08-15 10:49:00 +0100339{
340 struct drm_i915_private *dev_priv = engine->i915;
341
342 /* Our semaphore implementation is strictly monotonic (i.e. we proceed
343 * so long as the semaphore value in the register/page is greater
344 * than the sync value), so whenever we reset the seqno,
345 * so long as we reset the tracking semaphore value to 0, it will
346 * always be before the next request's seqno. If we don't reset
347 * the semaphore value, then when the seqno moves backwards all
348 * future waits will complete instantly (causing rendering corruption).
349 */
350 if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) {
351 I915_WRITE(RING_SYNC_0(engine->mmio_base), 0);
352 I915_WRITE(RING_SYNC_1(engine->mmio_base), 0);
353 if (HAS_VEBOX(dev_priv))
354 I915_WRITE(RING_SYNC_2(engine->mmio_base), 0);
355 }
Chris Wilson51d545d2016-08-15 10:49:02 +0100356 if (dev_priv->semaphore) {
357 struct page *page = i915_vma_first_page(dev_priv->semaphore);
358 void *semaphores;
359
360 /* Semaphores are in noncoherent memory, flush to be safe */
Chris Wilson24caf652017-03-20 14:56:09 +0000361 semaphores = kmap_atomic(page);
Chris Wilson57f275a2016-08-15 10:49:00 +0100362 memset(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0),
363 0, I915_NUM_ENGINES * gen8_semaphore_seqno_size);
Chris Wilson51d545d2016-08-15 10:49:02 +0100364 drm_clflush_virt_range(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0),
365 I915_NUM_ENGINES * gen8_semaphore_seqno_size);
Chris Wilson24caf652017-03-20 14:56:09 +0000366 kunmap_atomic(semaphores);
Chris Wilson57f275a2016-08-15 10:49:00 +0100367 }
Chris Wilson57f275a2016-08-15 10:49:00 +0100368
369 intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);
Chris Wilson14a6bbf2017-03-14 11:14:52 +0000370 clear_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted);
Chris Wilson73cb9702016-10-28 13:58:46 +0100371
Chris Wilson57f275a2016-08-15 10:49:00 +0100372 /* After manually advancing the seqno, fake the interrupt in case
373 * there are any waiters for that seqno.
374 */
375 intel_engine_wakeup(engine);
Chris Wilson2ca9faa2017-04-05 16:30:54 +0100376
377 GEM_BUG_ON(intel_engine_get_seqno(engine) != seqno);
Chris Wilson57f275a2016-08-15 10:49:00 +0100378}
379
Chris Wilson73cb9702016-10-28 13:58:46 +0100380static void intel_engine_init_timeline(struct intel_engine_cs *engine)
Chris Wilsondcff85c2016-08-05 10:14:11 +0100381{
Chris Wilson73cb9702016-10-28 13:58:46 +0100382 engine->timeline = &engine->i915->gt.global_timeline.engine[engine->id];
Chris Wilsondcff85c2016-08-05 10:14:11 +0100383}
384
Tvrtko Ursulin019bf272016-07-13 16:03:41 +0100385/**
386 * intel_engines_setup_common - setup engine state not requiring hw access
387 * @engine: Engine to setup.
388 *
389 * Initializes @engine@ structure members shared between legacy and execlists
390 * submission modes which do not require hardware access.
391 *
392 * Typically done early in the submission mode specific engine setup stage.
393 */
394void intel_engine_setup_common(struct intel_engine_cs *engine)
395{
Chris Wilson20311bd2016-11-14 20:41:03 +0000396 engine->execlist_queue = RB_ROOT;
397 engine->execlist_first = NULL;
Tvrtko Ursulin019bf272016-07-13 16:03:41 +0100398
Chris Wilson73cb9702016-10-28 13:58:46 +0100399 intel_engine_init_timeline(engine);
Tvrtko Ursulin019bf272016-07-13 16:03:41 +0100400 intel_engine_init_hangcheck(engine);
Chris Wilson115003e92016-08-04 16:32:19 +0100401 i915_gem_batch_pool_init(engine, &engine->batch_pool);
Chris Wilson7756e452016-08-18 17:17:10 +0100402
403 intel_engine_init_cmd_parser(engine);
Tvrtko Ursulin019bf272016-07-13 16:03:41 +0100404}
405
Chris Wilsonadc320c2016-08-15 10:48:59 +0100406int intel_engine_create_scratch(struct intel_engine_cs *engine, int size)
407{
408 struct drm_i915_gem_object *obj;
409 struct i915_vma *vma;
410 int ret;
411
412 WARN_ON(engine->scratch);
413
Tvrtko Ursulin187685c2016-12-01 14:16:36 +0000414 obj = i915_gem_object_create_stolen(engine->i915, size);
Chris Wilsonadc320c2016-08-15 10:48:59 +0100415 if (!obj)
Chris Wilson920cf412016-10-28 13:58:30 +0100416 obj = i915_gem_object_create_internal(engine->i915, size);
Chris Wilsonadc320c2016-08-15 10:48:59 +0100417 if (IS_ERR(obj)) {
418 DRM_ERROR("Failed to allocate scratch page\n");
419 return PTR_ERR(obj);
420 }
421
Chris Wilsona01cb372017-01-16 15:21:30 +0000422 vma = i915_vma_instance(obj, &engine->i915->ggtt.base, NULL);
Chris Wilsonadc320c2016-08-15 10:48:59 +0100423 if (IS_ERR(vma)) {
424 ret = PTR_ERR(vma);
425 goto err_unref;
426 }
427
428 ret = i915_vma_pin(vma, 0, 4096, PIN_GLOBAL | PIN_HIGH);
429 if (ret)
430 goto err_unref;
431
432 engine->scratch = vma;
Chris Wilsonbde13eb2016-08-15 10:49:07 +0100433 DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n",
434 engine->name, i915_ggtt_offset(vma));
Chris Wilsonadc320c2016-08-15 10:48:59 +0100435 return 0;
436
437err_unref:
438 i915_gem_object_put(obj);
439 return ret;
440}
441
442static void intel_engine_cleanup_scratch(struct intel_engine_cs *engine)
443{
Chris Wilson19880c42016-08-15 10:49:05 +0100444 i915_vma_unpin_and_release(&engine->scratch);
Chris Wilsonadc320c2016-08-15 10:48:59 +0100445}
446
Daniele Ceraolo Spurio486e93f2017-09-13 09:56:02 +0100447static void cleanup_phys_status_page(struct intel_engine_cs *engine)
448{
449 struct drm_i915_private *dev_priv = engine->i915;
450
451 if (!dev_priv->status_page_dmah)
452 return;
453
454 drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah);
455 engine->status_page.page_addr = NULL;
456}
457
458static void cleanup_status_page(struct intel_engine_cs *engine)
459{
460 struct i915_vma *vma;
461 struct drm_i915_gem_object *obj;
462
463 vma = fetch_and_zero(&engine->status_page.vma);
464 if (!vma)
465 return;
466
467 obj = vma->obj;
468
469 i915_vma_unpin(vma);
470 i915_vma_close(vma);
471
472 i915_gem_object_unpin_map(obj);
473 __i915_gem_object_release_unless_active(obj);
474}
475
476static int init_status_page(struct intel_engine_cs *engine)
477{
478 struct drm_i915_gem_object *obj;
479 struct i915_vma *vma;
480 unsigned int flags;
481 void *vaddr;
482 int ret;
483
484 obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE);
485 if (IS_ERR(obj)) {
486 DRM_ERROR("Failed to allocate status page\n");
487 return PTR_ERR(obj);
488 }
489
490 ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
491 if (ret)
492 goto err;
493
494 vma = i915_vma_instance(obj, &engine->i915->ggtt.base, NULL);
495 if (IS_ERR(vma)) {
496 ret = PTR_ERR(vma);
497 goto err;
498 }
499
500 flags = PIN_GLOBAL;
501 if (!HAS_LLC(engine->i915))
502 /* On g33, we cannot place HWS above 256MiB, so
503 * restrict its pinning to the low mappable arena.
504 * Though this restriction is not documented for
505 * gen4, gen5, or byt, they also behave similarly
506 * and hang if the HWS is placed at the top of the
507 * GTT. To generalise, it appears that all !llc
508 * platforms have issues with us placing the HWS
509 * above the mappable region (even though we never
510 * actually map it).
511 */
512 flags |= PIN_MAPPABLE;
Chris Wilson34a04e52017-09-13 09:56:03 +0100513 else
514 flags |= PIN_HIGH;
Daniele Ceraolo Spurio486e93f2017-09-13 09:56:02 +0100515 ret = i915_vma_pin(vma, 0, 4096, flags);
516 if (ret)
517 goto err;
518
519 vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB);
520 if (IS_ERR(vaddr)) {
521 ret = PTR_ERR(vaddr);
522 goto err_unpin;
523 }
524
525 engine->status_page.vma = vma;
526 engine->status_page.ggtt_offset = i915_ggtt_offset(vma);
527 engine->status_page.page_addr = memset(vaddr, 0, PAGE_SIZE);
528
529 DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
530 engine->name, i915_ggtt_offset(vma));
531 return 0;
532
533err_unpin:
534 i915_vma_unpin(vma);
535err:
536 i915_gem_object_put(obj);
537 return ret;
538}
539
540static int init_phys_status_page(struct intel_engine_cs *engine)
541{
542 struct drm_i915_private *dev_priv = engine->i915;
543
544 GEM_BUG_ON(engine->id != RCS);
545
546 dev_priv->status_page_dmah =
547 drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE);
548 if (!dev_priv->status_page_dmah)
549 return -ENOMEM;
550
551 engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
552 memset(engine->status_page.page_addr, 0, PAGE_SIZE);
553
554 return 0;
555}
556
Tvrtko Ursulin019bf272016-07-13 16:03:41 +0100557/**
558 * intel_engines_init_common - initialize cengine state which might require hw access
559 * @engine: Engine to initialize.
560 *
561 * Initializes @engine@ structure members shared between legacy and execlists
562 * submission modes which do require hardware access.
563 *
564 * Typcally done at later stages of submission mode specific engine setup.
565 *
566 * Returns zero on success or an error code on failure.
567 */
568int intel_engine_init_common(struct intel_engine_cs *engine)
569{
Chris Wilson266a2402017-05-04 10:33:08 +0100570 struct intel_ring *ring;
Tvrtko Ursulin019bf272016-07-13 16:03:41 +0100571 int ret;
572
Chris Wilsonff44ad52017-03-16 17:13:03 +0000573 engine->set_default_submission(engine);
574
Chris Wilsone8a9c582016-12-18 15:37:20 +0000575 /* We may need to do things with the shrinker which
576 * require us to immediately switch back to the default
577 * context. This can cause a problem as pinning the
578 * default context also requires GTT space which may not
579 * be available. To avoid this we always pin the default
580 * context.
581 */
Chris Wilson266a2402017-05-04 10:33:08 +0100582 ring = engine->context_pin(engine, engine->i915->kernel_context);
583 if (IS_ERR(ring))
584 return PTR_ERR(ring);
Tvrtko Ursulin019bf272016-07-13 16:03:41 +0100585
Chris Wilsone8a9c582016-12-18 15:37:20 +0000586 ret = intel_engine_init_breadcrumbs(engine);
587 if (ret)
588 goto err_unpin;
589
Chris Wilson4e50f082016-10-28 13:58:31 +0100590 ret = i915_gem_render_state_init(engine);
591 if (ret)
Daniele Ceraolo Spurio486e93f2017-09-13 09:56:02 +0100592 goto err_breadcrumbs;
593
594 if (HWS_NEEDS_PHYSICAL(engine->i915))
595 ret = init_phys_status_page(engine);
596 else
597 ret = init_status_page(engine);
598 if (ret)
599 goto err_rs_fini;
Chris Wilson4e50f082016-10-28 13:58:31 +0100600
Chris Wilson7756e452016-08-18 17:17:10 +0100601 return 0;
Chris Wilsone8a9c582016-12-18 15:37:20 +0000602
Daniele Ceraolo Spurio486e93f2017-09-13 09:56:02 +0100603err_rs_fini:
604 i915_gem_render_state_fini(engine);
605err_breadcrumbs:
606 intel_engine_fini_breadcrumbs(engine);
Chris Wilsone8a9c582016-12-18 15:37:20 +0000607err_unpin:
608 engine->context_unpin(engine, engine->i915->kernel_context);
609 return ret;
Tvrtko Ursulin019bf272016-07-13 16:03:41 +0100610}
Chris Wilson96a945a2016-08-03 13:19:16 +0100611
612/**
613 * intel_engines_cleanup_common - cleans up the engine state created by
614 * the common initiailizers.
615 * @engine: Engine to cleanup.
616 *
617 * This cleans up everything created by the common helpers.
618 */
619void intel_engine_cleanup_common(struct intel_engine_cs *engine)
620{
Chris Wilsonadc320c2016-08-15 10:48:59 +0100621 intel_engine_cleanup_scratch(engine);
622
Daniele Ceraolo Spurio486e93f2017-09-13 09:56:02 +0100623 if (HWS_NEEDS_PHYSICAL(engine->i915))
624 cleanup_phys_status_page(engine);
625 else
626 cleanup_status_page(engine);
627
Chris Wilson4e50f082016-10-28 13:58:31 +0100628 i915_gem_render_state_fini(engine);
Chris Wilson96a945a2016-08-03 13:19:16 +0100629 intel_engine_fini_breadcrumbs(engine);
Chris Wilson7756e452016-08-18 17:17:10 +0100630 intel_engine_cleanup_cmd_parser(engine);
Chris Wilson96a945a2016-08-03 13:19:16 +0100631 i915_gem_batch_pool_fini(&engine->batch_pool);
Chris Wilsone8a9c582016-12-18 15:37:20 +0000632
633 engine->context_unpin(engine, engine->i915->kernel_context);
Chris Wilson96a945a2016-08-03 13:19:16 +0100634}
Chris Wilson1b365952016-10-04 21:11:31 +0100635
636u64 intel_engine_get_active_head(struct intel_engine_cs *engine)
637{
638 struct drm_i915_private *dev_priv = engine->i915;
639 u64 acthd;
640
641 if (INTEL_GEN(dev_priv) >= 8)
642 acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base),
643 RING_ACTHD_UDW(engine->mmio_base));
644 else if (INTEL_GEN(dev_priv) >= 4)
645 acthd = I915_READ(RING_ACTHD(engine->mmio_base));
646 else
647 acthd = I915_READ(ACTHD);
648
649 return acthd;
650}
651
652u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine)
653{
654 struct drm_i915_private *dev_priv = engine->i915;
655 u64 bbaddr;
656
657 if (INTEL_GEN(dev_priv) >= 8)
658 bbaddr = I915_READ64_2x32(RING_BBADDR(engine->mmio_base),
659 RING_BBADDR_UDW(engine->mmio_base));
660 else
661 bbaddr = I915_READ(RING_BBADDR(engine->mmio_base));
662
663 return bbaddr;
664}
Chris Wilson0e704472016-10-12 10:05:17 +0100665
666const char *i915_cache_level_str(struct drm_i915_private *i915, int type)
667{
668 switch (type) {
669 case I915_CACHE_NONE: return " uncached";
670 case I915_CACHE_LLC: return HAS_LLC(i915) ? " LLC" : " snooped";
671 case I915_CACHE_L3_LLC: return " L3+LLC";
672 case I915_CACHE_WT: return " WT";
673 default: return "";
674 }
675}
676
677static inline uint32_t
678read_subslice_reg(struct drm_i915_private *dev_priv, int slice,
679 int subslice, i915_reg_t reg)
680{
681 uint32_t mcr;
682 uint32_t ret;
683 enum forcewake_domains fw_domains;
684
685 fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg,
686 FW_REG_READ);
687 fw_domains |= intel_uncore_forcewake_for_reg(dev_priv,
688 GEN8_MCR_SELECTOR,
689 FW_REG_READ | FW_REG_WRITE);
690
691 spin_lock_irq(&dev_priv->uncore.lock);
692 intel_uncore_forcewake_get__locked(dev_priv, fw_domains);
693
694 mcr = I915_READ_FW(GEN8_MCR_SELECTOR);
695 /*
696 * The HW expects the slice and sublice selectors to be reset to 0
697 * after reading out the registers.
698 */
699 WARN_ON_ONCE(mcr & (GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK));
700 mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK);
701 mcr |= GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice);
702 I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr);
703
704 ret = I915_READ_FW(reg);
705
706 mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK);
707 I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr);
708
709 intel_uncore_forcewake_put__locked(dev_priv, fw_domains);
710 spin_unlock_irq(&dev_priv->uncore.lock);
711
712 return ret;
713}
714
715/* NB: please notice the memset */
716void intel_engine_get_instdone(struct intel_engine_cs *engine,
717 struct intel_instdone *instdone)
718{
719 struct drm_i915_private *dev_priv = engine->i915;
720 u32 mmio_base = engine->mmio_base;
721 int slice;
722 int subslice;
723
724 memset(instdone, 0, sizeof(*instdone));
725
726 switch (INTEL_GEN(dev_priv)) {
727 default:
728 instdone->instdone = I915_READ(RING_INSTDONE(mmio_base));
729
730 if (engine->id != RCS)
731 break;
732
733 instdone->slice_common = I915_READ(GEN7_SC_INSTDONE);
734 for_each_instdone_slice_subslice(dev_priv, slice, subslice) {
735 instdone->sampler[slice][subslice] =
736 read_subslice_reg(dev_priv, slice, subslice,
737 GEN7_SAMPLER_INSTDONE);
738 instdone->row[slice][subslice] =
739 read_subslice_reg(dev_priv, slice, subslice,
740 GEN7_ROW_INSTDONE);
741 }
742 break;
743 case 7:
744 instdone->instdone = I915_READ(RING_INSTDONE(mmio_base));
745
746 if (engine->id != RCS)
747 break;
748
749 instdone->slice_common = I915_READ(GEN7_SC_INSTDONE);
750 instdone->sampler[0][0] = I915_READ(GEN7_SAMPLER_INSTDONE);
751 instdone->row[0][0] = I915_READ(GEN7_ROW_INSTDONE);
752
753 break;
754 case 6:
755 case 5:
756 case 4:
757 instdone->instdone = I915_READ(RING_INSTDONE(mmio_base));
758
759 if (engine->id == RCS)
760 /* HACK: Using the wrong struct member */
761 instdone->slice_common = I915_READ(GEN4_INSTDONE1);
762 break;
763 case 3:
764 case 2:
765 instdone->instdone = I915_READ(GEN2_INSTDONE);
766 break;
767 }
768}
Chris Wilsonf97fbf92017-02-13 17:15:14 +0000769
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +0000770static int wa_add(struct drm_i915_private *dev_priv,
771 i915_reg_t addr,
772 const u32 mask, const u32 val)
773{
774 const u32 idx = dev_priv->workarounds.count;
775
776 if (WARN_ON(idx >= I915_MAX_WA_REGS))
777 return -ENOSPC;
778
779 dev_priv->workarounds.reg[idx].addr = addr;
780 dev_priv->workarounds.reg[idx].value = val;
781 dev_priv->workarounds.reg[idx].mask = mask;
782
783 dev_priv->workarounds.count++;
784
785 return 0;
786}
787
788#define WA_REG(addr, mask, val) do { \
789 const int r = wa_add(dev_priv, (addr), (mask), (val)); \
790 if (r) \
791 return r; \
792 } while (0)
793
794#define WA_SET_BIT_MASKED(addr, mask) \
795 WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask))
796
797#define WA_CLR_BIT_MASKED(addr, mask) \
798 WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask))
799
800#define WA_SET_FIELD_MASKED(addr, mask, value) \
801 WA_REG(addr, mask, _MASKED_FIELD(mask, value))
802
803#define WA_SET_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) | (mask))
804#define WA_CLR_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) & ~(mask))
805
806#define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val)
807
808static int wa_ring_whitelist_reg(struct intel_engine_cs *engine,
809 i915_reg_t reg)
810{
811 struct drm_i915_private *dev_priv = engine->i915;
812 struct i915_workarounds *wa = &dev_priv->workarounds;
813 const uint32_t index = wa->hw_whitelist_count[engine->id];
814
815 if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS))
816 return -EINVAL;
817
818 WA_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index),
819 i915_mmio_reg_offset(reg));
820 wa->hw_whitelist_count[engine->id]++;
821
822 return 0;
823}
824
825static int gen8_init_workarounds(struct intel_engine_cs *engine)
826{
827 struct drm_i915_private *dev_priv = engine->i915;
828
829 WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING);
830
831 /* WaDisableAsyncFlipPerfMode:bdw,chv */
832 WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE);
833
834 /* WaDisablePartialInstShootdown:bdw,chv */
835 WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
836 PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
837
838 /* Use Force Non-Coherent whenever executing a 3D context. This is a
839 * workaround for for a possible hang in the unlikely event a TLB
840 * invalidation occurs during a PSD flush.
841 */
842 /* WaForceEnableNonCoherent:bdw,chv */
843 /* WaHdcDisableFetchWhenMasked:bdw,chv */
844 WA_SET_BIT_MASKED(HDC_CHICKEN0,
845 HDC_DONOT_FETCH_MEM_WHEN_MASKED |
846 HDC_FORCE_NON_COHERENT);
847
848 /* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0:
849 * "The Hierarchical Z RAW Stall Optimization allows non-overlapping
850 * polygons in the same 8x4 pixel/sample area to be processed without
851 * stalling waiting for the earlier ones to write to Hierarchical Z
852 * buffer."
853 *
854 * This optimization is off by default for BDW and CHV; turn it on.
855 */
856 WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE);
857
858 /* Wa4x4STCOptimizationDisable:bdw,chv */
859 WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE);
860
861 /*
862 * BSpec recommends 8x4 when MSAA is used,
863 * however in practice 16x4 seems fastest.
864 *
865 * Note that PS/WM thread counts depend on the WIZ hashing
866 * disable bit, which we don't touch here, but it's good
867 * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
868 */
869 WA_SET_FIELD_MASKED(GEN7_GT_MODE,
870 GEN6_WIZ_HASHING_MASK,
871 GEN6_WIZ_HASHING_16x4);
872
873 return 0;
874}
875
876static int bdw_init_workarounds(struct intel_engine_cs *engine)
877{
878 struct drm_i915_private *dev_priv = engine->i915;
879 int ret;
880
881 ret = gen8_init_workarounds(engine);
882 if (ret)
883 return ret;
884
885 /* WaDisableThreadStallDopClockGating:bdw (pre-production) */
886 WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
887
888 /* WaDisableDopClockGating:bdw
889 *
890 * Also see the related UCGTCL1 write in broadwell_init_clock_gating()
891 * to disable EUTC clock gating.
892 */
893 WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2,
894 DOP_CLOCK_GATING_DISABLE);
895
896 WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
897 GEN8_SAMPLER_POWER_BYPASS_DIS);
898
899 WA_SET_BIT_MASKED(HDC_CHICKEN0,
900 /* WaForceContextSaveRestoreNonCoherent:bdw */
901 HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
902 /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */
903 (IS_BDW_GT3(dev_priv) ? HDC_FENCE_DEST_SLM_DISABLE : 0));
904
905 return 0;
906}
907
908static int chv_init_workarounds(struct intel_engine_cs *engine)
909{
910 struct drm_i915_private *dev_priv = engine->i915;
911 int ret;
912
913 ret = gen8_init_workarounds(engine);
914 if (ret)
915 return ret;
916
917 /* WaDisableThreadStallDopClockGating:chv */
918 WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
919
920 /* Improve HiZ throughput on CHV. */
921 WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X);
922
923 return 0;
924}
925
926static int gen9_init_workarounds(struct intel_engine_cs *engine)
927{
928 struct drm_i915_private *dev_priv = engine->i915;
929 int ret;
930
Rodrigo Vivi46c26662017-06-16 15:49:58 -0700931 /* WaConextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl,glk,cfl */
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +0000932 I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE));
933
Rodrigo Vivi46c26662017-06-16 15:49:58 -0700934 /* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl,glk,cfl */
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +0000935 I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) |
936 GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE);
937
Rodrigo Vivi98eed3d2017-06-19 14:21:47 -0700938 /* WaDisableKillLogic:bxt,skl,kbl */
939 if (!IS_COFFEELAKE(dev_priv))
940 I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
941 ECOCHK_DIS_TLB);
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +0000942
Ville Syrjälä93564042017-08-24 22:10:51 +0300943 if (HAS_LLC(dev_priv)) {
944 /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl,kbl
945 *
946 * Must match Display Engine. See
947 * WaCompressedResourceDisplayNewHashMode.
948 */
949 WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
950 GEN9_PBE_COMPRESSED_HASH_SELECTION);
951 WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7,
952 GEN9_SAMPLER_HASH_COMPRESSED_READ_ADDR);
953 WA_SET_BIT(MMCD_MISC_CTRL, MMCD_PCLA | MMCD_HOTSPOT_EN);
954 }
955
Rodrigo Vivi46c26662017-06-16 15:49:58 -0700956 /* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl,glk,cfl */
957 /* WaDisablePartialInstShootdown:skl,bxt,kbl,glk,cfl */
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +0000958 WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
959 FLOW_CONTROL_ENABLE |
960 PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
961
962 /* Syncing dependencies between camera and graphics:skl,bxt,kbl */
Rodrigo Vivi46c26662017-06-16 15:49:58 -0700963 if (!IS_COFFEELAKE(dev_priv))
964 WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
965 GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC);
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +0000966
967 /* WaDisableDgMirrorFixInHalfSliceChicken5:bxt */
968 if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
969 WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
970 GEN9_DG_MIRROR_FIX_ENABLE);
971
972 /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:bxt */
973 if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
974 WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1,
975 GEN9_RHWO_OPTIMIZATION_DISABLE);
976 /*
977 * WA also requires GEN9_SLICE_COMMON_ECO_CHICKEN0[14:14] to be set
978 * but we do that in per ctx batchbuffer as there is an issue
979 * with this register not getting restored on ctx restore
980 */
981 }
982
Rodrigo Vivi46c26662017-06-16 15:49:58 -0700983 /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl,glk,cfl */
984 /* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl,cfl */
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +0000985 WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7,
Arkadiusz Hiler0b71cea2017-05-12 13:20:15 +0200986 GEN9_ENABLE_YV12_BUGFIX |
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +0000987 GEN9_ENABLE_GPGPU_PREEMPTION);
988
Rodrigo Vivi46c26662017-06-16 15:49:58 -0700989 /* Wa4x4STCOptimizationDisable:skl,bxt,kbl,glk,cfl */
990 /* WaDisablePartialResolveInVc:skl,bxt,kbl,cfl */
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +0000991 WA_SET_BIT_MASKED(CACHE_MODE_1, (GEN8_4x4_STC_OPTIMIZATION_DISABLE |
992 GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE));
993
Rodrigo Vivi46c26662017-06-16 15:49:58 -0700994 /* WaCcsTlbPrefetchDisable:skl,bxt,kbl,glk,cfl */
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +0000995 WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
996 GEN9_CCS_TLB_PREFETCH_ENABLE);
997
998 /* WaDisableMaskBasedCammingInRCC:bxt */
999 if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
1000 WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0,
1001 PIXEL_MASK_CAMMING_DISABLE);
1002
Rodrigo Vivi46c26662017-06-16 15:49:58 -07001003 /* WaForceContextSaveRestoreNonCoherent:skl,bxt,kbl,cfl */
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001004 WA_SET_BIT_MASKED(HDC_CHICKEN0,
1005 HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
1006 HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE);
1007
1008 /* WaForceEnableNonCoherent and WaDisableHDCInvalidation are
1009 * both tied to WaForceContextSaveRestoreNonCoherent
1010 * in some hsds for skl. We keep the tie for all gen9. The
1011 * documentation is a bit hazy and so we want to get common behaviour,
1012 * even though there is no clear evidence we would need both on kbl/bxt.
1013 * This area has been source of system hangs so we play it safe
1014 * and mimic the skl regardless of what bspec says.
1015 *
1016 * Use Force Non-Coherent whenever executing a 3D context. This
1017 * is a workaround for a possible hang in the unlikely event
1018 * a TLB invalidation occurs during a PSD flush.
1019 */
1020
Rodrigo Vivi46c26662017-06-16 15:49:58 -07001021 /* WaForceEnableNonCoherent:skl,bxt,kbl,cfl */
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001022 WA_SET_BIT_MASKED(HDC_CHICKEN0,
1023 HDC_FORCE_NON_COHERENT);
1024
Rodrigo Vivi98eed3d2017-06-19 14:21:47 -07001025 /* WaDisableHDCInvalidation:skl,bxt,kbl,cfl */
1026 I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
1027 BDW_DISABLE_HDC_INVALIDATION);
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001028
Rodrigo Vivi46c26662017-06-16 15:49:58 -07001029 /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl,cfl */
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001030 if (IS_SKYLAKE(dev_priv) ||
1031 IS_KABYLAKE(dev_priv) ||
Rodrigo Vivi46c26662017-06-16 15:49:58 -07001032 IS_COFFEELAKE(dev_priv) ||
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001033 IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0))
1034 WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
1035 GEN8_SAMPLER_POWER_BYPASS_DIS);
1036
Rodrigo Vivi46c26662017-06-16 15:49:58 -07001037 /* WaDisableSTUnitPowerOptimization:skl,bxt,kbl,glk,cfl */
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001038 WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE);
1039
Rodrigo Vivi46c26662017-06-16 15:49:58 -07001040 /* WaOCLCoherentLineFlush:skl,bxt,kbl,cfl */
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001041 I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) |
1042 GEN8_LQSC_FLUSH_COHERENT_LINES));
1043
Rodrigo Vivi46c26662017-06-16 15:49:58 -07001044 /* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt,glk,cfl */
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001045 ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG);
1046 if (ret)
1047 return ret;
1048
Rodrigo Vivi46c26662017-06-16 15:49:58 -07001049 /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl,cfl */
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001050 ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1);
1051 if (ret)
1052 return ret;
1053
Rodrigo Vivi46c26662017-06-16 15:49:58 -07001054 /* WaAllowUMDToModifyHDCChicken1:skl,bxt,kbl,glk,cfl */
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001055 ret = wa_ring_whitelist_reg(engine, GEN8_HDC_CHICKEN1);
1056 if (ret)
1057 return ret;
1058
1059 return 0;
1060}
1061
1062static int skl_tune_iz_hashing(struct intel_engine_cs *engine)
1063{
1064 struct drm_i915_private *dev_priv = engine->i915;
1065 u8 vals[3] = { 0, 0, 0 };
1066 unsigned int i;
1067
1068 for (i = 0; i < 3; i++) {
1069 u8 ss;
1070
1071 /*
1072 * Only consider slices where one, and only one, subslice has 7
1073 * EUs
1074 */
1075 if (!is_power_of_2(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i]))
1076 continue;
1077
1078 /*
1079 * subslice_7eu[i] != 0 (because of the check above) and
1080 * ss_max == 4 (maximum number of subslices possible per slice)
1081 *
1082 * -> 0 <= ss <= 3;
1083 */
1084 ss = ffs(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i]) - 1;
1085 vals[i] = 3 - ss;
1086 }
1087
1088 if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0)
1089 return 0;
1090
1091 /* Tune IZ hashing. See intel_device_info_runtime_init() */
1092 WA_SET_FIELD_MASKED(GEN7_GT_MODE,
1093 GEN9_IZ_HASHING_MASK(2) |
1094 GEN9_IZ_HASHING_MASK(1) |
1095 GEN9_IZ_HASHING_MASK(0),
1096 GEN9_IZ_HASHING(2, vals[2]) |
1097 GEN9_IZ_HASHING(1, vals[1]) |
1098 GEN9_IZ_HASHING(0, vals[0]));
1099
1100 return 0;
1101}
1102
1103static int skl_init_workarounds(struct intel_engine_cs *engine)
1104{
1105 struct drm_i915_private *dev_priv = engine->i915;
1106 int ret;
1107
1108 ret = gen9_init_workarounds(engine);
1109 if (ret)
1110 return ret;
1111
1112 /*
1113 * Actual WA is to disable percontext preemption granularity control
1114 * until D0 which is the default case so this is equivalent to
1115 * !WaDisablePerCtxtPreemptionGranularityControl:skl
1116 */
1117 I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1,
1118 _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL));
1119
1120 /* WaEnableGapsTsvCreditFix:skl */
1121 I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
1122 GEN9_GAPS_TSV_CREDIT_DISABLE));
1123
1124 /* WaDisableGafsUnitClkGating:skl */
Oscar Mateo4827c542017-09-07 08:40:07 -07001125 I915_WRITE(GEN7_UCGCTL4, (I915_READ(GEN7_UCGCTL4) |
1126 GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE));
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001127
1128 /* WaInPlaceDecompressionHang:skl */
1129 if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER))
Oscar Mateoefc886c2017-09-07 08:40:04 -07001130 I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA,
1131 (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) |
1132 GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS));
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001133
1134 /* WaDisableLSQCROPERFforOCL:skl */
1135 ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
1136 if (ret)
1137 return ret;
1138
1139 return skl_tune_iz_hashing(engine);
1140}
1141
1142static int bxt_init_workarounds(struct intel_engine_cs *engine)
1143{
1144 struct drm_i915_private *dev_priv = engine->i915;
1145 int ret;
1146
1147 ret = gen9_init_workarounds(engine);
1148 if (ret)
1149 return ret;
1150
1151 /* WaStoreMultiplePTEenable:bxt */
1152 /* This is a requirement according to Hardware specification */
1153 if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
1154 I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF);
1155
1156 /* WaSetClckGatingDisableMedia:bxt */
1157 if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
1158 I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) &
1159 ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE));
1160 }
1161
1162 /* WaDisableThreadStallDopClockGating:bxt */
1163 WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
1164 STALL_DOP_GATING_DISABLE);
1165
1166 /* WaDisablePooledEuLoadBalancingFix:bxt */
1167 if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) {
Oscar Mateo212154b2017-09-07 08:40:09 -07001168 I915_WRITE(FF_SLICE_CS_CHICKEN2,
1169 _MASKED_BIT_ENABLE(GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE));
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001170 }
1171
1172 /* WaDisableSbeCacheDispatchPortSharing:bxt */
1173 if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) {
1174 WA_SET_BIT_MASKED(
1175 GEN7_HALF_SLICE_CHICKEN1,
1176 GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
1177 }
1178
1179 /* WaDisableObjectLevelPreemptionForTrifanOrPolygon:bxt */
1180 /* WaDisableObjectLevelPreemptionForInstancedDraw:bxt */
1181 /* WaDisableObjectLevelPreemtionForInstanceId:bxt */
1182 /* WaDisableLSQCROPERFforOCL:bxt */
1183 if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
1184 ret = wa_ring_whitelist_reg(engine, GEN9_CS_DEBUG_MODE1);
1185 if (ret)
1186 return ret;
1187
1188 ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
1189 if (ret)
1190 return ret;
1191 }
1192
1193 /* WaProgramL3SqcReg1DefaultForPerf:bxt */
1194 if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER))
1195 I915_WRITE(GEN8_L3SQCREG1, L3_GENERAL_PRIO_CREDITS(62) |
1196 L3_HIGH_PRIO_CREDITS(2));
1197
1198 /* WaToEnableHwFixForPushConstHWBug:bxt */
1199 if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER))
1200 WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
1201 GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
1202
1203 /* WaInPlaceDecompressionHang:bxt */
1204 if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER))
Oscar Mateoefc886c2017-09-07 08:40:04 -07001205 I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA,
1206 (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) |
1207 GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS));
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001208
1209 return 0;
1210}
1211
Rodrigo Vivi90007bc2017-08-15 16:16:48 -07001212static int cnl_init_workarounds(struct intel_engine_cs *engine)
1213{
1214 struct drm_i915_private *dev_priv = engine->i915;
1215 int ret;
1216
Oscar Mateo6cf20a02017-09-07 08:40:05 -07001217 /* WaDisableI2mCycleOnWRPort:cnl (pre-prod) */
Rodrigo Vivi86ebb012017-08-29 16:07:51 -07001218 if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0))
Oscar Mateo6cf20a02017-09-07 08:40:05 -07001219 I915_WRITE(GAMT_CHKN_BIT_REG,
1220 (I915_READ(GAMT_CHKN_BIT_REG) |
1221 GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT));
Rodrigo Vivi86ebb012017-08-29 16:07:51 -07001222
Rodrigo Viviacfb5552017-08-23 13:35:04 -07001223 /* WaForceContextSaveRestoreNonCoherent:cnl */
1224 WA_SET_BIT_MASKED(CNL_HDC_CHICKEN0,
1225 HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT);
1226
Rodrigo Viviaa9f4c42017-09-06 15:03:25 -07001227 /* WaThrottleEUPerfToAvoidTDBackPressure:cnl(pre-prod) */
1228 if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0))
1229 WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, THROTTLE_12_5);
1230
Rodrigo Vivie6d1a4f2017-08-15 16:16:49 -07001231 /* WaDisableReplayBufferBankArbitrationOptimization:cnl */
1232 WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
1233 GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
1234
Rodrigo Vivid1d24752017-08-15 16:16:50 -07001235 /* WaDisableEnhancedSBEVertexCaching:cnl (pre-prod) */
1236 if (IS_CNL_REVID(dev_priv, 0, CNL_REVID_B0))
1237 WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
1238 GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE);
1239
Rodrigo Vivi90007bc2017-08-15 16:16:48 -07001240 /* WaInPlaceDecompressionHang:cnl */
Oscar Mateoefc886c2017-09-07 08:40:04 -07001241 I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA,
1242 (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) |
1243 GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS));
Rodrigo Vivi90007bc2017-08-15 16:16:48 -07001244
Oscar Mateo2cbecff2017-08-23 12:56:31 -07001245 /* WaPushConstantDereferenceHoldDisable:cnl */
Oscar Mateob27f5902017-09-07 08:40:06 -07001246 WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, PUSH_CONSTANT_DEREF_DISABLE);
Oscar Mateo2cbecff2017-08-23 12:56:31 -07001247
Rodrigo Vivi392572f2017-08-29 16:07:23 -07001248 /* FtrEnableFastAnisoL1BankingFix: cnl */
1249 WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, CNL_FAST_ANISO_L1_BANKING_FIX);
1250
Rodrigo Vivi90007bc2017-08-15 16:16:48 -07001251 /* WaEnablePreemptionGranularityControlByUMD:cnl */
1252 ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1);
1253 if (ret)
1254 return ret;
1255
1256 return 0;
1257}
1258
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001259static int kbl_init_workarounds(struct intel_engine_cs *engine)
1260{
1261 struct drm_i915_private *dev_priv = engine->i915;
1262 int ret;
1263
1264 ret = gen9_init_workarounds(engine);
1265 if (ret)
1266 return ret;
1267
1268 /* WaEnableGapsTsvCreditFix:kbl */
1269 I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
1270 GEN9_GAPS_TSV_CREDIT_DISABLE));
1271
1272 /* WaDisableDynamicCreditSharing:kbl */
1273 if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0))
Oscar Mateoc6ea497c2017-09-07 08:40:08 -07001274 I915_WRITE(GAMT_CHKN_BIT_REG,
1275 (I915_READ(GAMT_CHKN_BIT_REG) |
1276 GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING));
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001277
1278 /* WaDisableFenceDestinationToSLM:kbl (pre-prod) */
1279 if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_A0))
1280 WA_SET_BIT_MASKED(HDC_CHICKEN0,
1281 HDC_FENCE_DEST_SLM_DISABLE);
1282
1283 /* WaToEnableHwFixForPushConstHWBug:kbl */
1284 if (IS_KBL_REVID(dev_priv, KBL_REVID_C0, REVID_FOREVER))
1285 WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
1286 GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
1287
1288 /* WaDisableGafsUnitClkGating:kbl */
Oscar Mateo4827c542017-09-07 08:40:07 -07001289 I915_WRITE(GEN7_UCGCTL4, (I915_READ(GEN7_UCGCTL4) |
1290 GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE));
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001291
1292 /* WaDisableSbeCacheDispatchPortSharing:kbl */
1293 WA_SET_BIT_MASKED(
1294 GEN7_HALF_SLICE_CHICKEN1,
1295 GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
1296
1297 /* WaInPlaceDecompressionHang:kbl */
Oscar Mateoefc886c2017-09-07 08:40:04 -07001298 I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA,
1299 (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) |
1300 GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS));
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001301
1302 /* WaDisableLSQCROPERFforOCL:kbl */
1303 ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
1304 if (ret)
1305 return ret;
1306
1307 return 0;
1308}
1309
1310static int glk_init_workarounds(struct intel_engine_cs *engine)
1311{
1312 struct drm_i915_private *dev_priv = engine->i915;
1313 int ret;
1314
1315 ret = gen9_init_workarounds(engine);
1316 if (ret)
1317 return ret;
1318
1319 /* WaToEnableHwFixForPushConstHWBug:glk */
1320 WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
1321 GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
1322
1323 return 0;
1324}
1325
Rodrigo Vivi46c26662017-06-16 15:49:58 -07001326static int cfl_init_workarounds(struct intel_engine_cs *engine)
1327{
1328 struct drm_i915_private *dev_priv = engine->i915;
1329 int ret;
1330
1331 ret = gen9_init_workarounds(engine);
1332 if (ret)
1333 return ret;
1334
1335 /* WaEnableGapsTsvCreditFix:cfl */
1336 I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
1337 GEN9_GAPS_TSV_CREDIT_DISABLE));
1338
1339 /* WaToEnableHwFixForPushConstHWBug:cfl */
1340 WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
1341 GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
1342
1343 /* WaDisableGafsUnitClkGating:cfl */
Oscar Mateo4827c542017-09-07 08:40:07 -07001344 I915_WRITE(GEN7_UCGCTL4, (I915_READ(GEN7_UCGCTL4) |
1345 GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE));
Rodrigo Vivi46c26662017-06-16 15:49:58 -07001346
1347 /* WaDisableSbeCacheDispatchPortSharing:cfl */
1348 WA_SET_BIT_MASKED(
1349 GEN7_HALF_SLICE_CHICKEN1,
1350 GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
1351
1352 /* WaInPlaceDecompressionHang:cfl */
Oscar Mateoefc886c2017-09-07 08:40:04 -07001353 I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA,
1354 (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) |
1355 GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS));
Rodrigo Vivi46c26662017-06-16 15:49:58 -07001356
1357 return 0;
1358}
1359
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001360int init_workarounds_ring(struct intel_engine_cs *engine)
1361{
1362 struct drm_i915_private *dev_priv = engine->i915;
Chris Wilson02e012f2017-03-01 12:11:31 +00001363 int err;
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001364
1365 WARN_ON(engine->id != RCS);
1366
1367 dev_priv->workarounds.count = 0;
Chris Wilson02e012f2017-03-01 12:11:31 +00001368 dev_priv->workarounds.hw_whitelist_count[engine->id] = 0;
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001369
1370 if (IS_BROADWELL(dev_priv))
Chris Wilson02e012f2017-03-01 12:11:31 +00001371 err = bdw_init_workarounds(engine);
1372 else if (IS_CHERRYVIEW(dev_priv))
1373 err = chv_init_workarounds(engine);
1374 else if (IS_SKYLAKE(dev_priv))
1375 err = skl_init_workarounds(engine);
1376 else if (IS_BROXTON(dev_priv))
1377 err = bxt_init_workarounds(engine);
1378 else if (IS_KABYLAKE(dev_priv))
1379 err = kbl_init_workarounds(engine);
1380 else if (IS_GEMINILAKE(dev_priv))
1381 err = glk_init_workarounds(engine);
Rodrigo Vivi46c26662017-06-16 15:49:58 -07001382 else if (IS_COFFEELAKE(dev_priv))
1383 err = cfl_init_workarounds(engine);
Rodrigo Vivi90007bc2017-08-15 16:16:48 -07001384 else if (IS_CANNONLAKE(dev_priv))
1385 err = cnl_init_workarounds(engine);
Chris Wilson02e012f2017-03-01 12:11:31 +00001386 else
1387 err = 0;
1388 if (err)
1389 return err;
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001390
Chris Wilson02e012f2017-03-01 12:11:31 +00001391 DRM_DEBUG_DRIVER("%s: Number of context specific w/a: %d\n",
1392 engine->name, dev_priv->workarounds.count);
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001393 return 0;
1394}
1395
1396int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
1397{
1398 struct i915_workarounds *w = &req->i915->workarounds;
1399 u32 *cs;
1400 int ret, i;
1401
1402 if (w->count == 0)
1403 return 0;
1404
1405 ret = req->engine->emit_flush(req, EMIT_BARRIER);
1406 if (ret)
1407 return ret;
1408
1409 cs = intel_ring_begin(req, (w->count * 2 + 2));
1410 if (IS_ERR(cs))
1411 return PTR_ERR(cs);
1412
1413 *cs++ = MI_LOAD_REGISTER_IMM(w->count);
1414 for (i = 0; i < w->count; i++) {
1415 *cs++ = i915_mmio_reg_offset(w->reg[i].addr);
1416 *cs++ = w->reg[i].value;
1417 }
1418 *cs++ = MI_NOOP;
1419
1420 intel_ring_advance(req, cs);
1421
1422 ret = req->engine->emit_flush(req, EMIT_BARRIER);
1423 if (ret)
1424 return ret;
1425
Tvrtko Ursulin133b4bd2017-02-16 12:23:23 +00001426 return 0;
1427}
1428
Chris Wilsona091d4e2017-05-30 13:13:33 +01001429static bool ring_is_idle(struct intel_engine_cs *engine)
1430{
1431 struct drm_i915_private *dev_priv = engine->i915;
1432 bool idle = true;
1433
1434 intel_runtime_pm_get(dev_priv);
1435
Chris Wilsonaed2fc12017-05-30 13:13:34 +01001436 /* First check that no commands are left in the ring */
1437 if ((I915_READ_HEAD(engine) & HEAD_ADDR) !=
1438 (I915_READ_TAIL(engine) & TAIL_ADDR))
1439 idle = false;
1440
Chris Wilsona091d4e2017-05-30 13:13:33 +01001441 /* No bit for gen2, so assume the CS parser is idle */
1442 if (INTEL_GEN(dev_priv) > 2 && !(I915_READ_MODE(engine) & MODE_IDLE))
1443 idle = false;
1444
1445 intel_runtime_pm_put(dev_priv);
1446
1447 return idle;
1448}
1449
Chris Wilson54003672017-03-03 12:19:46 +00001450/**
1451 * intel_engine_is_idle() - Report if the engine has finished process all work
1452 * @engine: the intel_engine_cs
1453 *
1454 * Return true if there are no requests pending, nothing left to be submitted
1455 * to hardware, and that the engine is idle.
1456 */
1457bool intel_engine_is_idle(struct intel_engine_cs *engine)
1458{
1459 struct drm_i915_private *dev_priv = engine->i915;
1460
Chris Wilsona8e9a412017-04-11 20:00:42 +01001461 /* More white lies, if wedged, hw state is inconsistent */
1462 if (i915_terminally_wedged(&dev_priv->gpu_error))
1463 return true;
1464
Chris Wilson54003672017-03-03 12:19:46 +00001465 /* Any inflight/incomplete requests? */
1466 if (!i915_seqno_passed(intel_engine_get_seqno(engine),
1467 intel_engine_last_submit(engine)))
1468 return false;
1469
Chris Wilson8968a362017-04-12 00:44:26 +01001470 if (I915_SELFTEST_ONLY(engine->breadcrumbs.mock))
1471 return true;
1472
Chris Wilson54003672017-03-03 12:19:46 +00001473 /* Interrupt/tasklet pending? */
1474 if (test_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted))
1475 return false;
1476
1477 /* Both ports drained, no more ELSP submission? */
Chris Wilson77f0d0e2017-05-17 13:10:00 +01001478 if (port_request(&engine->execlist_port[0]))
Chris Wilson54003672017-03-03 12:19:46 +00001479 return false;
1480
Chris Wilsond6edb6e2017-07-21 13:32:24 +01001481 /* ELSP is empty, but there are ready requests? */
1482 if (READ_ONCE(engine->execlist_first))
1483 return false;
1484
Chris Wilson54003672017-03-03 12:19:46 +00001485 /* Ring stopped? */
Chris Wilsona091d4e2017-05-30 13:13:33 +01001486 if (!ring_is_idle(engine))
Chris Wilson54003672017-03-03 12:19:46 +00001487 return false;
1488
1489 return true;
1490}
1491
Chris Wilson05425242017-03-03 12:19:47 +00001492bool intel_engines_are_idle(struct drm_i915_private *dev_priv)
1493{
1494 struct intel_engine_cs *engine;
1495 enum intel_engine_id id;
1496
Chris Wilson8490ae202017-03-30 15:50:37 +01001497 if (READ_ONCE(dev_priv->gt.active_requests))
1498 return false;
1499
1500 /* If the driver is wedged, HW state may be very inconsistent and
1501 * report that it is still busy, even though we have stopped using it.
1502 */
1503 if (i915_terminally_wedged(&dev_priv->gpu_error))
1504 return true;
1505
Chris Wilson05425242017-03-03 12:19:47 +00001506 for_each_engine(engine, dev_priv, id) {
1507 if (!intel_engine_is_idle(engine))
1508 return false;
1509 }
1510
1511 return true;
1512}
1513
Chris Wilsonff44ad52017-03-16 17:13:03 +00001514void intel_engines_reset_default_submission(struct drm_i915_private *i915)
1515{
1516 struct intel_engine_cs *engine;
1517 enum intel_engine_id id;
1518
1519 for_each_engine(engine, i915, id)
1520 engine->set_default_submission(engine);
1521}
1522
Chris Wilson6c067572017-05-17 13:10:03 +01001523void intel_engines_mark_idle(struct drm_i915_private *i915)
1524{
1525 struct intel_engine_cs *engine;
1526 enum intel_engine_id id;
1527
1528 for_each_engine(engine, i915, id) {
1529 intel_engine_disarm_breadcrumbs(engine);
1530 i915_gem_batch_pool_fini(&engine->batch_pool);
Chris Wilson9cd90012017-06-27 16:25:10 +01001531 tasklet_kill(&engine->irq_tasklet);
Chris Wilson6c067572017-05-17 13:10:03 +01001532 engine->no_priolist = false;
1533 }
1534}
1535
Chris Wilson90cad092017-09-06 16:28:59 +01001536bool intel_engine_can_store_dword(struct intel_engine_cs *engine)
1537{
1538 switch (INTEL_GEN(engine->i915)) {
1539 case 2:
1540 return false; /* uses physical not virtual addresses */
1541 case 3:
1542 /* maybe only uses physical not virtual addresses */
1543 return !(IS_I915G(engine->i915) || IS_I915GM(engine->i915));
1544 case 6:
1545 return engine->class != VIDEO_DECODE_CLASS; /* b0rked */
1546 default:
1547 return true;
1548 }
1549}
1550
Chris Wilsonf97fbf92017-02-13 17:15:14 +00001551#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
1552#include "selftests/mock_engine.c"
1553#endif