diff mbox

[05/20] drm/i915: Save all GT WAs and apply them at a later time

Message ID 1509394647-23209-6-git-send-email-oscar.mateo@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

oscar.mateo@intel.com Oct. 30, 2017, 8:17 p.m. UTC
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@intel.com>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 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(-)

Comments

Joonas Lahtinen Oct. 31, 2017, 2:14 p.m. UTC | #1
On Mon, 2017-10-30 at 13:17 -0700, Oscar Mateo wrote:
> 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@intel.com>
> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>

This and the following patch are still a no-go and won't be merged. The
required changes for the series to be accepted (to make it more
declarative) were clearly described previously. If there are further
questions, we should discuss those instead wasting time looking at
respins that do not address the input given.

Respins that ignore review are a waste of everyone's time. So, please
react to the review instead of trying to brute force a series in as you
see fit.

Regards, Joonas
oscar.mateo@intel.com Oct. 31, 2017, 4:30 p.m. UTC | #2
On 10/31/2017 07:14 AM, Joonas Lahtinen wrote:
> On Mon, 2017-10-30 at 13:17 -0700, Oscar Mateo wrote:
>> 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@intel.com>
>> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
> This and the following patch are still a no-go and won't be merged. The
> required changes for the series to be accepted (to make it more
> declarative) were clearly described previously. If there are further
> questions, we should discuss those instead wasting time looking at
> respins that do not address the input given.
>
> Respins that ignore review are a waste of everyone's time. So, please
> react to the review instead of trying to brute force a series in as you
> see fit.
>
> Regards, Joonas

My apologies, I wasn't trying to "brute force" anything. I haven't been 
able to work on this for the last two weeks and I didn't want the issue 
to go cold, so I sent a version to attend to Ville's and Chris' review 
comments (this is useful anyway, because the same comments apply whether 
you go with functions or with a static table). I am working on a version 
that implements your suggestions and I will send it as soon as it's ready.

-- Oscar
David Weinehall Nov. 1, 2017, 10:46 a.m. UTC | #3
On Tue, Oct 31, 2017 at 09:30:27AM -0700, Oscar Mateo wrote:
> 
> 
> On 10/31/2017 07:14 AM, Joonas Lahtinen wrote:
> > On Mon, 2017-10-30 at 13:17 -0700, Oscar Mateo wrote:
> > > 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@intel.com>
> > > Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
> > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
> > This and the following patch are still a no-go and won't be merged. The
> > required changes for the series to be accepted (to make it more
> > declarative) were clearly described previously. If there are further
> > questions, we should discuss those instead wasting time looking at
> > respins that do not address the input given.
> > 
> > Respins that ignore review are a waste of everyone's time. So, please
> > react to the review instead of trying to brute force a series in as you
> > see fit.
> > 
> > Regards, Joonas
> 
> My apologies, I wasn't trying to "brute force" anything. I haven't been able
> to work on this for the last two weeks and I didn't want the issue to go
> cold, so I sent a version to attend to Ville's and Chris' review comments
> (this is useful anyway, because the same comments apply whether you go with
> functions or with a static table). I am working on a version that implements
> your suggestions and I will send it as soon as it's ready.

Typically when submitting a changeset that isn't ready to be merged,
you'd tag it RFC or similar.


Kind regards, David Weinehall
Chris Wilson Nov. 3, 2017, 2:31 a.m. UTC | #4
Quoting Joonas Lahtinen (2017-10-31 14:14:52)
> On Mon, 2017-10-30 at 13:17 -0700, Oscar Mateo wrote:
> > 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@intel.com>
> > Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
> 
> This and the following patch are still a no-go and won't be merged. The
> required changes for the series to be accepted (to make it more
> declarative) were clearly described previously. If there are further
> questions, we should discuss those instead wasting time looking at
> respins that do not address the input given.

I would like draw everyone's attention to

https://bugs.freedesktop.org/show_bug.cgi?id=103549

As much as I don't like gem_workarounds for its incestrous relationship
with the kernel it purports to be testing, that bug is exactly the type
of regression it prevents. It could not find this regression because it
requires us to be very formal in our w/a handling, i.e. we had not
declared the w/a for it to check; such formality being sought after here.

Whatever the design outcome, a good test plan is essential.
-Chris
diff mbox

Patch

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);