Commit 69bcdecf authored by Tvrtko Ursulin's avatar Tvrtko Ursulin

drm/i915: Move register white-listing to the common workaround framework

Instead of having a separate list of white-listed registers we can
trivially move this to the common workarounds framework.

This brings us one step closer to the goal of driving all workaround
classes using the same code.

v2:
 * Use GEM_DEBUG_WARN_ON for the sanity check. (Chris Wilson)

v3:
 * API rename. (Chris Wilson)
Signed-off-by: default avatarTvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20181203125014.3219-6-tvrtko.ursulin@linux.intel.com
parent 28d6ccce
......@@ -725,6 +725,7 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine)
i915_timeline_fini(&engine->timeline);
intel_wa_list_free(&engine->wa_list);
intel_wa_list_free(&engine->whitelist);
}
u64 intel_engine_get_active_head(const struct intel_engine_cs *engine)
......
......@@ -1652,7 +1652,7 @@ static int gen8_init_render_ring(struct intel_engine_cs *engine)
if (ret)
return ret;
intel_whitelist_workarounds_apply(engine);
intel_engine_apply_whitelist(engine);
/* We need to disable the AsyncFlip performance optimisations in order
* to use MI_WAIT_FOR_EVENT within the CS. It should already be
......@@ -1675,7 +1675,7 @@ static int gen9_init_render_ring(struct intel_engine_cs *engine)
if (ret)
return ret;
intel_whitelist_workarounds_apply(engine);
intel_engine_apply_whitelist(engine);
return 0;
}
......@@ -2307,6 +2307,7 @@ int logical_render_ring_init(struct intel_engine_cs *engine)
ret);
}
intel_engine_init_whitelist(engine);
intel_engine_init_workarounds(engine);
return 0;
......
......@@ -437,6 +437,7 @@ struct intel_engine_cs {
struct intel_hw_status_page status_page;
struct i915_ctx_workarounds wa_ctx;
struct i915_wa_list wa_list;
struct i915_wa_list whitelist;
struct i915_vma *scratch;
u32 irq_keep_mask; /* always keep these interrupts */
......
......@@ -1011,29 +1011,20 @@ bool intel_gt_verify_workarounds(struct drm_i915_private *dev_priv,
return wa_list_verify(dev_priv, &dev_priv->gt_wa_list, from);
}
struct whitelist {
i915_reg_t reg[RING_MAX_NONPRIV_SLOTS];
unsigned int count;
u32 nopid;
};
static void whitelist_reg(struct whitelist *w, i915_reg_t reg)
static void
whitelist_reg(struct i915_wa_list *wal, i915_reg_t reg)
{
if (GEM_DEBUG_WARN_ON(w->count >= RING_MAX_NONPRIV_SLOTS))
return;
w->reg[w->count++] = reg;
}
struct i915_wa wa = {
.reg = reg
};
static void bdw_whitelist_build(struct whitelist *w)
{
}
if (GEM_DEBUG_WARN_ON(wal->count >= RING_MAX_NONPRIV_SLOTS))
return;
static void chv_whitelist_build(struct whitelist *w)
{
wal_add(wal, &wa);
}
static void gen9_whitelist_build(struct whitelist *w)
static void gen9_whitelist_build(struct i915_wa_list *w)
{
/* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt,glk,cfl */
whitelist_reg(w, GEN9_CTX_PREEMPT_REG);
......@@ -1045,7 +1036,7 @@ static void gen9_whitelist_build(struct whitelist *w)
whitelist_reg(w, GEN8_HDC_CHICKEN1);
}
static void skl_whitelist_build(struct whitelist *w)
static void skl_whitelist_build(struct i915_wa_list *w)
{
gen9_whitelist_build(w);
......@@ -1053,12 +1044,12 @@ static void skl_whitelist_build(struct whitelist *w)
whitelist_reg(w, GEN8_L3SQCREG4);
}
static void bxt_whitelist_build(struct whitelist *w)
static void bxt_whitelist_build(struct i915_wa_list *w)
{
gen9_whitelist_build(w);
}
static void kbl_whitelist_build(struct whitelist *w)
static void kbl_whitelist_build(struct i915_wa_list *w)
{
gen9_whitelist_build(w);
......@@ -1066,7 +1057,7 @@ static void kbl_whitelist_build(struct whitelist *w)
whitelist_reg(w, GEN8_L3SQCREG4);
}
static void glk_whitelist_build(struct whitelist *w)
static void glk_whitelist_build(struct i915_wa_list *w)
{
gen9_whitelist_build(w);
......@@ -1074,18 +1065,18 @@ static void glk_whitelist_build(struct whitelist *w)
whitelist_reg(w, GEN9_SLICE_COMMON_ECO_CHICKEN1);
}
static void cfl_whitelist_build(struct whitelist *w)
static void cfl_whitelist_build(struct i915_wa_list *w)
{
gen9_whitelist_build(w);
}
static void cnl_whitelist_build(struct whitelist *w)
static void cnl_whitelist_build(struct i915_wa_list *w)
{
/* WaEnablePreemptionGranularityControlByUMD:cnl */
whitelist_reg(w, GEN8_CS_CHICKEN1);
}
static void icl_whitelist_build(struct whitelist *w)
static void icl_whitelist_build(struct i915_wa_list *w)
{
/* WaAllowUMDToModifyHalfSliceChicken7:icl */
whitelist_reg(w, GEN9_HALF_SLICE_CHICKEN7);
......@@ -1094,22 +1085,21 @@ static void icl_whitelist_build(struct whitelist *w)
whitelist_reg(w, GEN10_SAMPLER_MODE);
}
static struct whitelist *whitelist_build(struct intel_engine_cs *engine,
struct whitelist *w)
void intel_engine_init_whitelist(struct intel_engine_cs *engine)
{
struct drm_i915_private *i915 = engine->i915;
struct i915_wa_list *w = &engine->whitelist;
GEM_BUG_ON(engine->id != RCS);
w->count = 0;
w->nopid = i915_mmio_reg_offset(RING_NOPID(engine->mmio_base));
wa_init_start(w, "whitelist");
if (INTEL_GEN(i915) < 8)
return NULL;
return;
else if (IS_BROADWELL(i915))
bdw_whitelist_build(w);
return;
else if (IS_CHERRYVIEW(i915))
chv_whitelist_build(w);
return;
else if (IS_SKYLAKE(i915))
skl_whitelist_build(w);
else if (IS_BROXTON(i915))
......@@ -1127,37 +1117,30 @@ static struct whitelist *whitelist_build(struct intel_engine_cs *engine,
else
MISSING_CASE(INTEL_GEN(i915));
return w;
wa_init_finish(w);
}
static void whitelist_apply(struct intel_engine_cs *engine,
const struct whitelist *w)
void intel_engine_apply_whitelist(struct intel_engine_cs *engine)
{
struct drm_i915_private *dev_priv = engine->i915;
const struct i915_wa_list *wal = &engine->whitelist;
const u32 base = engine->mmio_base;
struct i915_wa *wa;
unsigned int i;
if (!w)
if (!wal->count)
return;
intel_uncore_forcewake_get(engine->i915, FORCEWAKE_ALL);
for (i = 0; i < w->count; i++)
I915_WRITE_FW(RING_FORCE_TO_NONPRIV(base, i),
i915_mmio_reg_offset(w->reg[i]));
for (i = 0, wa = wal->list; i < wal->count; i++, wa++)
I915_WRITE(RING_FORCE_TO_NONPRIV(base, i),
i915_mmio_reg_offset(wa->reg));
/* And clear the rest just in case of garbage */
for (; i < RING_MAX_NONPRIV_SLOTS; i++)
I915_WRITE_FW(RING_FORCE_TO_NONPRIV(base, i), w->nopid);
intel_uncore_forcewake_put(engine->i915, FORCEWAKE_ALL);
}
I915_WRITE(RING_FORCE_TO_NONPRIV(base, i),
i915_mmio_reg_offset(RING_NOPID(base)));
void intel_whitelist_workarounds_apply(struct intel_engine_cs *engine)
{
struct whitelist w;
whitelist_apply(engine, whitelist_build(engine, &w));
DRM_DEBUG_DRIVER("Applied %u %s workarounds\n", wal->count, wal->name);
}
static void rcs_engine_wa_init(struct intel_engine_cs *engine)
......
......@@ -35,7 +35,8 @@ void intel_gt_apply_workarounds(struct drm_i915_private *dev_priv);
bool intel_gt_verify_workarounds(struct drm_i915_private *dev_priv,
const char *from);
void intel_whitelist_workarounds_apply(struct intel_engine_cs *engine);
void intel_engine_init_whitelist(struct intel_engine_cs *engine);
void intel_engine_apply_whitelist(struct intel_engine_cs *engine);
void intel_engine_init_workarounds(struct intel_engine_cs *engine);
void intel_engine_apply_workarounds(struct intel_engine_cs *engine);
......
......@@ -94,17 +94,23 @@ read_nonprivs(struct i915_gem_context *ctx, struct intel_engine_cs *engine)
return ERR_PTR(err);
}
static u32 get_whitelist_reg(const struct whitelist *w, unsigned int i)
static u32
get_whitelist_reg(const struct intel_engine_cs *engine, unsigned int i)
{
return i < w->count ? i915_mmio_reg_offset(w->reg[i]) : w->nopid;
i915_reg_t reg = i < engine->whitelist.count ?
engine->whitelist.list[i].reg :
RING_NOPID(engine->mmio_base);
return i915_mmio_reg_offset(reg);
}
static void print_results(const struct whitelist *w, const u32 *results)
static void
print_results(const struct intel_engine_cs *engine, const u32 *results)
{
unsigned int i;
for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
u32 expected = get_whitelist_reg(w, i);
u32 expected = get_whitelist_reg(engine, i);
u32 actual = results[i];
pr_info("RING_NONPRIV[%d]: expected 0x%08x, found 0x%08x\n",
......@@ -112,8 +118,7 @@ static void print_results(const struct whitelist *w, const u32 *results)
}
}
static int check_whitelist(const struct whitelist *w,
struct i915_gem_context *ctx,
static int check_whitelist(struct i915_gem_context *ctx,
struct intel_engine_cs *engine)
{
struct drm_i915_gem_object *results;
......@@ -141,11 +146,11 @@ static int check_whitelist(const struct whitelist *w,
}
for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
u32 expected = get_whitelist_reg(w, i);
u32 expected = get_whitelist_reg(engine, i);
u32 actual = vaddr[i];
if (expected != actual) {
print_results(w, vaddr);
print_results(engine, vaddr);
pr_err("Invalid RING_NONPRIV[%d], expected 0x%08x, found 0x%08x\n",
i, expected, actual);
......@@ -217,7 +222,6 @@ switch_to_scratch_context(struct intel_engine_cs *engine,
static int check_whitelist_across_reset(struct intel_engine_cs *engine,
int (*reset)(struct intel_engine_cs *),
const struct whitelist *w,
const char *name)
{
struct drm_i915_private *i915 = engine->i915;
......@@ -227,7 +231,7 @@ static int check_whitelist_across_reset(struct intel_engine_cs *engine,
int err;
pr_info("Checking %d whitelisted registers (RING_NONPRIV) [%s]\n",
w->count, name);
engine->whitelist.count, name);
if (want_spin) {
err = igt_spinner_init(&spin, i915);
......@@ -239,7 +243,7 @@ static int check_whitelist_across_reset(struct intel_engine_cs *engine,
if (IS_ERR(ctx))
return PTR_ERR(ctx);
err = check_whitelist(w, ctx, engine);
err = check_whitelist(ctx, engine);
if (err) {
pr_err("Invalid whitelist *before* %s reset!\n", name);
goto out;
......@@ -263,7 +267,7 @@ static int check_whitelist_across_reset(struct intel_engine_cs *engine,
goto out;
}
err = check_whitelist(w, ctx, engine);
err = check_whitelist(ctx, engine);
if (err) {
pr_err("Whitelist not preserved in context across %s reset!\n",
name);
......@@ -276,7 +280,7 @@ static int check_whitelist_across_reset(struct intel_engine_cs *engine,
if (IS_ERR(ctx))
return PTR_ERR(ctx);
err = check_whitelist(w, ctx, engine);
err = check_whitelist(ctx, engine);
if (err) {
pr_err("Invalid whitelist *after* %s reset in fresh context!\n",
name);
......@@ -292,22 +296,18 @@ static int live_reset_whitelist(void *arg)
{
struct drm_i915_private *i915 = arg;
struct intel_engine_cs *engine = i915->engine[RCS];
struct whitelist w;
int err = 0;
/* If we reset the gpu, we should not lose the RING_NONPRIV */
if (!engine)
return 0;
if (!whitelist_build(engine, &w))
if (!engine || engine->whitelist.count == 0)
return 0;
igt_global_reset_lock(i915);
if (intel_has_reset_engine(i915)) {
err = check_whitelist_across_reset(engine,
do_engine_reset, &w,
do_engine_reset,
"engine");
if (err)
goto out;
......@@ -315,7 +315,7 @@ static int live_reset_whitelist(void *arg)
if (intel_has_gpu_reset(i915)) {
err = check_whitelist_across_reset(engine,
do_device_reset, &w,
do_device_reset,
"device");
if (err)
goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment