[PATCH 5/8] drm/i915/guc: Move WOPCM partitioning to init_early

Piotr Piórkowski piotr.piorkowski at intel.com
Thu Apr 5 12:53:54 UTC 2018


From: Michał Winiarski <michal.winiarski at intel.com>

Now that we know FW size early, we can reorder WOPCM with FW fetch and
partition early on. We can also separate actual partitioning from
constraints checking to reduce the code movement in following patches.

Signed-off-by: Michał Winiarski <michal.winiarski at intel.com>
Cc: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Jackie Li <yaodong.li at intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko at intel.com>
Cc: Piotr Piorkowski <piotr.piorkowski at intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c    |   2 +-
 drivers/gpu/drm/i915/intel_wopcm.c | 180 ++++++++++++++++++++++++-------------
 2 files changed, 121 insertions(+), 61 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index d354627882e3..7185231c6290 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -928,8 +928,8 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
 	/* This must be called before any calls to HAS_PCH_* */
 	intel_detect_pch(dev_priv);
 
-	intel_wopcm_init_early(&dev_priv->wopcm);
 	intel_uc_init_early(dev_priv);
+	intel_wopcm_init_early(&dev_priv->wopcm);
 	intel_pm_setup(dev_priv);
 	intel_init_dpio(dev_priv);
 	intel_power_domains_init(dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_wopcm.c b/drivers/gpu/drm/i915/intel_wopcm.c
index 6eeedb6a24fc..75ce4291188e 100644
--- a/drivers/gpu/drm/i915/intel_wopcm.c
+++ b/drivers/gpu/drm/i915/intel_wopcm.c
@@ -66,22 +66,6 @@
 #define GEN10_GUC_FW_RESERVED	(256 * 1024)
 #define GEN10_GUC_WOPCM_OFFSET	(GUC_WOPCM_RESERVED + GEN10_GUC_FW_RESERVED)
 
-/**
- * intel_wopcm_init_early() - Early initialization of the WOPCM.
- * @wopcm: pointer to intel_wopcm.
- *
- * Setup the size of WOPCM which will be used by later on WOPCM partitioning.
- */
-void intel_wopcm_init_early(struct intel_wopcm *wopcm)
-{
-	if (!HAS_GUC(wopcm_to_i915(wopcm)))
-		return;
-
-	wopcm->size = GEN9_WOPCM_SIZE;
-
-	DRM_DEBUG_DRIVER("WOPCM size: %uKiB\n", wopcm->size / 1024);
-}
-
 static inline u32 context_reserved_size(struct drm_i915_private *i915)
 {
 	if (IS_GEN9_LP(i915))
@@ -92,6 +76,17 @@ static inline u32 context_reserved_size(struct drm_i915_private *i915)
 		return 0;
 }
 
+static inline u32 guc_fw_size_in_wopcm(u32 guc_fw_size)
+{
+	return ALIGN(guc_fw_size + GUC_WOPCM_RESERVED +
+		     GUC_WOPCM_STACK_RESERVED, PAGE_SIZE);
+}
+
+static inline u32 huc_fw_size_in_wopcm(u32 huc_fw_size)
+{
+	return huc_fw_size + WOPCM_RESERVED_SIZE;
+}
+
 static u32
 additional_size_for_dword_gap_restriction(struct drm_i915_private *i915,
 					  u32 guc_wopcm_base,
@@ -141,18 +136,18 @@ additional_size_for_huc_restriction(struct drm_i915_private *i915,
 	return additional_size;
 }
 
-static inline int check_hw_restriction(struct drm_i915_private *i915,
-				       u32 guc_wopcm_base, u32 guc_wopcm_size,
-				       u32 huc_fw_size)
+static int wopcm_check_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);
 	u32 size;
 
-	size = additional_size_for_dword_gap_restriction(i915, guc_wopcm_base,
-							 guc_wopcm_size);
+	size = additional_size_for_dword_gap_restriction(i915, wopcm->guc.base,
+							 wopcm->guc.size);
 	if (size)
 		goto err;
 
-	size = additional_size_for_huc_restriction(i915, guc_wopcm_size,
+	size = additional_size_for_huc_restriction(i915, wopcm->guc.size,
 						   huc_fw_size);
 	if (size)
 		goto err;
@@ -161,69 +156,134 @@ static inline int check_hw_restriction(struct drm_i915_private *i915,
 
 err:
 	DRM_ERROR("GuC WOPCM size %uKiB is too small. %uKiB more needed.\n",
-		  guc_wopcm_size / 1024,
+		  wopcm->guc.size / 1024,
 		  size / 1024);
 
 	return -E2BIG;
 }
 
+static void wopcm_guc_region_init(struct intel_wopcm *wopcm)
+{
+	struct drm_i915_private *dev_priv = wopcm_to_i915(wopcm);
+	u32 huc_fw_size = intel_uc_fw_get_upload_size(&dev_priv->huc.fw);
+	u32 ctx_rsvd = context_reserved_size(dev_priv);
+
+	GEM_BUG_ON(!wopcm->size);
+
+	wopcm->guc.base = ALIGN(huc_fw_size_in_wopcm(huc_fw_size),
+				GUC_WOPCM_OFFSET_ALIGNMENT);
+
+	wopcm->guc.size = ALIGN(wopcm->size - wopcm->guc.base - ctx_rsvd,
+				PAGE_SIZE);
+}
+
 /**
- * intel_wopcm_init() - Initialize the WOPCM structure.
+ * intel_wopcm_init_early() - Early initialization of the WOPCM.
  * @wopcm: pointer to intel_wopcm.
  *
- * This function will partition WOPCM space based on GuC and HuC firmware sizes
- * and will allocate max remaining for use by GuC. This function will also
- * enforce platform dependent hardware restrictions on GuC WOPCM offset and
- * size. It will fail the WOPCM init if any of these checks were failed, so that
- * the following GuC firmware uploading would be aborted.
- *
- * Return: 0 on success, non-zero error code on failure.
+ * Setup the size of WOPCM and partition the GuC region.
  */
-int intel_wopcm_init(struct intel_wopcm *wopcm)
+void intel_wopcm_init_early(struct intel_wopcm *wopcm)
 {
 	struct drm_i915_private *i915 = wopcm_to_i915(wopcm);
-	u32 guc_fw_size = intel_uc_fw_get_upload_size(&i915->guc.fw);
-	u32 huc_fw_size = intel_uc_fw_get_upload_size(&i915->huc.fw);
-	u32 ctx_rsvd = context_reserved_size(i915);
-	u32 guc_wopcm_base;
-	u32 guc_wopcm_size;
-	u32 guc_wopcm_rsvd;
-	int err;
 
 	if (!HAS_GUC(i915) || !USES_GUC(i915))
-		return 0;
+		return;
 
-	GEM_BUG_ON(!wopcm->size);
+	wopcm->size = GEN9_WOPCM_SIZE;
 
-	guc_wopcm_base = ALIGN(huc_fw_size + WOPCM_RESERVED_SIZE,
-			       GUC_WOPCM_OFFSET_ALIGNMENT);
-	if ((guc_wopcm_base + ctx_rsvd) >= wopcm->size) {
-		DRM_ERROR("GuC WOPCM base (%uKiB) is too big.\n",
-			  guc_wopcm_base / 1024);
+	wopcm_guc_region_init(wopcm);
+
+	DRM_DEBUG_DRIVER("WOPCM size: %uKiB\n", wopcm->size / 1024);
+	DRM_DEBUG_DRIVER("GuC WOPCM Region: [%uKiB, %uKiB)\n",
+			 wopcm->guc.base / 1024,
+			 (wopcm->guc.base + wopcm->guc.size) / 1024);
+}
+
+static int check_huc_fw_fits(struct intel_wopcm *wopcm, u32 huc_fw_size)
+{
+	if (huc_fw_size_in_wopcm(huc_fw_size) > wopcm->guc.base) {
+		DRM_ERROR("Need %uKiB WOPCM for HuC, %uKiB available.\n",
+			  huc_fw_size_in_wopcm(huc_fw_size) / 1024,
+			  wopcm->guc.base / 1024);
 		return -E2BIG;
 	}
 
-	guc_wopcm_size = wopcm->size - guc_wopcm_base - ctx_rsvd;
-	guc_wopcm_size &= GUC_WOPCM_SIZE_MASK;
-
-	DRM_DEBUG_DRIVER("Calculated GuC WOPCM Region: [%uKiB, %uKiB)\n",
-			 guc_wopcm_base / 1024, guc_wopcm_size / 1024);
+	return 0;
+}
 
-	guc_wopcm_rsvd = GUC_WOPCM_RESERVED + GUC_WOPCM_STACK_RESERVED;
-	if ((guc_fw_size + guc_wopcm_rsvd) > guc_wopcm_size) {
+static int check_guc_fw_fits(struct intel_wopcm *wopcm, u32 guc_fw_size)
+{
+	if (guc_fw_size_in_wopcm(guc_fw_size) > wopcm->guc.size) {
 		DRM_ERROR("Need %uKiB WOPCM for GuC, %uKiB available.\n",
-			  (guc_fw_size + guc_wopcm_rsvd) / 1024,
-			  guc_wopcm_size / 1024);
+			  huc_fw_size_in_wopcm(guc_fw_size) / 1024,
+			  wopcm->guc.size / 1024);
+		return -E2BIG;
+	}
+
+	return 0;
+}
+
+static int check_ctx_rsvd_fits(struct intel_wopcm *wopcm, u32 ctx_rsvd)
+{
+	if ((wopcm->guc.base + wopcm->guc.size + ctx_rsvd) > wopcm->size) {
+		DRM_ERROR("GuC WOPCM base (%uKiB) is too big.\n",
+			  wopcm->guc.base / 1024);
 		return -E2BIG;
 	}
 
-	err = check_hw_restriction(i915, guc_wopcm_base, guc_wopcm_size,
-				   huc_fw_size);
+	return 0;
+}
+
+static bool wopcm_check_components_fit(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);
+	u32 guc_fw_size = intel_uc_fw_get_upload_size(&i915->guc.fw);
+	u32 ctx_rsvd = context_reserved_size(i915);
+	int err;
+
+	err = check_huc_fw_fits(wopcm, huc_fw_size);
+	if (err)
+		return err;
+
+	err = check_guc_fw_fits(wopcm, guc_fw_size);
+	if (err)
+		return err;
+
+	err = check_ctx_rsvd_fits(wopcm, ctx_rsvd);
 	if (err)
 		return err;
 
-	wopcm->guc.base = guc_wopcm_base;
-	wopcm->guc.size = guc_wopcm_size;
+	return 0;
+}
+
+/**
+ * intel_wopcm_init() - Initialize the WOPCM structure.
+ * @wopcm: pointer to intel_wopcm.
+ *
+ * This function will partition WOPCM space based on GuC and HuC firmware sizes
+ * and will allocate max remaining for use by GuC. This function will also
+ * enforce platform dependent hardware restrictions on GuC WOPCM offset and
+ * size. It will fail the WOPCM init if any of these checks were failed, so that
+ * the following GuC firmware uploading would be aborted.
+ *
+ * Return: 0 on success, non-zero error code on failure.
+ */
+int intel_wopcm_init(struct intel_wopcm *wopcm)
+{
+	int err;
+
+	if (!wopcm->size)
+		return 0;
+
+	err = wopcm_check_hw_restrictions(wopcm);
+	if (err)
+		return err;
+
+	err = wopcm_check_components_fit(wopcm);
+	if (err)
+		return err;
 
 	return 0;
 }
@@ -260,7 +320,7 @@ int intel_wopcm_init_hw(struct intel_wopcm *wopcm)
 	u32 mask;
 	int err;
 
-	if (!HAS_GUC(dev_priv) || !USES_GUC(dev_priv))
+	if (!wopcm->size)
 		return 0;
 
 	GEM_BUG_ON(!wopcm->guc.size);
-- 
2.14.3



More information about the Intel-gfx-trybot mailing list