By doing this, we can dump these workarounds in debugfs for validation (which, at the moment, we are only able to do for the contexts WAs). v2: - Wrong macro used for MMIO set bit masked - Improved naming - Rebased v3: - GT instead of MMIO (Chris, Mika) - Leave L3_PRIO_CREDITS_MASK for a separate patch - Rebased v4: Carry the init_early nomenclature over (Chris) Signed-off-by: Oscar Mateo <oscar.mateo@xxxxxxxxx> Cc: Mika Kuoppala <mika.kuoppala@xxxxxxxxxxxxxxx> Cc: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> Reviewed-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/i915_drv.c | 5 + drivers/gpu/drm/i915/i915_drv.h | 4 + drivers/gpu/drm/i915/intel_workarounds.c | 247 ++++++++++++++++++++----------- drivers/gpu/drm/i915/intel_workarounds.h | 1 + 4 files changed, 170 insertions(+), 87 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index af74574..361d4a3 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -49,6 +49,7 @@ #include "i915_drv.h" #include "i915_trace.h" #include "i915_vgpu.h" +#include "intel_workarounds.h" #include "intel_drv.h" #include "intel_uc.h" @@ -886,6 +887,10 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, BUG_ON(device_info->gen > sizeof(device_info->gen_mask) * BITS_PER_BYTE); device_info->gen_mask = BIT(device_info->gen - 1); + ret = intel_gt_workarounds_init_early(dev_priv); + if (ret < 0) + return ret; + spin_lock_init(&dev_priv->irq_lock); spin_lock_init(&dev_priv->gpu_error.lock); mutex_init(&dev_priv->backlight_lock); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e6daf53..ca88f31 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1976,11 +1976,15 @@ struct i915_wa_reg { }; #define I915_MAX_CTX_WA_REGS 16 +#define I915_MAX_MMIO_WA_REGS 32 struct i915_workarounds { struct i915_wa_reg ctx_wa_reg[I915_MAX_CTX_WA_REGS]; u32 ctx_wa_count; + struct i915_wa_reg gt_wa_reg[I915_MAX_MMIO_WA_REGS]; + u32 gt_wa_count; + u32 hw_whitelist_count[I915_NUM_ENGINES]; }; diff --git a/drivers/gpu/drm/i915/intel_workarounds.c b/drivers/gpu/drm/i915/intel_workarounds.c index f4bc2d3..51868fe 100644 --- a/drivers/gpu/drm/i915/intel_workarounds.c +++ b/drivers/gpu/drm/i915/intel_workarounds.c @@ -513,15 +513,53 @@ int intel_ctx_workarounds_emit(struct drm_i915_gem_request *req) return 0; } -static void bdw_gt_workarounds_apply(struct drm_i915_private *dev_priv) +static int gt_wa_add(struct drm_i915_private *dev_priv, + i915_reg_t addr, + const u32 mask, const u32 val) { + const u32 idx = dev_priv->workarounds.gt_wa_count; + + if (WARN_ON(idx >= I915_MAX_MMIO_WA_REGS)) + return -ENOSPC; + + dev_priv->workarounds.gt_wa_reg[idx].addr = addr; + dev_priv->workarounds.gt_wa_reg[idx].value = val; + dev_priv->workarounds.gt_wa_reg[idx].mask = mask; + + dev_priv->workarounds.gt_wa_count++; + + return 0; +} + +#define GT_WA_REG(addr, mask, val) do { \ + const int r = gt_wa_add(dev_priv, (addr), (mask), (val)); \ + if (r) \ + return r; \ + } while (0) + +#define GT_WA_SET_BIT(addr, mask) \ + GT_WA_REG(addr, (mask), (mask)) + +#define GT_WA_SET_BIT_MASKED(addr, mask) \ + GT_WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask)) + +#define GT_WA_CLR_BIT(addr, mask) \ + GT_WA_REG(addr, (mask), 0) + +#define GT_WA_SET_FIELD(addr, mask, value) \ + GT_WA_REG(addr, (mask), (value)) + +static int bdw_gt_workarounds_init_early(struct drm_i915_private *dev_priv) +{ + return 0; } -static void chv_gt_workarounds_apply(struct drm_i915_private *dev_priv) +static int chv_gt_workarounds_init_early(struct drm_i915_private *dev_priv) { + return 0; } -static void gen9_gt_workarounds_apply(struct drm_i915_private *dev_priv) +static int gen9_gt_workarounds_init_early(struct drm_i915_private *dev_priv) { if (HAS_LLC(dev_priv)) { /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl,kbl @@ -529,180 +567,215 @@ static void gen9_gt_workarounds_apply(struct drm_i915_private *dev_priv) * Must match Display Engine. See * WaCompressedResourceDisplayNewHashMode. */ - I915_WRITE(MMCD_MISC_CTRL, - I915_READ(MMCD_MISC_CTRL) | - MMCD_PCLA | - MMCD_HOTSPOT_EN); + GT_WA_SET_BIT(MMCD_MISC_CTRL, MMCD_PCLA | MMCD_HOTSPOT_EN); } /* WaContextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl,glk,cfl */ - I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, - _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE)); + GT_WA_SET_BIT_MASKED(GEN9_CSFE_CHICKEN1_RCS, + GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE); /* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl,glk,cfl */ - I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) | - GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE); + GT_WA_SET_BIT(BDW_SCRATCH1, GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE); /* WaDisableKillLogic:bxt,skl,kbl */ if (!IS_COFFEELAKE(dev_priv)) - I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | - ECOCHK_DIS_TLB); + GT_WA_SET_BIT(GAM_ECOCHK, ECOCHK_DIS_TLB); /* WaDisableHDCInvalidation:skl,bxt,kbl,cfl */ - I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | - BDW_DISABLE_HDC_INVALIDATION); + GT_WA_SET_BIT(GAM_ECOCHK, BDW_DISABLE_HDC_INVALIDATION); /* WaOCLCoherentLineFlush:skl,bxt,kbl,cfl */ - I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) | - GEN8_LQSC_FLUSH_COHERENT_LINES)); + GT_WA_SET_BIT(GEN8_L3SQCREG4, GEN8_LQSC_FLUSH_COHERENT_LINES); /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl,cfl,[cnl] */ - I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, - _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); + GT_WA_SET_BIT_MASKED(GEN7_FF_SLICE_CS_CHICKEN1, + GEN9_FFSC_PERCTX_PREEMPT_CTRL); + + return 0; } -static void skl_gt_workarounds_apply(struct drm_i915_private *dev_priv) +static int skl_gt_workarounds_init_early(struct drm_i915_private *dev_priv) { - gen9_gt_workarounds_apply(dev_priv); + int ret; + + ret = gen9_gt_workarounds_init_early(dev_priv); + if (ret) + return ret; /* WaEnableGapsTsvCreditFix:skl */ - I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | - GEN9_GAPS_TSV_CREDIT_DISABLE)); + GT_WA_SET_BIT(GEN8_GARBCNTL, GEN9_GAPS_TSV_CREDIT_DISABLE); /* WaDisableGafsUnitClkGating:skl */ - I915_WRITE(GEN7_UCGCTL4, (I915_READ(GEN7_UCGCTL4) | - GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE)); + GT_WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); /* WaInPlaceDecompressionHang:skl */ if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER)) - I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, - (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | - GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); + GT_WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, + GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); + + return 0; } -static void bxt_gt_workarounds_apply(struct drm_i915_private *dev_priv) +static int bxt_gt_workarounds_init_early(struct drm_i915_private *dev_priv) { - gen9_gt_workarounds_apply(dev_priv); + int ret; + + ret = gen9_gt_workarounds_init_early(dev_priv); + if (ret) + return ret; /* WaStoreMultiplePTEenable:bxt */ /* This is a requirement according to Hardware specification */ if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) - I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF); + GT_WA_SET_BIT(TILECTL, TILECTL_TLBPF); /* WaSetClckGatingDisableMedia:bxt */ if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { - I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) & - ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE)); + GT_WA_CLR_BIT(GEN7_MISCCPCTL, GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE); } /* WaDisablePooledEuLoadBalancingFix:bxt */ if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) { - I915_WRITE(FF_SLICE_CS_CHICKEN2, - _MASKED_BIT_ENABLE(GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE)); + GT_WA_SET_BIT_MASKED(FF_SLICE_CS_CHICKEN2, + GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE); } /* WaProgramL3SqcReg1DefaultForPerf:bxt */ - if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) { - u32 val = I915_READ(GEN8_L3SQCREG1); - val &= ~L3_PRIO_CREDITS_MASK; - val |= L3_GENERAL_PRIO_CREDITS(62) | L3_HIGH_PRIO_CREDITS(2); - I915_WRITE(GEN8_L3SQCREG1, val); - } + if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) + GT_WA_SET_FIELD(GEN8_L3SQCREG1, L3_PRIO_CREDITS_MASK, + L3_GENERAL_PRIO_CREDITS(62) | + L3_HIGH_PRIO_CREDITS(2)); /* WaInPlaceDecompressionHang:bxt */ if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER)) - I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, - (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | - GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); + GT_WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, + GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); + + return 0; } -static void kbl_gt_workarounds_apply(struct drm_i915_private *dev_priv) +static int kbl_gt_workarounds_init_early(struct drm_i915_private *dev_priv) { - gen9_gt_workarounds_apply(dev_priv); + int ret; + + ret = gen9_gt_workarounds_init_early(dev_priv); + if (ret) + return ret; /* WaEnableGapsTsvCreditFix:kbl */ - I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | - GEN9_GAPS_TSV_CREDIT_DISABLE)); + GT_WA_SET_BIT(GEN8_GARBCNTL, GEN9_GAPS_TSV_CREDIT_DISABLE); /* WaDisableDynamicCreditSharing:kbl */ if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) - I915_WRITE(GAMT_CHKN_BIT_REG, - (I915_READ(GAMT_CHKN_BIT_REG) | - GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING)); + GT_WA_SET_BIT(GAMT_CHKN_BIT_REG, + GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING); /* WaDisableGafsUnitClkGating:kbl */ - I915_WRITE(GEN7_UCGCTL4, (I915_READ(GEN7_UCGCTL4) | - GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE)); + GT_WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); /* WaInPlaceDecompressionHang:kbl */ - I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, - (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | - GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); + GT_WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, + GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); + + return 0; } -static void glk_gt_workarounds_apply(struct drm_i915_private *dev_priv) +static int glk_gt_workarounds_init_early(struct drm_i915_private *dev_priv) { - gen9_gt_workarounds_apply(dev_priv); + int ret = gen9_gt_workarounds_init_early(dev_priv); + if (ret) + return ret; + + return 0; } -static void cfl_gt_workarounds_apply(struct drm_i915_private *dev_priv) +static int cfl_gt_workarounds_init_early(struct drm_i915_private *dev_priv) { - gen9_gt_workarounds_apply(dev_priv); + int ret; + + ret = gen9_gt_workarounds_init_early(dev_priv); + if (ret) + return ret; /* WaEnableGapsTsvCreditFix:cfl */ - I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | - GEN9_GAPS_TSV_CREDIT_DISABLE)); + GT_WA_SET_BIT(GEN8_GARBCNTL, GEN9_GAPS_TSV_CREDIT_DISABLE); /* WaDisableGafsUnitClkGating:cfl */ - I915_WRITE(GEN7_UCGCTL4, (I915_READ(GEN7_UCGCTL4) | - GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE)); + GT_WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); /* WaInPlaceDecompressionHang:cfl */ - I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, - (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | - GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); + GT_WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, + GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); + + return 0; } -static void cnl_gt_workarounds_apply(struct drm_i915_private *dev_priv) +static int cnl_gt_workarounds_init_early(struct drm_i915_private *dev_priv) { /* WaDisableI2mCycleOnWRPort:cnl (pre-prod) */ if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0)) - I915_WRITE(GAMT_CHKN_BIT_REG, - (I915_READ(GAMT_CHKN_BIT_REG) | - GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT)); + GT_WA_SET_BIT(GAMT_CHKN_BIT_REG, + GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT); /* WaInPlaceDecompressionHang:cnl */ - I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, - (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | - GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); + GT_WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, + GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); /* WaEnablePreemptionGranularityControlByUMD:cnl */ - I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, - _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); + GT_WA_SET_BIT_MASKED(GEN7_FF_SLICE_CS_CHICKEN1, + GEN9_FFSC_PERCTX_PREEMPT_CTRL); + + return 0; } -void intel_gt_workarounds_apply(struct drm_i915_private *dev_priv) +int intel_gt_workarounds_init_early(struct drm_i915_private *dev_priv) { + int err; + + dev_priv->workarounds.gt_wa_count = 0; + if (INTEL_GEN(dev_priv) < 8) - return; + err = 0; else if (IS_BROADWELL(dev_priv)) - bdw_gt_workarounds_apply(dev_priv); + err = bdw_gt_workarounds_init_early(dev_priv); else if (IS_CHERRYVIEW(dev_priv)) - chv_gt_workarounds_apply(dev_priv); + err = chv_gt_workarounds_init_early(dev_priv); else if (IS_SKYLAKE(dev_priv)) - skl_gt_workarounds_apply(dev_priv); + err = skl_gt_workarounds_init_early(dev_priv); else if (IS_BROXTON(dev_priv)) - bxt_gt_workarounds_apply(dev_priv); + err = bxt_gt_workarounds_init_early(dev_priv); else if (IS_KABYLAKE(dev_priv)) - kbl_gt_workarounds_apply(dev_priv); + err = kbl_gt_workarounds_init_early(dev_priv); else if (IS_GEMINILAKE(dev_priv)) - glk_gt_workarounds_apply(dev_priv); + err = glk_gt_workarounds_init_early(dev_priv); else if (IS_COFFEELAKE(dev_priv)) - cfl_gt_workarounds_apply(dev_priv); + err = cfl_gt_workarounds_init_early(dev_priv); else if (IS_CANNONLAKE(dev_priv)) - cnl_gt_workarounds_apply(dev_priv); - else + err = cnl_gt_workarounds_init_early(dev_priv); + else { MISSING_CASE(INTEL_GEN(dev_priv)); + err = 0; + } + if (err) + return err; + + DRM_DEBUG_DRIVER("Number of GT w/a: %d\n", + dev_priv->workarounds.gt_wa_count); + return 0; +} + +void intel_gt_workarounds_apply(struct drm_i915_private *dev_priv) +{ + struct i915_workarounds *w = &dev_priv->workarounds; + int i; + + for (i = 0; i < w->gt_wa_count; i++) { + i915_reg_t addr = w->gt_wa_reg[i].addr; + u32 value = w->gt_wa_reg[i].value; + u32 mask = w->gt_wa_reg[i].mask; + + I915_WRITE(addr, (I915_READ(addr) & ~mask) | value); + } } static int wa_ring_whitelist_reg(struct intel_engine_cs *engine, diff --git a/drivers/gpu/drm/i915/intel_workarounds.h b/drivers/gpu/drm/i915/intel_workarounds.h index bba51bb..19cd81e 100644 --- a/drivers/gpu/drm/i915/intel_workarounds.h +++ b/drivers/gpu/drm/i915/intel_workarounds.h @@ -28,6 +28,7 @@ int intel_ctx_workarounds_init(struct drm_i915_private *dev_priv); int intel_ctx_workarounds_emit(struct drm_i915_gem_request *req); +int intel_gt_workarounds_init_early(struct drm_i915_private *dev_priv); void intel_gt_workarounds_apply(struct drm_i915_private *dev_priv); int intel_whitelist_workarounds_apply(struct intel_engine_cs *engine); -- 1.9.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx