@@ -5154,11 +5154,7 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv)
goto out;
}
- ret = intel_wopcm_init_hw(&dev_priv->wopcm);
- if (ret) {
- DRM_ERROR("Enabling WOPCM failed (%d)\n", ret);
- goto out;
- }
+ intel_wopcm_init_hw(&dev_priv->wopcm);
/* We can't enable contexts until all firmware is loaded */
ret = intel_uc_init_hw(dev_priv);
@@ -182,7 +182,7 @@ __guc_region_grow(struct intel_wopcm *wopcm, u32 size)
wopcm->guc.size += size;
}
-static void wopcm_adjust_for_hw_restrictions(struct intel_wopcm *wopcm)
+static int wopcm_adjust_for_hw_restrictions(struct intel_wopcm *wopcm)
{
struct drm_i915_private *i915 = wopcm_to_i915(wopcm);
u32 huc_fw_size = intel_uc_fw_get_upload_size(&i915->huc.fw);
@@ -191,19 +191,29 @@ static void wopcm_adjust_for_hw_restrictions(struct intel_wopcm *wopcm)
if (IS_GEN9(i915) || IS_CNL_REVID(i915, CNL_REVID_A0, CNL_REVID_A0)) {
size = gen9_size_for_dword_gap_restriction(wopcm->guc.base,
wopcm->guc.size);
- if (size)
+ if (size) {
+ if (wopcm->guc.base_locked || wopcm->guc.size_locked)
+ return -E2BIG;
+
__guc_region_grow(wopcm, size);
+ }
size = gen9_size_for_huc_restriction(wopcm->guc.size,
huc_fw_size);
- if (size)
+ if (size) {
+ if (wopcm->guc.base_locked || wopcm->guc.size_locked)
+ return -E2BIG;
+
__guc_region_grow(wopcm, size);
+ }
GEM_BUG_ON(gen9_size_for_dword_gap_restriction(wopcm->guc.base,
wopcm->guc.size));
GEM_BUG_ON(gen9_size_for_huc_restriction(wopcm->guc.size,
huc_fw_size));
}
+
+ return 0;
}
static bool wopcm_check_components_fit(struct intel_wopcm *wopcm)
@@ -233,12 +243,30 @@ static int wopcm_guc_region_init(struct intel_wopcm *wopcm)
{
struct drm_i915_private *dev_priv = wopcm_to_i915(wopcm);
u32 guc_fw_size = intel_uc_fw_get_upload_size(&dev_priv->guc.fw);
+ u32 huc_fw_size = intel_uc_fw_get_upload_size(&dev_priv->huc.fw);
u32 ctx_rsvd = context_reserved_size(dev_priv);
+ u32 reg_val;
- wopcm->guc.size = guc_fw_size_in_wopcm(guc_fw_size);
+ reg_val = I915_READ(GUC_WOPCM_SIZE);
+ if (reg_val & GUC_WOPCM_SIZE_LOCKED) {
+ wopcm->guc.size = (reg_val & GUC_WOPCM_SIZE_MASK);
+ wopcm->guc.size_locked = true;
+ } else {
+ wopcm->guc.size = guc_fw_size_in_wopcm(guc_fw_size);
+ }
- wopcm->guc.base = ALIGN_DOWN(wopcm->size - ctx_rsvd - wopcm->guc.size,
- GUC_WOPCM_OFFSET_ALIGNMENT);
+ reg_val = I915_READ(DMA_GUC_WOPCM_OFFSET);
+ if (reg_val & GUC_WOPCM_OFFSET_VALID) {
+ if (huc_fw_size && !(reg_val & HUC_LOADING_AGENT_GUC))
+ return -EIO;
+
+ wopcm->guc.base = (reg_val & GUC_WOPCM_OFFSET_MASK);
+ wopcm->guc.base_locked = true;
+ } else {
+ wopcm->guc.base = ALIGN_DOWN(wopcm->size - wopcm->guc.size -
+ ctx_rsvd,
+ GUC_WOPCM_OFFSET_ALIGNMENT);
+ }
return 0;
}
@@ -265,7 +293,9 @@ int intel_wopcm_init(struct intel_wopcm *wopcm)
if (err)
return err;
- wopcm_adjust_for_hw_restrictions(wopcm);
+ err = wopcm_adjust_for_hw_restrictions(wopcm);
+ if (err)
+ return err;
err = wopcm_check_components_fit(wopcm);
if (err)
@@ -278,66 +308,37 @@ int intel_wopcm_init(struct intel_wopcm *wopcm)
return 0;
}
-static inline int write_and_verify(struct drm_i915_private *dev_priv,
- i915_reg_t reg, u32 val, u32 mask,
- u32 locked_bit)
-{
- u32 reg_val;
-
- GEM_BUG_ON(val & ~mask);
-
- I915_WRITE(reg, val);
-
- reg_val = I915_READ(reg);
-
- return (reg_val & mask) != (val | locked_bit) ? -EIO : 0;
-}
-
/**
* intel_wopcm_init_hw() - Setup GuC WOPCM registers.
* @wopcm: pointer to intel_wopcm.
*
- * Setup the GuC WOPCM size and offset registers with the calculated values. It
- * will verify the register values to make sure the registers are locked with
- * correct values.
+ * Setup the GuC WOPCM size and offset registers with the calculated values.
*
- * Return: 0 on success. -EIO if registers were locked with incorrect values.
*/
-int intel_wopcm_init_hw(struct intel_wopcm *wopcm)
+void intel_wopcm_init_hw(struct intel_wopcm *wopcm)
{
struct drm_i915_private *dev_priv = wopcm_to_i915(wopcm);
- u32 huc_agent;
- u32 mask;
- int err;
if (!USES_GUC(dev_priv))
- return 0;
+ return;
GEM_BUG_ON(!HAS_GUC(dev_priv));
GEM_BUG_ON(!wopcm->guc.size);
GEM_BUG_ON(!wopcm->guc.base);
- err = write_and_verify(dev_priv, GUC_WOPCM_SIZE, wopcm->guc.size,
- GUC_WOPCM_SIZE_MASK | GUC_WOPCM_SIZE_LOCKED,
- GUC_WOPCM_SIZE_LOCKED);
- if (err)
- goto err_out;
-
- huc_agent = USES_HUC(dev_priv) ? HUC_LOADING_AGENT_GUC : 0;
- mask = GUC_WOPCM_OFFSET_MASK | GUC_WOPCM_OFFSET_VALID | huc_agent;
- err = write_and_verify(dev_priv, DMA_GUC_WOPCM_OFFSET,
- wopcm->guc.base | huc_agent, mask,
- GUC_WOPCM_OFFSET_VALID);
- if (err)
- goto err_out;
-
- return 0;
-
-err_out:
- DRM_ERROR("Failed to init WOPCM registers:\n");
- DRM_ERROR("DMA_GUC_WOPCM_OFFSET=%#x\n",
- I915_READ(DMA_GUC_WOPCM_OFFSET));
- DRM_ERROR("GUC_WOPCM_SIZE=%#x\n", I915_READ(GUC_WOPCM_SIZE));
+ if (!wopcm->guc.size_locked) {
+ I915_WRITE(GUC_WOPCM_SIZE, wopcm->guc.size &
+ GUC_WOPCM_SIZE_MASK);
+ wopcm->guc.size_locked = true;
+ GEM_BUG_ON(!I915_READ(GUC_WOPCM_SIZE) & GUC_WOPCM_SIZE_LOCKED);
+ }
- return err;
+ if (!wopcm->guc.base_locked) {
+ I915_WRITE(DMA_GUC_WOPCM_OFFSET,
+ (GUC_WOPCM_OFFSET_MASK & wopcm->guc.base) |
+ HUC_LOADING_AGENT_GUC);
+ wopcm->guc.size_locked = true;
+ GEM_BUG_ON(!I915_READ(DMA_GUC_WOPCM_OFFSET) &
+ GUC_WOPCM_OFFSET_VALID);
+ }
}
@@ -14,18 +14,22 @@
* @size: Size of overall WOPCM.
* @guc: GuC WOPCM Region info.
* @guc.base: GuC WOPCM base which is offset from WOPCM base.
+ * @guc.base_locked: True if base register was locked during partitioning.
* @guc.size: Size of the GuC WOPCM region.
+ * @guc.size_locked: True if size register was locked during partitioning.
*/
struct intel_wopcm {
u32 size;
struct {
u32 base;
+ bool base_locked;
u32 size;
+ bool size_locked;
} guc;
};
void intel_wopcm_init_early(struct intel_wopcm *wopcm);
int intel_wopcm_init(struct intel_wopcm *wopcm);
-int intel_wopcm_init_hw(struct intel_wopcm *wopcm);
+void intel_wopcm_init_hw(struct intel_wopcm *wopcm);
#endif
It's possible that when we're being loaded, the write-once registers were already programmed. It's also possible, that values present in those registers match our FW size and HW restrictions. Rather than failing the module load when we detect any differences from our preferred values, let's replace them with what's present in the registers, failing the load only if we're unable to satisfy the constraints. Signed-off-by: Michał Winiarski <michal.winiarski@intel.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Jackie Li <yaodong.li@intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com> --- drivers/gpu/drm/i915/i915_gem.c | 6 +-- drivers/gpu/drm/i915/intel_wopcm.c | 107 +++++++++++++++++++------------------ drivers/gpu/drm/i915/intel_wopcm.h | 6 ++- 3 files changed, 60 insertions(+), 59 deletions(-)