aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c12
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h15
-rw-r--r--drivers/gpu/drm/i915/i915_gem_context.c6
-rw-r--r--drivers/gpu/drm/i915/intel_engine_cs.c1
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.c2
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c2
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h1
-rw-r--r--drivers/gpu/drm/i915/intel_workarounds.c333
-rw-r--r--drivers/gpu/drm/i915/intel_workarounds.h5
9 files changed, 168 insertions, 209 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 129b9a6f8309..38dcee1ca062 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -3375,13 +3375,15 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
3375 3375
3376static int i915_wa_registers(struct seq_file *m, void *unused) 3376static int i915_wa_registers(struct seq_file *m, void *unused)
3377{ 3377{
3378 struct i915_workarounds *wa = &node_to_i915(m->private)->workarounds; 3378 struct drm_i915_private *i915 = node_to_i915(m->private);
3379 int i; 3379 const struct i915_wa_list *wal = &i915->engine[RCS]->ctx_wa_list;
3380 struct i915_wa *wa;
3381 unsigned int i;
3380 3382
3381 seq_printf(m, "Workarounds applied: %d\n", wa->count); 3383 seq_printf(m, "Workarounds applied: %u\n", wal->count);
3382 for (i = 0; i < wa->count; ++i) 3384 for (i = 0, wa = wal->list; i < wal->count; i++, wa++)
3383 seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X\n", 3385 seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X\n",
3384 wa->reg[i].addr, wa->reg[i].value, wa->reg[i].mask); 3386 i915_mmio_reg_offset(wa->reg), wa->val, wa->mask);
3385 3387
3386 return 0; 3388 return 0;
3387} 3389}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index d725390d5a48..23a3dc6f3907 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1190,20 +1190,6 @@ struct i915_frontbuffer_tracking {
1190 unsigned flip_bits; 1190 unsigned flip_bits;
1191}; 1191};
1192 1192
1193struct i915_wa_reg {
1194 u32 addr;
1195 u32 value;
1196 /* bitmask representing WA bits */
1197 u32 mask;
1198};
1199
1200#define I915_MAX_WA_REGS 16
1201
1202struct i915_workarounds {
1203 struct i915_wa_reg reg[I915_MAX_WA_REGS];
1204 u32 count;
1205};
1206
1207struct i915_virtual_gpu { 1193struct i915_virtual_gpu {
1208 bool active; 1194 bool active;
1209 u32 caps; 1195 u32 caps;
@@ -1653,7 +1639,6 @@ struct drm_i915_private {
1653 1639
1654 int dpio_phy_iosf_port[I915_NUM_PHYS_VLV]; 1640 int dpio_phy_iosf_port[I915_NUM_PHYS_VLV];
1655 1641
1656 struct i915_workarounds workarounds;
1657 struct i915_wa_list gt_wa_list; 1642 struct i915_wa_list gt_wa_list;
1658 1643
1659 struct i915_frontbuffer_tracking fb_tracking; 1644 struct i915_frontbuffer_tracking fb_tracking;
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index b97963db0287..371c07087095 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -535,16 +535,12 @@ static bool needs_preempt_context(struct drm_i915_private *i915)
535int i915_gem_contexts_init(struct drm_i915_private *dev_priv) 535int i915_gem_contexts_init(struct drm_i915_private *dev_priv)
536{ 536{
537 struct i915_gem_context *ctx; 537 struct i915_gem_context *ctx;
538 int ret;
539 538
540 /* Reassure ourselves we are only called once */ 539 /* Reassure ourselves we are only called once */
541 GEM_BUG_ON(dev_priv->kernel_context); 540 GEM_BUG_ON(dev_priv->kernel_context);
542 GEM_BUG_ON(dev_priv->preempt_context); 541 GEM_BUG_ON(dev_priv->preempt_context);
543 542
544 ret = intel_ctx_workarounds_init(dev_priv); 543 intel_engine_init_ctx_wa(dev_priv->engine[RCS]);
545 if (ret)
546 return ret;
547
548 init_contexts(dev_priv); 544 init_contexts(dev_priv);
549 545
550 /* lowest priority; idle task */ 546 /* lowest priority; idle task */
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index 496462d77ebc..6b427bc52f78 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -724,6 +724,7 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine)
724 724
725 i915_timeline_fini(&engine->timeline); 725 i915_timeline_fini(&engine->timeline);
726 726
727 intel_wa_list_free(&engine->ctx_wa_list);
727 intel_wa_list_free(&engine->wa_list); 728 intel_wa_list_free(&engine->wa_list);
728 intel_wa_list_free(&engine->whitelist); 729 intel_wa_list_free(&engine->whitelist);
729} 730}
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 92e1f08e1483..87227fd9ae5f 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -2087,7 +2087,7 @@ static int gen8_init_rcs_context(struct i915_request *rq)
2087{ 2087{
2088 int ret; 2088 int ret;
2089 2089
2090 ret = intel_ctx_workarounds_emit(rq); 2090 ret = intel_engine_emit_ctx_wa(rq);
2091 if (ret) 2091 if (ret)
2092 return ret; 2092 return ret;
2093 2093
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 81b10d85b738..7f88df5bff09 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -656,7 +656,7 @@ static int intel_rcs_ctx_init(struct i915_request *rq)
656{ 656{
657 int ret; 657 int ret;
658 658
659 ret = intel_ctx_workarounds_emit(rq); 659 ret = intel_engine_emit_ctx_wa(rq);
660 if (ret != 0) 660 if (ret != 0)
661 return ret; 661 return ret;
662 662
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 7b110e221749..927bb21a2b0b 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -436,6 +436,7 @@ struct intel_engine_cs {
436 436
437 struct intel_hw_status_page status_page; 437 struct intel_hw_status_page status_page;
438 struct i915_ctx_workarounds wa_ctx; 438 struct i915_ctx_workarounds wa_ctx;
439 struct i915_wa_list ctx_wa_list;
439 struct i915_wa_list wa_list; 440 struct i915_wa_list wa_list;
440 struct i915_wa_list whitelist; 441 struct i915_wa_list whitelist;
441 struct i915_vma *scratch; 442 struct i915_vma *scratch;
diff --git a/drivers/gpu/drm/i915/intel_workarounds.c b/drivers/gpu/drm/i915/intel_workarounds.c
index d920a6256c83..e52bd3f5d526 100644
--- a/drivers/gpu/drm/i915/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/intel_workarounds.c
@@ -59,61 +59,87 @@ static void wa_init_finish(struct i915_wa_list *wal)
59 return; 59 return;
60 60
61 DRM_DEBUG_DRIVER("Initialized %u %s workarounds\n", 61 DRM_DEBUG_DRIVER("Initialized %u %s workarounds\n",
62 wal->count, wal->name); 62 wal->wa_count, wal->name);
63} 63}
64 64
65static void wa_add(struct drm_i915_private *i915, 65static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa)
66 i915_reg_t reg, const u32 mask, const u32 val)
67{ 66{
68 struct i915_workarounds *wa = &i915->workarounds; 67 unsigned int addr = i915_mmio_reg_offset(wa->reg);
69 unsigned int start = 0, end = wa->count; 68 unsigned int start = 0, end = wal->count;
70 unsigned int addr = i915_mmio_reg_offset(reg); 69 const unsigned int grow = 1 << 4;
71 struct i915_wa_reg *r; 70 struct i915_wa *wa_;
71
72 GEM_BUG_ON(!is_power_of_2(grow));
73
74 if (IS_ALIGNED(wal->count, grow)) { /* Either uninitialized or full. */
75 struct i915_wa *list;
76
77 list = kmalloc_array(ALIGN(wal->count + 1, grow), sizeof(*wa),
78 GFP_KERNEL);
79 if (!list) {
80 DRM_ERROR("No space for workaround init!\n");
81 return;
82 }
83
84 if (wal->list)
85 memcpy(list, wal->list, sizeof(*wa) * wal->count);
86
87 wal->list = list;
88 }
72 89
73 while (start < end) { 90 while (start < end) {
74 unsigned int mid = start + (end - start) / 2; 91 unsigned int mid = start + (end - start) / 2;
75 92
76 if (wa->reg[mid].addr < addr) { 93 if (i915_mmio_reg_offset(wal->list[mid].reg) < addr) {
77 start = mid + 1; 94 start = mid + 1;
78 } else if (wa->reg[mid].addr > addr) { 95 } else if (i915_mmio_reg_offset(wal->list[mid].reg) > addr) {
79 end = mid; 96 end = mid;
80 } else { 97 } else {
81 r = &wa->reg[mid]; 98 wa_ = &wal->list[mid];
82 99
83 if ((mask & ~r->mask) == 0) { 100 if ((wa->mask & ~wa_->mask) == 0) {
84 DRM_ERROR("Discarding overwritten w/a for reg %04x (mask: %08x, value: %08x)\n", 101 DRM_ERROR("Discarding overwritten w/a for reg %04x (mask: %08x, value: %08x)\n",
85 addr, r->mask, r->value); 102 i915_mmio_reg_offset(wa_->reg),
103 wa_->mask, wa_->val);
86 104
87 r->value &= ~mask; 105 wa_->val &= ~wa->mask;
88 } 106 }
89 107
90 r->value |= val; 108 wal->wa_count++;
91 r->mask |= mask; 109 wa_->val |= wa->val;
110 wa_->mask |= wa->mask;
92 return; 111 return;
93 } 112 }
94 } 113 }
95 114
96 if (WARN_ON_ONCE(wa->count >= I915_MAX_WA_REGS)) { 115 wal->wa_count++;
97 DRM_ERROR("Dropping w/a for reg %04x (mask: %08x, value: %08x)\n", 116 wa_ = &wal->list[wal->count++];
98 addr, mask, val); 117 *wa_ = *wa;
99 return;
100 }
101 118
102 r = &wa->reg[wa->count++]; 119 while (wa_-- > wal->list) {
103 r->addr = addr; 120 GEM_BUG_ON(i915_mmio_reg_offset(wa_[0].reg) ==
104 r->value = val; 121 i915_mmio_reg_offset(wa_[1].reg));
105 r->mask = mask; 122 if (i915_mmio_reg_offset(wa_[1].reg) >
106 123 i915_mmio_reg_offset(wa_[0].reg))
107 while (r-- > wa->reg) {
108 GEM_BUG_ON(r[0].addr == r[1].addr);
109 if (r[1].addr > r[0].addr)
110 break; 124 break;
111 125
112 swap(r[1], r[0]); 126 swap(wa_[1], wa_[0]);
113 } 127 }
114} 128}
115 129
116#define WA_REG(addr, mask, val) wa_add(dev_priv, (addr), (mask), (val)) 130static void
131__wa_add(struct i915_wa_list *wal, i915_reg_t reg, u32 mask, u32 val)
132{
133 struct i915_wa wa = {
134 .reg = reg,
135 .mask = mask,
136 .val = val
137 };
138
139 _wa_add(wal, &wa);
140}
141
142#define WA_REG(addr, mask, val) __wa_add(wal, (addr), (mask), (val))
117 143
118#define WA_SET_BIT_MASKED(addr, mask) \ 144#define WA_SET_BIT_MASKED(addr, mask) \
119 WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask)) 145 WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask))
@@ -124,8 +150,10 @@ static void wa_add(struct drm_i915_private *i915,
124#define WA_SET_FIELD_MASKED(addr, mask, value) \ 150#define WA_SET_FIELD_MASKED(addr, mask, value) \
125 WA_REG(addr, (mask), _MASKED_FIELD(mask, value)) 151 WA_REG(addr, (mask), _MASKED_FIELD(mask, value))
126 152
127static int gen8_ctx_workarounds_init(struct drm_i915_private *dev_priv) 153static void gen8_ctx_workarounds_init(struct intel_engine_cs *engine)
128{ 154{
155 struct i915_wa_list *wal = &engine->ctx_wa_list;
156
129 WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING); 157 WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING);
130 158
131 /* WaDisableAsyncFlipPerfMode:bdw,chv */ 159 /* WaDisableAsyncFlipPerfMode:bdw,chv */
@@ -169,17 +197,14 @@ static int gen8_ctx_workarounds_init(struct drm_i915_private *dev_priv)
169 WA_SET_FIELD_MASKED(GEN7_GT_MODE, 197 WA_SET_FIELD_MASKED(GEN7_GT_MODE,
170 GEN6_WIZ_HASHING_MASK, 198 GEN6_WIZ_HASHING_MASK,
171 GEN6_WIZ_HASHING_16x4); 199 GEN6_WIZ_HASHING_16x4);
172
173 return 0;
174} 200}
175 201
176static int bdw_ctx_workarounds_init(struct drm_i915_private *dev_priv) 202static void bdw_ctx_workarounds_init(struct intel_engine_cs *engine)
177{ 203{
178 int ret; 204 struct drm_i915_private *i915 = engine->i915;
205 struct i915_wa_list *wal = &engine->ctx_wa_list;
179 206
180 ret = gen8_ctx_workarounds_init(dev_priv); 207 gen8_ctx_workarounds_init(engine);
181 if (ret)
182 return ret;
183 208
184 /* WaDisableThreadStallDopClockGating:bdw (pre-production) */ 209 /* WaDisableThreadStallDopClockGating:bdw (pre-production) */
185 WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 210 WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
@@ -199,31 +224,28 @@ static int bdw_ctx_workarounds_init(struct drm_i915_private *dev_priv)
199 /* WaForceContextSaveRestoreNonCoherent:bdw */ 224 /* WaForceContextSaveRestoreNonCoherent:bdw */
200 HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | 225 HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
201 /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */ 226 /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */
202 (IS_BDW_GT3(dev_priv) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); 227 (IS_BDW_GT3(i915) ? HDC_FENCE_DEST_SLM_DISABLE : 0));
203
204 return 0;
205} 228}
206 229
207static int chv_ctx_workarounds_init(struct drm_i915_private *dev_priv) 230static void chv_ctx_workarounds_init(struct intel_engine_cs *engine)
208{ 231{
209 int ret; 232 struct i915_wa_list *wal = &engine->ctx_wa_list;
210 233
211 ret = gen8_ctx_workarounds_init(dev_priv); 234 gen8_ctx_workarounds_init(engine);
212 if (ret)
213 return ret;
214 235
215 /* WaDisableThreadStallDopClockGating:chv */ 236 /* WaDisableThreadStallDopClockGating:chv */
216 WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 237 WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
217 238
218 /* Improve HiZ throughput on CHV. */ 239 /* Improve HiZ throughput on CHV. */
219 WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X); 240 WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X);
220
221 return 0;
222} 241}
223 242
224static int gen9_ctx_workarounds_init(struct drm_i915_private *dev_priv) 243static void gen9_ctx_workarounds_init(struct intel_engine_cs *engine)
225{ 244{
226 if (HAS_LLC(dev_priv)) { 245 struct drm_i915_private *i915 = engine->i915;
246 struct i915_wa_list *wal = &engine->ctx_wa_list;
247
248 if (HAS_LLC(i915)) {
227 /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl,kbl 249 /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl,kbl
228 * 250 *
229 * Must match Display Engine. See 251 * Must match Display Engine. See
@@ -242,7 +264,7 @@ static int gen9_ctx_workarounds_init(struct drm_i915_private *dev_priv)
242 PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 264 PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
243 265
244 /* Syncing dependencies between camera and graphics:skl,bxt,kbl */ 266 /* Syncing dependencies between camera and graphics:skl,bxt,kbl */
245 if (!IS_COFFEELAKE(dev_priv)) 267 if (!IS_COFFEELAKE(i915))
246 WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 268 WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
247 GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC); 269 GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC);
248 270
@@ -285,9 +307,7 @@ static int gen9_ctx_workarounds_init(struct drm_i915_private *dev_priv)
285 HDC_FORCE_NON_COHERENT); 307 HDC_FORCE_NON_COHERENT);
286 308
287 /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl,cfl */ 309 /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl,cfl */
288 if (IS_SKYLAKE(dev_priv) || 310 if (IS_SKYLAKE(i915) || IS_KABYLAKE(i915) || IS_COFFEELAKE(i915))
289 IS_KABYLAKE(dev_priv) ||
290 IS_COFFEELAKE(dev_priv))
291 WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 311 WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
292 GEN8_SAMPLER_POWER_BYPASS_DIS); 312 GEN8_SAMPLER_POWER_BYPASS_DIS);
293 313
@@ -314,14 +334,14 @@ static int gen9_ctx_workarounds_init(struct drm_i915_private *dev_priv)
314 GEN9_PREEMPT_GPGPU_COMMAND_LEVEL); 334 GEN9_PREEMPT_GPGPU_COMMAND_LEVEL);
315 335
316 /* WaClearHIZ_WM_CHICKEN3:bxt,glk */ 336 /* WaClearHIZ_WM_CHICKEN3:bxt,glk */
317 if (IS_GEN9_LP(dev_priv)) 337 if (IS_GEN9_LP(i915))
318 WA_SET_BIT_MASKED(GEN9_WM_CHICKEN3, GEN9_FACTOR_IN_CLR_VAL_HIZ); 338 WA_SET_BIT_MASKED(GEN9_WM_CHICKEN3, GEN9_FACTOR_IN_CLR_VAL_HIZ);
319
320 return 0;
321} 339}
322 340
323static int skl_tune_iz_hashing(struct drm_i915_private *dev_priv) 341static void skl_tune_iz_hashing(struct intel_engine_cs *engine)
324{ 342{
343 struct drm_i915_private *i915 = engine->i915;
344 struct i915_wa_list *wal = &engine->ctx_wa_list;
325 u8 vals[3] = { 0, 0, 0 }; 345 u8 vals[3] = { 0, 0, 0 };
326 unsigned int i; 346 unsigned int i;
327 347
@@ -332,7 +352,7 @@ static int skl_tune_iz_hashing(struct drm_i915_private *dev_priv)
332 * Only consider slices where one, and only one, subslice has 7 352 * Only consider slices where one, and only one, subslice has 7
333 * EUs 353 * EUs
334 */ 354 */
335 if (!is_power_of_2(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i])) 355 if (!is_power_of_2(INTEL_INFO(i915)->sseu.subslice_7eu[i]))
336 continue; 356 continue;
337 357
338 /* 358 /*
@@ -341,12 +361,12 @@ static int skl_tune_iz_hashing(struct drm_i915_private *dev_priv)
341 * 361 *
342 * -> 0 <= ss <= 3; 362 * -> 0 <= ss <= 3;
343 */ 363 */
344 ss = ffs(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i]) - 1; 364 ss = ffs(INTEL_INFO(i915)->sseu.subslice_7eu[i]) - 1;
345 vals[i] = 3 - ss; 365 vals[i] = 3 - ss;
346 } 366 }
347 367
348 if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0) 368 if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0)
349 return 0; 369 return;
350 370
351 /* Tune IZ hashing. See intel_device_info_runtime_init() */ 371 /* Tune IZ hashing. See intel_device_info_runtime_init() */
352 WA_SET_FIELD_MASKED(GEN7_GT_MODE, 372 WA_SET_FIELD_MASKED(GEN7_GT_MODE,
@@ -356,28 +376,19 @@ static int skl_tune_iz_hashing(struct drm_i915_private *dev_priv)
356 GEN9_IZ_HASHING(2, vals[2]) | 376 GEN9_IZ_HASHING(2, vals[2]) |
357 GEN9_IZ_HASHING(1, vals[1]) | 377 GEN9_IZ_HASHING(1, vals[1]) |
358 GEN9_IZ_HASHING(0, vals[0])); 378 GEN9_IZ_HASHING(0, vals[0]));
359
360 return 0;
361} 379}
362 380
363static int skl_ctx_workarounds_init(struct drm_i915_private *dev_priv) 381static void skl_ctx_workarounds_init(struct intel_engine_cs *engine)
364{ 382{
365 int ret; 383 gen9_ctx_workarounds_init(engine);
366 384 skl_tune_iz_hashing(engine);
367 ret = gen9_ctx_workarounds_init(dev_priv);
368 if (ret)
369 return ret;
370
371 return skl_tune_iz_hashing(dev_priv);
372} 385}
373 386
374static int bxt_ctx_workarounds_init(struct drm_i915_private *dev_priv) 387static void bxt_ctx_workarounds_init(struct intel_engine_cs *engine)
375{ 388{
376 int ret; 389 struct i915_wa_list *wal = &engine->ctx_wa_list;
377 390
378 ret = gen9_ctx_workarounds_init(dev_priv); 391 gen9_ctx_workarounds_init(engine);
379 if (ret)
380 return ret;
381 392
382 /* WaDisableThreadStallDopClockGating:bxt */ 393 /* WaDisableThreadStallDopClockGating:bxt */
383 WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 394 WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
@@ -386,52 +397,41 @@ static int bxt_ctx_workarounds_init(struct drm_i915_private *dev_priv)
386 /* WaToEnableHwFixForPushConstHWBug:bxt */ 397 /* WaToEnableHwFixForPushConstHWBug:bxt */
387 WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 398 WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
388 GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 399 GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
389
390 return 0;
391} 400}
392 401
393static int kbl_ctx_workarounds_init(struct drm_i915_private *dev_priv) 402static void kbl_ctx_workarounds_init(struct intel_engine_cs *engine)
394{ 403{
395 int ret; 404 struct drm_i915_private *i915 = engine->i915;
405 struct i915_wa_list *wal = &engine->ctx_wa_list;
396 406
397 ret = gen9_ctx_workarounds_init(dev_priv); 407 gen9_ctx_workarounds_init(engine);
398 if (ret)
399 return ret;
400 408
401 /* WaToEnableHwFixForPushConstHWBug:kbl */ 409 /* WaToEnableHwFixForPushConstHWBug:kbl */
402 if (IS_KBL_REVID(dev_priv, KBL_REVID_C0, REVID_FOREVER)) 410 if (IS_KBL_REVID(i915, KBL_REVID_C0, REVID_FOREVER))
403 WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 411 WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
404 GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 412 GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
405 413
406 /* WaDisableSbeCacheDispatchPortSharing:kbl */ 414 /* WaDisableSbeCacheDispatchPortSharing:kbl */
407 WA_SET_BIT_MASKED(GEN7_HALF_SLICE_CHICKEN1, 415 WA_SET_BIT_MASKED(GEN7_HALF_SLICE_CHICKEN1,
408 GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 416 GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
409
410 return 0;
411} 417}
412 418
413static int glk_ctx_workarounds_init(struct drm_i915_private *dev_priv) 419static void glk_ctx_workarounds_init(struct intel_engine_cs *engine)
414{ 420{
415 int ret; 421 struct i915_wa_list *wal = &engine->ctx_wa_list;
416 422
417 ret = gen9_ctx_workarounds_init(dev_priv); 423 gen9_ctx_workarounds_init(engine);
418 if (ret)
419 return ret;
420 424
421 /* WaToEnableHwFixForPushConstHWBug:glk */ 425 /* WaToEnableHwFixForPushConstHWBug:glk */
422 WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 426 WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
423 GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 427 GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
424
425 return 0;
426} 428}
427 429
428static int cfl_ctx_workarounds_init(struct drm_i915_private *dev_priv) 430static void cfl_ctx_workarounds_init(struct intel_engine_cs *engine)
429{ 431{
430 int ret; 432 struct i915_wa_list *wal = &engine->ctx_wa_list;
431 433
432 ret = gen9_ctx_workarounds_init(dev_priv); 434 gen9_ctx_workarounds_init(engine);
433 if (ret)
434 return ret;
435 435
436 /* WaToEnableHwFixForPushConstHWBug:cfl */ 436 /* WaToEnableHwFixForPushConstHWBug:cfl */
437 WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 437 WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
@@ -440,18 +440,19 @@ static int cfl_ctx_workarounds_init(struct drm_i915_private *dev_priv)
440 /* WaDisableSbeCacheDispatchPortSharing:cfl */ 440 /* WaDisableSbeCacheDispatchPortSharing:cfl */
441 WA_SET_BIT_MASKED(GEN7_HALF_SLICE_CHICKEN1, 441 WA_SET_BIT_MASKED(GEN7_HALF_SLICE_CHICKEN1,
442 GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 442 GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
443
444 return 0;
445} 443}
446 444
447static int cnl_ctx_workarounds_init(struct drm_i915_private *dev_priv) 445static void cnl_ctx_workarounds_init(struct intel_engine_cs *engine)
448{ 446{
447 struct drm_i915_private *i915 = engine->i915;
448 struct i915_wa_list *wal = &engine->ctx_wa_list;
449
449 /* WaForceContextSaveRestoreNonCoherent:cnl */ 450 /* WaForceContextSaveRestoreNonCoherent:cnl */
450 WA_SET_BIT_MASKED(CNL_HDC_CHICKEN0, 451 WA_SET_BIT_MASKED(CNL_HDC_CHICKEN0,
451 HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT); 452 HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT);
452 453
453 /* WaThrottleEUPerfToAvoidTDBackPressure:cnl(pre-prod) */ 454 /* WaThrottleEUPerfToAvoidTDBackPressure:cnl(pre-prod) */
454 if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0)) 455 if (IS_CNL_REVID(i915, CNL_REVID_B0, CNL_REVID_B0))
455 WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, THROTTLE_12_5); 456 WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, THROTTLE_12_5);
456 457
457 /* WaDisableReplayBufferBankArbitrationOptimization:cnl */ 458 /* WaDisableReplayBufferBankArbitrationOptimization:cnl */
@@ -459,7 +460,7 @@ static int cnl_ctx_workarounds_init(struct drm_i915_private *dev_priv)
459 GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 460 GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
460 461
461 /* WaDisableEnhancedSBEVertexCaching:cnl (pre-prod) */ 462 /* WaDisableEnhancedSBEVertexCaching:cnl (pre-prod) */
462 if (IS_CNL_REVID(dev_priv, 0, CNL_REVID_B0)) 463 if (IS_CNL_REVID(i915, 0, CNL_REVID_B0))
463 WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 464 WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
464 GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE); 465 GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE);
465 466
@@ -479,16 +480,17 @@ static int cnl_ctx_workarounds_init(struct drm_i915_private *dev_priv)
479 480
480 /* WaDisableEarlyEOT:cnl */ 481 /* WaDisableEarlyEOT:cnl */
481 WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, DISABLE_EARLY_EOT); 482 WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, DISABLE_EARLY_EOT);
482
483 return 0;
484} 483}
485 484
486static int icl_ctx_workarounds_init(struct drm_i915_private *dev_priv) 485static void icl_ctx_workarounds_init(struct intel_engine_cs *engine)
487{ 486{
487 struct drm_i915_private *i915 = engine->i915;
488 struct i915_wa_list *wal = &engine->ctx_wa_list;
489
488 /* Wa_1604370585:icl (pre-prod) 490 /* Wa_1604370585:icl (pre-prod)
489 * Formerly known as WaPushConstantDereferenceHoldDisable 491 * Formerly known as WaPushConstantDereferenceHoldDisable
490 */ 492 */
491 if (IS_ICL_REVID(dev_priv, ICL_REVID_A0, ICL_REVID_B0)) 493 if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_B0))
492 WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, 494 WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2,
493 PUSH_CONSTANT_DEREF_DISABLE); 495 PUSH_CONSTANT_DEREF_DISABLE);
494 496
@@ -504,7 +506,7 @@ static int icl_ctx_workarounds_init(struct drm_i915_private *dev_priv)
504 /* Wa_2006611047:icl (pre-prod) 506 /* Wa_2006611047:icl (pre-prod)
505 * Formerly known as WaDisableImprovedTdlClkGating 507 * Formerly known as WaDisableImprovedTdlClkGating
506 */ 508 */
507 if (IS_ICL_REVID(dev_priv, ICL_REVID_A0, ICL_REVID_A0)) 509 if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_A0))
508 WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, 510 WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2,
509 GEN11_TDL_CLOCK_GATING_FIX_DISABLE); 511 GEN11_TDL_CLOCK_GATING_FIX_DISABLE);
510 512
@@ -513,70 +515,67 @@ static int icl_ctx_workarounds_init(struct drm_i915_private *dev_priv)
513 GEN11_STATE_CACHE_REDIRECT_TO_CS); 515 GEN11_STATE_CACHE_REDIRECT_TO_CS);
514 516
515 /* Wa_2006665173:icl (pre-prod) */ 517 /* Wa_2006665173:icl (pre-prod) */
516 if (IS_ICL_REVID(dev_priv, ICL_REVID_A0, ICL_REVID_A0)) 518 if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_A0))
517 WA_SET_BIT_MASKED(GEN11_COMMON_SLICE_CHICKEN3, 519 WA_SET_BIT_MASKED(GEN11_COMMON_SLICE_CHICKEN3,
518 GEN11_BLEND_EMB_FIX_DISABLE_IN_RCC); 520 GEN11_BLEND_EMB_FIX_DISABLE_IN_RCC);
519
520 return 0;
521} 521}
522 522
523int intel_ctx_workarounds_init(struct drm_i915_private *dev_priv) 523void intel_engine_init_ctx_wa(struct intel_engine_cs *engine)
524{ 524{
525 int err = 0; 525 struct drm_i915_private *i915 = engine->i915;
526 526 struct i915_wa_list *wal = &engine->ctx_wa_list;
527 dev_priv->workarounds.count = 0; 527
528 528 wa_init_start(wal, "context");
529 if (INTEL_GEN(dev_priv) < 8) 529
530 err = 0; 530 if (INTEL_GEN(i915) < 8)
531 else if (IS_BROADWELL(dev_priv)) 531 return;
532 err = bdw_ctx_workarounds_init(dev_priv); 532 else if (IS_BROADWELL(i915))
533 else if (IS_CHERRYVIEW(dev_priv)) 533 bdw_ctx_workarounds_init(engine);
534 err = chv_ctx_workarounds_init(dev_priv); 534 else if (IS_CHERRYVIEW(i915))
535 else if (IS_SKYLAKE(dev_priv)) 535 chv_ctx_workarounds_init(engine);
536 err = skl_ctx_workarounds_init(dev_priv); 536 else if (IS_SKYLAKE(i915))
537 else if (IS_BROXTON(dev_priv)) 537 skl_ctx_workarounds_init(engine);
538 err = bxt_ctx_workarounds_init(dev_priv); 538 else if (IS_BROXTON(i915))
539 else if (IS_KABYLAKE(dev_priv)) 539 bxt_ctx_workarounds_init(engine);
540 err = kbl_ctx_workarounds_init(dev_priv); 540 else if (IS_KABYLAKE(i915))
541 else if (IS_GEMINILAKE(dev_priv)) 541 kbl_ctx_workarounds_init(engine);
542 err = glk_ctx_workarounds_init(dev_priv); 542 else if (IS_GEMINILAKE(i915))
543 else if (IS_COFFEELAKE(dev_priv)) 543 glk_ctx_workarounds_init(engine);
544 err = cfl_ctx_workarounds_init(dev_priv); 544 else if (IS_COFFEELAKE(i915))
545 else if (IS_CANNONLAKE(dev_priv)) 545 cfl_ctx_workarounds_init(engine);
546 err = cnl_ctx_workarounds_init(dev_priv); 546 else if (IS_CANNONLAKE(i915))
547 else if (IS_ICELAKE(dev_priv)) 547 cnl_ctx_workarounds_init(engine);
548 err = icl_ctx_workarounds_init(dev_priv); 548 else if (IS_ICELAKE(i915))
549 icl_ctx_workarounds_init(engine);
549 else 550 else
550 MISSING_CASE(INTEL_GEN(dev_priv)); 551 MISSING_CASE(INTEL_GEN(i915));
551 if (err)
552 return err;
553 552
554 DRM_DEBUG_DRIVER("Number of context specific w/a: %d\n", 553 wa_init_finish(wal);
555 dev_priv->workarounds.count);
556 return 0;
557} 554}
558 555
559int intel_ctx_workarounds_emit(struct i915_request *rq) 556int intel_engine_emit_ctx_wa(struct i915_request *rq)
560{ 557{
561 struct i915_workarounds *w = &rq->i915->workarounds; 558 struct i915_wa_list *wal = &rq->engine->ctx_wa_list;
559 struct i915_wa *wa;
560 unsigned int i;
562 u32 *cs; 561 u32 *cs;
563 int ret, i; 562 int ret;
564 563
565 if (w->count == 0) 564 if (wal->count == 0)
566 return 0; 565 return 0;
567 566
568 ret = rq->engine->emit_flush(rq, EMIT_BARRIER); 567 ret = rq->engine->emit_flush(rq, EMIT_BARRIER);
569 if (ret) 568 if (ret)
570 return ret; 569 return ret;
571 570
572 cs = intel_ring_begin(rq, (w->count * 2 + 2)); 571 cs = intel_ring_begin(rq, (wal->count * 2 + 2));
573 if (IS_ERR(cs)) 572 if (IS_ERR(cs))
574 return PTR_ERR(cs); 573 return PTR_ERR(cs);
575 574
576 *cs++ = MI_LOAD_REGISTER_IMM(w->count); 575 *cs++ = MI_LOAD_REGISTER_IMM(wal->count);
577 for (i = 0; i < w->count; i++) { 576 for (i = 0, wa = wal->list; i < wal->count; i++, wa++) {
578 *cs++ = w->reg[i].addr; 577 *cs++ = i915_mmio_reg_offset(wa->reg);
579 *cs++ = w->reg[i].value; 578 *cs++ = wa->val;
580 } 579 }
581 *cs++ = MI_NOOP; 580 *cs++ = MI_NOOP;
582 581
@@ -590,32 +589,6 @@ int intel_ctx_workarounds_emit(struct i915_request *rq)
590} 589}
591 590
592static void 591static void
593wal_add(struct i915_wa_list *wal, const struct i915_wa *wa)
594{
595 const unsigned int grow = 1 << 4;
596
597 GEM_BUG_ON(!is_power_of_2(grow));
598
599 if (IS_ALIGNED(wal->count, grow)) { /* Either uninitialized or full. */
600 struct i915_wa *list;
601
602 list = kmalloc_array(ALIGN(wal->count + 1, grow), sizeof(*wa),
603 GFP_KERNEL);
604 if (!list) {
605 DRM_ERROR("No space for workaround init!\n");
606 return;
607 }
608
609 if (wal->list)
610 memcpy(list, wal->list, sizeof(*wa) * wal->count);
611
612 wal->list = list;
613 }
614
615 wal->list[wal->count++] = *wa;
616}
617
618static void
619wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val) 592wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
620{ 593{
621 struct i915_wa wa = { 594 struct i915_wa wa = {
@@ -624,7 +597,7 @@ wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
624 .val = _MASKED_BIT_ENABLE(val) 597 .val = _MASKED_BIT_ENABLE(val)
625 }; 598 };
626 599
627 wal_add(wal, &wa); 600 _wa_add(wal, &wa);
628} 601}
629 602
630static void 603static void
@@ -637,7 +610,7 @@ wa_write_masked_or(struct i915_wa_list *wal, i915_reg_t reg, u32 mask,
637 .val = val 610 .val = val
638 }; 611 };
639 612
640 wal_add(wal, &wa); 613 _wa_add(wal, &wa);
641} 614}
642 615
643static void 616static void
@@ -1021,7 +994,7 @@ whitelist_reg(struct i915_wa_list *wal, i915_reg_t reg)
1021 if (GEM_DEBUG_WARN_ON(wal->count >= RING_MAX_NONPRIV_SLOTS)) 994 if (GEM_DEBUG_WARN_ON(wal->count >= RING_MAX_NONPRIV_SLOTS))
1022 return; 995 return;
1023 996
1024 wal_add(wal, &wa); 997 _wa_add(wal, &wa);
1025} 998}
1026 999
1027static void gen9_whitelist_build(struct i915_wa_list *w) 1000static void gen9_whitelist_build(struct i915_wa_list *w)
diff --git a/drivers/gpu/drm/i915/intel_workarounds.h b/drivers/gpu/drm/i915/intel_workarounds.h
index 3f99bfcb4a03..7c734714b05e 100644
--- a/drivers/gpu/drm/i915/intel_workarounds.h
+++ b/drivers/gpu/drm/i915/intel_workarounds.h
@@ -19,6 +19,7 @@ struct i915_wa_list {
19 const char *name; 19 const char *name;
20 struct i915_wa *list; 20 struct i915_wa *list;
21 unsigned int count; 21 unsigned int count;
22 unsigned int wa_count;
22}; 23};
23 24
24static inline void intel_wa_list_free(struct i915_wa_list *wal) 25static inline void intel_wa_list_free(struct i915_wa_list *wal)
@@ -27,8 +28,8 @@ static inline void intel_wa_list_free(struct i915_wa_list *wal)
27 memset(wal, 0, sizeof(*wal)); 28 memset(wal, 0, sizeof(*wal));
28} 29}
29 30
30int intel_ctx_workarounds_init(struct drm_i915_private *dev_priv); 31void intel_engine_init_ctx_wa(struct intel_engine_cs *engine);
31int intel_ctx_workarounds_emit(struct i915_request *rq); 32int intel_engine_emit_ctx_wa(struct i915_request *rq);
32 33
33void intel_gt_init_workarounds(struct drm_i915_private *dev_priv); 34void intel_gt_init_workarounds(struct drm_i915_private *dev_priv);
34void intel_gt_apply_workarounds(struct drm_i915_private *dev_priv); 35void intel_gt_apply_workarounds(struct drm_i915_private *dev_priv);