All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v9 1/7] drm/i915/guc: Move GuC WOPCM related code into separate files
@ 2018-02-08 23:03 Jackie Li
  2018-02-08 23:03 ` [PATCH v9 2/7] drm/i915/guc: Rename guc_ggtt_offset to intel_guc_ggtt_offset Jackie Li
                   ` (7 more replies)
  0 siblings, 8 replies; 23+ messages in thread
From: Jackie Li @ 2018-02-08 23:03 UTC (permalink / raw)
  To: intel-gfx

intel_guc_reg.h should only include definition for GuC registers and
related register bits. Non-register related GuC WOPCM macro definitions
should not be defined in intel_guc_reg.h.

This patch cleans up intel_guc_reg.h and moves GuC WOPCM related code into
new created separate files as future patches will increase the complexity
of determining the GuC WOPCM offset and size.

v8:
 - Fixed naming, coding style issues and typo in commit message (Sagar)
 - Updated commit message to explain why we need create new file for GuC
   WOPCM related code (Chris)

v9:
 - Corrected kernel-doc format (Sagar)
 - Simplified commit message (Michal)
 - Updated license of new created files to use SPDX (Michal)
 - Updated macros and added more comments to be reader friendly (Michal)

Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Sagar Arun Kamble <sagar.a.kamble@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Sagar Arun Kamble <sagar.a.kamble@intel.com> (v8)
Signed-off-by: Jackie Li <yaodong.li@intel.com>
---
 drivers/gpu/drm/i915/Makefile          |  1 +
 drivers/gpu/drm/i915/intel_guc.c       | 11 --------
 drivers/gpu/drm/i915/intel_guc.h       |  2 +-
 drivers/gpu/drm/i915/intel_guc_reg.h   |  4 ---
 drivers/gpu/drm/i915/intel_guc_wopcm.c | 48 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_guc_wopcm.h | 45 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_uc.c        |  2 +-
 drivers/gpu/drm/i915/intel_uc_fw.c     |  2 +-
 8 files changed, 97 insertions(+), 18 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_guc_wopcm.c
 create mode 100644 drivers/gpu/drm/i915/intel_guc_wopcm.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index f55cc02..418d96b 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -89,6 +89,7 @@ i915-y += intel_uc.o \
 	  intel_guc_fw.o \
 	  intel_guc_log.o \
 	  intel_guc_submission.o \
+	  intel_guc_wopcm.o \
 	  intel_huc.o
 
 # autogenerated null render state
diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c
index 21140cc..9f45e6d 100644
--- a/drivers/gpu/drm/i915/intel_guc.c
+++ b/drivers/gpu/drm/i915/intel_guc.c
@@ -509,14 +509,3 @@ struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size)
 	i915_gem_object_put(obj);
 	return vma;
 }
-
-u32 intel_guc_wopcm_size(struct drm_i915_private *dev_priv)
-{
-	u32 wopcm_size = GUC_WOPCM_TOP;
-
-	/* On BXT, the top of WOPCM is reserved for RC6 context */
-	if (IS_GEN9_LP(dev_priv))
-		wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED;
-
-	return wopcm_size;
-}
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 52856a9..9e0a97e 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -31,6 +31,7 @@
 #include "intel_guc_ct.h"
 #include "intel_guc_log.h"
 #include "intel_guc_reg.h"
+#include "intel_guc_wopcm.h"
 #include "intel_uc_fw.h"
 #include "i915_vma.h"
 
@@ -130,6 +131,5 @@ int intel_guc_auth_huc(struct intel_guc *guc, u32 rsa_offset);
 int intel_guc_suspend(struct drm_i915_private *dev_priv);
 int intel_guc_resume(struct drm_i915_private *dev_priv);
 struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size);
-u32 intel_guc_wopcm_size(struct drm_i915_private *dev_priv);
 
 #endif
diff --git a/drivers/gpu/drm/i915/intel_guc_reg.h b/drivers/gpu/drm/i915/intel_guc_reg.h
index 19a9247..1f52fb8 100644
--- a/drivers/gpu/drm/i915/intel_guc_reg.h
+++ b/drivers/gpu/drm/i915/intel_guc_reg.h
@@ -68,7 +68,6 @@
 #define DMA_GUC_WOPCM_OFFSET		_MMIO(0xc340)
 #define   HUC_LOADING_AGENT_VCR		  (0<<1)
 #define   HUC_LOADING_AGENT_GUC		  (1<<1)
-#define   GUC_WOPCM_OFFSET_VALUE	  0x80000	/* 512KB */
 #define GUC_MAX_IDLE_COUNT		_MMIO(0xC3E4)
 
 #define HUC_STATUS2             _MMIO(0xD3B0)
@@ -76,9 +75,6 @@
 
 /* Defines WOPCM space available to GuC firmware */
 #define GUC_WOPCM_SIZE			_MMIO(0xc050)
-/* GuC addresses below GUC_WOPCM_TOP don't map through the GTT */
-#define   GUC_WOPCM_TOP			  (0x80 << 12)	/* 512KB */
-#define   BXT_GUC_WOPCM_RC6_RESERVED	  (0x10 << 12)	/* 64KB  */
 
 /* GuC addresses above GUC_GGTT_TOP also don't map through the GTT */
 #define GUC_GGTT_TOP			0xFEE00000
diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.c b/drivers/gpu/drm/i915/intel_guc_wopcm.c
new file mode 100644
index 0000000..c3d54f8
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_guc_wopcm.c
@@ -0,0 +1,48 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright © 2017-2018 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "intel_guc_wopcm.h"
+#include "i915_drv.h"
+
+/**
+ * intel_guc_wopcm_size() - Get the size of GuC WOPCM.
+ * @guc: intel guc.
+ *
+ * Get the platform specific GuC WOPCM size.
+ *
+ * Return: size of the GuC WOPCM.
+ */
+u32 intel_guc_wopcm_size(struct intel_guc *guc)
+{
+	struct drm_i915_private *i915 = guc_to_i915(guc);
+	u32 size = GUC_WOPCM_TOP;
+
+	/* On BXT, the top of WOPCM is reserved for RC6 context */
+	if (IS_GEN9_LP(i915))
+		size -= BXT_GUC_WOPCM_RC6_RESERVED;
+
+	return size;
+}
diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.h b/drivers/gpu/drm/i915/intel_guc_wopcm.h
new file mode 100644
index 0000000..7323604
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_guc_wopcm.h
@@ -0,0 +1,45 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright © 2017-2018 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _INTEL_GUC_WOPCM_H_
+#define _INTEL_GUC_WOPCM_H_
+
+#include <linux/types.h>
+
+struct intel_guc;
+
+/* 512KB static offset from WOPCM base. */
+#define GUC_WOPCM_OFFSET_VALUE		(512 << 10)
+/*
+ * 512KB static GuC WOPCM size from GUC_WOPCM_OFFSET_VALUE to the end of GuC
+ * WOPCM. GuC addresses below GUC_WOPCM_TOP don't map through the GTT.
+ */
+#define GUC_WOPCM_TOP			(512 << 10)
+#define BXT_GUC_WOPCM_RC6_RESERVED	(64 << 10)
+
+u32 intel_guc_wopcm_size(struct intel_guc *guc);
+
+#endif
diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c
index 9f1bac6..1b2831b 100644
--- a/drivers/gpu/drm/i915/intel_uc.c
+++ b/drivers/gpu/drm/i915/intel_uc.c
@@ -340,7 +340,7 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv)
 	gen9_reset_guc_interrupts(dev_priv);
 
 	/* init WOPCM */
-	I915_WRITE(GUC_WOPCM_SIZE, intel_guc_wopcm_size(dev_priv));
+	I915_WRITE(GUC_WOPCM_SIZE, intel_guc_wopcm_size(guc));
 	I915_WRITE(DMA_GUC_WOPCM_OFFSET,
 		   GUC_WOPCM_OFFSET_VALUE | HUC_LOADING_AGENT_GUC);
 
diff --git a/drivers/gpu/drm/i915/intel_uc_fw.c b/drivers/gpu/drm/i915/intel_uc_fw.c
index 784eff9..24945cf 100644
--- a/drivers/gpu/drm/i915/intel_uc_fw.c
+++ b/drivers/gpu/drm/i915/intel_uc_fw.c
@@ -97,7 +97,7 @@ void intel_uc_fw_fetch(struct drm_i915_private *dev_priv,
 
 	/* Header and uCode will be loaded to WOPCM */
 	size = uc_fw->header_size + uc_fw->ucode_size;
-	if (size > intel_guc_wopcm_size(dev_priv)) {
+	if (size > intel_guc_wopcm_size(&dev_priv->guc)) {
 		DRM_WARN("%s: Firmware is too large to fit in WOPCM\n",
 			 intel_uc_fw_type_repr(uc_fw->type));
 		err = -E2BIG;
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v9 2/7] drm/i915/guc: Rename guc_ggtt_offset to intel_guc_ggtt_offset
  2018-02-08 23:03 [PATCH v9 1/7] drm/i915/guc: Move GuC WOPCM related code into separate files Jackie Li
@ 2018-02-08 23:03 ` Jackie Li
  2018-02-09  8:01   ` Joonas Lahtinen
  2018-02-08 23:03 ` [PATCH v9 3/7] drm/i915/guc: Implement dynamic GuC WOPCM offset and size Jackie Li
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 23+ messages in thread
From: Jackie Li @ 2018-02-08 23:03 UTC (permalink / raw)
  To: intel-gfx

GuC related exported functions should start with "intel_guc_" prefix and
pass intel_guc as the first parameter since its guc related. Current
guc_ggtt_offset() failed to follow this code convention and this is a
problem for future patches that needs to access intel_guc data to verify
the GGTT offset against the GuC WOPCM top.

This patch renames the guc_ggtt_offset to intel_guc_ggtt_offset and updates
the related code to pass intel_guc pointer to this function call, so that
we can have a unified coding style for GuC code and also enable the future
patches to get GuC related data from intel_guc to do the offset
verification. Meanwhile, this patch also moves the GUC_GGTT_TOP from
intel_guc_regs.h to intel_guc.h since it is not GuC register related
definition.

v8:
 - Fixed coding style issues and moved GUC_GGTT_TOP to intel_guc.h (Sagar)
 - Updated commit message to explain to reason and motivation to add
   intel_guc as the first parameter of intel_guc_ggtt_offset (Chris)

v9:
 - Fixed code alignment issue due to line break (Chris)

Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Sagar Arun Kamble <sagar.a.kamble@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Sagar Arun Kamble <sagar.a.kamble@intel.com> (v8)
Signed-off-by: Jackie Li <yaodong.li@intel.com>
---
 drivers/gpu/drm/i915/intel_guc.c            | 12 +++++++-----
 drivers/gpu/drm/i915/intel_guc.h            | 14 ++++++++++++--
 drivers/gpu/drm/i915/intel_guc_ads.c        | 25 +++++++++++++------------
 drivers/gpu/drm/i915/intel_guc_ct.c         |  5 +++--
 drivers/gpu/drm/i915/intel_guc_fw.c         |  2 +-
 drivers/gpu/drm/i915/intel_guc_log.c        |  2 +-
 drivers/gpu/drm/i915/intel_guc_reg.h        |  3 ---
 drivers/gpu/drm/i915/intel_guc_submission.c | 10 +++++-----
 drivers/gpu/drm/i915/intel_huc.c            |  6 ++++--
 9 files changed, 46 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c
index 9f45e6d..d9bc2a9 100644
--- a/drivers/gpu/drm/i915/intel_guc.c
+++ b/drivers/gpu/drm/i915/intel_guc.c
@@ -269,8 +269,10 @@ void intel_guc_init_params(struct intel_guc *guc)
 
 	/* If GuC submission is enabled, set up additional parameters here */
 	if (USES_GUC_SUBMISSION(dev_priv)) {
-		u32 ads = guc_ggtt_offset(guc->ads_vma) >> PAGE_SHIFT;
-		u32 pgs = guc_ggtt_offset(dev_priv->guc.stage_desc_pool);
+		u32 ads = intel_guc_ggtt_offset(guc,
+						guc->ads_vma) >> PAGE_SHIFT;
+		u32 pgs = intel_guc_ggtt_offset(guc,
+						dev_priv->guc.stage_desc_pool);
 		u32 ctx_in_16 = GUC_MAX_STAGE_DESCRIPTORS / 16;
 
 		params[GUC_CTL_DEBUG] |= ads << GUC_ADS_ADDR_SHIFT;
@@ -418,7 +420,7 @@ int intel_guc_suspend(struct drm_i915_private *dev_priv)
 	data[0] = INTEL_GUC_ACTION_ENTER_S_STATE;
 	/* any value greater than GUC_POWER_D0 */
 	data[1] = GUC_POWER_D1;
-	data[2] = guc_ggtt_offset(guc->shared_data);
+	data[2] = intel_guc_ggtt_offset(guc, guc->shared_data);
 
 	return intel_guc_send(guc, data, ARRAY_SIZE(data));
 }
@@ -441,7 +443,7 @@ int intel_guc_reset_engine(struct intel_guc *guc,
 	data[3] = 0;
 	data[4] = 0;
 	data[5] = guc->execbuf_client->stage_id;
-	data[6] = guc_ggtt_offset(guc->shared_data);
+	data[6] = intel_guc_ggtt_offset(guc, guc->shared_data);
 
 	return intel_guc_send(guc, data, ARRAY_SIZE(data));
 }
@@ -463,7 +465,7 @@ int intel_guc_resume(struct drm_i915_private *dev_priv)
 
 	data[0] = INTEL_GUC_ACTION_EXIT_S_STATE;
 	data[1] = GUC_POWER_D0;
-	data[2] = guc_ggtt_offset(guc->shared_data);
+	data[2] = intel_guc_ggtt_offset(guc, guc->shared_data);
 
 	return intel_guc_send(guc, data, ARRAY_SIZE(data));
 }
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 9e0a97e..50be6de 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -101,13 +101,23 @@ static inline void intel_guc_notify(struct intel_guc *guc)
 	guc->notify(guc);
 }
 
-/*
+/* GuC addresses above GUC_GGTT_TOP also don't map through the GTT */
+#define GUC_GGTT_TOP	0xFEE00000
+
+/**
+ * intel_guc_ggtt_offset() - Get and validate the GGTT offset of @vma
+ * @guc: intel guc.
+ * @vma: i915 graphics virtual memory area.
+ *
  * GuC does not allow any gfx GGTT address that falls into range [0, WOPCM_TOP),
  * which is reserved for Boot ROM, SRAM and WOPCM. Currently this top address is
  * 512K. In order to exclude 0-512K address space from GGTT, all gfx objects
  * used by GuC is pinned with PIN_OFFSET_BIAS along with size of WOPCM.
+ *
+ * Return: GGTT offset that meets the GuC gfx address requirement.
  */
-static inline u32 guc_ggtt_offset(struct i915_vma *vma)
+static inline u32 intel_guc_ggtt_offset(struct intel_guc *guc,
+					struct i915_vma *vma)
 {
 	u32 offset = i915_ggtt_offset(vma);
 
diff --git a/drivers/gpu/drm/i915/intel_guc_ads.c b/drivers/gpu/drm/i915/intel_guc_ads.c
index ac62753..2cd2bb5 100644
--- a/drivers/gpu/drm/i915/intel_guc_ads.c
+++ b/drivers/gpu/drm/i915/intel_guc_ads.c
@@ -113,17 +113,6 @@ int intel_guc_ads_create(struct intel_guc *guc)
 		blob->reg_state.white_list[engine->guc_id].count = 0;
 	}
 
-	/*
-	 * The GuC requires a "Golden Context" when it reinitialises
-	 * engines after a reset. Here we use the Render ring default
-	 * context, which must already exist and be pinned in the GGTT,
-	 * so its address won't change after we've told the GuC where
-	 * to find it. Note that we have to skip our header (1 page),
-	 * because our GuC shared data is there.
-	 */
-	blob->ads.golden_context_lrca =
-		guc_ggtt_offset(dev_priv->kernel_context->engine[RCS].state) +
-		skipped_offset;
 
 	/*
 	 * The GuC expects us to exclude the portion of the context image that
@@ -135,11 +124,23 @@ int intel_guc_ads_create(struct intel_guc *guc)
 		blob->ads.eng_state_size[engine->guc_id] =
 			engine->context_size - skipped_size;
 
-	base = guc_ggtt_offset(vma);
+	base = intel_guc_ggtt_offset(guc, vma);
 	blob->ads.scheduler_policies = base + ptr_offset(blob, policies);
 	blob->ads.reg_state_buffer = base + ptr_offset(blob, reg_state_buffer);
 	blob->ads.reg_state_addr = base + ptr_offset(blob, reg_state);
 
+	/*
+	 * The GuC requires a "Golden Context" when it reinitialises
+	 * engines after a reset. Here we use the Render ring default
+	 * context, which must already exist and be pinned in the GGTT,
+	 * so its address won't change after we've told the GuC where
+	 * to find it. Note that we have to skip our header (1 page),
+	 * because our GuC shared data is there.
+	 */
+	vma = dev_priv->kernel_context->engine[RCS].state;
+	blob->ads.golden_context_lrca =
+		intel_guc_ggtt_offset(guc, vma) + skipped_offset;
+
 	kunmap(page);
 
 	return 0;
diff --git a/drivers/gpu/drm/i915/intel_guc_ct.c b/drivers/gpu/drm/i915/intel_guc_ct.c
index 24ad557..0a0d3d5 100644
--- a/drivers/gpu/drm/i915/intel_guc_ct.c
+++ b/drivers/gpu/drm/i915/intel_guc_ct.c
@@ -156,7 +156,8 @@ static int ctch_init(struct intel_guc *guc,
 		err = PTR_ERR(blob);
 		goto err_vma;
 	}
-	DRM_DEBUG_DRIVER("CT: vma base=%#x\n", guc_ggtt_offset(ctch->vma));
+	DRM_DEBUG_DRIVER("CT: vma base=%#x\n",
+			 intel_guc_ggtt_offset(guc, ctch->vma));
 
 	/* store pointers to desc and cmds */
 	for (i = 0; i < ARRAY_SIZE(ctch->ctbs); i++) {
@@ -202,7 +203,7 @@ static int ctch_open(struct intel_guc *guc,
 	}
 
 	/* vma should be already allocated and map'ed */
-	base = guc_ggtt_offset(ctch->vma);
+	base = intel_guc_ggtt_offset(guc, ctch->vma);
 
 	/* (re)initialize descriptors
 	 * cmds buffers are in the second half of the blob page
diff --git a/drivers/gpu/drm/i915/intel_guc_fw.c b/drivers/gpu/drm/i915/intel_guc_fw.c
index 3b09329..178d339 100644
--- a/drivers/gpu/drm/i915/intel_guc_fw.c
+++ b/drivers/gpu/drm/i915/intel_guc_fw.c
@@ -165,7 +165,7 @@ static int guc_xfer_ucode(struct intel_guc *guc, struct i915_vma *vma)
 	I915_WRITE(DMA_COPY_SIZE, guc_fw->header_size + guc_fw->ucode_size);
 
 	/* Set the source address for the new blob */
-	offset = guc_ggtt_offset(vma) + guc_fw->header_offset;
+	offset = intel_guc_ggtt_offset(guc, vma) + guc_fw->header_offset;
 	I915_WRITE(DMA_ADDR_0_LOW, lower_32_bits(offset));
 	I915_WRITE(DMA_ADDR_0_HIGH, upper_32_bits(offset) & 0xFFFF);
 
diff --git a/drivers/gpu/drm/i915/intel_guc_log.c b/drivers/gpu/drm/i915/intel_guc_log.c
index 7b5074e..eca8725 100644
--- a/drivers/gpu/drm/i915/intel_guc_log.c
+++ b/drivers/gpu/drm/i915/intel_guc_log.c
@@ -638,7 +638,7 @@ int intel_guc_log_create(struct intel_guc *guc)
 		(GUC_LOG_ISR_PAGES << GUC_LOG_ISR_SHIFT) |
 		(GUC_LOG_CRASH_PAGES << GUC_LOG_CRASH_SHIFT);
 
-	offset = guc_ggtt_offset(vma) >> PAGE_SHIFT; /* in pages */
+	offset = intel_guc_ggtt_offset(guc, vma) >> PAGE_SHIFT; /* in pages */
 	guc->log.flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags;
 
 	return 0;
diff --git a/drivers/gpu/drm/i915/intel_guc_reg.h b/drivers/gpu/drm/i915/intel_guc_reg.h
index 1f52fb8..de4f78b 100644
--- a/drivers/gpu/drm/i915/intel_guc_reg.h
+++ b/drivers/gpu/drm/i915/intel_guc_reg.h
@@ -76,9 +76,6 @@
 /* Defines WOPCM space available to GuC firmware */
 #define GUC_WOPCM_SIZE			_MMIO(0xc050)
 
-/* GuC addresses above GUC_GGTT_TOP also don't map through the GTT */
-#define GUC_GGTT_TOP			0xFEE00000
-
 #define GEN8_GT_PM_CONFIG		_MMIO(0x138140)
 #define GEN9LP_GT_PM_CONFIG		_MMIO(0x138140)
 #define GEN9_GT_PM_CONFIG		_MMIO(0x13816c)
diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c
index b43b58c..ebfcb9f 100644
--- a/drivers/gpu/drm/i915/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/intel_guc_submission.c
@@ -375,8 +375,8 @@ static void guc_stage_desc_init(struct intel_guc *guc,
 		lrc->context_desc = lower_32_bits(ce->lrc_desc);
 
 		/* The state page is after PPHWSP */
-		lrc->ring_lrca =
-			guc_ggtt_offset(ce->state) + LRC_STATE_PN * PAGE_SIZE;
+		lrc->ring_lrca = intel_guc_ggtt_offset(guc, ce->state) +
+				 LRC_STATE_PN * PAGE_SIZE;
 
 		/* XXX: In direct submission, the GuC wants the HW context id
 		 * here. In proxy submission, it wants the stage id
@@ -384,7 +384,7 @@ static void guc_stage_desc_init(struct intel_guc *guc,
 		lrc->context_id = (client->stage_id << GUC_ELC_CTXID_OFFSET) |
 				(guc_engine_id << GUC_ELC_ENGINE_OFFSET);
 
-		lrc->ring_begin = guc_ggtt_offset(ce->ring->vma);
+		lrc->ring_begin = intel_guc_ggtt_offset(guc, ce->ring->vma);
 		lrc->ring_end = lrc->ring_begin + ce->ring->size - 1;
 		lrc->ring_next_free_location = lrc->ring_begin;
 		lrc->ring_current_tail_pointer_value = 0;
@@ -400,7 +400,7 @@ static void guc_stage_desc_init(struct intel_guc *guc,
 	 * The doorbell, process descriptor, and workqueue are all parts
 	 * of the client object, which the GuC will reference via the GGTT
 	 */
-	gfx_addr = guc_ggtt_offset(client->vma);
+	gfx_addr = intel_guc_ggtt_offset(guc, client->vma);
 	desc->db_trigger_phy = sg_dma_address(client->vma->pages->sgl) +
 				client->doorbell_offset;
 	desc->db_trigger_cpu = ptr_to_u64(__get_doorbell(client));
@@ -596,7 +596,7 @@ static void inject_preempt_context(struct work_struct *work)
 	data[3] = engine->guc_id;
 	data[4] = guc->execbuf_client->priority;
 	data[5] = guc->execbuf_client->stage_id;
-	data[6] = guc_ggtt_offset(guc->shared_data);
+	data[6] = intel_guc_ggtt_offset(guc, guc->shared_data);
 
 	if (WARN_ON(intel_guc_send(guc, data, ARRAY_SIZE(data)))) {
 		execlists_clear_active(&engine->execlists,
diff --git a/drivers/gpu/drm/i915/intel_huc.c b/drivers/gpu/drm/i915/intel_huc.c
index 8ed0518..aed9c1c 100644
--- a/drivers/gpu/drm/i915/intel_huc.c
+++ b/drivers/gpu/drm/i915/intel_huc.c
@@ -137,7 +137,8 @@ static int huc_ucode_xfer(struct intel_uc_fw *huc_fw, struct i915_vma *vma)
 	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
 
 	/* Set the source address for the uCode */
-	offset = guc_ggtt_offset(vma) + huc_fw->header_offset;
+	offset = intel_guc_ggtt_offset(&dev_priv->guc, vma) +
+		 huc_fw->header_offset;
 	I915_WRITE(DMA_ADDR_0_LOW, lower_32_bits(offset));
 	I915_WRITE(DMA_ADDR_0_HIGH, upper_32_bits(offset) & 0xFFFF);
 
@@ -213,7 +214,8 @@ int intel_huc_auth(struct intel_huc *huc)
 	}
 
 	ret = intel_guc_auth_huc(guc,
-				 guc_ggtt_offset(vma) + huc->fw.rsa_offset);
+				 intel_guc_ggtt_offset(guc, vma) +
+				 huc->fw.rsa_offset);
 	if (ret) {
 		DRM_ERROR("HuC: GuC did not ack Auth request %d\n", ret);
 		goto out;
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v9 3/7] drm/i915/guc: Implement dynamic GuC WOPCM offset and size
  2018-02-08 23:03 [PATCH v9 1/7] drm/i915/guc: Move GuC WOPCM related code into separate files Jackie Li
  2018-02-08 23:03 ` [PATCH v9 2/7] drm/i915/guc: Rename guc_ggtt_offset to intel_guc_ggtt_offset Jackie Li
@ 2018-02-08 23:03 ` Jackie Li
  2018-02-09  9:31   ` Joonas Lahtinen
  2018-02-09 17:24   ` Michal Wajdeczko
  2018-02-08 23:03 ` [PATCH v9 4/7] drm/i915/guc: Add support to return CNL specific reserved GuC WOPCM size Jackie Li
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 23+ messages in thread
From: Jackie Li @ 2018-02-08 23:03 UTC (permalink / raw)
  To: intel-gfx; +Cc: Sujaritha Sundaresan

Hardware may have specific restrictions on GuC WOPCM offset and size. On
Gen9, the value of the GuC WOPCM size register needs to be larger than the
value of GuC WOPCM offset register + a Gen9 specific offset (144KB) for
reserved GuC WOPCM. Fail to enforce such a restriction on GuC WOPCM size
will lead to GuC firmware execution failures. So we need add code to verify
the GuC WOPCM offset and size to avoid any GuC failures. On the other hand,
with current static GuC WOPCM offset and size values (512KB for both offset
and size), the GuC WOPCM size verification will fail on Gen9 even if it can
be fixed by lowering the GuC WOPCM offset by calculating its value based on
HuC firmware size (which is likely less than 200KB on Gen9), so that we can
have a GuC WOPCM size value which is large enough to pass the GuC WOPCM
size check.

This patch updates the reserved GuC WOPCM size for RC6 context on Gen9 to
24KB to strictly align with the Gen9 GuC WOPCM layout and add support to
return CNL specific hardware reserved GuC WOPCM size. It also adds support
to verify the GuC WOPCM size aganist the Gen9 hardware restrictions.
Meanwhile, it provides a common way to calculate GuC WOPCM offset and size
based on GuC and HuC firmware sizes for all GuC/HuC enabled platforms.
Currently, GuC WOPCM offset is calculated based on HuC firmware size +
reserved WOPCM size while GuC WOPCM size is set to total WOPCM size - GuC
WOPCM offset - hardware reserved GuC WOPCM size. In this case, GuC WOPCM
offset will be updated based on the size of HuC firmware while GuC WOPCM
size will be set to use all the remaining WOPCM space.

v2:
 - Removed intel_wopcm_init (Ville/Sagar/Joonas)
 - Renamed and Moved the intel_wopcm_partition into intel_guc (Sagar)
 - Removed unnecessary function calls (Joonas)
 - Init GuC WOPCM partition as soon as firmware fetching is completed

v3:
 - Fixed indentation issues (Chris)
 - Removed layering violation code (Chris/Michal)
 - Created separat files for GuC wopcm code  (Michal)
 - Used inline function to avoid code duplication (Michal)

v4:
 - Preset the GuC WOPCM top during early GuC init (Chris)
 - Fail intel_uc_init_hw() as soon as GuC WOPCM partitioning failed

v5:
 - Moved GuC DMA WOPCM register updating code into intel_guc_wopcm.c
 - Took care of the locking status before writing to GuC DMA
   Write-Once registers. (Joonas)

v6:
 - Made sure the GuC WOPCM size to be multiple of 4K (4K aligned)

v8:
 - Updated comments and fixed naming issues (Sagar/Joonas)
 - Updated commit message to include more description about the hardware
   restriction on GuC WOPCM size (Sagar)

v9:
 - Minor changes variable names and code comments (Sagar)
 - Added detailed GuC WOPCM layout drawing (Sagar/Michal)
 - Refined macro definitions to be reader friendly (Michal)
 - Removed redundent check to valid flag (Michal)
 - Unified first parameter for exported GuC WOPCM functions (Michal)
 - Refined the name and parameter list of hardware restriction checking
   functions (Michal)

Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Sagar Arun Kamble <sagar.a.kamble@intel.com>
Cc: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com>
Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: John Spotswood <john.a.spotswood@intel.com>
Cc: Oscar Mateo <oscar.mateo@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Sagar Arun Kamble <sagar.a.kamble@intel.com> (v8)
Signed-off-by: Jackie Li <yaodong.li@intel.com>
---
 drivers/gpu/drm/i915/i915_gem_context.c |   5 +-
 drivers/gpu/drm/i915/intel_guc.c        |   5 +-
 drivers/gpu/drm/i915/intel_guc.h        |  12 ++--
 drivers/gpu/drm/i915/intel_guc_wopcm.c  | 115 +++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/intel_guc_wopcm.h  |  85 +++++++++++++++++++++--
 drivers/gpu/drm/i915/intel_huc.c        |   2 +-
 drivers/gpu/drm/i915/intel_uc.c         |  11 ++-
 drivers/gpu/drm/i915/intel_uc_fw.c      |  11 ++-
 drivers/gpu/drm/i915/intel_uc_fw.h      |  16 +++++
 9 files changed, 229 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 3d75f48..414eab2 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -312,12 +312,13 @@ __create_hw_context(struct drm_i915_private *dev_priv,
 	ctx->desc_template =
 		default_desc_template(dev_priv, dev_priv->mm.aliasing_ppgtt);
 
-	/* GuC requires the ring to be placed above GUC_WOPCM_TOP. If GuC is not
+	/*
+	 * GuC requires the ring to be placed above GuC WOPCM top. If GuC is not
 	 * present or not in use we still need a small bias as ring wraparound
 	 * at offset 0 sometimes hangs. No idea why.
 	 */
 	if (USES_GUC(dev_priv))
-		ctx->ggtt_offset_bias = GUC_WOPCM_TOP;
+		ctx->ggtt_offset_bias = dev_priv->guc.wopcm.top;
 	else
 		ctx->ggtt_offset_bias = I915_GTT_PAGE_SIZE;
 
diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c
index d9bc2a9..ecd5da2 100644
--- a/drivers/gpu/drm/i915/intel_guc.c
+++ b/drivers/gpu/drm/i915/intel_guc.c
@@ -65,6 +65,7 @@ void intel_guc_init_early(struct intel_guc *guc)
 	intel_guc_fw_init_early(guc);
 	intel_guc_ct_init_early(&guc->ct);
 	intel_guc_log_init_early(guc);
+	intel_guc_wopcm_init_early(&guc->wopcm);
 
 	mutex_init(&guc->send_mutex);
 	guc->send = intel_guc_send_nop;
@@ -478,7 +479,7 @@ int intel_guc_resume(struct drm_i915_private *dev_priv)
  * This is a wrapper to create an object for use with the GuC. In order to
  * use it inside the GuC, an object needs to be pinned lifetime, so we allocate
  * both some backing storage and a range inside the Global GTT. We must pin
- * it in the GGTT somewhere other than than [0, GUC_WOPCM_TOP) because that
+ * it in the GGTT somewhere other than than [0, GuC WOPCM top) because that
  * range is reserved inside GuC.
  *
  * Return:	A i915_vma if successful, otherwise an ERR_PTR.
@@ -499,7 +500,7 @@ struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size)
 		goto err;
 
 	ret = i915_vma_pin(vma, 0, PAGE_SIZE,
-			   PIN_GLOBAL | PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
+			   PIN_GLOBAL | PIN_OFFSET_BIAS | guc->wopcm.top);
 	if (ret) {
 		vma = ERR_PTR(ret);
 		goto err;
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 50be6de..06f315e 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -49,6 +49,7 @@ struct intel_guc {
 	struct intel_uc_fw fw;
 	struct intel_guc_log log;
 	struct intel_guc_ct ct;
+	struct intel_guc_wopcm wopcm;
 
 	/* Log snapshot if GuC errors during load */
 	struct drm_i915_gem_object *load_err_log;
@@ -109,10 +110,10 @@ static inline void intel_guc_notify(struct intel_guc *guc)
  * @guc: intel guc.
  * @vma: i915 graphics virtual memory area.
  *
- * GuC does not allow any gfx GGTT address that falls into range [0, WOPCM_TOP),
- * which is reserved for Boot ROM, SRAM and WOPCM. Currently this top address is
- * 512K. In order to exclude 0-512K address space from GGTT, all gfx objects
- * used by GuC is pinned with PIN_OFFSET_BIAS along with size of WOPCM.
+ * GuC does not allow any gfx GGTT address that falls into range
+ * [0, GuC WOPCM top), which is reserved for Boot ROM, SRAM and WOPCM.
+ * All gfx objects used by GuC is pinned with PIN_OFFSET_BIAS along with
+ * top of WOPCM.
  *
  * Return: GGTT offset that meets the GuC gfx address requirement.
  */
@@ -121,7 +122,8 @@ static inline u32 intel_guc_ggtt_offset(struct intel_guc *guc,
 {
 	u32 offset = i915_ggtt_offset(vma);
 
-	GEM_BUG_ON(offset < GUC_WOPCM_TOP);
+	GEM_BUG_ON(!guc->wopcm.valid);
+	GEM_BUG_ON(offset < guc->wopcm.top);
 	GEM_BUG_ON(range_overflows_t(u64, offset, vma->size, GUC_GGTT_TOP));
 
 	return offset;
diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.c b/drivers/gpu/drm/i915/intel_guc_wopcm.c
index c3d54f8..8b2ce49 100644
--- a/drivers/gpu/drm/i915/intel_guc_wopcm.c
+++ b/drivers/gpu/drm/i915/intel_guc_wopcm.c
@@ -27,22 +27,115 @@
 #include "intel_guc_wopcm.h"
 #include "i915_drv.h"
 
+static inline u32 guc_wopcm_context_reserved_size(struct intel_guc *guc)
+{
+	struct drm_i915_private *i915 = guc_to_i915(guc);
+
+	if (IS_GEN9_LP(i915))
+		return BXT_GUC_WOPCM_RC6_CTX_RESERVED;
+
+	return 0;
+}
+
+static inline int gen9_guc_wopcm_size_check(struct intel_guc_wopcm *guc_wopcm)
+{
+	u32 guc_wopcm_start;
+	u32 delta;
+
+	/*
+	 * GuC WOPCM size is at least a dword larger than the offset from WOPCM
+	 * base (GuC WOPCM offset from WOPCM base + GEN9_GUC_WOPCM_OFFSET) due
+	 * to hardware limitation on Gen9.
+	 */
+	guc_wopcm_start = guc_wopcm->offset + GEN9_GUC_WOPCM_OFFSET;
+	if (unlikely(guc_wopcm_start > guc_wopcm->size))
+		return -E2BIG;
+
+	delta = guc_wopcm->size - guc_wopcm_start;
+	if (unlikely(delta < sizeof(u32)))
+		return -E2BIG;
+
+	return 0;
+}
+
+static inline int guc_wopcm_size_check(struct intel_guc *guc)
+{
+	struct drm_i915_private *i915 = guc_to_i915(guc);
+	struct intel_guc_wopcm *guc_wopcm = &guc->wopcm;
+
+	if (IS_GEN9(i915))
+		return gen9_guc_wopcm_size_check(guc_wopcm);
+
+	return 0;
+}
+
 /**
- * intel_guc_wopcm_size() - Get the size of GuC WOPCM.
- * @guc: intel guc.
+ * intel_guc_wopcm_init() - Initialize the GuC WOPCM.
+ * @guc_wopcm: intel_guc_wopcm..
+ * @guc_fw_size: size of GuC firmware.
+ * @huc_fw_size: size of HuC firmware.
  *
- * Get the platform specific GuC WOPCM size.
+ * Calculate the GuC WOPCM offset and size based on GuC and HuC firmware sizes.
+ * This function will set the GuC WOPCM size to the size of maximum WOPCM
+ * available for GuC. This function will also enforce platform dependent
+ * hardware restrictions on GuC WOPCM offset and size. It will fail the GuC
+ * WOPCM init if any of these checks were failed, so that the following GuC
+ * firmware uploading would be aborted.
  *
- * Return: size of the GuC WOPCM.
+ * Return: 0 on success, non-zero error code on failure.
  */
-u32 intel_guc_wopcm_size(struct intel_guc *guc)
+int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32 guc_fw_size,
+			 u32 huc_fw_size)
 {
-	struct drm_i915_private *i915 = guc_to_i915(guc);
-	u32 size = GUC_WOPCM_TOP;
+	struct intel_guc *guc =
+		container_of(guc_wopcm, struct intel_guc, wopcm);
+	u32 reserved = guc_wopcm_context_reserved_size(guc);
+	u32 offset, size, top;
+	int err;
 
-	/* On BXT, the top of WOPCM is reserved for RC6 context */
-	if (IS_GEN9_LP(i915))
-		size -= BXT_GUC_WOPCM_RC6_RESERVED;
+	if (!guc_fw_size)
+		return -EINVAL;
+
+	if (reserved >= WOPCM_DEFAULT_SIZE)
+		return -E2BIG;
+
+	offset = huc_fw_size + WOPCM_RESERVED_SIZE;
+	if (offset >= WOPCM_DEFAULT_SIZE)
+		return -E2BIG;
+
+	/* Hardware requires GuC WOPCM offset to be 16K aligned. */
+	offset = ALIGN(offset, GUC_WOPCM_OFFSET_ALIGNMENT);
+	if ((offset + reserved) >= WOPCM_DEFAULT_SIZE)
+		return -E2BIG;
+
+	top = WOPCM_DEFAULT_SIZE - offset;
+	size = top - reserved;
+
+	/* GuC WOPCM size must be multiple of 4K pages */
+	size &= PAGE_MASK;
+
+	/*
+	 * GuC firmware size needs to be less than or equal to the size of the
+	 * available GuC WOPCM (total available GuC WOPCM size - reserved size).
+	 * Need extra 8K stack for GuC firmware.
+	 */
+	reserved = GUC_WOPCM_RESERVED + GUC_WOPCM_STACK_RESERVED;
+	if ((guc_fw_size + reserved) > size)
+		return -E2BIG;
+
+	guc->wopcm.offset = offset;
+	guc->wopcm.size = size;
+	guc->wopcm.top = top;
+
+	/* Check platform specific restrictions */
+	err = guc_wopcm_size_check(guc);
+	if (err)
+		return err;
+
+	guc->wopcm.valid = 1;
+
+	DRM_DEBUG_DRIVER("GuC WOPCM offset %dKB, size %dKB, top %dKB\n",
+			 offset >> 10, size >> 10, top >> 10);
 
-	return size;
+	return 0;
 }
diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.h b/drivers/gpu/drm/i915/intel_guc_wopcm.h
index 7323604..3af7ca9 100644
--- a/drivers/gpu/drm/i915/intel_guc_wopcm.h
+++ b/drivers/gpu/drm/i915/intel_guc_wopcm.h
@@ -31,15 +31,86 @@
 
 struct intel_guc;
 
-/* 512KB static offset from WOPCM base. */
-#define GUC_WOPCM_OFFSET_VALUE		(512 << 10)
 /*
- * 512KB static GuC WOPCM size from GUC_WOPCM_OFFSET_VALUE to the end of GuC
- * WOPCM. GuC addresses below GUC_WOPCM_TOP don't map through the GTT.
+ * The layout of the WOPCM will be determined by GuC WOPCM size and offset
+ * registers settings. Currently, GuC WOPCM code calculates the GuC WOPCM offset
+ * and size values based on a layout as shown below:
+ *
+ *   +=====+==>+====================+<== GuC WOPCM top
+ *   ^     ^   |  HW contexts RSVD  |
+ *   |     |   +--------------------+<== GuC WOPCM size
+ *   |     |   |                    |
+ *   |    GuC  |                    |
+ *   |   WOPCM +--------------------+<== (Platform specific size)
+ *   |     |   |    GuC FW RSVD     |
+ * WOPCM   |   +------------------- +<== (16KB)
+ *   |     v   |   RSVD GUC WOPCM   |
+ *   |     +==>+====================+<== GuC WOPCM offset
+ *   |         |     RSVD WOPCM     |
+ *   |         +------------------- +
+ *   v         |      HuC FW        |
+ *   +========>+====================+<== WOPCM Base
+ *
+ * GuC accessible WOPCM starts at GuC WOPCM offset and ends at GuC WOPCM size.
+ * The top part of the GuC WOPCM is reserved for hardware contexts (e.g. RC6
+ * context). We need to keep tracking the GuC WOPCM top since hardware requires
+ * the GGTT offset of a GuC accessible GEM buffer to be larger than the value of
+ * GuC WOPCM top. The values of GuC WOPCM size and top should be set to the
+ * length from GuC WOPCM offset in bytes.
+ */
+
+/* Default WOPCM size 1MB. */
+#define WOPCM_DEFAULT_SIZE		(0x1 << 20)
+/* The initial 16KB WOPCM (RSVD WOPCM) is reserved. */
+#define WOPCM_RESERVED_SIZE		(16 << 10)
+
+/* GUC WOPCM offset needs to be 16KB aligned. */
+#define GUC_WOPCM_OFFSET_ALIGNMENT	(16 << 10)
+/* 16KB reserved at the beginning of GuC WOPCM. */
+#define GUC_WOPCM_RESERVED		(16 << 10)
+/* 8KB from GUC_WOPCM_RESERVED is reserved for GuC stack. */
+#define GUC_WOPCM_STACK_RESERVED	(8 << 10)
+/* 24KB at the end of GuC WOPCM is reserved for RC6 CTX on BXT. */
+#define BXT_GUC_WOPCM_RC6_CTX_RESERVED	(24 << 10)
+
+/*
+ * GuC WOPCM starts at 144KB (GUC_WOPCM_RESERVED + 128KB reserved for GuC
+ * firmware loading) from GuC WOPCM offset on BXT.
+ */
+#define GEN9_GUC_WOPCM_OFFSET		(144 << 10)
+
+/**
+ * intel_guc_wopcm - GuC WOPCM related settings.
+ * @offset: GuC WOPCM offset from the WOPCM base.
+ * @size: size of GuC WOPCM for GuC firmware.
+ * @top: start of the non-GuC WOPCM memory.
+ * @valid: whether this structure contains valid (1-valid, 0-invalid) info.
+ *
+ * We simply use this structure to track the GuC use of WOPCM. The layout of
+ * WOPCM would be defined by writing to GuC WOPCM offset and size registers.
+ */
+struct intel_guc_wopcm {
+	u32 offset;
+	u32 size;
+	u32 top;
+	u32 valid;
+};
+
+/**
+ * intel_guc_wopcm_init_early() - Early initialization of the GuC WOPCM.
+ * @guc_wopcm: intel_guc_wopcm.
+ *
+ * Setup the GuC WOPCM top to the top of the overall WOPCM. This will guarantee
+ * that the allocation of the GuC accessible objects won't fall into WOPCM when
+ * GuC partition isn't present.
+ *
  */
-#define GUC_WOPCM_TOP			(512 << 10)
-#define BXT_GUC_WOPCM_RC6_RESERVED	(64 << 10)
+static inline void intel_guc_wopcm_init_early(struct intel_guc_wopcm *guc_wopcm)
+{
+	guc_wopcm->top = WOPCM_DEFAULT_SIZE;
+}
 
-u32 intel_guc_wopcm_size(struct intel_guc *guc);
+int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32 guc_size,
+			 u32 huc_size);
 
 #endif
diff --git a/drivers/gpu/drm/i915/intel_huc.c b/drivers/gpu/drm/i915/intel_huc.c
index aed9c1c..dc6a6c6 100644
--- a/drivers/gpu/drm/i915/intel_huc.c
+++ b/drivers/gpu/drm/i915/intel_huc.c
@@ -206,7 +206,7 @@ int intel_huc_auth(struct intel_huc *huc)
 		return -ENOEXEC;
 
 	vma = i915_gem_object_ggtt_pin(huc->fw.obj, NULL, 0, 0,
-				PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
+				PIN_OFFSET_BIAS | guc->wopcm.top);
 	if (IS_ERR(vma)) {
 		ret = PTR_ERR(vma);
 		DRM_ERROR("HuC: Failed to pin huc fw object %d\n", ret);
diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c
index 1b2831b..c842f36 100644
--- a/drivers/gpu/drm/i915/intel_uc.c
+++ b/drivers/gpu/drm/i915/intel_uc.c
@@ -283,6 +283,9 @@ void intel_uc_fini_misc(struct drm_i915_private *dev_priv)
 int intel_uc_init(struct drm_i915_private *dev_priv)
 {
 	struct intel_guc *guc = &dev_priv->guc;
+	struct intel_huc *huc = &dev_priv->huc;
+	u32 guc_fw_size = intel_uc_fw_get_size(&guc->fw);
+	u32 huc_fw_size = intel_uc_fw_get_size(&huc->fw);
 	int ret;
 
 	if (!USES_GUC(dev_priv))
@@ -291,6 +294,10 @@ int intel_uc_init(struct drm_i915_private *dev_priv)
 	if (!HAS_GUC(dev_priv))
 		return -ENODEV;
 
+	ret = intel_guc_wopcm_init(&guc->wopcm, guc_fw_size, huc_fw_size);
+	if (ret)
+		return ret;
+
 	ret = intel_guc_init(guc);
 	if (ret)
 		return ret;
@@ -340,9 +347,9 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv)
 	gen9_reset_guc_interrupts(dev_priv);
 
 	/* init WOPCM */
-	I915_WRITE(GUC_WOPCM_SIZE, intel_guc_wopcm_size(guc));
+	I915_WRITE(GUC_WOPCM_SIZE, guc->wopcm.size);
 	I915_WRITE(DMA_GUC_WOPCM_OFFSET,
-		   GUC_WOPCM_OFFSET_VALUE | HUC_LOADING_AGENT_GUC);
+		   guc->wopcm.offset | HUC_LOADING_AGENT_GUC);
 
 	/* WaEnableuKernelHeaderValidFix:skl */
 	/* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */
diff --git a/drivers/gpu/drm/i915/intel_uc_fw.c b/drivers/gpu/drm/i915/intel_uc_fw.c
index 24945cf..791263a 100644
--- a/drivers/gpu/drm/i915/intel_uc_fw.c
+++ b/drivers/gpu/drm/i915/intel_uc_fw.c
@@ -95,9 +95,13 @@ void intel_uc_fw_fetch(struct drm_i915_private *dev_priv,
 	uc_fw->ucode_offset = uc_fw->header_offset + uc_fw->header_size;
 	uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32);
 
-	/* Header and uCode will be loaded to WOPCM */
+	/*
+	 * Header and uCode will be loaded to WOPCM
+	 * Only check the size against the overall available WOPCM here. Will
+	 * continue to check the size during WOPCM partition calculation.
+	 */
 	size = uc_fw->header_size + uc_fw->ucode_size;
-	if (size > intel_guc_wopcm_size(&dev_priv->guc)) {
+	if (size > WOPCM_DEFAULT_SIZE) {
 		DRM_WARN("%s: Firmware is too large to fit in WOPCM\n",
 			 intel_uc_fw_type_repr(uc_fw->type));
 		err = -E2BIG;
@@ -207,6 +211,7 @@ int intel_uc_fw_upload(struct intel_uc_fw *uc_fw,
 		       int (*xfer)(struct intel_uc_fw *uc_fw,
 				   struct i915_vma *vma))
 {
+	struct drm_i915_private *i915 = to_i915(uc_fw->obj->base.dev);
 	struct i915_vma *vma;
 	int err;
 
@@ -230,7 +235,7 @@ int intel_uc_fw_upload(struct intel_uc_fw *uc_fw,
 	}
 
 	vma = i915_gem_object_ggtt_pin(uc_fw->obj, NULL, 0, 0,
-				       PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
+				       PIN_OFFSET_BIAS | i915->guc.wopcm.top);
 	if (IS_ERR(vma)) {
 		err = PTR_ERR(vma);
 		DRM_DEBUG_DRIVER("%s fw ggtt-pin err=%d\n",
diff --git a/drivers/gpu/drm/i915/intel_uc_fw.h b/drivers/gpu/drm/i915/intel_uc_fw.h
index d5fd460..298d475 100644
--- a/drivers/gpu/drm/i915/intel_uc_fw.h
+++ b/drivers/gpu/drm/i915/intel_uc_fw.h
@@ -115,6 +115,22 @@ static inline bool intel_uc_fw_is_selected(struct intel_uc_fw *uc_fw)
 	return uc_fw->path != NULL;
 }
 
+/**
+ * intel_uc_fw_get_size() - Get the size of the firmware.
+ * @uc_fw: intel_uc_fw structure.
+ *
+ * Get the size of the firmware that will be placed in WOPCM.
+ *
+ * Return: Zero on invalid firmware status. actual size on success.
+ */
+static inline u32 intel_uc_fw_get_size(struct intel_uc_fw *uc_fw)
+{
+	if (uc_fw->fetch_status != INTEL_UC_FIRMWARE_SUCCESS)
+		return 0;
+
+	return uc_fw->header_size + uc_fw->ucode_size;
+}
+
 void intel_uc_fw_fetch(struct drm_i915_private *dev_priv,
 		       struct intel_uc_fw *uc_fw);
 int intel_uc_fw_upload(struct intel_uc_fw *uc_fw,
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v9 4/7] drm/i915/guc: Add support to return CNL specific reserved GuC WOPCM size
  2018-02-08 23:03 [PATCH v9 1/7] drm/i915/guc: Move GuC WOPCM related code into separate files Jackie Li
  2018-02-08 23:03 ` [PATCH v9 2/7] drm/i915/guc: Rename guc_ggtt_offset to intel_guc_ggtt_offset Jackie Li
  2018-02-08 23:03 ` [PATCH v9 3/7] drm/i915/guc: Implement dynamic GuC WOPCM offset and size Jackie Li
@ 2018-02-08 23:03 ` Jackie Li
  2018-02-09  9:37   ` Joonas Lahtinen
  2018-02-08 23:03 ` [PATCH v9 5/7] drm/i915/guc: Add HuC firmware size related restriction for Gen9 and CNL A0 Jackie Li
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 23+ messages in thread
From: Jackie Li @ 2018-02-08 23:03 UTC (permalink / raw)
  To: intel-gfx

CNL has its specific reserved GuC WOPCM size for RC6 and other hardware
contexts.

This patch updates the code to return CNL specific reserved GuC WOPCM size
for RC6 and other hardware contexts so that the GuC WOPCM size can be
calculated correctly for CNL.

v9:
 - Created a new patch for these changes originally made in v8 4/6 patch of
   this series (Sagar/Michal)

Cc: Sagar Arun Kamble <sagar.a.kamble@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Jackie Li <yaodong.li@intel.com>
---
 drivers/gpu/drm/i915/intel_guc_wopcm.c | 3 +++
 drivers/gpu/drm/i915/intel_guc_wopcm.h | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.c b/drivers/gpu/drm/i915/intel_guc_wopcm.c
index 8b2ce49..d0185b0 100644
--- a/drivers/gpu/drm/i915/intel_guc_wopcm.c
+++ b/drivers/gpu/drm/i915/intel_guc_wopcm.c
@@ -34,6 +34,9 @@ static inline u32 guc_wopcm_context_reserved_size(struct intel_guc *guc)
 	if (IS_GEN9_LP(i915))
 		return BXT_GUC_WOPCM_RC6_CTX_RESERVED;
 
+	if (IS_GEN10(i915))
+		return CNL_GUC_WOPCM_HW_CTX_RESERVED;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.h b/drivers/gpu/drm/i915/intel_guc_wopcm.h
index 3af7ca9..1c5ffeb 100644
--- a/drivers/gpu/drm/i915/intel_guc_wopcm.h
+++ b/drivers/gpu/drm/i915/intel_guc_wopcm.h
@@ -72,6 +72,8 @@ struct intel_guc;
 #define GUC_WOPCM_STACK_RESERVED	(8 << 10)
 /* 24KB at the end of GuC WOPCM is reserved for RC6 CTX on BXT. */
 #define BXT_GUC_WOPCM_RC6_CTX_RESERVED	(24 << 10)
+/* 36KB WOPCM reserved at the end of GuC WOPCM on CNL. */
+#define CNL_GUC_WOPCM_HW_CTX_RESERVED	(36 << 10)
 
 /*
  * GuC WOPCM starts at 144KB (GUC_WOPCM_RESERVED + 128KB reserved for GuC
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v9 5/7] drm/i915/guc: Add HuC firmware size related restriction for Gen9 and CNL A0
  2018-02-08 23:03 [PATCH v9 1/7] drm/i915/guc: Move GuC WOPCM related code into separate files Jackie Li
                   ` (2 preceding siblings ...)
  2018-02-08 23:03 ` [PATCH v9 4/7] drm/i915/guc: Add support to return CNL specific reserved GuC WOPCM size Jackie Li
@ 2018-02-08 23:03 ` Jackie Li
  2018-02-09  9:57   ` Joonas Lahtinen
  2018-02-08 23:03 ` [PATCH v9 6/7] drm/i915/guc: Check the locking status of GuC WOPCM registers Jackie Li
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 23+ messages in thread
From: Jackie Li @ 2018-02-08 23:03 UTC (permalink / raw)
  To: intel-gfx

On CNL A0 and Gen9, there's a hardware restriction that requires the
available GuC WOPCM size to be larger than or equal to HuC firmware size.

This patch adds new verfication code to ensure the available GuC WOPCM size
to be larger than or equal to HuC firmware size on both Gen9 and CNL A0.

v6:
 - Extended HuC FW size check against GuC WOPCM size to all
   Gen9 and CNL A0 platforms

v7:
 - Fixed patch format issues

v8:
 - Renamed variables and functions to avoid ambiguity (Joonas)
 - Updated commit message and comments to be more comprehensive (Sagar)

v9:
 - Moved code that is not related to restriction check into a separate
   patch and updated the commit message accordingly (Sagar/Michal)
 - Avoided to call uc_get_fw_size for better layer isolation (Michal)

Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Sagar Arun Kamble <sagar.a.kamble@intel.com>
Cc: John Spotswood <john.a.spotswood@intel.com>
Cc: Jeff McGee <jeff.mcgee@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Sagar Arun Kamble <sagar.a.kamble@intel.com> (v8)
Signed-off-by: Jackie Li <yaodong.li@intel.com>
---
 drivers/gpu/drm/i915/intel_guc_wopcm.c | 28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.c b/drivers/gpu/drm/i915/intel_guc_wopcm.c
index d0185b0..2e8e9ec 100644
--- a/drivers/gpu/drm/i915/intel_guc_wopcm.c
+++ b/drivers/gpu/drm/i915/intel_guc_wopcm.c
@@ -40,7 +40,22 @@ static inline u32 guc_wopcm_context_reserved_size(struct intel_guc *guc)
 	return 0;
 }
 
-static inline int gen9_guc_wopcm_size_check(struct intel_guc_wopcm *guc_wopcm)
+static inline int guc_wopcm_check_huc_fw_size(struct intel_guc_wopcm *guc_wopcm,
+					      u32 huc_fw_size)
+{
+	/*
+	 * On Gen9 & CNL A0, hardware requires the total available GuC WOPCM
+	 * size to be larger than or equal to HuC firmware size. Otherwise,
+	 * firmware uploading would fail.
+	 */
+	if (unlikely(guc_wopcm->size - GUC_WOPCM_RESERVED < huc_fw_size))
+		return -E2BIG;
+
+	return 0;
+}
+
+static inline int gen9_guc_wopcm_size_check(struct intel_guc_wopcm *guc_wopcm,
+					    u32 huc_fw_size)
 {
 	u32 guc_wopcm_start;
 	u32 delta;
@@ -58,16 +73,19 @@ static inline int gen9_guc_wopcm_size_check(struct intel_guc_wopcm *guc_wopcm)
 	if (unlikely(delta < sizeof(u32)))
 		return -E2BIG;
 
-	return 0;
+	return guc_wopcm_check_huc_fw_size(guc_wopcm, huc_fw_size);
 }
 
-static inline int guc_wopcm_size_check(struct intel_guc *guc)
+static inline int guc_wopcm_size_check(struct intel_guc *guc, u32 huc_fw_size)
 {
 	struct drm_i915_private *i915 = guc_to_i915(guc);
 	struct intel_guc_wopcm *guc_wopcm = &guc->wopcm;
 
 	if (IS_GEN9(i915))
-		return gen9_guc_wopcm_size_check(guc_wopcm);
+		return gen9_guc_wopcm_size_check(guc_wopcm, huc_fw_size);
+
+	if (IS_CNL_REVID(i915, CNL_REVID_A0, CNL_REVID_A0))
+		return guc_wopcm_check_huc_fw_size(guc_wopcm, huc_fw_size);
 
 	return 0;
 }
@@ -131,7 +149,7 @@ int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32 guc_fw_size,
 	guc->wopcm.top = top;
 
 	/* Check platform specific restrictions */
-	err = guc_wopcm_size_check(guc);
+	err = guc_wopcm_size_check(guc, huc_fw_size);
 	if (err)
 		return err;
 
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v9 6/7] drm/i915/guc: Check the locking status of GuC WOPCM registers
  2018-02-08 23:03 [PATCH v9 1/7] drm/i915/guc: Move GuC WOPCM related code into separate files Jackie Li
                   ` (3 preceding siblings ...)
  2018-02-08 23:03 ` [PATCH v9 5/7] drm/i915/guc: Add HuC firmware size related restriction for Gen9 and CNL A0 Jackie Li
@ 2018-02-08 23:03 ` Jackie Li
  2018-02-08 23:31   ` Chris Wilson
                     ` (2 more replies)
  2018-02-08 23:03 ` [PATCH v9 7/7] HAX Enable GuC Submission for CI Jackie Li
                   ` (2 subsequent siblings)
  7 siblings, 3 replies; 23+ messages in thread
From: Jackie Li @ 2018-02-08 23:03 UTC (permalink / raw)
  To: intel-gfx

GuC WOPCM registers are write-once registers. Current driver code accesses
these registers without checking the accessibility to these registers which
will lead to unpredictable driver behaviors if these registers were touch
by other components (such as faulty BIOS code).

This patch moves the GuC WOPCM registers updating code into
intel_guc_wopcm.c and adds check before and after the update to GuC WOPCM
registers so that we can make sure the driver is in a known state before
and after writing to these write-once registers.

v6:
 - Made sure module reloading won't bug the kernel while doing
   locking status checking

v7:
 - Fixed patch format issues

v8:
 - Fixed coding style issue on register lock bit macro definition (Sagar)

v9:
 - Avoided to use redundant !! to cast uint to bool (Chris)
 - Return error code instead of GEM_BUG_ON for locked with invalid register
   values case (Sagar)
 - Updated guc_wopcm_hw_init to use guc_wopcm as first parameter (Michal)
 - Added code to set and validate the HuC_LOADING_AGENT_GUC bit in GuC
   WOPCM offset register based on the presence of HuC firmware (Michal)
 - Use bit fields instead of macros for GuC WOPCM flags (Michal)

Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Jackie Li <yaodong.li@intel.com>
---
 drivers/gpu/drm/i915/intel_guc_reg.h   |   2 +
 drivers/gpu/drm/i915/intel_guc_wopcm.c | 117 ++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_guc_wopcm.h |  12 +++-
 drivers/gpu/drm/i915/intel_uc.c        |   9 ++-
 4 files changed, 130 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_guc_reg.h b/drivers/gpu/drm/i915/intel_guc_reg.h
index de4f78b..170d9cd 100644
--- a/drivers/gpu/drm/i915/intel_guc_reg.h
+++ b/drivers/gpu/drm/i915/intel_guc_reg.h
@@ -66,6 +66,8 @@
 #define   UOS_MOVE			  (1<<4)
 #define   START_DMA			  (1<<0)
 #define DMA_GUC_WOPCM_OFFSET		_MMIO(0xc340)
+#define   GUC_WOPCM_OFFSET_SHIFT	14
+#define   GUC_WOPCM_OFFSET_MASK		  (0x3ffff << GUC_WOPCM_OFFSET_SHIFT)
 #define   HUC_LOADING_AGENT_VCR		  (0<<1)
 #define   HUC_LOADING_AGENT_GUC		  (1<<1)
 #define GUC_MAX_IDLE_COUNT		_MMIO(0xC3E4)
diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.c b/drivers/gpu/drm/i915/intel_guc_wopcm.c
index 2e8e9ec..0af435a 100644
--- a/drivers/gpu/drm/i915/intel_guc_wopcm.c
+++ b/drivers/gpu/drm/i915/intel_guc_wopcm.c
@@ -90,6 +90,69 @@ static inline int guc_wopcm_size_check(struct intel_guc *guc, u32 huc_fw_size)
 	return 0;
 }
 
+static inline bool __reg_locked(struct drm_i915_private *dev_priv,
+				i915_reg_t reg)
+{
+	/* Set of bit-0 means this write-once register is locked. */
+	return I915_READ(reg) & BIT(0);
+}
+
+static inline bool guc_wopcm_locked(struct intel_guc *guc)
+{
+	struct drm_i915_private *i915 = guc_to_i915(guc);
+	bool size_reg_locked = __reg_locked(i915, GUC_WOPCM_SIZE);
+	bool offset_reg_locked = __reg_locked(i915, DMA_GUC_WOPCM_OFFSET);
+
+	return size_reg_locked && offset_reg_locked;
+}
+
+static inline void guc_wopcm_hw_update(struct intel_guc *guc)
+{
+	struct drm_i915_private *dev_priv = guc_to_i915(guc);
+	u32 offset_reg_val;
+
+	/* GuC WOPCM registers should be unlocked at this point. */
+	GEM_BUG_ON(__reg_locked(dev_priv, GUC_WOPCM_SIZE));
+	GEM_BUG_ON(__reg_locked(dev_priv, DMA_GUC_WOPCM_OFFSET));
+
+	offset_reg_val = guc->wopcm.offset;
+	if (guc->wopcm.need_load_huc_fw)
+		offset_reg_val |= HUC_LOADING_AGENT_GUC;
+
+	I915_WRITE(GUC_WOPCM_SIZE, guc->wopcm.size);
+	I915_WRITE(DMA_GUC_WOPCM_OFFSET, offset_reg_val);
+
+	GEM_BUG_ON(!__reg_locked(dev_priv, GUC_WOPCM_SIZE));
+	GEM_BUG_ON(!__reg_locked(dev_priv, DMA_GUC_WOPCM_OFFSET));
+}
+
+static inline bool guc_wopcm_regs_valid(struct intel_guc *guc)
+{
+	struct drm_i915_private *dev_priv = guc_to_i915(guc);
+	u32 size, offset;
+	bool guc_loads_huc;
+	u32 reg_val;
+
+	reg_val = I915_READ(GUC_WOPCM_SIZE);
+	/* GuC WOPCM size should be always multiple of 4K pages. */
+	size = reg_val & PAGE_MASK;
+
+	reg_val = I915_READ(DMA_GUC_WOPCM_OFFSET);
+	guc_loads_huc = reg_val & HUC_LOADING_AGENT_GUC;
+	offset = reg_val & GUC_WOPCM_OFFSET_MASK;
+
+	if (guc->wopcm.need_load_huc_fw && !guc_loads_huc)
+		return false;
+
+	return (size == guc->wopcm.size) && (offset == guc->wopcm.offset);
+}
+
+static inline
+struct intel_guc *guc_wopcm_to_guc(struct intel_guc_wopcm *guc_wopcm)
+{
+	return container_of(guc_wopcm, struct intel_guc, wopcm);
+}
+
 /**
  * intel_guc_wopcm_init() - Initialize the GuC WOPCM.
  * @guc_wopcm: intel_guc_wopcm..
@@ -108,12 +171,13 @@ static inline int guc_wopcm_size_check(struct intel_guc *guc, u32 huc_fw_size)
 int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32 guc_fw_size,
 			 u32 huc_fw_size)
 {
-	struct intel_guc *guc =
-		container_of(guc_wopcm, struct intel_guc, wopcm);
+	struct intel_guc *guc = guc_wopcm_to_guc(guc_wopcm);
 	u32 reserved = guc_wopcm_context_reserved_size(guc);
 	u32 offset, size, top;
 	int err;
 
+	GEM_BUG_ON(guc->wopcm.valid);
+
 	if (!guc_fw_size)
 		return -EINVAL;
 
@@ -147,6 +211,8 @@ int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32 guc_fw_size,
 	guc->wopcm.offset = offset;
 	guc->wopcm.size = size;
 	guc->wopcm.top = top;
+	/* Use GuC to load HuC firmware if HuC firmware is present. */
+	guc->wopcm.need_load_huc_fw = huc_fw_size ? 1 : 0;
 
 	/* Check platform specific restrictions */
 	err = guc_wopcm_size_check(guc, huc_fw_size);
@@ -160,3 +226,50 @@ int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32 guc_fw_size,
 
 	return 0;
 }
+
+/**
+ * intel_guc_wopcm_init_hw() - Setup GuC WOPCM registers.
+ * @guc_wopcm: intel_guc_wopcm.
+ *
+ * Setup the GuC WOPCM size and offset registers with the stored values. It will
+ * also check the registers locking status to determine whether these registers
+ * are unlocked and can be updated.
+ *
+ * Return: 0 on success. -EINVAL if registers were locked with incorrect values.
+ */
+int intel_guc_wopcm_init_hw(struct intel_guc_wopcm *guc_wopcm)
+{
+	struct intel_guc *guc = guc_wopcm_to_guc(guc_wopcm);
+	bool locked = guc_wopcm_locked(guc);
+
+	GEM_BUG_ON(!guc->wopcm.valid);
+
+	/*
+	 * Bug if driver hasn't updated the HW Registers and GuC WOPCM has been
+	 * locked. Return directly if WOPCM was locked and we have updated
+	 * the registers.
+	 */
+	if (locked) {
+		if (guc->wopcm.hw_updated)
+			return 0;
+
+		/*
+		 * Mark as updated if registers contained correct values.
+		 * This will happen while reloading the driver module without
+		 * rebooting the system.
+		 */
+		if (guc_wopcm_regs_valid(guc))
+			goto out;
+
+		/* Register locked without valid values. Abort HW init. */
+		return -EINVAL;
+	}
+
+	/* Always update registers when GuC WOPCM is not locked. */
+	guc_wopcm_hw_update(guc);
+
+out:
+	guc->wopcm.hw_updated = 1;
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.h b/drivers/gpu/drm/i915/intel_guc_wopcm.h
index 1c5ffeb..471fb8e 100644
--- a/drivers/gpu/drm/i915/intel_guc_wopcm.h
+++ b/drivers/gpu/drm/i915/intel_guc_wopcm.h
@@ -86,7 +86,9 @@ struct intel_guc;
  * @offset: GuC WOPCM offset from the WOPCM base.
  * @size: size of GuC WOPCM for GuC firmware.
  * @top: start of the non-GuC WOPCM memory.
- * @valid: whether this structure contains valid (1-valid, 0-invalid) info.
+ * @valid: whether the values in this struct are valid.
+ * @hw_updated: GuC WOPCM registers has been updated with values in this struct.
+ * @need_load_huc_fw: whether need to configure GuC to load HuC firmware.
  *
  * We simply use this structure to track the GuC use of WOPCM. The layout of
  * WOPCM would be defined by writing to GuC WOPCM offset and size registers.
@@ -95,7 +97,11 @@ struct intel_guc_wopcm {
 	u32 offset;
 	u32 size;
 	u32 top;
-	u32 valid;
+
+	/* GuC WOPCM flags below. */
+	u32 valid:1;
+	u32 hw_updated:1;
+	u32 need_load_huc_fw:1;
 };
 
 /**
@@ -114,5 +120,5 @@ static inline void intel_guc_wopcm_init_early(struct intel_guc_wopcm *guc_wopcm)
 
 int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32 guc_size,
 			 u32 huc_size);
-
+int intel_guc_wopcm_init_hw(struct intel_guc_wopcm *guc_wopcm);
 #endif
diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c
index c842f36..8938096 100644
--- a/drivers/gpu/drm/i915/intel_uc.c
+++ b/drivers/gpu/drm/i915/intel_uc.c
@@ -343,14 +343,13 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv)
 
 	GEM_BUG_ON(!HAS_GUC(dev_priv));
 
+	ret = intel_guc_wopcm_init_hw(&guc->wopcm);
+	if (ret)
+		goto err_out;
+
 	guc_disable_communication(guc);
 	gen9_reset_guc_interrupts(dev_priv);
 
-	/* init WOPCM */
-	I915_WRITE(GUC_WOPCM_SIZE, guc->wopcm.size);
-	I915_WRITE(DMA_GUC_WOPCM_OFFSET,
-		   guc->wopcm.offset | HUC_LOADING_AGENT_GUC);
-
 	/* WaEnableuKernelHeaderValidFix:skl */
 	/* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */
 	if (IS_GEN9(dev_priv))
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v9 7/7] HAX Enable GuC Submission for CI
  2018-02-08 23:03 [PATCH v9 1/7] drm/i915/guc: Move GuC WOPCM related code into separate files Jackie Li
                   ` (4 preceding siblings ...)
  2018-02-08 23:03 ` [PATCH v9 6/7] drm/i915/guc: Check the locking status of GuC WOPCM registers Jackie Li
@ 2018-02-08 23:03 ` Jackie Li
  2018-02-08 23:29 ` ✗ Fi.CI.BAT: failure for series starting with [v9,1/7] drm/i915/guc: Move GuC WOPCM related code into separate files Patchwork
  2018-02-09 16:46 ` [PATCH v9 1/7] " Michal Wajdeczko
  7 siblings, 0 replies; 23+ messages in thread
From: Jackie Li @ 2018-02-08 23:03 UTC (permalink / raw)
  To: intel-gfx

Signed-off-by: Jackie Li <yaodong.li@intel.com>
---
 drivers/gpu/drm/i915/i915_params.c     | 2 +-
 drivers/gpu/drm/i915/i915_params.h     | 2 +-
 drivers/gpu/drm/i915/intel_guc_wopcm.c | 6 ++++++
 3 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index 08108ce..b49ae20 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -152,7 +152,7 @@ i915_param_named_unsafe(edp_vswing, int, 0400,
 i915_param_named_unsafe(enable_guc, int, 0400,
 	"Enable GuC load for GuC submission and/or HuC load. "
 	"Required functionality can be selected using bitmask values. "
-	"(-1=auto, 0=disable [default], 1=GuC submission, 2=HuC load)");
+	"(-1=auto [default], 0=disable, 1=GuC submission, 2=HuC load)");
 
 i915_param_named(guc_log_level, int, 0400,
 	"GuC firmware logging level. Requires GuC to be loaded. "
diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h
index 430f5f9..3deae1e 100644
--- a/drivers/gpu/drm/i915/i915_params.h
+++ b/drivers/gpu/drm/i915/i915_params.h
@@ -47,7 +47,7 @@ struct drm_printer;
 	param(int, disable_power_well, -1) \
 	param(int, enable_ips, 1) \
 	param(int, invert_brightness, 0) \
-	param(int, enable_guc, 0) \
+	param(int, enable_guc, -1) \
 	param(int, guc_log_level, 0) \
 	param(char *, guc_firmware_path, NULL) \
 	param(char *, huc_firmware_path, NULL) \
diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.c b/drivers/gpu/drm/i915/intel_guc_wopcm.c
index 0af435a..9dc54a3 100644
--- a/drivers/gpu/drm/i915/intel_guc_wopcm.c
+++ b/drivers/gpu/drm/i915/intel_guc_wopcm.c
@@ -176,6 +176,9 @@ int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32 guc_fw_size,
 	u32 offset, size, top;
 	int err;
 
+	DRM_DEBUG_DRIVER("guc_fw size %u, huc_fw_size %u\n", guc_fw_size,
+			 huc_fw_size);
+
 	GEM_BUG_ON(guc->wopcm.valid);
 
 	if (!guc_fw_size)
@@ -242,6 +245,9 @@ int intel_guc_wopcm_init_hw(struct intel_guc_wopcm *guc_wopcm)
 	struct intel_guc *guc = guc_wopcm_to_guc(guc_wopcm);
 	bool locked = guc_wopcm_locked(guc);
 
+	DRM_DEBUG_DRIVER("locked = %s, valid = %s\n", yesno(locked),
+			 yesno(guc->wopcm.valid));
+
 	GEM_BUG_ON(!guc->wopcm.valid);
 
 	/*
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* ✗ Fi.CI.BAT: failure for series starting with [v9,1/7] drm/i915/guc: Move GuC WOPCM related code into separate files
  2018-02-08 23:03 [PATCH v9 1/7] drm/i915/guc: Move GuC WOPCM related code into separate files Jackie Li
                   ` (5 preceding siblings ...)
  2018-02-08 23:03 ` [PATCH v9 7/7] HAX Enable GuC Submission for CI Jackie Li
@ 2018-02-08 23:29 ` Patchwork
  2018-02-09 16:46 ` [PATCH v9 1/7] " Michal Wajdeczko
  7 siblings, 0 replies; 23+ messages in thread
From: Patchwork @ 2018-02-08 23:29 UTC (permalink / raw)
  To: Jackie Li; +Cc: intel-gfx

== Series Details ==

Series: series starting with [v9,1/7] drm/i915/guc: Move GuC WOPCM related code into separate files
URL   : https://patchwork.freedesktop.org/series/37957/
State : failure

== Summary ==

Series 37957v1 series starting with [v9,1/7] drm/i915/guc: Move GuC WOPCM related code into separate files
https://patchwork.freedesktop.org/api/1.0/series/37957/revisions/1/mbox/

Test core_auth:
        Subgroup basic-auth:
                pass       -> SKIP       (fi-skl-gvtdvm)
Test core_prop_blob:
        Subgroup basic:
                pass       -> SKIP       (fi-skl-gvtdvm)
Test debugfs_test:
        Subgroup read_all_entries:
                pass       -> SKIP       (fi-skl-gvtdvm)
Test drv_getparams_basic:
        Subgroup basic-eu-total:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup basic-subslice-total:
                pass       -> SKIP       (fi-skl-gvtdvm)
Test drv_hangman:
        Subgroup error-state-basic:
                pass       -> SKIP       (fi-skl-gvtdvm)
Test gem_basic:
        Subgroup bad-close:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup create-close:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup create-fd-close:
                pass       -> SKIP       (fi-skl-gvtdvm)
Test gem_busy:
        Subgroup basic-busy-default:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup basic-hang-default:
                pass       -> SKIP       (fi-skl-gvtdvm) fdo#104108 +2
Test gem_close_race:
        Subgroup basic-process:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup basic-threads:
                pass       -> SKIP       (fi-skl-gvtdvm)
Test gem_cpu_reloc:
        Subgroup basic:
                pass       -> SKIP       (fi-skl-gvtdvm)
Test gem_cs_tlb:
        Subgroup basic-default:
                pass       -> SKIP       (fi-skl-gvtdvm)
Test gem_ctx_create:
        Subgroup basic:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup basic-files:
                pass       -> SKIP       (fi-skl-gvtdvm)
Test gem_ctx_exec:
        Subgroup basic:
                pass       -> SKIP       (fi-skl-gvtdvm)
Test gem_ctx_param:
        Subgroup basic:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup basic-default:
                pass       -> SKIP       (fi-skl-gvtdvm)
Test gem_ctx_switch:
        Subgroup basic-default:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup basic-default-heavy:
                pass       -> SKIP       (fi-skl-gvtdvm)
Test gem_exec_basic:
        Subgroup basic-blt:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup basic-bsd:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup basic-bsd1:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup basic-bsd2:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup basic-default:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup basic-render:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup basic-vebox:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup gtt-blt:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup gtt-bsd:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup gtt-bsd1:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup gtt-bsd2:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup gtt-default:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup gtt-render:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup gtt-vebox:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup readonly-blt:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup readonly-bsd:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup readonly-bsd1:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup readonly-bsd2:
                pass       -> SKIP       (fi-skl-gvtdvm)
        Subgroup readonly-default:
                pass       -> SKIP       (fi-skl-gvtdvm)
WARNING: Long output truncated

6c10ba221576c523e2574d83e75a87cdc7b0bc1e drm-tip: 2018y-02m-08d-19h-13m-44s UTC integration manifest
daec9e19f238 HAX Enable GuC Submission for CI
feeb9019dcae drm/i915/guc: Check the locking status of GuC WOPCM registers
72ea1468572b drm/i915/guc: Add HuC firmware size related restriction for Gen9 and CNL A0
adcf737521db drm/i915/guc: Add support to return CNL specific reserved GuC WOPCM size
a10189a5a83f drm/i915/guc: Implement dynamic GuC WOPCM offset and size
b086e9167a1a drm/i915/guc: Rename guc_ggtt_offset to intel_guc_ggtt_offset
750ecf0e36ae drm/i915/guc: Move GuC WOPCM related code into separate files

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_7961/issues.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v9 6/7] drm/i915/guc: Check the locking status of GuC WOPCM registers
  2018-02-08 23:03 ` [PATCH v9 6/7] drm/i915/guc: Check the locking status of GuC WOPCM registers Jackie Li
@ 2018-02-08 23:31   ` Chris Wilson
  2018-02-09  5:05     ` Yaodong Li
  2018-02-09 10:47   ` Joonas Lahtinen
  2018-02-09 19:42   ` Michal Wajdeczko
  2 siblings, 1 reply; 23+ messages in thread
From: Chris Wilson @ 2018-02-08 23:31 UTC (permalink / raw)
  To: Jackie Li, intel-gfx

Quoting Jackie Li (2018-02-08 23:03:54)
> @@ -95,7 +97,11 @@ struct intel_guc_wopcm {
>         u32 offset;
>         u32 size;
>         u32 top;
> -       u32 valid;
> +
> +       /* GuC WOPCM flags below. */
> +       u32 valid:1;
> +       u32 hw_updated:1;
> +       u32 need_load_huc_fw:1;

bool need_load_huc_fw:1; etc

> @@ -147,6 +211,8 @@ int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32 guc_fw_size,
>         guc->wopcm.offset = offset;
>         guc->wopcm.size = size;
>         guc->wopcm.top = top;
> +       /* Use GuC to load HuC firmware if HuC firmware is present. */
> +       guc->wopcm.need_load_huc_fw = huc_fw_size ? 1 : 0;

Then the compiler will do the right thing with

	guc->wopcm.need_load_huc_fw = huc_fw_size;

bools, use them ;)
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v9 6/7] drm/i915/guc: Check the locking status of GuC WOPCM registers
  2018-02-08 23:31   ` Chris Wilson
@ 2018-02-09  5:05     ` Yaodong Li
  0 siblings, 0 replies; 23+ messages in thread
From: Yaodong Li @ 2018-02-09  5:05 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx

On 02/08/2018 03:31 PM, Chris Wilson wrote:
> Quoting Jackie Li (2018-02-08 23:03:54)
>> @@ -95,7 +97,11 @@ struct intel_guc_wopcm {
>>          u32 offset;
>>          u32 size;
>>          u32 top;
>> -       u32 valid;
>> +
>> +       /* GuC WOPCM flags below. */
>> +       u32 valid:1;
>> +       u32 hw_updated:1;
>> +       u32 need_load_huc_fw:1;
> bool need_load_huc_fw:1; etc
>
>> @@ -147,6 +211,8 @@ int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32 guc_fw_size,
>>          guc->wopcm.offset = offset;
>>          guc->wopcm.size = size;
>>          guc->wopcm.top = top;
>> +       /* Use GuC to load HuC firmware if HuC firmware is present. */
>> +       guc->wopcm.need_load_huc_fw = huc_fw_size ? 1 : 0;
> Then the compiler will do the right thing with
>
> 	guc->wopcm.need_load_huc_fw = huc_fw_size;
>
> bools, use them ;)
Thanks Chris!

To be honest, I would still end up with *guc->wopcm.need_load_huc_fw = 
huc_fw_size ? 1 : 0*
even if I had used bool for these flags.However, my main consideration 
to use *u32* instead of
*bool* was to make it flexible to add to flags bits,  e.g. easy to 
append new flags/fields which
needs more than 1-bit (may be overthinking here). we sure can use 
u8/16/32 for such new flags,
but it's a little bit odd to have something like:
     bool flag1:1;
     u8 flag2:2;

Plus, the mysterious bool size was another reason I was reluctant to use 
bool in struct (even through
I always got size = 1 byte for a bool type :-[).

Appreciate for more insights on the use of bool.

Regards,
-Jackie

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v9 2/7] drm/i915/guc: Rename guc_ggtt_offset to intel_guc_ggtt_offset
  2018-02-08 23:03 ` [PATCH v9 2/7] drm/i915/guc: Rename guc_ggtt_offset to intel_guc_ggtt_offset Jackie Li
@ 2018-02-09  8:01   ` Joonas Lahtinen
  0 siblings, 0 replies; 23+ messages in thread
From: Joonas Lahtinen @ 2018-02-09  8:01 UTC (permalink / raw)
  To: Jackie Li, intel-gfx

Quoting Jackie Li (2018-02-09 01:03:50)
> GuC related exported functions should start with "intel_guc_" prefix and
> pass intel_guc as the first parameter since its guc related. Current
> guc_ggtt_offset() failed to follow this code convention and this is a
> problem for future patches that needs to access intel_guc data to verify
> the GGTT offset against the GuC WOPCM top.
> 
> This patch renames the guc_ggtt_offset to intel_guc_ggtt_offset and updates
> the related code to pass intel_guc pointer to this function call, so that
> we can have a unified coding style for GuC code and also enable the future
> patches to get GuC related data from intel_guc to do the offset
> verification. Meanwhile, this patch also moves the GUC_GGTT_TOP from
> intel_guc_regs.h to intel_guc.h since it is not GuC register related
> definition.
> 
> v8:
>  - Fixed coding style issues and moved GUC_GGTT_TOP to intel_guc.h (Sagar)
>  - Updated commit message to explain to reason and motivation to add
>    intel_guc as the first parameter of intel_guc_ggtt_offset (Chris)
> 
> v9:
>  - Fixed code alignment issue due to line break (Chris)
> 
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> Cc: Sagar Arun Kamble <sagar.a.kamble@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Reviewed-by: Sagar Arun Kamble <sagar.a.kamble@intel.com> (v8)
> Signed-off-by: Jackie Li <yaodong.li@intel.com>

<SNIP>

> --- a/drivers/gpu/drm/i915/intel_guc.c
> +++ b/drivers/gpu/drm/i915/intel_guc.c
> @@ -269,8 +269,10 @@ void intel_guc_init_params(struct intel_guc *guc)
>  
>         /* If GuC submission is enabled, set up additional parameters here */
>         if (USES_GUC_SUBMISSION(dev_priv)) {
> -               u32 ads = guc_ggtt_offset(guc->ads_vma) >> PAGE_SHIFT;
> -               u32 pgs = guc_ggtt_offset(dev_priv->guc.stage_desc_pool);
> +               u32 ads = intel_guc_ggtt_offset(guc,
> +                                               guc->ads_vma) >> PAGE_SHIFT;
> +               u32 pgs = intel_guc_ggtt_offset(guc,
> +                                               dev_priv->guc.stage_desc_pool);

I must wonder why the other is addressed through dev_priv->guc and other
directly. guc->stage_desc_pool would work equally, right?

> @@ -135,11 +124,23 @@ int intel_guc_ads_create(struct intel_guc *guc)
>                 blob->ads.eng_state_size[engine->guc_id] =
>                         engine->context_size - skipped_size;
>  
> -       base = guc_ggtt_offset(vma);
> +       base = intel_guc_ggtt_offset(guc, vma);
>         blob->ads.scheduler_policies = base + ptr_offset(blob, policies);
>         blob->ads.reg_state_buffer = base + ptr_offset(blob, reg_state_buffer);
>         blob->ads.reg_state_addr = base + ptr_offset(blob, reg_state);
>  
> +       /*
> +        * The GuC requires a "Golden Context" when it reinitialises
> +        * engines after a reset. Here we use the Render ring default
> +        * context, which must already exist and be pinned in the GGTT,
> +        * so its address won't change after we've told the GuC where
> +        * to find it. Note that we have to skip our header (1 page),
> +        * because our GuC shared data is there.
> +        */
> +       vma = dev_priv->kernel_context->engine[RCS].state;

vma variable is being reused here, you want to have another variable for
each different use, this avoids nasty merge conflicts and at worst, bugs.

> diff --git a/drivers/gpu/drm/i915/intel_guc_log.c b/drivers/gpu/drm/i915/intel_guc_log.c
> index 7b5074e..eca8725 100644
> --- a/drivers/gpu/drm/i915/intel_guc_log.c
> +++ b/drivers/gpu/drm/i915/intel_guc_log.c
> @@ -638,7 +638,7 @@ int intel_guc_log_create(struct intel_guc *guc)
>                 (GUC_LOG_ISR_PAGES << GUC_LOG_ISR_SHIFT) |
>                 (GUC_LOG_CRASH_PAGES << GUC_LOG_CRASH_SHIFT);
>  
> -       offset = guc_ggtt_offset(vma) >> PAGE_SHIFT; /* in pages */
> +       offset = intel_guc_ggtt_offset(guc, vma) >> PAGE_SHIFT; /* in pages */

It's obvious it's in pages, you can drop the comment.

With those addressed, this is:

Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>

Regards, Joonas
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v9 3/7] drm/i915/guc: Implement dynamic GuC WOPCM offset and size
  2018-02-08 23:03 ` [PATCH v9 3/7] drm/i915/guc: Implement dynamic GuC WOPCM offset and size Jackie Li
@ 2018-02-09  9:31   ` Joonas Lahtinen
  2018-02-09 17:24   ` Michal Wajdeczko
  1 sibling, 0 replies; 23+ messages in thread
From: Joonas Lahtinen @ 2018-02-09  9:31 UTC (permalink / raw)
  To: Jackie Li, intel-gfx; +Cc: Sujaritha Sundaresan

Quoting Jackie Li (2018-02-09 01:03:51)
> Hardware may have specific restrictions on GuC WOPCM offset and size. On
> Gen9, the value of the GuC WOPCM size register needs to be larger than the
> value of GuC WOPCM offset register + a Gen9 specific offset (144KB) for
> reserved GuC WOPCM. Fail to enforce such a restriction on GuC WOPCM size
> will lead to GuC firmware execution failures. So we need add code to verify
> the GuC WOPCM offset and size to avoid any GuC failures. On the other hand,
> with current static GuC WOPCM offset and size values (512KB for both offset
> and size), the GuC WOPCM size verification will fail on Gen9 even if it can
> be fixed by lowering the GuC WOPCM offset by calculating its value based on
> HuC firmware size (which is likely less than 200KB on Gen9), so that we can
> have a GuC WOPCM size value which is large enough to pass the GuC WOPCM
> size check.
> 
> This patch updates the reserved GuC WOPCM size for RC6 context on Gen9 to
> 24KB to strictly align with the Gen9 GuC WOPCM layout and add support to
> return CNL specific hardware reserved GuC WOPCM size. It also adds support
> to verify the GuC WOPCM size aganist the Gen9 hardware restrictions.
> Meanwhile, it provides a common way to calculate GuC WOPCM offset and size
> based on GuC and HuC firmware sizes for all GuC/HuC enabled platforms.
> Currently, GuC WOPCM offset is calculated based on HuC firmware size +
> reserved WOPCM size while GuC WOPCM size is set to total WOPCM size - GuC
> WOPCM offset - hardware reserved GuC WOPCM size. In this case, GuC WOPCM
> offset will be updated based on the size of HuC firmware while GuC WOPCM
> size will be set to use all the remaining WOPCM space.
> 
> v2:
>  - Removed intel_wopcm_init (Ville/Sagar/Joonas)
>  - Renamed and Moved the intel_wopcm_partition into intel_guc (Sagar)
>  - Removed unnecessary function calls (Joonas)
>  - Init GuC WOPCM partition as soon as firmware fetching is completed
> 
> v3:
>  - Fixed indentation issues (Chris)
>  - Removed layering violation code (Chris/Michal)
>  - Created separat files for GuC wopcm code  (Michal)
>  - Used inline function to avoid code duplication (Michal)
> 
> v4:
>  - Preset the GuC WOPCM top during early GuC init (Chris)
>  - Fail intel_uc_init_hw() as soon as GuC WOPCM partitioning failed
> 
> v5:
>  - Moved GuC DMA WOPCM register updating code into intel_guc_wopcm.c
>  - Took care of the locking status before writing to GuC DMA
>    Write-Once registers. (Joonas)
> 
> v6:
>  - Made sure the GuC WOPCM size to be multiple of 4K (4K aligned)
> 
> v8:
>  - Updated comments and fixed naming issues (Sagar/Joonas)
>  - Updated commit message to include more description about the hardware
>    restriction on GuC WOPCM size (Sagar)
> 
> v9:
>  - Minor changes variable names and code comments (Sagar)
>  - Added detailed GuC WOPCM layout drawing (Sagar/Michal)
>  - Refined macro definitions to be reader friendly (Michal)
>  - Removed redundent check to valid flag (Michal)
>  - Unified first parameter for exported GuC WOPCM functions (Michal)
>  - Refined the name and parameter list of hardware restriction checking
>    functions (Michal)
> 
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> Cc: Sagar Arun Kamble <sagar.a.kamble@intel.com>
> Cc: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com>
> Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Cc: John Spotswood <john.a.spotswood@intel.com>
> Cc: Oscar Mateo <oscar.mateo@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Reviewed-by: Sagar Arun Kamble <sagar.a.kamble@intel.com> (v8)
> Signed-off-by: Jackie Li <yaodong.li@intel.com>

<SNIP>

> --- a/drivers/gpu/drm/i915/intel_guc_wopcm.c
> +++ b/drivers/gpu/drm/i915/intel_guc_wopcm.c
> @@ -27,22 +27,115 @@
>  #include "intel_guc_wopcm.h"
>  #include "i915_drv.h"
>  
> +static inline u32 guc_wopcm_context_reserved_size(struct intel_guc *guc)

This is intel_guc_wopcm file, so context_reserved_size() would be enough. But if
you feel like it is needed in the usage context, it's ok this way too.

> +int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32 guc_fw_size,
> +                        u32 huc_fw_size)
>  {
> -       struct drm_i915_private *i915 = guc_to_i915(guc);
> -       u32 size = GUC_WOPCM_TOP;
> +       struct intel_guc *guc =
> +               container_of(guc_wopcm, struct intel_guc, wopcm);
> +       u32 reserved = guc_wopcm_context_reserved_size(guc);
> +       u32 offset, size, top;
> +       int err;
>  
> -       /* On BXT, the top of WOPCM is reserved for RC6 context */
> -       if (IS_GEN9_LP(i915))
> -               size -= BXT_GUC_WOPCM_RC6_RESERVED;
> +       if (!guc_fw_size)
> +               return -EINVAL;
> +
> +       if (reserved >= WOPCM_DEFAULT_SIZE)
> +               return -E2BIG;
> +
> +       offset = huc_fw_size + WOPCM_RESERVED_SIZE;
> +       if (offset >= WOPCM_DEFAULT_SIZE)
> +               return -E2BIG;
> +
> +       /* Hardware requires GuC WOPCM offset to be 16K aligned. */
> +       offset = ALIGN(offset, GUC_WOPCM_OFFSET_ALIGNMENT);
> +       if ((offset + reserved) >= WOPCM_DEFAULT_SIZE)
> +               return -E2BIG;
> +

Unless we're expecting a u32 wrap-around, could not we consolidate these
checks some? At least just checking offset against WOPCM_DEFAULT_SIZE
feels repetitive when in the next moment, we check ALIGN(offset) +
reserved vs. same limit.

> +       top = WOPCM_DEFAULT_SIZE - offset;
> +       size = top - reserved;
> +
> +       /* GuC WOPCM size must be multiple of 4K pages */
> +       size &= PAGE_MASK;
> +
> +       /*
> +        * GuC firmware size needs to be less than or equal to the size of the
> +        * available GuC WOPCM (total available GuC WOPCM size - reserved size).
> +        * Need extra 8K stack for GuC firmware.
> +        */
> +       reserved = GUC_WOPCM_RESERVED + GUC_WOPCM_STACK_RESERVED;
> +       if ((guc_fw_size + reserved) > size)
> +               return -E2BIG;
> +
> +       guc->wopcm.offset = offset;
> +       guc->wopcm.size = size;
> +       guc->wopcm.top = top;
> +
> +       /* Check platform specific restrictions */
> +       err = guc_wopcm_size_check(guc);
> +       if (err)
> +               return err;
> +
> +       guc->wopcm.valid = 1;
> +
> +       DRM_DEBUG_DRIVER("GuC WOPCM offset %dKB, size %dKB, top %dKB\n",
> +                        offset >> 10, size >> 10, top >> 10);
>  
> -       return size;
> +       return 0;
>  }

<SNIP>

>  /*
> - * 512KB static GuC WOPCM size from GUC_WOPCM_OFFSET_VALUE to the end of GuC
> - * WOPCM. GuC addresses below GUC_WOPCM_TOP don't map through the GTT.
> + * The layout of the WOPCM will be determined by GuC WOPCM size and offset
> + * registers settings. Currently, GuC WOPCM code calculates the GuC WOPCM offset
> + * and size values based on a layout as shown below:
> + *
> + *   +=====+==>+====================+<== GuC WOPCM top
> + *   ^     ^   |  HW contexts RSVD  |
> + *   |     |   +--------------------+<== GuC WOPCM size
> + *   |     |   |                    |
> + *   |    GuC  |                    |
> + *   |   WOPCM +--------------------+<== (Platform specific size)
> + *   |     |   |    GuC FW RSVD     |
> + * WOPCM   |   +------------------- +<== (16KB)
> + *   |     v   |   RSVD GUC WOPCM   |
> + *   |     +==>+====================+<== GuC WOPCM offset
> + *   |         |     RSVD WOPCM     |
> + *   |         +------------------- +
> + *   v         |      HuC FW        |
> + *   +========>+====================+<== WOPCM Base
> + *
> + * GuC accessible WOPCM starts at GuC WOPCM offset and ends at GuC WOPCM size.
> + * The top part of the GuC WOPCM is reserved for hardware contexts (e.g. RC6
> + * context). We need to keep tracking the GuC WOPCM top since hardware requires
> + * the GGTT offset of a GuC accessible GEM buffer to be larger than the value of
> + * GuC WOPCM top. The values of GuC WOPCM size and top should be set to the
> + * length from GuC WOPCM offset in bytes.
> + */
> +

This diagram is a nice touch!

> +/* Default WOPCM size 1MB. */
> +#define WOPCM_DEFAULT_SIZE             (0x1 << 20)
> +/* The initial 16KB WOPCM (RSVD WOPCM) is reserved. */
> +#define WOPCM_RESERVED_SIZE            (16 << 10)

We might want to throw these to a more generic place, but they'll do
here for now as this is the only user.

> +static inline void intel_guc_wopcm_init_early(struct intel_guc_wopcm *guc_wopcm)
> +{
> +       guc_wopcm->top = WOPCM_DEFAULT_SIZE;
> +}

For header file brevity, move the implementation + comment to the .c file,
static inline header functions are an optimization for speed critical and often
used functions, which this definitely is not.

With the init_early function moved (and other changes at your
discretion) this is:

Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>

Regards, Joonas
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v9 4/7] drm/i915/guc: Add support to return CNL specific reserved GuC WOPCM size
  2018-02-08 23:03 ` [PATCH v9 4/7] drm/i915/guc: Add support to return CNL specific reserved GuC WOPCM size Jackie Li
@ 2018-02-09  9:37   ` Joonas Lahtinen
  0 siblings, 0 replies; 23+ messages in thread
From: Joonas Lahtinen @ 2018-02-09  9:37 UTC (permalink / raw)
  To: Jackie Li, intel-gfx

Quoting Jackie Li (2018-02-09 01:03:52)
> CNL has its specific reserved GuC WOPCM size for RC6 and other hardware
> contexts.
> 
> This patch updates the code to return CNL specific reserved GuC WOPCM size
> for RC6 and other hardware contexts so that the GuC WOPCM size can be
> calculated correctly for CNL.
> 
> v9:
>  - Created a new patch for these changes originally made in v8 4/6 patch of
>    this series (Sagar/Michal)
> 
> Cc: Sagar Arun Kamble <sagar.a.kamble@intel.com>
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Signed-off-by: Jackie Li <yaodong.li@intel.com>

<SNIP>

> diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.c b/drivers/gpu/drm/i915/intel_guc_wopcm.c
> index 8b2ce49..d0185b0 100644
> --- a/drivers/gpu/drm/i915/intel_guc_wopcm.c
> +++ b/drivers/gpu/drm/i915/intel_guc_wopcm.c
> @@ -34,6 +34,9 @@ static inline u32 guc_wopcm_context_reserved_size(struct intel_guc *guc)
>         if (IS_GEN9_LP(i915))
>                 return BXT_GUC_WOPCM_RC6_CTX_RESERVED;
>  
> +       if (IS_GEN10(i915))
> +               return CNL_GUC_WOPCM_HW_CTX_RESERVED;
> +
>         return 0;
>  }
>  

This should maybe be a if-else ladder, with the last branch applying to
any Gen10+, as it's a reasonable expectation that size is what it was in
the previous platform (or is it?). So;

if (gen9_lp)
	...
else if (gen => 10)
	...

Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>

Regards, Joonas
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v9 5/7] drm/i915/guc: Add HuC firmware size related restriction for Gen9 and CNL A0
  2018-02-08 23:03 ` [PATCH v9 5/7] drm/i915/guc: Add HuC firmware size related restriction for Gen9 and CNL A0 Jackie Li
@ 2018-02-09  9:57   ` Joonas Lahtinen
  0 siblings, 0 replies; 23+ messages in thread
From: Joonas Lahtinen @ 2018-02-09  9:57 UTC (permalink / raw)
  To: Jackie Li, intel-gfx

Quoting Jackie Li (2018-02-09 01:03:53)
> On CNL A0 and Gen9, there's a hardware restriction that requires the
> available GuC WOPCM size to be larger than or equal to HuC firmware size.
> 
> This patch adds new verfication code to ensure the available GuC WOPCM size
> to be larger than or equal to HuC firmware size on both Gen9 and CNL A0.
> 
> v6:
>  - Extended HuC FW size check against GuC WOPCM size to all
>    Gen9 and CNL A0 platforms
> 
> v7:
>  - Fixed patch format issues
> 
> v8:
>  - Renamed variables and functions to avoid ambiguity (Joonas)
>  - Updated commit message and comments to be more comprehensive (Sagar)
> 
> v9:
>  - Moved code that is not related to restriction check into a separate
>    patch and updated the commit message accordingly (Sagar/Michal)
>  - Avoided to call uc_get_fw_size for better layer isolation (Michal)
> 
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> Cc: Sagar Arun Kamble <sagar.a.kamble@intel.com>
> Cc: John Spotswood <john.a.spotswood@intel.com>
> Cc: Jeff McGee <jeff.mcgee@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Reviewed-by: Sagar Arun Kamble <sagar.a.kamble@intel.com> (v8)
> Signed-off-by: Jackie Li <yaodong.li@intel.com>

<SNIP>

> -static inline int gen9_guc_wopcm_size_check(struct intel_guc_wopcm *guc_wopcm)
> +static inline int guc_wopcm_check_huc_fw_size(struct intel_guc_wopcm *guc_wopcm,
> +                                             u32 huc_fw_size)

You can abbreviate here as there are local funcs, "check_huc_fw_fits" is
enough.

> +{
> +       /*
> +        * On Gen9 & CNL A0, hardware requires the total available GuC WOPCM
> +        * size to be larger than or equal to HuC firmware size. Otherwise,
> +        * firmware uploading would fail.
> +        */
> +       if (unlikely(guc_wopcm->size - GUC_WOPCM_RESERVED < huc_fw_size))
> +               return -E2BIG;

Again, it is overkill to try to educate branch predictor when this is
called once during boot, just do the check without unlikely() wrapping
:)

> +
> +       return 0;
> +}
> +
> +static inline int gen9_guc_wopcm_size_check(struct intel_guc_wopcm *guc_wopcm,
> +                                           u32 huc_fw_size)

Abbreviate to gen9_check_dword_gap or something, don't bring the huc_fw_size
here.

>  {
>         u32 guc_wopcm_start;
>         u32 delta;
> @@ -58,16 +73,19 @@ static inline int gen9_guc_wopcm_size_check(struct intel_guc_wopcm *guc_wopcm)
>         if (unlikely(delta < sizeof(u32)))
>                 return -E2BIG;
>  
> -       return 0;
> +       return guc_wopcm_check_huc_fw_size(guc_wopcm, huc_fw_size);
>  }
>  
> -static inline int guc_wopcm_size_check(struct intel_guc *guc)
> +static inline int guc_wopcm_size_check(struct intel_guc *guc, u32 huc_fw_size)
>  {
>         struct drm_i915_private *i915 = guc_to_i915(guc);
>         struct intel_guc_wopcm *guc_wopcm = &guc->wopcm;
	int err = 0;

>  
>         if (IS_GEN9(i915))
> -               return gen9_guc_wopcm_size_check(guc_wopcm);
> +               return gen9_guc_wopcm_size_check(guc_wopcm, huc_fw_size);
	if (..)
		err = gen9_check_dword_gap(guc_wopcm);
	if (err)
		goto err;
> +
> +       if (IS_CNL_REVID(i915, CNL_REVID_A0, CNL_REVID_A0))
> +               return guc_wopcm_check_huc_fw_size(guc_wopcm, huc_fw_size);
>  

	if (IS_GEN9(i915) || IS_CNL_REVID(...))
		err = check_huc_fw_fit(...)
out:
	return err;

This will better isolate the "two bugs", and huc_fw_size only goes to one
of the checks, which makes the picture clearer.

>         return 0;
>  }
> @@ -131,7 +149,7 @@ int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32 guc_fw_size,
>         guc->wopcm.top = top;
>  
>         /* Check platform specific restrictions */
> -       err = guc_wopcm_size_check(guc);
> +       err = guc_wopcm_size_check(guc, huc_fw_size);

s/guc_wopcm_size_check/size_checks/ as we're doing multiple (that's
the only information the comment carries). Then drop the comment.

Regards, Joonas
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v9 6/7] drm/i915/guc: Check the locking status of GuC WOPCM registers
  2018-02-08 23:03 ` [PATCH v9 6/7] drm/i915/guc: Check the locking status of GuC WOPCM registers Jackie Li
  2018-02-08 23:31   ` Chris Wilson
@ 2018-02-09 10:47   ` Joonas Lahtinen
  2018-02-11  0:36     ` Yaodong Li
  2018-02-09 19:42   ` Michal Wajdeczko
  2 siblings, 1 reply; 23+ messages in thread
From: Joonas Lahtinen @ 2018-02-09 10:47 UTC (permalink / raw)
  To: Jackie Li, intel-gfx

Quoting Jackie Li (2018-02-09 01:03:54)
> GuC WOPCM registers are write-once registers. Current driver code accesses
> these registers without checking the accessibility to these registers which
> will lead to unpredictable driver behaviors if these registers were touch
> by other components (such as faulty BIOS code).
> 
> This patch moves the GuC WOPCM registers updating code into
> intel_guc_wopcm.c and adds check before and after the update to GuC WOPCM
> registers so that we can make sure the driver is in a known state before
> and after writing to these write-once registers.
> 
> v6:
>  - Made sure module reloading won't bug the kernel while doing
>    locking status checking
> 
> v7:
>  - Fixed patch format issues
> 
> v8:
>  - Fixed coding style issue on register lock bit macro definition (Sagar)
> 
> v9:
>  - Avoided to use redundant !! to cast uint to bool (Chris)
>  - Return error code instead of GEM_BUG_ON for locked with invalid register
>    values case (Sagar)
>  - Updated guc_wopcm_hw_init to use guc_wopcm as first parameter (Michal)
>  - Added code to set and validate the HuC_LOADING_AGENT_GUC bit in GuC
>    WOPCM offset register based on the presence of HuC firmware (Michal)
>  - Use bit fields instead of macros for GuC WOPCM flags (Michal)
> 
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Signed-off-by: Jackie Li <yaodong.li@intel.com>

<SNIP>

> +++ b/drivers/gpu/drm/i915/intel_guc_wopcm.c
> +static inline bool guc_wopcm_locked(struct intel_guc *guc)
> +{
> +       struct drm_i915_private *i915 = guc_to_i915(guc);
> +       bool size_reg_locked = __reg_locked(i915, GUC_WOPCM_SIZE);
> +       bool offset_reg_locked = __reg_locked(i915, DMA_GUC_WOPCM_OFFSET);
> +
> +       return size_reg_locked && offset_reg_locked;

Hmm, isn't this supposed to be || instead, if either of the registers is
locked, we can't really do much?

> +static inline void guc_wopcm_hw_update(struct intel_guc *guc)
> +{
> +       struct drm_i915_private *dev_priv = guc_to_i915(guc);
> +       u32 offset_reg_val;
> +
> +       /* GuC WOPCM registers should be unlocked at this point. */
> +       GEM_BUG_ON(__reg_locked(dev_priv, GUC_WOPCM_SIZE));
> +       GEM_BUG_ON(__reg_locked(dev_priv, DMA_GUC_WOPCM_OFFSET));
> +
> +       offset_reg_val = guc->wopcm.offset;
> +       if (guc->wopcm.need_load_huc_fw)

"load_huc_fw" would read better here.

> +               offset_reg_val |= HUC_LOADING_AGENT_GUC;
> +
> +       I915_WRITE(GUC_WOPCM_SIZE, guc->wopcm.size);
> +       I915_WRITE(DMA_GUC_WOPCM_OFFSET, offset_reg_val);
> +
> +       GEM_BUG_ON(!__reg_locked(dev_priv, GUC_WOPCM_SIZE));
> +       GEM_BUG_ON(!__reg_locked(dev_priv, DMA_GUC_WOPCM_OFFSET));

This could use static inline write_lockable_reg() helper with a return value.
I think we need to propagate the error all the way up the chain, as it's
not a driver programmer error if these registers are locked, instead it is
likely to be a BIOS problem.

In the helper we could also test if the value is locked but happens to
match what we were intending to write, then we could call it success and
maybe emit an INFO message.

> +}
> +
> +static inline bool guc_wopcm_regs_valid(struct intel_guc *guc)
> +{
> +       struct drm_i915_private *dev_priv = guc_to_i915(guc);
> +       u32 size, offset;
> +       bool guc_loads_huc;
> +       u32 reg_val;
> +
> +       reg_val = I915_READ(GUC_WOPCM_SIZE);
> +       /* GuC WOPCM size should be always multiple of 4K pages. */
> +       size = reg_val & PAGE_MASK;
> +
> +       reg_val = I915_READ(DMA_GUC_WOPCM_OFFSET);
> +       guc_loads_huc = reg_val & HUC_LOADING_AGENT_GUC;
> +       offset = reg_val & GUC_WOPCM_OFFSET_MASK;
> +
> +       if (guc->wopcm.need_load_huc_fw && !guc_loads_huc)
> +               return false;
> +
> +       return (size == guc->wopcm.size) && (offset == guc->wopcm.offset);
> +}

This seems to have much of what I wrote above already. I'd still split
the actual writes in a helper that will report the per-register a
WARN about "mismatch between locked register value and computed value"
or so. Dumping both the computed an actual register value.

> @@ -147,6 +211,8 @@ int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32 guc_fw_size,
>         guc->wopcm.offset = offset;
>         guc->wopcm.size = size;
>         guc->wopcm.top = top;
> +       /* Use GuC to load HuC firmware if HuC firmware is present. */

Comment is again more on the "what" side, so can be dropped.

> +       guc->wopcm.need_load_huc_fw = huc_fw_size ? 1 : 0;

	... = huc_fw_size > 0;

Will literally read as "set guc load_huc_fw if huc_fw_size is
greater than zero."

> +int intel_guc_wopcm_init_hw(struct intel_guc_wopcm *guc_wopcm)
> +{
> +       struct intel_guc *guc = guc_wopcm_to_guc(guc_wopcm);
> +       bool locked = guc_wopcm_locked(guc);
> +
> +       GEM_BUG_ON(!guc->wopcm.valid);
> +
> +       /*
> +        * Bug if driver hasn't updated the HW Registers and GuC WOPCM has been
> +        * locked. Return directly if WOPCM was locked and we have updated
> +        * the registers.
> +        */
> +       if (locked) {
> +               if (guc->wopcm.hw_updated)
> +                       return 0;
> +
> +               /*
> +                * Mark as updated if registers contained correct values.
> +                * This will happen while reloading the driver module without
> +                * rebooting the system.
> +                */
> +               if (guc_wopcm_regs_valid(guc))
> +                       goto out;
> +
> +               /* Register locked without valid values. Abort HW init. */
> +               return -EINVAL;
> +       }
> +
> +       /* Always update registers when GuC WOPCM is not locked. */
> +       guc_wopcm_hw_update(guc);

This flow will become more clear with the helpers, and we will get a
splat in the kernel message with less code about which register actually
was locked and how the value mismatched.

I'm up for discussion, but to my eyes the code flow would become more clear if
we start with the assumption "we can write the register values to what we have
calculated", and then make it an error that is propagated back up if we can't.

Regards, Joonas
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v9 1/7] drm/i915/guc: Move GuC WOPCM related code into separate files
  2018-02-08 23:03 [PATCH v9 1/7] drm/i915/guc: Move GuC WOPCM related code into separate files Jackie Li
                   ` (6 preceding siblings ...)
  2018-02-08 23:29 ` ✗ Fi.CI.BAT: failure for series starting with [v9,1/7] drm/i915/guc: Move GuC WOPCM related code into separate files Patchwork
@ 2018-02-09 16:46 ` Michal Wajdeczko
  2018-02-09 19:38   ` Yaodong Li
  7 siblings, 1 reply; 23+ messages in thread
From: Michal Wajdeczko @ 2018-02-09 16:46 UTC (permalink / raw)
  To: intel-gfx, Jackie Li

On Fri, 09 Feb 2018 00:03:49 +0100, Jackie Li <yaodong.li@intel.com> wrote:

> intel_guc_reg.h should only include definition for GuC registers and
> related register bits. Non-register related GuC WOPCM macro definitions
> should not be defined in intel_guc_reg.h.
>
> This patch cleans up intel_guc_reg.h and moves GuC WOPCM related code  
> into
> new created separate files as future patches will increase the complexity
> of determining the GuC WOPCM offset and size.
>
> v8:
>  - Fixed naming, coding style issues and typo in commit message (Sagar)
>  - Updated commit message to explain why we need create new file for GuC
>    WOPCM related code (Chris)
>
> v9:
>  - Corrected kernel-doc format (Sagar)
>  - Simplified commit message (Michal)
>  - Updated license of new created files to use SPDX (Michal)
>  - Updated macros and added more comments to be reader friendly (Michal)
>
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> Cc: Sagar Arun Kamble <sagar.a.kamble@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Reviewed-by: Sagar Arun Kamble <sagar.a.kamble@intel.com> (v8)
> Signed-off-by: Jackie Li <yaodong.li@intel.com>
> ---
>  drivers/gpu/drm/i915/Makefile          |  1 +
>  drivers/gpu/drm/i915/intel_guc.c       | 11 --------
>  drivers/gpu/drm/i915/intel_guc.h       |  2 +-
>  drivers/gpu/drm/i915/intel_guc_reg.h   |  4 ---
>  drivers/gpu/drm/i915/intel_guc_wopcm.c | 48  
> ++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_guc_wopcm.h | 45  
> +++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_uc.c        |  2 +-
>  drivers/gpu/drm/i915/intel_uc_fw.c     |  2 +-
>  8 files changed, 97 insertions(+), 18 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/intel_guc_wopcm.c
>  create mode 100644 drivers/gpu/drm/i915/intel_guc_wopcm.h
>
> diff --git a/drivers/gpu/drm/i915/Makefile  
> b/drivers/gpu/drm/i915/Makefile
> index f55cc02..418d96b 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -89,6 +89,7 @@ i915-y += intel_uc.o \
>  	  intel_guc_fw.o \
>  	  intel_guc_log.o \
>  	  intel_guc_submission.o \
> +	  intel_guc_wopcm.o \
>  	  intel_huc.o
> # autogenerated null render state
> diff --git a/drivers/gpu/drm/i915/intel_guc.c  
> b/drivers/gpu/drm/i915/intel_guc.c
> index 21140cc..9f45e6d 100644
> --- a/drivers/gpu/drm/i915/intel_guc.c
> +++ b/drivers/gpu/drm/i915/intel_guc.c
> @@ -509,14 +509,3 @@ struct i915_vma *intel_guc_allocate_vma(struct  
> intel_guc *guc, u32 size)
>  	i915_gem_object_put(obj);
>  	return vma;
>  }
> -
> -u32 intel_guc_wopcm_size(struct drm_i915_private *dev_priv)
> -{
> -	u32 wopcm_size = GUC_WOPCM_TOP;
> -
> -	/* On BXT, the top of WOPCM is reserved for RC6 context */
> -	if (IS_GEN9_LP(dev_priv))
> -		wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED;
> -
> -	return wopcm_size;
> -}
> diff --git a/drivers/gpu/drm/i915/intel_guc.h  
> b/drivers/gpu/drm/i915/intel_guc.h
> index 52856a9..9e0a97e 100644
> --- a/drivers/gpu/drm/i915/intel_guc.h
> +++ b/drivers/gpu/drm/i915/intel_guc.h
> @@ -31,6 +31,7 @@
>  #include "intel_guc_ct.h"
>  #include "intel_guc_log.h"
>  #include "intel_guc_reg.h"
> +#include "intel_guc_wopcm.h"
>  #include "intel_uc_fw.h"
>  #include "i915_vma.h"
> @@ -130,6 +131,5 @@ int intel_guc_auth_huc(struct intel_guc *guc, u32  
> rsa_offset);
>  int intel_guc_suspend(struct drm_i915_private *dev_priv);
>  int intel_guc_resume(struct drm_i915_private *dev_priv);
>  struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32  
> size);
> -u32 intel_guc_wopcm_size(struct drm_i915_private *dev_priv);
> #endif
> diff --git a/drivers/gpu/drm/i915/intel_guc_reg.h  
> b/drivers/gpu/drm/i915/intel_guc_reg.h
> index 19a9247..1f52fb8 100644
> --- a/drivers/gpu/drm/i915/intel_guc_reg.h
> +++ b/drivers/gpu/drm/i915/intel_guc_reg.h
> @@ -68,7 +68,6 @@
>  #define DMA_GUC_WOPCM_OFFSET		_MMIO(0xc340)
>  #define   HUC_LOADING_AGENT_VCR		  (0<<1)
>  #define   HUC_LOADING_AGENT_GUC		  (1<<1)
> -#define   GUC_WOPCM_OFFSET_VALUE	  0x80000	/* 512KB */
>  #define GUC_MAX_IDLE_COUNT		_MMIO(0xC3E4)
> #define HUC_STATUS2             _MMIO(0xD3B0)
> @@ -76,9 +75,6 @@
> /* Defines WOPCM space available to GuC firmware */
>  #define GUC_WOPCM_SIZE			_MMIO(0xc050)
> -/* GuC addresses below GUC_WOPCM_TOP don't map through the GTT */
> -#define   GUC_WOPCM_TOP			  (0x80 << 12)	/* 512KB */
> -#define   BXT_GUC_WOPCM_RC6_RESERVED	  (0x10 << 12)	/* 64KB  */
> /* GuC addresses above GUC_GGTT_TOP also don't map through the GTT */
>  #define GUC_GGTT_TOP			0xFEE00000
> diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.c  
> b/drivers/gpu/drm/i915/intel_guc_wopcm.c
> new file mode 100644
> index 0000000..c3d54f8
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_guc_wopcm.c
> @@ -0,0 +1,48 @@
> +/*
> + * SPDX-License-Identifier: MIT
> + *
> + * Copyright © 2017-2018 Intel Corporation
> + *

Do we really want to keep legacy license text?
Note that in other file (intel_lrc_reg.h) we have only SPDX tag.

> + * Permission is hereby granted, free of charge, to any person  
> obtaining a
> + * copy of this software and associated documentation files (the  
> "Software"),
> + * to deal in the Software without restriction, including without  
> limitation
> + * the rights to use, copy, modify, merge, publish, distribute,  
> sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the  
> next
> + * paragraph) shall be included in all copies or substantial portions  
> of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,  
> EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF  
> MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT  
> SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR  
> OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,  
> ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER  
> DEALINGS
> + * IN THE SOFTWARE.
> + *
> + */
> +
> +#include "intel_guc_wopcm.h"
> +#include "i915_drv.h"
> +
> +/**
> + * intel_guc_wopcm_size() - Get the size of GuC WOPCM.
> + * @guc: intel guc.
> + *
> + * Get the platform specific GuC WOPCM size.
> + *
> + * Return: size of the GuC WOPCM.
> + */
> +u32 intel_guc_wopcm_size(struct intel_guc *guc)
> +{
> +	struct drm_i915_private *i915 = guc_to_i915(guc);
> +	u32 size = GUC_WOPCM_TOP;
> +
> +	/* On BXT, the top of WOPCM is reserved for RC6 context */
> +	if (IS_GEN9_LP(i915))
> +		size -= BXT_GUC_WOPCM_RC6_RESERVED;
> +
> +	return size;
> +}
> diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.h  
> b/drivers/gpu/drm/i915/intel_guc_wopcm.h
> new file mode 100644
> index 0000000..7323604
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_guc_wopcm.h
> @@ -0,0 +1,45 @@
> +/*
> + * SPDX-License-Identifier: MIT
> + *
> + * Copyright © 2017-2018 Intel Corporation
> + *

Same here.

> + * Permission is hereby granted, free of charge, to any person  
> obtaining a
> + * copy of this software and associated documentation files (the  
> "Software"),
> + * to deal in the Software without restriction, including without  
> limitation
> + * the rights to use, copy, modify, merge, publish, distribute,  
> sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the  
> next
> + * paragraph) shall be included in all copies or substantial portions  
> of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,  
> EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF  
> MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT  
> SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR  
> OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,  
> ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER  
> DEALINGS
> + * IN THE SOFTWARE.
> + *
> + */
> +
> +#ifndef _INTEL_GUC_WOPCM_H_
> +#define _INTEL_GUC_WOPCM_H_
> +
> +#include <linux/types.h>
> +
> +struct intel_guc;
> +
> +/* 512KB static offset from WOPCM base. */
> +#define GUC_WOPCM_OFFSET_VALUE		(512 << 10)
> +/*
> + * 512KB static GuC WOPCM size from GUC_WOPCM_OFFSET_VALUE to the end  
> of GuC
> + * WOPCM. GuC addresses below GUC_WOPCM_TOP don't map through the GTT.
> + */
> +#define GUC_WOPCM_TOP			(512 << 10)
> +#define BXT_GUC_WOPCM_RC6_RESERVED	(64 << 10)
> +
> +u32 intel_guc_wopcm_size(struct intel_guc *guc);
> +
> +#endif
> diff --git a/drivers/gpu/drm/i915/intel_uc.c  
> b/drivers/gpu/drm/i915/intel_uc.c
> index 9f1bac6..1b2831b 100644
> --- a/drivers/gpu/drm/i915/intel_uc.c
> +++ b/drivers/gpu/drm/i915/intel_uc.c
> @@ -340,7 +340,7 @@ int intel_uc_init_hw(struct drm_i915_private  
> *dev_priv)
>  	gen9_reset_guc_interrupts(dev_priv);
> 	/* init WOPCM */
> -	I915_WRITE(GUC_WOPCM_SIZE, intel_guc_wopcm_size(dev_priv));
> +	I915_WRITE(GUC_WOPCM_SIZE, intel_guc_wopcm_size(guc));
>  	I915_WRITE(DMA_GUC_WOPCM_OFFSET,
>  		   GUC_WOPCM_OFFSET_VALUE | HUC_LOADING_AGENT_GUC);
> diff --git a/drivers/gpu/drm/i915/intel_uc_fw.c  
> b/drivers/gpu/drm/i915/intel_uc_fw.c
> index 784eff9..24945cf 100644
> --- a/drivers/gpu/drm/i915/intel_uc_fw.c
> +++ b/drivers/gpu/drm/i915/intel_uc_fw.c
> @@ -97,7 +97,7 @@ void intel_uc_fw_fetch(struct drm_i915_private  
> *dev_priv,
> 	/* Header and uCode will be loaded to WOPCM */
>  	size = uc_fw->header_size + uc_fw->ucode_size;
> -	if (size > intel_guc_wopcm_size(dev_priv)) {
> +	if (size > intel_guc_wopcm_size(&dev_priv->guc)) {
>  		DRM_WARN("%s: Firmware is too large to fit in WOPCM\n",
>  			 intel_uc_fw_type_repr(uc_fw->type));
>  		err = -E2BIG;
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v9 3/7] drm/i915/guc: Implement dynamic GuC WOPCM offset and size
  2018-02-08 23:03 ` [PATCH v9 3/7] drm/i915/guc: Implement dynamic GuC WOPCM offset and size Jackie Li
  2018-02-09  9:31   ` Joonas Lahtinen
@ 2018-02-09 17:24   ` Michal Wajdeczko
  2018-02-09 19:32     ` Yaodong Li
  1 sibling, 1 reply; 23+ messages in thread
From: Michal Wajdeczko @ 2018-02-09 17:24 UTC (permalink / raw)
  To: intel-gfx, Jackie Li; +Cc: Sujaritha Sundaresan

On Fri, 09 Feb 2018 00:03:51 +0100, Jackie Li <yaodong.li@intel.com> wrote:

> Hardware may have specific restrictions on GuC WOPCM offset and size. On
> Gen9, the value of the GuC WOPCM size register needs to be larger than  
> the
> value of GuC WOPCM offset register + a Gen9 specific offset (144KB) for
> reserved GuC WOPCM. Fail to enforce such a restriction on GuC WOPCM size
> will lead to GuC firmware execution failures. So we need add code to  
> verify
> the GuC WOPCM offset and size to avoid any GuC failures. On the other  
> hand,
> with current static GuC WOPCM offset and size values (512KB for both  
> offset
> and size), the GuC WOPCM size verification will fail on Gen9 even if it  
> can
> be fixed by lowering the GuC WOPCM offset by calculating its value based  
> on
> HuC firmware size (which is likely less than 200KB on Gen9), so that we  
> can
> have a GuC WOPCM size value which is large enough to pass the GuC WOPCM
> size check.
>
> This patch updates the reserved GuC WOPCM size for RC6 context on Gen9 to
> 24KB to strictly align with the Gen9 GuC WOPCM layout and add support to
> return CNL specific hardware reserved GuC WOPCM size. It also adds  
> support
> to verify the GuC WOPCM size aganist the Gen9 hardware restrictions.
> Meanwhile, it provides a common way to calculate GuC WOPCM offset and  
> size
> based on GuC and HuC firmware sizes for all GuC/HuC enabled platforms.
> Currently, GuC WOPCM offset is calculated based on HuC firmware size +
> reserved WOPCM size while GuC WOPCM size is set to total WOPCM size - GuC
> WOPCM offset - hardware reserved GuC WOPCM size. In this case, GuC WOPCM
> offset will be updated based on the size of HuC firmware while GuC WOPCM
> size will be set to use all the remaining WOPCM space.
>
> v2:
>  - Removed intel_wopcm_init (Ville/Sagar/Joonas)
>  - Renamed and Moved the intel_wopcm_partition into intel_guc (Sagar)
>  - Removed unnecessary function calls (Joonas)
>  - Init GuC WOPCM partition as soon as firmware fetching is completed
>
> v3:
>  - Fixed indentation issues (Chris)
>  - Removed layering violation code (Chris/Michal)
>  - Created separat files for GuC wopcm code  (Michal)
>  - Used inline function to avoid code duplication (Michal)
>
> v4:
>  - Preset the GuC WOPCM top during early GuC init (Chris)
>  - Fail intel_uc_init_hw() as soon as GuC WOPCM partitioning failed
>
> v5:
>  - Moved GuC DMA WOPCM register updating code into intel_guc_wopcm.c
>  - Took care of the locking status before writing to GuC DMA
>    Write-Once registers. (Joonas)
>
> v6:
>  - Made sure the GuC WOPCM size to be multiple of 4K (4K aligned)
>
> v8:
>  - Updated comments and fixed naming issues (Sagar/Joonas)
>  - Updated commit message to include more description about the hardware
>    restriction on GuC WOPCM size (Sagar)
>
> v9:
>  - Minor changes variable names and code comments (Sagar)
>  - Added detailed GuC WOPCM layout drawing (Sagar/Michal)
>  - Refined macro definitions to be reader friendly (Michal)
>  - Removed redundent check to valid flag (Michal)
>  - Unified first parameter for exported GuC WOPCM functions (Michal)
>  - Refined the name and parameter list of hardware restriction checking
>    functions (Michal)
>
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> Cc: Sagar Arun Kamble <sagar.a.kamble@intel.com>
> Cc: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com>
> Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Cc: John Spotswood <john.a.spotswood@intel.com>
> Cc: Oscar Mateo <oscar.mateo@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Reviewed-by: Sagar Arun Kamble <sagar.a.kamble@intel.com> (v8)
> Signed-off-by: Jackie Li <yaodong.li@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_gem_context.c |   5 +-
>  drivers/gpu/drm/i915/intel_guc.c        |   5 +-
>  drivers/gpu/drm/i915/intel_guc.h        |  12 ++--
>  drivers/gpu/drm/i915/intel_guc_wopcm.c  | 115  
> +++++++++++++++++++++++++++++---
>  drivers/gpu/drm/i915/intel_guc_wopcm.h  |  85 +++++++++++++++++++++--
>  drivers/gpu/drm/i915/intel_huc.c        |   2 +-
>  drivers/gpu/drm/i915/intel_uc.c         |  11 ++-
>  drivers/gpu/drm/i915/intel_uc_fw.c      |  11 ++-
>  drivers/gpu/drm/i915/intel_uc_fw.h      |  16 +++++
>  9 files changed, 229 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_context.c  
> b/drivers/gpu/drm/i915/i915_gem_context.c
> index 3d75f48..414eab2 100644
> --- a/drivers/gpu/drm/i915/i915_gem_context.c
> +++ b/drivers/gpu/drm/i915/i915_gem_context.c
> @@ -312,12 +312,13 @@ __create_hw_context(struct drm_i915_private  
> *dev_priv,
>  	ctx->desc_template =
>  		default_desc_template(dev_priv, dev_priv->mm.aliasing_ppgtt);
> -	/* GuC requires the ring to be placed above GUC_WOPCM_TOP. If GuC is  
> not
> +	/*
> +	 * GuC requires the ring to be placed above GuC WOPCM top. If GuC is  
> not
>  	 * present or not in use we still need a small bias as ring wraparound
>  	 * at offset 0 sometimes hangs. No idea why.
>  	 */
>  	if (USES_GUC(dev_priv))
> -		ctx->ggtt_offset_bias = GUC_WOPCM_TOP;
> +		ctx->ggtt_offset_bias = dev_priv->guc.wopcm.top;
>  	else
>  		ctx->ggtt_offset_bias = I915_GTT_PAGE_SIZE;
> diff --git a/drivers/gpu/drm/i915/intel_guc.c  
> b/drivers/gpu/drm/i915/intel_guc.c
> index d9bc2a9..ecd5da2 100644
> --- a/drivers/gpu/drm/i915/intel_guc.c
> +++ b/drivers/gpu/drm/i915/intel_guc.c
> @@ -65,6 +65,7 @@ void intel_guc_init_early(struct intel_guc *guc)
>  	intel_guc_fw_init_early(guc);
>  	intel_guc_ct_init_early(&guc->ct);
>  	intel_guc_log_init_early(guc);
> +	intel_guc_wopcm_init_early(&guc->wopcm);
> 	mutex_init(&guc->send_mutex);
>  	guc->send = intel_guc_send_nop;
> @@ -478,7 +479,7 @@ int intel_guc_resume(struct drm_i915_private  
> *dev_priv)
>   * This is a wrapper to create an object for use with the GuC. In order  
> to
>   * use it inside the GuC, an object needs to be pinned lifetime, so we  
> allocate
>   * both some backing storage and a range inside the Global GTT. We must  
> pin
> - * it in the GGTT somewhere other than than [0, GUC_WOPCM_TOP) because  
> that
> + * it in the GGTT somewhere other than than [0, GuC WOPCM top) because  
> that
>   * range is reserved inside GuC.
>   *
>   * Return:	A i915_vma if successful, otherwise an ERR_PTR.
> @@ -499,7 +500,7 @@ struct i915_vma *intel_guc_allocate_vma(struct  
> intel_guc *guc, u32 size)
>  		goto err;
> 	ret = i915_vma_pin(vma, 0, PAGE_SIZE,
> -			   PIN_GLOBAL | PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
> +			   PIN_GLOBAL | PIN_OFFSET_BIAS | guc->wopcm.top);
>  	if (ret) {
>  		vma = ERR_PTR(ret);
>  		goto err;
> diff --git a/drivers/gpu/drm/i915/intel_guc.h  
> b/drivers/gpu/drm/i915/intel_guc.h
> index 50be6de..06f315e 100644
> --- a/drivers/gpu/drm/i915/intel_guc.h
> +++ b/drivers/gpu/drm/i915/intel_guc.h
> @@ -49,6 +49,7 @@ struct intel_guc {
>  	struct intel_uc_fw fw;
>  	struct intel_guc_log log;
>  	struct intel_guc_ct ct;
> +	struct intel_guc_wopcm wopcm;
> 	/* Log snapshot if GuC errors during load */
>  	struct drm_i915_gem_object *load_err_log;
> @@ -109,10 +110,10 @@ static inline void intel_guc_notify(struct  
> intel_guc *guc)
>   * @guc: intel guc.
>   * @vma: i915 graphics virtual memory area.
>   *
> - * GuC does not allow any gfx GGTT address that falls into range [0,  
> WOPCM_TOP),
> - * which is reserved for Boot ROM, SRAM and WOPCM. Currently this top  
> address is
> - * 512K. In order to exclude 0-512K address space from GGTT, all gfx  
> objects
> - * used by GuC is pinned with PIN_OFFSET_BIAS along with size of WOPCM.
> + * GuC does not allow any gfx GGTT address that falls into range
> + * [0, GuC WOPCM top), which is reserved for Boot ROM, SRAM and WOPCM.
> + * All gfx objects used by GuC is pinned with PIN_OFFSET_BIAS along with
> + * top of WOPCM.
>   *
>   * Return: GGTT offset that meets the GuC gfx address requirement.
>   */
> @@ -121,7 +122,8 @@ static inline u32 intel_guc_ggtt_offset(struct  
> intel_guc *guc,
>  {
>  	u32 offset = i915_ggtt_offset(vma);
> -	GEM_BUG_ON(offset < GUC_WOPCM_TOP);
> +	GEM_BUG_ON(!guc->wopcm.valid);
> +	GEM_BUG_ON(offset < guc->wopcm.top);
>  	GEM_BUG_ON(range_overflows_t(u64, offset, vma->size, GUC_GGTT_TOP));
> 	return offset;
> diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.c  
> b/drivers/gpu/drm/i915/intel_guc_wopcm.c
> index c3d54f8..8b2ce49 100644
> --- a/drivers/gpu/drm/i915/intel_guc_wopcm.c
> +++ b/drivers/gpu/drm/i915/intel_guc_wopcm.c
> @@ -27,22 +27,115 @@
>  #include "intel_guc_wopcm.h"
>  #include "i915_drv.h"
> +static inline u32 guc_wopcm_context_reserved_size(struct intel_guc *guc)
> +{
> +	struct drm_i915_private *i915 = guc_to_i915(guc);
> +
> +	if (IS_GEN9_LP(i915))
> +		return BXT_GUC_WOPCM_RC6_CTX_RESERVED;
> +
> +	return 0;
> +}
> +
> +static inline int gen9_guc_wopcm_size_check(struct intel_guc_wopcm  
> *guc_wopcm)
> +{
> +	u32 guc_wopcm_start;
> +	u32 delta;
> +
> +	/*
> +	 * GuC WOPCM size is at least a dword larger than the offset from WOPCM
> +	 * base (GuC WOPCM offset from WOPCM base + GEN9_GUC_WOPCM_OFFSET) due
> +	 * to hardware limitation on Gen9.
> +	 */
> +	guc_wopcm_start = guc_wopcm->offset + GEN9_GUC_WOPCM_OFFSET;
> +	if (unlikely(guc_wopcm_start > guc_wopcm->size))
> +		return -E2BIG;
> +
> +	delta = guc_wopcm->size - guc_wopcm_start;
> +	if (unlikely(delta < sizeof(u32)))
> +		return -E2BIG;
> +
> +	return 0;
> +}
> +
> +static inline int guc_wopcm_size_check(struct intel_guc *guc)
> +{
> +	struct drm_i915_private *i915 = guc_to_i915(guc);
> +	struct intel_guc_wopcm *guc_wopcm = &guc->wopcm;
> +
> +	if (IS_GEN9(i915))
> +		return gen9_guc_wopcm_size_check(guc_wopcm);
> +
> +	return 0;
> +}
> +
>  /**
> - * intel_guc_wopcm_size() - Get the size of GuC WOPCM.
> - * @guc: intel guc.
> + * intel_guc_wopcm_init() - Initialize the GuC WOPCM.
> + * @guc_wopcm: intel_guc_wopcm..

Please use better description, maybe "[pointer to] GuC WOPCM"
And remove redundant trailing dot.

> + * @guc_fw_size: size of GuC firmware.
> + * @huc_fw_size: size of HuC firmware.
>   *
> - * Get the platform specific GuC WOPCM size.
> + * Calculate the GuC WOPCM offset and size based on GuC and HuC  
> firmware sizes.
> + * This function will set the GuC WOPCM size to the size of maximum  
> WOPCM
> + * available for GuC. This function will also enforce platform dependent
> + * hardware restrictions on GuC WOPCM offset and size. It will fail the  
> GuC
> + * WOPCM init if any of these checks were failed, so that the following  
> GuC
> + * firmware uploading would be aborted.
>   *
> - * Return: size of the GuC WOPCM.
> + * Return: 0 on success, non-zero error code on failure.
>   */
> -u32 intel_guc_wopcm_size(struct intel_guc *guc)
> +int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32  
> guc_fw_size,
> +			 u32 huc_fw_size)
>  {
> -	struct drm_i915_private *i915 = guc_to_i915(guc);
> -	u32 size = GUC_WOPCM_TOP;
> +	struct intel_guc *guc =
> +		container_of(guc_wopcm, struct intel_guc, wopcm);

If you define this as "wopcm_to_guc" inline helper, then maybe
all your functions could take "wopcm" as first parameter?

> +	u32 reserved = guc_wopcm_context_reserved_size(guc);
> +	u32 offset, size, top;
> +	int err;
> -	/* On BXT, the top of WOPCM is reserved for RC6 context */
> -	if (IS_GEN9_LP(i915))
> -		size -= BXT_GUC_WOPCM_RC6_RESERVED;
> +	if (!guc_fw_size)
> +		return -EINVAL;

As there are many reasons to fail, maybe it would be good idea to
add at least DRM_DEBUG_DRIVER to each failing condition?

> +
> +	if (reserved >= WOPCM_DEFAULT_SIZE)
> +		return -E2BIG;

Do we really need to check this every time in runtime?
I think we can enforce this as GEM_BUG_ON here or in
guc_wopcm_context_reserved_size() function.

> +
> +	offset = huc_fw_size + WOPCM_RESERVED_SIZE;
> +	if (offset >= WOPCM_DEFAULT_SIZE)
> +		return -E2BIG;
> +
> +	/* Hardware requires GuC WOPCM offset to be 16K aligned. */
> +	offset = ALIGN(offset, GUC_WOPCM_OFFSET_ALIGNMENT);
> +	if ((offset + reserved) >= WOPCM_DEFAULT_SIZE)
> +		return -E2BIG;
> +
> +	top = WOPCM_DEFAULT_SIZE - offset;
> +	size = top - reserved;
> +
> +	/* GuC WOPCM size must be multiple of 4K pages */
> +	size &= PAGE_MASK;

Hmm, this will work only in CONFIG_IA64_PAGE_SIZE_4KB, is it ok?

> +
> +	/*
> +	 * GuC firmware size needs to be less than or equal to the size of the
> +	 * available GuC WOPCM (total available GuC WOPCM size - reserved  
> size).
> +	 * Need extra 8K stack for GuC firmware.
> +	 */
> +	reserved = GUC_WOPCM_RESERVED + GUC_WOPCM_STACK_RESERVED;
> +	if ((guc_fw_size + reserved) > size)
> +		return -E2BIG;
> +
> +	guc->wopcm.offset = offset;
> +	guc->wopcm.size = size;
> +	guc->wopcm.top = top;
> +
> +	/* Check platform specific restrictions */
> +	err = guc_wopcm_size_check(guc);

maybe "guc_wopcm_check_size(guc_wopcm)"

> +	if (err)
> +		return err;
> +
> +	guc->wopcm.valid = 1;
> +
> +	DRM_DEBUG_DRIVER("GuC WOPCM offset %dKB, size %dKB, top %dKB\n",
> +			 offset >> 10, size >> 10, top >> 10);
> -	return size;
> +	return 0;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.h  
> b/drivers/gpu/drm/i915/intel_guc_wopcm.h
> index 7323604..3af7ca9 100644
> --- a/drivers/gpu/drm/i915/intel_guc_wopcm.h
> +++ b/drivers/gpu/drm/i915/intel_guc_wopcm.h
> @@ -31,15 +31,86 @@
> struct intel_guc;
> -/* 512KB static offset from WOPCM base. */
> -#define GUC_WOPCM_OFFSET_VALUE		(512 << 10)
>  /*
> - * 512KB static GuC WOPCM size from GUC_WOPCM_OFFSET_VALUE to the end  
> of GuC
> - * WOPCM. GuC addresses below GUC_WOPCM_TOP don't map through the GTT.
> + * The layout of the WOPCM will be determined by GuC WOPCM size and  
> offset
> + * registers settings. Currently, GuC WOPCM code calculates the GuC  
> WOPCM offset
> + * and size values based on a layout as shown below:
> + *
> + *   +=====+==>+====================+<== GuC WOPCM top
> + *   ^     ^   |  HW contexts RSVD  |
> + *   |     |   +--------------------+<== GuC WOPCM size
> + *   |     |   |                    |
> + *   |    GuC  |                    |
> + *   |   WOPCM +--------------------+<== (Platform specific size)
> + *   |     |   |    GuC FW RSVD     |
> + * WOPCM   |   +------------------- +<== (16KB)
> + *   |     v   |   RSVD GUC WOPCM   |

Please be consistent in naming: Guc vs. GUC

> + *   |     +==>+====================+<== GuC WOPCM offset
> + *   |         |     RSVD WOPCM     |
> + *   |         +------------------- +
> + *   v         |      HuC FW        |
> + *   +========>+====================+<== WOPCM Base
> + *
> + * GuC accessible WOPCM starts at GuC WOPCM offset and ends at GuC  
> WOPCM size.
> + * The top part of the GuC WOPCM is reserved for hardware contexts  
> (e.g. RC6
> + * context). We need to keep tracking the GuC WOPCM top since hardware  
> requires
> + * the GGTT offset of a GuC accessible GEM buffer to be larger than the  
> value of
> + * GuC WOPCM top. The values of GuC WOPCM size and top should be set to  
> the
> + * length from GuC WOPCM offset in bytes.
> + */
> +
> +/* Default WOPCM size 1MB. */
> +#define WOPCM_DEFAULT_SIZE		(0x1 << 20)

(1 << 20) or (1024 * 1024)

> +/* The initial 16KB WOPCM (RSVD WOPCM) is reserved. */
> +#define WOPCM_RESERVED_SIZE		(16 << 10)
> +
> +/* GUC WOPCM offset needs to be 16KB aligned. */
> +#define GUC_WOPCM_OFFSET_ALIGNMENT	(16 << 10)
> +/* 16KB reserved at the beginning of GuC WOPCM. */
> +#define GUC_WOPCM_RESERVED		(16 << 10)
> +/* 8KB from GUC_WOPCM_RESERVED is reserved for GuC stack. */
> +#define GUC_WOPCM_STACK_RESERVED	(8 << 10)
> +/* 24KB at the end of GuC WOPCM is reserved for RC6 CTX on BXT. */
> +#define BXT_GUC_WOPCM_RC6_CTX_RESERVED	(24 << 10)
> +
> +/*
> + * GuC WOPCM starts at 144KB (GUC_WOPCM_RESERVED + 128KB reserved for  
> GuC
> + * firmware loading) from GuC WOPCM offset on BXT.
> + */
> +#define GEN9_GUC_WOPCM_OFFSET		(144 << 10)

Other BXT specific macro (BXT_GUC_WOPCM_RC6_CTX_RESERVED) was
defined with BXT_ prefix ... can we use common prefix?

> +
> +/**
> + * intel_guc_wopcm - GuC WOPCM related settings.
> + * @offset: GuC WOPCM offset from the WOPCM base.
> + * @size: size of GuC WOPCM for GuC firmware.
> + * @top: start of the non-GuC WOPCM memory.
> + * @valid: whether this structure contains valid (1-valid, 0-invalid)  
> info.
> + *
> + * We simply use this structure to track the GuC use of WOPCM. The  
> layout of
> + * WOPCM would be defined by writing to GuC WOPCM offset and size  
> registers.
> + */
> +struct intel_guc_wopcm {
> +	u32 offset;
> +	u32 size;
> +	u32 top;
> +	u32 valid;
> +};
> +
> +/**
> + * intel_guc_wopcm_init_early() - Early initialization of the GuC WOPCM.
> + * @guc_wopcm: intel_guc_wopcm.
> + *
> + * Setup the GuC WOPCM top to the top of the overall WOPCM. This will  
> guarantee
> + * that the allocation of the GuC accessible objects won't fall into  
> WOPCM when
> + * GuC partition isn't present.
> + *
>   */
> -#define GUC_WOPCM_TOP			(512 << 10)
> -#define BXT_GUC_WOPCM_RC6_RESERVED	(64 << 10)
> +static inline void intel_guc_wopcm_init_early(struct intel_guc_wopcm  
> *guc_wopcm)
> +{
> +	guc_wopcm->top = WOPCM_DEFAULT_SIZE;
> +}
> -u32 intel_guc_wopcm_size(struct intel_guc *guc);
> +int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32  
> guc_size,
> +			 u32 huc_size);
> #endif
> diff --git a/drivers/gpu/drm/i915/intel_huc.c  
> b/drivers/gpu/drm/i915/intel_huc.c
> index aed9c1c..dc6a6c6 100644
> --- a/drivers/gpu/drm/i915/intel_huc.c
> +++ b/drivers/gpu/drm/i915/intel_huc.c
> @@ -206,7 +206,7 @@ int intel_huc_auth(struct intel_huc *huc)
>  		return -ENOEXEC;
> 	vma = i915_gem_object_ggtt_pin(huc->fw.obj, NULL, 0, 0,
> -				PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
> +				PIN_OFFSET_BIAS | guc->wopcm.top);
>  	if (IS_ERR(vma)) {
>  		ret = PTR_ERR(vma);
>  		DRM_ERROR("HuC: Failed to pin huc fw object %d\n", ret);
> diff --git a/drivers/gpu/drm/i915/intel_uc.c  
> b/drivers/gpu/drm/i915/intel_uc.c
> index 1b2831b..c842f36 100644
> --- a/drivers/gpu/drm/i915/intel_uc.c
> +++ b/drivers/gpu/drm/i915/intel_uc.c
> @@ -283,6 +283,9 @@ void intel_uc_fini_misc(struct drm_i915_private  
> *dev_priv)
>  int intel_uc_init(struct drm_i915_private *dev_priv)
>  {
>  	struct intel_guc *guc = &dev_priv->guc;
> +	struct intel_huc *huc = &dev_priv->huc;
> +	u32 guc_fw_size = intel_uc_fw_get_size(&guc->fw);
> +	u32 huc_fw_size = intel_uc_fw_get_size(&huc->fw);
>  	int ret;
> 	if (!USES_GUC(dev_priv))
> @@ -291,6 +294,10 @@ int intel_uc_init(struct drm_i915_private *dev_priv)
>  	if (!HAS_GUC(dev_priv))
>  		return -ENODEV;
> +	ret = intel_guc_wopcm_init(&guc->wopcm, guc_fw_size, huc_fw_size);
> +	if (ret)
> +		return ret;
> +
>  	ret = intel_guc_init(guc);
>  	if (ret)
>  		return ret;
> @@ -340,9 +347,9 @@ int intel_uc_init_hw(struct drm_i915_private  
> *dev_priv)
>  	gen9_reset_guc_interrupts(dev_priv);
> 	/* init WOPCM */
> -	I915_WRITE(GUC_WOPCM_SIZE, intel_guc_wopcm_size(guc));
> +	I915_WRITE(GUC_WOPCM_SIZE, guc->wopcm.size);
>  	I915_WRITE(DMA_GUC_WOPCM_OFFSET,
> -		   GUC_WOPCM_OFFSET_VALUE | HUC_LOADING_AGENT_GUC);
> +		   guc->wopcm.offset | HUC_LOADING_AGENT_GUC);
> 	/* WaEnableuKernelHeaderValidFix:skl */
>  	/* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */
> diff --git a/drivers/gpu/drm/i915/intel_uc_fw.c  
> b/drivers/gpu/drm/i915/intel_uc_fw.c
> index 24945cf..791263a 100644
> --- a/drivers/gpu/drm/i915/intel_uc_fw.c
> +++ b/drivers/gpu/drm/i915/intel_uc_fw.c
> @@ -95,9 +95,13 @@ void intel_uc_fw_fetch(struct drm_i915_private  
> *dev_priv,
>  	uc_fw->ucode_offset = uc_fw->header_offset + uc_fw->header_size;
>  	uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32);
> -	/* Header and uCode will be loaded to WOPCM */
> +	/*
> +	 * Header and uCode will be loaded to WOPCM
> +	 * Only check the size against the overall available WOPCM here. Will
> +	 * continue to check the size during WOPCM partition calculation.
> +	 */
>  	size = uc_fw->header_size + uc_fw->ucode_size;
> -	if (size > intel_guc_wopcm_size(&dev_priv->guc)) {
> +	if (size > WOPCM_DEFAULT_SIZE) {
>  		DRM_WARN("%s: Firmware is too large to fit in WOPCM\n",
>  			 intel_uc_fw_type_repr(uc_fw->type));
>  		err = -E2BIG;
> @@ -207,6 +211,7 @@ int intel_uc_fw_upload(struct intel_uc_fw *uc_fw,
>  		       int (*xfer)(struct intel_uc_fw *uc_fw,
>  				   struct i915_vma *vma))
>  {
> +	struct drm_i915_private *i915 = to_i915(uc_fw->obj->base.dev);
>  	struct i915_vma *vma;
>  	int err;
> @@ -230,7 +235,7 @@ int intel_uc_fw_upload(struct intel_uc_fw *uc_fw,
>  	}
> 	vma = i915_gem_object_ggtt_pin(uc_fw->obj, NULL, 0, 0,
> -				       PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
> +				       PIN_OFFSET_BIAS | i915->guc.wopcm.top);
>  	if (IS_ERR(vma)) {
>  		err = PTR_ERR(vma);
>  		DRM_DEBUG_DRIVER("%s fw ggtt-pin err=%d\n",
> diff --git a/drivers/gpu/drm/i915/intel_uc_fw.h  
> b/drivers/gpu/drm/i915/intel_uc_fw.h
> index d5fd460..298d475 100644
> --- a/drivers/gpu/drm/i915/intel_uc_fw.h
> +++ b/drivers/gpu/drm/i915/intel_uc_fw.h
> @@ -115,6 +115,22 @@ static inline bool intel_uc_fw_is_selected(struct  
> intel_uc_fw *uc_fw)
>  	return uc_fw->path != NULL;
>  }
> +/**
> + * intel_uc_fw_get_size() - Get the size of the firmware.
> + * @uc_fw: intel_uc_fw structure.
> + *
> + * Get the size of the firmware that will be placed in WOPCM.
> + *
> + * Return: Zero on invalid firmware status. actual size on success.

Return: Size of the firmware, or zero on firmware fetch failure.

> + */
> +static inline u32 intel_uc_fw_get_size(struct intel_uc_fw *uc_fw)
> +{
> +	if (uc_fw->fetch_status != INTEL_UC_FIRMWARE_SUCCESS)
> +		return 0;
> +
> +	return uc_fw->header_size + uc_fw->ucode_size;
> +}
> +
>  void intel_uc_fw_fetch(struct drm_i915_private *dev_priv,
>  		       struct intel_uc_fw *uc_fw);
>  int intel_uc_fw_upload(struct intel_uc_fw *uc_fw,
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v9 3/7] drm/i915/guc: Implement dynamic GuC WOPCM offset and size
  2018-02-09 17:24   ` Michal Wajdeczko
@ 2018-02-09 19:32     ` Yaodong Li
  0 siblings, 0 replies; 23+ messages in thread
From: Yaodong Li @ 2018-02-09 19:32 UTC (permalink / raw)
  To: Michal Wajdeczko, intel-gfx; +Cc: Sujaritha Sundaresan

On 02/09/2018 09:24 AM, Michal Wajdeczko wrote:
>> +    struct intel_guc *guc =
>> +        container_of(guc_wopcm, struct intel_guc, wopcm);
>
> If you define this as "wopcm_to_guc" inline helper, then maybe
> all your functions could take "wopcm" as first parameter?
First thought is this is only one time work, so wanted to keep the code
simple. The following patch added an inline for this when there are more
places needs to use wopcm_to_guc.
>
>> +    u32 reserved = guc_wopcm_context_reserved_size(guc);
>> +    u32 offset, size, top;
>> +    int err;
>> -    /* On BXT, the top of WOPCM is reserved for RC6 context */
>> -    if (IS_GEN9_LP(i915))
>> -        size -= BXT_GUC_WOPCM_RC6_RESERVED;
>> +    if (!guc_fw_size)
>> +        return -EINVAL;
>
> As there are many reasons to fail, maybe it would be good idea to
> add at least DRM_DEBUG_DRIVER to each failing condition?
>
Honestly. that's my personal preference too:-) but I am trying to catch
up with the coding style to avoid these redundancies.
I thought there are redundant because:
0) this func is called by uc_init which will print error message when
     this failed.
1) there are two types of errors: invalid parameters. or FW sizes are
      too big to fit in WOPCM. the upper layer error message could 
easily reflect
     these info by check the error code.
and more, I now do feel some of these checks are redundant and will
remove them. :-)
>> +
>> +    if (reserved >= WOPCM_DEFAULT_SIZE)
>> +        return -E2BIG;
>
> Do we really need to check this every time in runtime?
> I think we can enforce this as GEM_BUG_ON here or in
> guc_wopcm_context_reserved_size() function.
>
Yes. this is redundant since we are total having control
of this value.
>
>> +/* 24KB at the end of GuC WOPCM is reserved for RC6 CTX on BXT. */
>> +#define BXT_GUC_WOPCM_RC6_CTX_RESERVED    (24 << 10)
>> +
>> +/*
>> + * GuC WOPCM starts at 144KB (GUC_WOPCM_RESERVED + 128KB reserved 
>> for GuC
>> + * firmware loading) from GuC WOPCM offset on BXT.
>> + */
>> +#define GEN9_GUC_WOPCM_OFFSET        (144 << 10)
>
> Other BXT specific macro (BXT_GUC_WOPCM_RC6_CTX_RESERVED) was
> defined with BXT_ prefix ... can we use common prefix?
>
BXT suggests this is only for Gen9 LP while Gen9 means it's for all Gen9.:-)

Regards,
-Jackie
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v9 1/7] drm/i915/guc: Move GuC WOPCM related code into separate files
  2018-02-09 16:46 ` [PATCH v9 1/7] " Michal Wajdeczko
@ 2018-02-09 19:38   ` Yaodong Li
  2018-02-09 20:59     ` Michel Thierry
  0 siblings, 1 reply; 23+ messages in thread
From: Yaodong Li @ 2018-02-09 19:38 UTC (permalink / raw)
  To: Michal Wajdeczko, intel-gfx

On 02/09/2018 08:46 AM, Michal Wajdeczko wrote:
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/intel_guc_wopcm.c
>> @@ -0,0 +1,48 @@
>> +/*
>> + * SPDX-License-Identifier: MIT
>> + *
>> + * Copyright © 2017-2018 Intel Corporation
>> + *
>
> Do we really want to keep legacy license text?
> Note that in other file (intel_lrc_reg.h) we have only SPDX tag.
Same question here. Updated based on the comments.

Regards,
-Jackie
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v9 6/7] drm/i915/guc: Check the locking status of GuC WOPCM registers
  2018-02-08 23:03 ` [PATCH v9 6/7] drm/i915/guc: Check the locking status of GuC WOPCM registers Jackie Li
  2018-02-08 23:31   ` Chris Wilson
  2018-02-09 10:47   ` Joonas Lahtinen
@ 2018-02-09 19:42   ` Michal Wajdeczko
  2018-02-09 22:12     ` Yaodong Li
  2 siblings, 1 reply; 23+ messages in thread
From: Michal Wajdeczko @ 2018-02-09 19:42 UTC (permalink / raw)
  To: intel-gfx, Jackie Li

On Fri, 09 Feb 2018 00:03:54 +0100, Jackie Li <yaodong.li@intel.com> wrote:

Few more comments in addition to Joonas/Chris

> GuC WOPCM registers are write-once registers. Current driver code  
> accesses
> these registers without checking the accessibility to these registers  
> which
> will lead to unpredictable driver behaviors if these registers were touch
> by other components (such as faulty BIOS code).
>
> This patch moves the GuC WOPCM registers updating code into
> intel_guc_wopcm.c and adds check before and after the update to GuC WOPCM
> registers so that we can make sure the driver is in a known state before
> and after writing to these write-once registers.
>
> v6:
>  - Made sure module reloading won't bug the kernel while doing
>    locking status checking
>
> v7:
>  - Fixed patch format issues
>
> v8:
>  - Fixed coding style issue on register lock bit macro definition (Sagar)
>
> v9:
>  - Avoided to use redundant !! to cast uint to bool (Chris)
>  - Return error code instead of GEM_BUG_ON for locked with invalid  
> register
>    values case (Sagar)
>  - Updated guc_wopcm_hw_init to use guc_wopcm as first parameter (Michal)
>  - Added code to set and validate the HuC_LOADING_AGENT_GUC bit in GuC
>    WOPCM offset register based on the presence of HuC firmware (Michal)
>  - Use bit fields instead of macros for GuC WOPCM flags (Michal)
>
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Signed-off-by: Jackie Li <yaodong.li@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_guc_reg.h   |   2 +
>  drivers/gpu/drm/i915/intel_guc_wopcm.c | 117  
> ++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/intel_guc_wopcm.h |  12 +++-
>  drivers/gpu/drm/i915/intel_uc.c        |   9 ++-
>  4 files changed, 130 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_guc_reg.h  
> b/drivers/gpu/drm/i915/intel_guc_reg.h
> index de4f78b..170d9cd 100644
> --- a/drivers/gpu/drm/i915/intel_guc_reg.h
> +++ b/drivers/gpu/drm/i915/intel_guc_reg.h
> @@ -66,6 +66,8 @@
>  #define   UOS_MOVE			  (1<<4)
>  #define   START_DMA			  (1<<0)
>  #define DMA_GUC_WOPCM_OFFSET		_MMIO(0xc340)
> +#define   GUC_WOPCM_OFFSET_SHIFT	14
> +#define   GUC_WOPCM_OFFSET_MASK		  (0x3ffff << GUC_WOPCM_OFFSET_SHIFT)
>  #define   HUC_LOADING_AGENT_VCR		  (0<<1)
>  #define   HUC_LOADING_AGENT_GUC		  (1<<1)
>  #define GUC_MAX_IDLE_COUNT		_MMIO(0xC3E4)
> diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.c  
> b/drivers/gpu/drm/i915/intel_guc_wopcm.c
> index 2e8e9ec..0af435a 100644
> --- a/drivers/gpu/drm/i915/intel_guc_wopcm.c
> +++ b/drivers/gpu/drm/i915/intel_guc_wopcm.c
> @@ -90,6 +90,69 @@ static inline int guc_wopcm_size_check(struct  
> intel_guc *guc, u32 huc_fw_size)
>  	return 0;
>  }
> +static inline bool __reg_locked(struct drm_i915_private *dev_priv,
> +				i915_reg_t reg)
> +{
> +	/* Set of bit-0 means this write-once register is locked. */
> +	return I915_READ(reg) & BIT(0);
> +}

Hmm, I'm still not happy as not all registers supports write-once bit.
What about something more generic/robust

static inline bool
__reg_test(struct drm_i915_private *dev_priv, i915_reg_t reg, u32 mask,  
u32 value)
{
	return (I915_READ(reg) & mask) == value;
}

static inline bool
__reg_is_set(struct drm_i915_private *dev_priv, i915_reg_t reg, u32 value)
{
	return __reg_test(dev_priv, reg, value, value);
}
...
#define WOPCM_OFFSET_VALID  (1<<0)
...
#define WOPCM_LOCKED        (1<<0)
...
locked = __reg_is_set(i915, GUC_WOPCM_SIZE, WOPCM_LOCKED);
locked = __reg_is_set(i915, DMA_GUC_WOPCM_OFFSET, WOPCM_OFFSET_VALID);

> +
> +static inline bool guc_wopcm_locked(struct intel_guc *guc)
> +{
> +	struct drm_i915_private *i915 = guc_to_i915(guc);
> +	bool size_reg_locked = __reg_locked(i915, GUC_WOPCM_SIZE);
> +	bool offset_reg_locked = __reg_locked(i915, DMA_GUC_WOPCM_OFFSET);
> +
> +	return size_reg_locked && offset_reg_locked;
> +}
> +
> +static inline void guc_wopcm_hw_update(struct intel_guc *guc)
> +{
> +	struct drm_i915_private *dev_priv = guc_to_i915(guc);
> +	u32 offset_reg_val;
> +
> +	/* GuC WOPCM registers should be unlocked at this point. */
> +	GEM_BUG_ON(__reg_locked(dev_priv, GUC_WOPCM_SIZE));
> +	GEM_BUG_ON(__reg_locked(dev_priv, DMA_GUC_WOPCM_OFFSET));

I'm not sure that GEM_BUG_ON can be used on bits that we don't
fully control

> +
> +	offset_reg_val = guc->wopcm.offset;
> +	if (guc->wopcm.need_load_huc_fw)
> +		offset_reg_val |= HUC_LOADING_AGENT_GUC;
> +
> +	I915_WRITE(GUC_WOPCM_SIZE, guc->wopcm.size);
> +	I915_WRITE(DMA_GUC_WOPCM_OFFSET, offset_reg_val);
> +
> +	GEM_BUG_ON(!__reg_locked(dev_priv, GUC_WOPCM_SIZE));
> +	GEM_BUG_ON(!__reg_locked(dev_priv, DMA_GUC_WOPCM_OFFSET));
> +}
> +
> +static inline bool guc_wopcm_regs_valid(struct intel_guc *guc)

can't we always have intel_guc_wopcm as first param ?

> +{
> +	struct drm_i915_private *dev_priv = guc_to_i915(guc);
> +	u32 size, offset;
> +	bool guc_loads_huc;
> +	u32 reg_val;
> +
> +	reg_val = I915_READ(GUC_WOPCM_SIZE);
> +	/* GuC WOPCM size should be always multiple of 4K pages. */
> +	size = reg_val & PAGE_MASK;
> +
> +	reg_val = I915_READ(DMA_GUC_WOPCM_OFFSET);
> +	guc_loads_huc = reg_val & HUC_LOADING_AGENT_GUC;
> +	offset = reg_val & GUC_WOPCM_OFFSET_MASK;
> +
> +	if (guc->wopcm.need_load_huc_fw && !guc_loads_huc)
> +		return false;
> +
> +	return (size == guc->wopcm.size) && (offset == guc->wopcm.offset);
> +}
> +
> +static inline
> +struct intel_guc *guc_wopcm_to_guc(struct intel_guc_wopcm *guc_wopcm)
> +{
> +	return container_of(guc_wopcm, struct intel_guc, wopcm);
> +}
> +
>  /**
>   * intel_guc_wopcm_init() - Initialize the GuC WOPCM.
>   * @guc_wopcm: intel_guc_wopcm..
> @@ -108,12 +171,13 @@ static inline int guc_wopcm_size_check(struct  
> intel_guc *guc, u32 huc_fw_size)
>  int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32  
> guc_fw_size,
>  			 u32 huc_fw_size)
>  {
> -	struct intel_guc *guc =
> -		container_of(guc_wopcm, struct intel_guc, wopcm);
> +	struct intel_guc *guc = guc_wopcm_to_guc(guc_wopcm);
>  	u32 reserved = guc_wopcm_context_reserved_size(guc);
>  	u32 offset, size, top;
>  	int err;
> +	GEM_BUG_ON(guc->wopcm.valid);
> +
>  	if (!guc_fw_size)
>  		return -EINVAL;
> @@ -147,6 +211,8 @@ int intel_guc_wopcm_init(struct intel_guc_wopcm  
> *guc_wopcm, u32 guc_fw_size,
>  	guc->wopcm.offset = offset;
>  	guc->wopcm.size = size;
>  	guc->wopcm.top = top;
> +	/* Use GuC to load HuC firmware if HuC firmware is present. */
> +	guc->wopcm.need_load_huc_fw = huc_fw_size ? 1 : 0;
> 	/* Check platform specific restrictions */
>  	err = guc_wopcm_size_check(guc, huc_fw_size);
> @@ -160,3 +226,50 @@ int intel_guc_wopcm_init(struct intel_guc_wopcm  
> *guc_wopcm, u32 guc_fw_size,
> 	return 0;
>  }
> +
> +/**
> + * intel_guc_wopcm_init_hw() - Setup GuC WOPCM registers.
> + * @guc_wopcm: intel_guc_wopcm.
> + *
> + * Setup the GuC WOPCM size and offset registers with the stored  
> values. It will
> + * also check the registers locking status to determine whether these  
> registers
> + * are unlocked and can be updated.
> + *
> + * Return: 0 on success. -EINVAL if registers were locked with  
> incorrect values.
> + */
> +int intel_guc_wopcm_init_hw(struct intel_guc_wopcm *guc_wopcm)
> +{
> +	struct intel_guc *guc = guc_wopcm_to_guc(guc_wopcm);
> +	bool locked = guc_wopcm_locked(guc);
> +
> +	GEM_BUG_ON(!guc->wopcm.valid);
> +
> +	/*
> +	 * Bug if driver hasn't updated the HW Registers and GuC WOPCM has been
> +	 * locked. Return directly if WOPCM was locked and we have updated
> +	 * the registers.
> +	 */
> +	if (locked) {
> +		if (guc->wopcm.hw_updated)
> +			return 0;
> +
> +		/*
> +		 * Mark as updated if registers contained correct values.
> +		 * This will happen while reloading the driver module without
> +		 * rebooting the system.
> +		 */
> +		if (guc_wopcm_regs_valid(guc))
> +			goto out;
> +
> +		/* Register locked without valid values. Abort HW init. */
> +		return -EINVAL;

I'm not sure that EINVAL is correct error code here ... maybe EACCES ?

> +	}
> +
> +	/* Always update registers when GuC WOPCM is not locked. */
> +	guc_wopcm_hw_update(guc);
> +
> +out:
> +	guc->wopcm.hw_updated = 1;
> +
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.h  
> b/drivers/gpu/drm/i915/intel_guc_wopcm.h
> index 1c5ffeb..471fb8e 100644
> --- a/drivers/gpu/drm/i915/intel_guc_wopcm.h
> +++ b/drivers/gpu/drm/i915/intel_guc_wopcm.h
> @@ -86,7 +86,9 @@ struct intel_guc;
>   * @offset: GuC WOPCM offset from the WOPCM base.
>   * @size: size of GuC WOPCM for GuC firmware.
>   * @top: start of the non-GuC WOPCM memory.
> - * @valid: whether this structure contains valid (1-valid, 0-invalid)  
> info.
> + * @valid: whether the values in this struct are valid.
> + * @hw_updated: GuC WOPCM registers has been updated with values in  
> this struct.
> + * @need_load_huc_fw: whether need to configure GuC to load HuC  
> firmware.
>   *
>   * We simply use this structure to track the GuC use of WOPCM. The  
> layout of
>   * WOPCM would be defined by writing to GuC WOPCM offset and size  
> registers.
> @@ -95,7 +97,11 @@ struct intel_guc_wopcm {
>  	u32 offset;
>  	u32 size;
>  	u32 top;
> -	u32 valid;
> +
> +	/* GuC WOPCM flags below. */
> +	u32 valid:1;
> +	u32 hw_updated:1;
> +	u32 need_load_huc_fw:1;
>  };
> /**
> @@ -114,5 +120,5 @@ static inline void intel_guc_wopcm_init_early(struct  
> intel_guc_wopcm *guc_wopcm)
> int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32 guc_size,
>  			 u32 huc_size);
> -
> +int intel_guc_wopcm_init_hw(struct intel_guc_wopcm *guc_wopcm);
>  #endif
> diff --git a/drivers/gpu/drm/i915/intel_uc.c  
> b/drivers/gpu/drm/i915/intel_uc.c
> index c842f36..8938096 100644
> --- a/drivers/gpu/drm/i915/intel_uc.c
> +++ b/drivers/gpu/drm/i915/intel_uc.c
> @@ -343,14 +343,13 @@ int intel_uc_init_hw(struct drm_i915_private  
> *dev_priv)
> 	GEM_BUG_ON(!HAS_GUC(dev_priv));
> +	ret = intel_guc_wopcm_init_hw(&guc->wopcm);

Again, extra error path without single log message...

> +	if (ret)
> +		goto err_out;
> +
>  	guc_disable_communication(guc);
>  	gen9_reset_guc_interrupts(dev_priv);
> -	/* init WOPCM */
> -	I915_WRITE(GUC_WOPCM_SIZE, guc->wopcm.size);
> -	I915_WRITE(DMA_GUC_WOPCM_OFFSET,
> -		   guc->wopcm.offset | HUC_LOADING_AGENT_GUC);
> -
>  	/* WaEnableuKernelHeaderValidFix:skl */
>  	/* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */
>  	if (IS_GEN9(dev_priv))

Regards,
Michal
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v9 1/7] drm/i915/guc: Move GuC WOPCM related code into separate files
  2018-02-09 19:38   ` Yaodong Li
@ 2018-02-09 20:59     ` Michel Thierry
  0 siblings, 0 replies; 23+ messages in thread
From: Michel Thierry @ 2018-02-09 20:59 UTC (permalink / raw)
  To: Yaodong Li, Wajdeczko, Michal, intel-gfx

On 2/9/2018 11:38 AM, Yaodong Li wrote:
> On 02/09/2018 08:46 AM, Michal Wajdeczko wrote:
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/i915/intel_guc_wopcm.c
>>> @@ -0,0 +1,48 @@
>>> +/*
>>> + * SPDX-License-Identifier: MIT
>>> + *
>>> + * Copyright © 2017-2018 Intel Corporation
>>> + *
>>
>> Do we really want to keep legacy license text?
>> Note that in other file (intel_lrc_reg.h) we have only SPDX tag.
> Same question here. Updated based on the comments.
> 

Hi,

After much deliberation[1], the consensus was to use just this:

/*
  * SPDX-License-Identifier: MIT
  *
  * Copyright © 201x-201x Intel Corporation
  */


[1]: 
https://lists.freedesktop.org/archives/intel-gfx/2018-January/153469.html

> Regards,
> -Jackie
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v9 6/7] drm/i915/guc: Check the locking status of GuC WOPCM registers
  2018-02-09 19:42   ` Michal Wajdeczko
@ 2018-02-09 22:12     ` Yaodong Li
  0 siblings, 0 replies; 23+ messages in thread
From: Yaodong Li @ 2018-02-09 22:12 UTC (permalink / raw)
  To: Michal Wajdeczko, intel-gfx

On 02/09/2018 11:42 AM, Michal Wajdeczko wrote:
>
>> +static inline bool __reg_locked(struct drm_i915_private *dev_priv,
>> +                i915_reg_t reg)
>> +{
>> +    /* Set of bit-0 means this write-once register is locked. */
>> +    return I915_READ(reg) & BIT(0);
>> +}
>
> Hmm, I'm still not happy as not all registers supports write-once bit.
> What about something more generic/robust
>
> static inline bool
> __reg_test(struct drm_i915_private *dev_priv, i915_reg_t reg, u32 
> mask, u32 value)
> {
>     return (I915_READ(reg) & mask) == value;
> }
>
> static inline bool
> __reg_is_set(struct drm_i915_private *dev_priv, i915_reg_t reg, u32 
> value)
> {
>     return __reg_test(dev_priv, reg, value, value);
> }
> ...
> #define WOPCM_OFFSET_VALID  (1<<0)
> ...
> #define WOPCM_LOCKED        (1<<0)
> ...
> locked = __reg_is_set(i915, GUC_WOPCM_SIZE, WOPCM_LOCKED);
> locked = __reg_is_set(i915, DMA_GUC_WOPCM_OFFSET, WOPCM_OFFSET_VALID);
>
Feels like a bit over engineering in this way. two reasons:
0) we use this only in this file and with full control over it.
1) All GuC WOPCM related registers are all write-once registers (and 
using the same bit
     for locking status)
>> +    /* GuC WOPCM registers should be unlocked at this point. */
>> +    GEM_BUG_ON(__reg_locked(dev_priv, GUC_WOPCM_SIZE));
>> +    GEM_BUG_ON(__reg_locked(dev_priv, DMA_GUC_WOPCM_OFFSET));
>
> I'm not sure that GEM_BUG_ON can be used on bits that we don't
> fully control
>
Agreed. at least it's not a GEM Bug.
>>
>> +}
>> +
>> +static inline bool guc_wopcm_regs_valid(struct intel_guc *guc)
>
> can't we always have intel_guc_wopcm as first param ?
I don't think it's necessary for it's a static func plus we would need 
another
wopcm_to_guc() with a guc_wopcm first param. we can save some time
with no confusion to external callers in this way. so why not?
>
>> +        /* Register locked without valid values. Abort HW init. */
>> +        return -EINVAL;
>
> I'm not sure that EINVAL is correct error code here ... maybe EACCES ?
>
hmm, EACCES (-13) always feels like no permission to do this. It's more 
like a IO error, so
maybe -EIO and go ahead to trigger GEM warning for this such an error? 
since I found following
code in uc_init_hw()
     if (GEM_WARN_ON(ret == -EIO))
         ret = -EINVAL;

Regards,
-Jackie
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v9 6/7] drm/i915/guc: Check the locking status of GuC WOPCM registers
  2018-02-09 10:47   ` Joonas Lahtinen
@ 2018-02-11  0:36     ` Yaodong Li
  0 siblings, 0 replies; 23+ messages in thread
From: Yaodong Li @ 2018-02-11  0:36 UTC (permalink / raw)
  To: Joonas Lahtinen, intel-gfx



On 02/09/2018 02:47 AM, Joonas Lahtinen wrote:
>> +++ b/drivers/gpu/drm/i915/intel_guc_wopcm.c
>> +static inline bool guc_wopcm_locked(struct intel_guc *guc)
>> +{
>> +       struct drm_i915_private *i915 = guc_to_i915(guc);
>> +       bool size_reg_locked = __reg_locked(i915, GUC_WOPCM_SIZE);
>> +       bool offset_reg_locked = __reg_locked(i915, DMA_GUC_WOPCM_OFFSET);
>> +
>> +       return size_reg_locked && offset_reg_locked;
> Hmm, isn't this supposed to be || instead, if either of the registers is
> locked, we can't really do much?
It is an issue!

The intention was letting following GEM_BUG_ON to fail the
"only one reg" locked case. However, after adding the validation
of the already locked reg values, I think we need update the logic
code a little bit (to use the locked reg if it contained the valid value).

Also, I think it makes sense to introduce some helper
functions as you mentioned below to make things clearer.
so I will rework this part of code to make it clearer and address
this issue at the same time.

Thanks & Regards,
-Jackie
>> +static inline void guc_wopcm_hw_update(struct intel_guc *guc)
>> +{
>> +       struct drm_i915_private *dev_priv = guc_to_i915(guc);
>> +       u32 offset_reg_val;
>> +
>> +       /* GuC WOPCM registers should be unlocked at this point. */
>> +       GEM_BUG_ON(__reg_locked(dev_priv, GUC_WOPCM_SIZE));
>> +       GEM_BUG_ON(__reg_locked(dev_priv, DMA_GUC_WOPCM_OFFSET));
>> +
>> +       offset_reg_val = guc->wopcm.offset;
>> +       if (guc->wopcm.need_load_huc_fw)
> "load_huc_fw" would read better here.
>
>> +               offset_reg_val |= HUC_LOADING_AGENT_GUC;
>> +
>> +       I915_WRITE(GUC_WOPCM_SIZE, guc->wopcm.size);
>> +       I915_WRITE(DMA_GUC_WOPCM_OFFSET, offset_reg_val);
>> +
>> +       GEM_BUG_ON(!__reg_locked(dev_priv, GUC_WOPCM_SIZE));
>> +       GEM_BUG_ON(!__reg_locked(dev_priv, DMA_GUC_WOPCM_OFFSET));
> This could use static inline write_lockable_reg() helper with a return value.
> I think we need to propagate the error all the way up the chain, as it's
> not a driver programmer error if these registers are locked, instead it is
> likely to be a BIOS problem.
>
> In the helper we could also test if the value is locked but happens to
> match what we were intending to write, then we could call it success and
> maybe emit an INFO message.
>
>> +}
>> +
>> +static inline bool guc_wopcm_regs_valid(struct intel_guc *guc)
>> +{
>> +       struct drm_i915_private *dev_priv = guc_to_i915(guc);
>> +       u32 size, offset;
>> +       bool guc_loads_huc;
>> +       u32 reg_val;
>> +
>> +       reg_val = I915_READ(GUC_WOPCM_SIZE);
>> +       /* GuC WOPCM size should be always multiple of 4K pages. */
>> +       size = reg_val & PAGE_MASK;
>> +
>> +       reg_val = I915_READ(DMA_GUC_WOPCM_OFFSET);
>> +       guc_loads_huc = reg_val & HUC_LOADING_AGENT_GUC;
>> +       offset = reg_val & GUC_WOPCM_OFFSET_MASK;
>> +
>> +       if (guc->wopcm.need_load_huc_fw && !guc_loads_huc)
>> +               return false;
>> +
>> +       return (size == guc->wopcm.size) && (offset == guc->wopcm.offset);
>> +}
> This seems to have much of what I wrote above already. I'd still split
> the actual writes in a helper that will report the per-register a
> WARN about "mismatch between locked register value and computed value"
> or so. Dumping both the computed an actual register value.
>
>> @@ -147,6 +211,8 @@ int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32 guc_fw_size,
>>          guc->wopcm.offset = offset;
>>          guc->wopcm.size = size;
>>          guc->wopcm.top = top;
>> +       /* Use GuC to load HuC firmware if HuC firmware is present. */
> Comment is again more on the "what" side, so can be dropped.
>
>> +       guc->wopcm.need_load_huc_fw = huc_fw_size ? 1 : 0;
> 	... = huc_fw_size > 0;
>
> Will literally read as "set guc load_huc_fw if huc_fw_size is
> greater than zero."
>
>> +int intel_guc_wopcm_init_hw(struct intel_guc_wopcm *guc_wopcm)
>> +{
>> +       struct intel_guc *guc = guc_wopcm_to_guc(guc_wopcm);
>> +       bool locked = guc_wopcm_locked(guc);
>> +
>> +       GEM_BUG_ON(!guc->wopcm.valid);
>> +
>> +       /*
>> +        * Bug if driver hasn't updated the HW Registers and GuC WOPCM has been
>> +        * locked. Return directly if WOPCM was locked and we have updated
>> +        * the registers.
>> +        */
>> +       if (locked) {
>> +               if (guc->wopcm.hw_updated)
>> +                       return 0;
>> +
>> +               /*
>> +                * Mark as updated if registers contained correct values.
>> +                * This will happen while reloading the driver module without
>> +                * rebooting the system.
>> +                */
>> +               if (guc_wopcm_regs_valid(guc))
>> +                       goto out;
>> +
>> +               /* Register locked without valid values. Abort HW init. */
>> +               return -EINVAL;
>> +       }
>> +
>> +       /* Always update registers when GuC WOPCM is not locked. */
>> +       guc_wopcm_hw_update(guc);
> This flow will become more clear with the helpers, and we will get a
> splat in the kernel message with less code about which register actually
> was locked and how the value mismatched.
>
> I'm up for discussion, but to my eyes the code flow would become more clear if
> we start with the assumption "we can write the register values to what we have
> calculated", and then make it an error that is propagated back up if we can't.
>
> Regards, Joonas

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2018-02-11  0:37 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-08 23:03 [PATCH v9 1/7] drm/i915/guc: Move GuC WOPCM related code into separate files Jackie Li
2018-02-08 23:03 ` [PATCH v9 2/7] drm/i915/guc: Rename guc_ggtt_offset to intel_guc_ggtt_offset Jackie Li
2018-02-09  8:01   ` Joonas Lahtinen
2018-02-08 23:03 ` [PATCH v9 3/7] drm/i915/guc: Implement dynamic GuC WOPCM offset and size Jackie Li
2018-02-09  9:31   ` Joonas Lahtinen
2018-02-09 17:24   ` Michal Wajdeczko
2018-02-09 19:32     ` Yaodong Li
2018-02-08 23:03 ` [PATCH v9 4/7] drm/i915/guc: Add support to return CNL specific reserved GuC WOPCM size Jackie Li
2018-02-09  9:37   ` Joonas Lahtinen
2018-02-08 23:03 ` [PATCH v9 5/7] drm/i915/guc: Add HuC firmware size related restriction for Gen9 and CNL A0 Jackie Li
2018-02-09  9:57   ` Joonas Lahtinen
2018-02-08 23:03 ` [PATCH v9 6/7] drm/i915/guc: Check the locking status of GuC WOPCM registers Jackie Li
2018-02-08 23:31   ` Chris Wilson
2018-02-09  5:05     ` Yaodong Li
2018-02-09 10:47   ` Joonas Lahtinen
2018-02-11  0:36     ` Yaodong Li
2018-02-09 19:42   ` Michal Wajdeczko
2018-02-09 22:12     ` Yaodong Li
2018-02-08 23:03 ` [PATCH v9 7/7] HAX Enable GuC Submission for CI Jackie Li
2018-02-08 23:29 ` ✗ Fi.CI.BAT: failure for series starting with [v9,1/7] drm/i915/guc: Move GuC WOPCM related code into separate files Patchwork
2018-02-09 16:46 ` [PATCH v9 1/7] " Michal Wajdeczko
2018-02-09 19:38   ` Yaodong Li
2018-02-09 20:59     ` Michel Thierry

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.