diff options
Diffstat (limited to 'drivers/gpu/drm/i915/gt/intel_workarounds.c')
-rw-r--r-- | drivers/gpu/drm/i915/gt/intel_workarounds.c | 138 |
1 files changed, 107 insertions, 31 deletions
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index 4e292d4bf7b9..887e0dc701f7 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -116,17 +116,17 @@ static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa) } else { wa_ = &wal->list[mid]; - if ((wa->mask & ~wa_->mask) == 0) { - DRM_ERROR("Discarding overwritten w/a for reg %04x (mask: %08x, value: %08x)\n", + if ((wa->clr | wa_->clr) && !(wa->clr & ~wa_->clr)) { + DRM_ERROR("Discarding overwritten w/a for reg %04x (clear: %08x, set: %08x)\n", i915_mmio_reg_offset(wa_->reg), - wa_->mask, wa_->val); + wa_->clr, wa_->set); - wa_->val &= ~wa->mask; + wa_->set &= ~wa->clr; } wal->wa_count++; - wa_->val |= wa->val; - wa_->mask |= wa->mask; + wa_->set |= wa->set; + wa_->clr |= wa->clr; wa_->read |= wa->read; return; } @@ -147,13 +147,13 @@ static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa) } } -static void wa_add(struct i915_wa_list *wal, i915_reg_t reg, u32 mask, - u32 val, u32 read_mask) +static void wa_add(struct i915_wa_list *wal, i915_reg_t reg, + u32 clear, u32 set, u32 read_mask) { struct i915_wa wa = { .reg = reg, - .mask = mask, - .val = val, + .clr = clear, + .set = set, .read = read_mask, }; @@ -161,38 +161,43 @@ static void wa_add(struct i915_wa_list *wal, i915_reg_t reg, u32 mask, } static void -wa_write_masked_or(struct i915_wa_list *wal, i915_reg_t reg, u32 mask, - u32 val) +wa_write_masked_or(struct i915_wa_list *wal, i915_reg_t reg, u32 clear, u32 set) { - wa_add(wal, reg, mask, val, mask); + wa_add(wal, reg, clear, set, clear); } static void -wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val) +wa_write(struct i915_wa_list *wal, i915_reg_t reg, u32 set) +{ + wa_write_masked_or(wal, reg, ~0, set); +} + +static void +wa_write_or(struct i915_wa_list *wal, i915_reg_t reg, u32 set) { - wa_write_masked_or(wal, reg, val, _MASKED_BIT_ENABLE(val)); + wa_write_masked_or(wal, reg, set, set); } static void -wa_write(struct i915_wa_list *wal, i915_reg_t reg, u32 val) +wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val) { - wa_write_masked_or(wal, reg, ~0, val); + wa_add(wal, reg, 0, _MASKED_BIT_ENABLE(val), val); } static void -wa_write_or(struct i915_wa_list *wal, i915_reg_t reg, u32 val) +wa_masked_dis(struct i915_wa_list *wal, i915_reg_t reg, u32 val) { - wa_write_masked_or(wal, reg, val, val); + wa_add(wal, reg, 0, _MASKED_BIT_DISABLE(val), val); } #define WA_SET_BIT_MASKED(addr, mask) \ - wa_write_masked_or(wal, (addr), (mask), _MASKED_BIT_ENABLE(mask)) + wa_masked_en(wal, (addr), (mask)) #define WA_CLR_BIT_MASKED(addr, mask) \ - wa_write_masked_or(wal, (addr), (mask), _MASKED_BIT_DISABLE(mask)) + wa_masked_dis(wal, (addr), (mask)) #define WA_SET_FIELD_MASKED(addr, mask, value) \ - wa_write_masked_or(wal, (addr), (mask), _MASKED_FIELD((mask), (value))) + wa_write_masked_or(wal, (addr), 0, _MASKED_FIELD((mask), (value))) static void gen8_ctx_workarounds_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) @@ -662,7 +667,7 @@ int intel_engine_emit_ctx_wa(struct i915_request *rq) *cs++ = MI_LOAD_REGISTER_IMM(wal->count); for (i = 0, wa = wal->list; i < wal->count; i++, wa++) { *cs++ = i915_mmio_reg_offset(wa->reg); - *cs++ = wa->val; + *cs++ = wa->set; } *cs++ = MI_NOOP; @@ -827,7 +832,7 @@ wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal) DRM_WARN("No common index found between subslice mask %x and L3 bank mask %x!\n", intel_sseu_get_subslices(sseu, slice), l3_en); subslice = fls(l3_en); - WARN_ON(!subslice); + drm_WARN_ON(&i915->drm, !subslice); } subslice--; @@ -991,11 +996,10 @@ wal_get_fw_for_rmw(struct intel_uncore *uncore, const struct i915_wa_list *wal) static bool wa_verify(const struct i915_wa *wa, u32 cur, const char *name, const char *from) { - if ((cur ^ wa->val) & wa->read) { - DRM_ERROR("%s workaround lost on %s! (%x=%x/%x, expected %x, mask=%x)\n", + if ((cur ^ wa->set) & wa->read) { + DRM_ERROR("%s workaround lost on %s! (%x=%x/%x, expected %x)\n", name, from, i915_mmio_reg_offset(wa->reg), - cur, cur & wa->read, - wa->val, wa->mask); + cur, cur & wa->read, wa->set); return false; } @@ -1020,7 +1024,10 @@ wa_list_apply(struct intel_uncore *uncore, const struct i915_wa_list *wal) intel_uncore_forcewake_get__locked(uncore, fw); for (i = 0, wa = wal->list; i < wal->count; i++, wa++) { - intel_uncore_rmw_fw(uncore, wa->reg, wa->mask, wa->val); + if (wa->clr) + intel_uncore_rmw_fw(uncore, wa->reg, wa->clr, wa->set); + else + intel_uncore_write_fw(uncore, wa->reg, wa->set); if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) wa_verify(wa, intel_uncore_read_fw(uncore, wa->reg), @@ -1254,6 +1261,9 @@ static void tgl_whitelist_build(struct intel_engine_cs *engine) whitelist_reg_ext(w, PS_INVOCATION_COUNT, RING_FORCE_TO_NONPRIV_ACCESS_RD | RING_FORCE_TO_NONPRIV_RANGE_4); + + /* Wa_1808121037:tgl */ + whitelist_reg(w, GEN7_COMMON_SLICE_CHICKEN1); break; default: break; @@ -1345,6 +1355,16 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) wa_write_or(wal, GEN7_SARCHKMD, GEN7_DISABLE_SAMPLER_PREFETCH); + + /* Wa_1407928979:tgl */ + wa_write_or(wal, + GEN7_FF_THREAD_MODE, + GEN12_FF_TESSELATION_DOP_GATE_DISABLE); + + /* Wa_1606931601:tgl */ + wa_masked_en(wal, + GEN7_ROW_CHICKEN2, + GEN12_DISABLE_EARLY_READ); } if (IS_GEN(i915, 11)) { @@ -1457,6 +1477,52 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) GEN8_L3SQCREG4, GEN8_LQSC_FLUSH_COHERENT_LINES); } + + if (IS_GEN(i915, 7)) + /* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */ + wa_masked_en(wal, + GFX_MODE_GEN7, + GFX_TLB_INVALIDATE_EXPLICIT | GFX_REPLAY_MODE); + + if (IS_GEN_RANGE(i915, 6, 7)) + /* + * We need to disable the AsyncFlip performance optimisations in + * order to use MI_WAIT_FOR_EVENT within the CS. It should + * already be programmed to '1' on all products. + * + * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv + */ + wa_masked_en(wal, + MI_MODE, + ASYNC_FLIP_PERF_DISABLE); + + if (IS_GEN(i915, 6)) { + /* + * Required for the hardware to program scanline values for + * waiting + * WaEnableFlushTlbInvalidationMode:snb + */ + wa_masked_en(wal, + GFX_MODE, + GFX_TLB_INVALIDATE_EXPLICIT); + + /* + * From the Sandybridge PRM, volume 1 part 3, page 24: + * "If this bit is set, STCunit will have LRA as replacement + * policy. [...] This bit must be reset. LRA replacement + * policy is not supported." + */ + wa_masked_dis(wal, + CACHE_MODE_0, + CM0_STC_EVICT_DISABLE_LRA_SNB); + } + + if (IS_GEN_RANGE(i915, 4, 6)) + /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ + wa_add(wal, MI_MODE, + 0, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH), + /* XXX bit doesn't stick on Broadwater */ + IS_I965G(i915) ? 0 : VS_TIMER_DISPATCH); } static void @@ -1475,7 +1541,7 @@ xcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) static void engine_init_workarounds(struct intel_engine_cs *engine, struct i915_wa_list *wal) { - if (I915_SELFTEST_ONLY(INTEL_GEN(engine->i915) < 8)) + if (I915_SELFTEST_ONLY(INTEL_GEN(engine->i915) < 4)) return; if (engine->class == RENDER_CLASS) @@ -1488,7 +1554,7 @@ void intel_engine_init_workarounds(struct intel_engine_cs *engine) { struct i915_wa_list *wal = &engine->wa_list; - if (INTEL_GEN(engine->i915) < 8) + if (INTEL_GEN(engine->i915) < 4) return; wa_init_start(wal, "engine", engine->name); @@ -1612,6 +1678,16 @@ static int engine_wa_list_verify(struct intel_context *ce, goto err_vma; } + i915_vma_lock(vma); + err = i915_request_await_object(rq, vma->obj, true); + if (err == 0) + err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); + i915_vma_unlock(vma); + if (err) { + i915_request_add(rq); + goto err_vma; + } + err = wa_list_srm(rq, wal, vma); if (err) goto err_vma; |