All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] HuC Loading Patches
@ 2016-06-21 18:11 Peter Antoine
  2016-06-21 18:11 ` [PATCH 1/6] drm/i915/guc: Make the GuC fw loading helper functions general Peter Antoine
                   ` (6 more replies)
  0 siblings, 7 replies; 40+ messages in thread
From: Peter Antoine @ 2016-06-21 18:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: sean.v.kelley, lawrence.t.li, rodrigo.vivi

This patch series enables the HuC loading. These patches are a port of the
patches that were created by Yu Dai (Alex) and have been ported to work with
the new GuC patches.

The series include a patch to enable the HuC on BXT. This is a separate patch
as the state of the BXT HuC firmware is still in flux, so the patch can be
dropped without delaying the series.

Alex Dai (3):
  drm/i915/huc: Unified css_header struct for GuC and HuC
  drm/i915/huc: Add HuC fw loading support
  drm/i915/huc: Add debugfs for HuC loading status check

Peter Antoine (3):
  drm/i915/guc: Make the GuC fw loading helper functions general
  drm/i915/huc: Support HuC authentication
  drm/i915/huc: Add BXT HuC Loading Support

 drivers/gpu/drm/i915/Makefile              |   1 +
 drivers/gpu/drm/i915/i915_debugfs.c        |  44 ++++-
 drivers/gpu/drm/i915/i915_dma.c            |   3 +
 drivers/gpu/drm/i915/i915_drv.h            |   3 +
 drivers/gpu/drm/i915/i915_guc_reg.h        |   3 +
 drivers/gpu/drm/i915/i915_guc_submission.c |  69 ++++++-
 drivers/gpu/drm/i915/intel_guc.h           |  46 +++--
 drivers/gpu/drm/i915/intel_guc_fwif.h      |  17 +-
 drivers/gpu/drm/i915/intel_guc_loader.c    | 281 +++++++++++++++++------------
 drivers/gpu/drm/i915/intel_huc.h           |  44 +++++
 drivers/gpu/drm/i915/intel_huc_loader.c    | 274 ++++++++++++++++++++++++++++
 11 files changed, 634 insertions(+), 151 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_huc.h
 create mode 100644 drivers/gpu/drm/i915/intel_huc_loader.c

-- 
1.9.1

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

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

* [PATCH 1/6] drm/i915/guc: Make the GuC fw loading helper functions general
  2016-06-21 18:11 [PATCH 0/6] HuC Loading Patches Peter Antoine
@ 2016-06-21 18:11 ` Peter Antoine
  2016-06-28 14:24   ` Dave Gordon
  2016-06-21 18:11 ` [PATCH 2/6] drm/i915/huc: Unified css_header struct for GuC and HuC Peter Antoine
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 40+ messages in thread
From: Peter Antoine @ 2016-06-21 18:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: sean.v.kelley, lawrence.t.li, rodrigo.vivi

Rename some of the GuC fw loading code to make them more general. We
will utilize them for HuC loading as well.
    s/intel_guc_fw/intel_uc_fw/g
    s/GUC_FIRMWARE/UC_FIRMWARE/g

Struct intel_guc_fw is renamed to intel_uc_fw. Prefix of tts members,
such as 'guc' or 'guc_fw' either is renamed to 'uc' or removed for
same purpose.

Signed-off-by: Alex Dai <yu.dai@intel.com>
Signed-off-by: Peter Antoine <peter.antoine@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c        |  12 +-
 drivers/gpu/drm/i915/i915_guc_submission.c |   4 +-
 drivers/gpu/drm/i915/intel_guc.h           |  39 ++---
 drivers/gpu/drm/i915/intel_guc_loader.c    | 221 ++++++++++++++++-------------
 4 files changed, 151 insertions(+), 125 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 7d63af0..69964c2 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2483,7 +2483,7 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data)
 {
 	struct drm_info_node *node = m->private;
 	struct drm_i915_private *dev_priv = node->minor->dev->dev_private;
-	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
+	struct intel_uc_fw *guc_fw = &dev_priv->guc.guc_fw;
 	u32 tmp, i;
 
 	if (!HAS_GUC_UCODE(dev_priv))
@@ -2491,15 +2491,15 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data)
 
 	seq_printf(m, "GuC firmware status:\n");
 	seq_printf(m, "\tpath: %s\n",
-		guc_fw->guc_fw_path);
+		guc_fw->uc_fw_path);
 	seq_printf(m, "\tfetch: %s\n",
-		intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status));
+		intel_uc_fw_status_repr(guc_fw->fetch_status));
 	seq_printf(m, "\tload: %s\n",
-		intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
+		intel_uc_fw_status_repr(guc_fw->load_status));
 	seq_printf(m, "\tversion wanted: %d.%d\n",
-		guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted);
+		guc_fw->major_ver_wanted, guc_fw->minor_ver_wanted);
 	seq_printf(m, "\tversion found: %d.%d\n",
-		guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found);
+		guc_fw->major_ver_found, guc_fw->minor_ver_found);
 	seq_printf(m, "\theader: offset is %d; size = %d\n",
 		guc_fw->header_offset, guc_fw->header_size);
 	seq_printf(m, "\tuCode: offset is %d; size = %d\n",
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index 01c7cdf..bfb8400 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -1039,7 +1039,7 @@ int intel_guc_suspend(struct drm_device *dev)
 	struct i915_gem_context *ctx;
 	u32 data[3];
 
-	if (guc->guc_fw.guc_fw_load_status != GUC_FIRMWARE_SUCCESS)
+	if (guc->guc_fw.load_status != UC_FIRMWARE_SUCCESS)
 		return 0;
 
 	ctx = dev_priv->kernel_context;
@@ -1065,7 +1065,7 @@ int intel_guc_resume(struct drm_device *dev)
 	struct i915_gem_context *ctx;
 	u32 data[3];
 
-	if (guc->guc_fw.guc_fw_load_status != GUC_FIRMWARE_SUCCESS)
+	if (guc->guc_fw.load_status != UC_FIRMWARE_SUCCESS)
 		return 0;
 
 	ctx = dev_priv->kernel_context;
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 3e3e743..836420b 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -90,29 +90,29 @@ struct i915_guc_client {
 	uint64_t submissions[I915_NUM_ENGINES];
 };
 
-enum intel_guc_fw_status {
-	GUC_FIRMWARE_FAIL = -1,
-	GUC_FIRMWARE_NONE = 0,
-	GUC_FIRMWARE_PENDING,
-	GUC_FIRMWARE_SUCCESS
+enum intel_uc_fw_status {
+	UC_FIRMWARE_FAIL = -1,
+	UC_FIRMWARE_NONE = 0,
+	UC_FIRMWARE_PENDING,
+	UC_FIRMWARE_SUCCESS
 };
 
 /*
  * This structure encapsulates all the data needed during the process
  * of fetching, caching, and loading the firmware image into the GuC.
  */
-struct intel_guc_fw {
-	struct drm_device *		guc_dev;
-	const char *			guc_fw_path;
-	size_t				guc_fw_size;
-	struct drm_i915_gem_object *	guc_fw_obj;
-	enum intel_guc_fw_status	guc_fw_fetch_status;
-	enum intel_guc_fw_status	guc_fw_load_status;
-
-	uint16_t			guc_fw_major_wanted;
-	uint16_t			guc_fw_minor_wanted;
-	uint16_t			guc_fw_major_found;
-	uint16_t			guc_fw_minor_found;
+struct intel_uc_fw {
+	struct drm_device *uc_dev;
+	const char *uc_fw_path;
+	size_t uc_fw_size;
+	struct drm_i915_gem_object *uc_fw_obj;
+	enum intel_uc_fw_status fetch_status;
+	enum intel_uc_fw_status	load_status;
+
+	uint16_t major_ver_wanted;
+	uint16_t minor_ver_wanted;
+	uint16_t major_ver_found;
+	uint16_t minor_ver_found;
 
 	uint32_t header_size;
 	uint32_t header_offset;
@@ -123,7 +123,7 @@ struct intel_guc_fw {
 };
 
 struct intel_guc {
-	struct intel_guc_fw guc_fw;
+	struct intel_uc_fw guc_fw;
 	uint32_t log_flags;
 	struct drm_i915_gem_object *log_obj;
 
@@ -152,9 +152,10 @@ struct intel_guc {
 extern void intel_guc_init(struct drm_device *dev);
 extern int intel_guc_setup(struct drm_device *dev);
 extern void intel_guc_fini(struct drm_device *dev);
-extern const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status);
+extern const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status);
 extern int intel_guc_suspend(struct drm_device *dev);
 extern int intel_guc_resume(struct drm_device *dev);
+void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw);
 
 /* i915_guc_submission.c */
 int i915_guc_submission_init(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
index 8fe96a2..ff054f5 100644
--- a/drivers/gpu/drm/i915/intel_guc_loader.c
+++ b/drivers/gpu/drm/i915/intel_guc_loader.c
@@ -66,16 +66,16 @@ MODULE_FIRMWARE(I915_SKL_GUC_UCODE);
 MODULE_FIRMWARE(I915_BXT_GUC_UCODE);
 
 /* User-friendly representation of an enum */
-const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status)
+const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status)
 {
 	switch (status) {
-	case GUC_FIRMWARE_FAIL:
+	case UC_FIRMWARE_FAIL:
 		return "FAIL";
-	case GUC_FIRMWARE_NONE:
+	case UC_FIRMWARE_NONE:
 		return "NONE";
-	case GUC_FIRMWARE_PENDING:
+	case UC_FIRMWARE_PENDING:
 		return "PENDING";
-	case GUC_FIRMWARE_SUCCESS:
+	case UC_FIRMWARE_SUCCESS:
 		return "SUCCESS";
 	default:
 		return "UNKNOWN!";
@@ -238,8 +238,8 @@ static inline bool guc_ucode_response(struct drm_i915_private *dev_priv,
  */
 static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv)
 {
-	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
-	struct drm_i915_gem_object *fw_obj = guc_fw->guc_fw_obj;
+	struct intel_uc_fw *guc_fw = &dev_priv->guc.guc_fw;
+	struct drm_i915_gem_object *fw_obj = guc_fw->uc_fw_obj;
 	unsigned long offset;
 	struct sg_table *sg = fw_obj->pages;
 	u32 status, rsa[UOS_RSA_SCRATCH_MAX_COUNT];
@@ -311,17 +311,17 @@ static u32 guc_wopcm_size(struct drm_i915_private *dev_priv)
  */
 static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
 {
-	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
+	struct intel_uc_fw *guc_fw = &dev_priv->guc.guc_fw;
 	struct drm_device *dev = dev_priv->dev;
 	int ret;
 
-	ret = i915_gem_object_set_to_gtt_domain(guc_fw->guc_fw_obj, false);
+	ret = i915_gem_object_set_to_gtt_domain(guc_fw->uc_fw_obj, false);
 	if (ret) {
 		DRM_DEBUG_DRIVER("set-domain failed %d\n", ret);
 		return ret;
 	}
 
-	ret = i915_gem_obj_ggtt_pin(guc_fw->guc_fw_obj, 0, 0);
+	ret = i915_gem_obj_ggtt_pin(guc_fw->uc_fw_obj, 0, 0);
 	if (ret) {
 		DRM_DEBUG_DRIVER("pin failed %d\n", ret);
 		return ret;
@@ -373,7 +373,7 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
 	 * We keep the object pages for reuse during resume. But we can unpin it
 	 * now that DMA has completed, so it doesn't continue to take up space.
 	 */
-	i915_gem_object_ggtt_unpin(guc_fw->guc_fw_obj);
+	i915_gem_object_ggtt_unpin(guc_fw->uc_fw_obj);
 
 	return ret;
 }
@@ -412,46 +412,58 @@ static int i915_reset_guc(struct drm_i915_private *dev_priv)
 int intel_guc_setup(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
-	const char *fw_path = guc_fw->guc_fw_path;
-	int retries, ret, err;
-
-	DRM_DEBUG_DRIVER("GuC fw status: path %s, fetch %s, load %s\n",
-		fw_path,
-		intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status),
-		intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
-
-	/* Loading forbidden, or no firmware to load? */
-	if (!i915.enable_guc_loading) {
-		err = 0;
-		goto fail;
-	} else if (fw_path == NULL) {
-		/* Device is known to have no uCode (e.g. no GuC) */
-		err = -ENXIO;
-		goto fail;
-	} else if (*fw_path == '\0') {
-		/* Device has a GuC but we don't know what f/w to load? */
-		DRM_INFO("No GuC firmware known for this platform\n");
-		err = -ENODEV;
-		goto fail;
-	}
+	struct intel_uc_fw *guc_fw = &dev_priv->guc.guc_fw;
+	int retries, ret, err = 0;
+
+	if (!i915.enable_guc_loading)
+		return 0;
+
+	DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n",
+		intel_uc_fw_status_repr(guc_fw->fetch_status),
+		intel_uc_fw_status_repr(guc_fw->load_status));
+
+	direct_interrupts_to_host(dev_priv);
+
+	if (guc_fw->fetch_status == UC_FIRMWARE_NONE)
+		return 0;
+
+	if (guc_fw->fetch_status == UC_FIRMWARE_SUCCESS &&
+	    guc_fw->load_status == UC_FIRMWARE_FAIL)
+		return -ENOEXEC;
 
-	/* Fetch failed, or already fetched but failed to load? */
-	if (guc_fw->guc_fw_fetch_status != GUC_FIRMWARE_SUCCESS) {
+	guc_fw->load_status = UC_FIRMWARE_PENDING;
+
+	DRM_DEBUG_DRIVER("GuC fw fetch status %s\n",
+		intel_uc_fw_status_repr(guc_fw->fetch_status));
+
+	switch (guc_fw->fetch_status) {
+	case UC_FIRMWARE_FAIL:
+		/* something went wrong :( */
 		err = -EIO;
 		goto fail;
-	} else if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_FAIL) {
-		err = -ENOEXEC;
+
+	case UC_FIRMWARE_NONE:
+	case UC_FIRMWARE_PENDING:
+	default:
+		/* "can't happen" */
+		WARN_ONCE(1, "GuC fw %s invalid guc_fw_fetch_status %s [%d]\n",
+			guc_fw->uc_fw_path,
+			intel_uc_fw_status_repr(guc_fw->fetch_status),
+			guc_fw->fetch_status);
+		err = -ENXIO;
 		goto fail;
+
+	case UC_FIRMWARE_SUCCESS:
+		break;
 	}
 
 	direct_interrupts_to_host(dev_priv);
 
-	guc_fw->guc_fw_load_status = GUC_FIRMWARE_PENDING;
+	guc_fw->load_status = UC_FIRMWARE_PENDING;
 
 	DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n",
-		intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status),
-		intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
+		intel_uc_fw_status_repr(guc_fw->fetch_status),
+		intel_uc_fw_status_repr(guc_fw->load_status));
 
 	err = i915_guc_submission_init(dev_priv);
 	if (err)
@@ -485,11 +497,11 @@ int intel_guc_setup(struct drm_device *dev)
 			 "retry %d more time(s)\n", err, retries);
 	}
 
-	guc_fw->guc_fw_load_status = GUC_FIRMWARE_SUCCESS;
+	guc_fw->load_status = UC_FIRMWARE_SUCCESS;
 
 	DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n",
-		intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status),
-		intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
+		intel_uc_fw_status_repr(guc_fw->fetch_status),
+		intel_uc_fw_status_repr(guc_fw->load_status));
 
 	if (i915.enable_guc_submission) {
 		err = i915_guc_submission_enable(dev_priv);
@@ -501,8 +513,8 @@ int intel_guc_setup(struct drm_device *dev)
 	return 0;
 
 fail:
-	if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_PENDING)
-		guc_fw->guc_fw_load_status = GUC_FIRMWARE_FAIL;
+	if (guc_fw->load_status == UC_FIRMWARE_PENDING)
+		guc_fw->load_status = UC_FIRMWARE_FAIL;
 
 	direct_interrupts_to_host(dev_priv);
 	i915_guc_submission_disable(dev_priv);
@@ -535,7 +547,7 @@ fail:
 		DRM_ERROR("GuC firmware load failed: %d\n", err);
 
 	if (i915.enable_guc_submission) {
-		if (fw_path == NULL)
+		if (guc_fw->uc_fw_path == NULL)
 			DRM_INFO("GuC submission without firmware not supported\n");
 		if (ret == 0)
 			DRM_INFO("Falling back from GuC submission to execlist mode\n");
@@ -547,7 +559,18 @@ fail:
 	return ret;
 }
 
-static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw)
+/**
+ * intel_uc_fw_fetch() - fetch fw blob and save it to internal obj
+ * @dev:	drm device
+ * @uc_fw:	the intel_uc_fw to be setup
+ *
+ * The caller should have setup fw path and fw version required. This function
+ * first fetch the fw blob from file system. If succeed, it will do some basic
+ * check based on css header information. At last, a GEM obj is created and
+ * filled with the fw data. This obj will be loaded to HW at later stage of
+ * driver init process.
+ */
+void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw)
 {
 	struct drm_i915_gem_object *obj;
 	const struct firmware *fw;
@@ -555,17 +578,17 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw)
 	size_t size;
 	int err;
 
-	DRM_DEBUG_DRIVER("before requesting firmware: GuC fw fetch status %s\n",
-		intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status));
+	DRM_DEBUG_DRIVER("before requesting firmware: uC fw fetch status %s\n",
+		intel_uc_fw_status_repr(uc_fw->fetch_status));
 
-	err = request_firmware(&fw, guc_fw->guc_fw_path, &dev->pdev->dev);
+	err = request_firmware(&fw, uc_fw->uc_fw_path, &dev->pdev->dev);
 	if (err)
 		goto fail;
 	if (!fw)
 		goto fail;
 
-	DRM_DEBUG_DRIVER("fetch GuC fw from %s succeeded, fw %p\n",
-		guc_fw->guc_fw_path, fw);
+	DRM_DEBUG_DRIVER("fetch uC fw from %s succeeded, fw %p\n",
+		uc_fw->uc_fw_path, fw);
 
 	/* Check the size of the blob before examining buffer contents */
 	if (fw->size < sizeof(struct guc_css_header)) {
@@ -576,62 +599,64 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw)
 	css = (struct guc_css_header *)fw->data;
 
 	/* Firmware bits always start from header */
-	guc_fw->header_offset = 0;
-	guc_fw->header_size = (css->header_size_dw - css->modulus_size_dw -
+	uc_fw->header_offset = 0;
+	uc_fw->header_size = (css->header_size_dw - css->modulus_size_dw -
 		css->key_size_dw - css->exponent_size_dw) * sizeof(u32);
 
-	if (guc_fw->header_size != sizeof(struct guc_css_header)) {
+	if (uc_fw->header_size != sizeof(struct guc_css_header)) {
 		DRM_ERROR("CSS header definition mismatch\n");
 		goto fail;
 	}
 
 	/* then, uCode */
-	guc_fw->ucode_offset = guc_fw->header_offset + guc_fw->header_size;
-	guc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32);
+	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);
 
 	/* now RSA */
 	if (css->key_size_dw != UOS_RSA_SCRATCH_MAX_COUNT) {
 		DRM_ERROR("RSA key size is bad\n");
 		goto fail;
 	}
-	guc_fw->rsa_offset = guc_fw->ucode_offset + guc_fw->ucode_size;
-	guc_fw->rsa_size = css->key_size_dw * sizeof(u32);
+	uc_fw->rsa_offset = uc_fw->ucode_offset + uc_fw->ucode_size;
+	uc_fw->rsa_size = css->key_size_dw * sizeof(u32);
 
 	/* At least, it should have header, uCode and RSA. Size of all three. */
-	size = guc_fw->header_size + guc_fw->ucode_size + guc_fw->rsa_size;
+	size = uc_fw->header_size + uc_fw->ucode_size + uc_fw->rsa_size;
 	if (fw->size < size) {
 		DRM_ERROR("Missing firmware components\n");
 		goto fail;
 	}
 
 	/* Header and uCode will be loaded to WOPCM. Size of the two. */
-	size = guc_fw->header_size + guc_fw->ucode_size;
+	size = uc_fw->header_size + uc_fw->ucode_size;
+
+	/* Top 32k of WOPCM is reserved (8K stack + 24k RC6 context). */
 	if (size > guc_wopcm_size(dev->dev_private)) {
 		DRM_ERROR("Firmware is too large to fit in WOPCM\n");
 		goto fail;
 	}
 
 	/*
-	 * The GuC firmware image has the version number embedded at a well-known
+	 * The uC firmware image has the version number embedded at a well-known
 	 * offset within the firmware blob; note that major / minor version are
 	 * TWO bytes each (i.e. u16), although all pointers and offsets are defined
 	 * in terms of bytes (u8).
 	 */
-	guc_fw->guc_fw_major_found = css->guc_sw_version >> 16;
-	guc_fw->guc_fw_minor_found = css->guc_sw_version & 0xFFFF;
-
-	if (guc_fw->guc_fw_major_found != guc_fw->guc_fw_major_wanted ||
-	    guc_fw->guc_fw_minor_found < guc_fw->guc_fw_minor_wanted) {
-		DRM_ERROR("GuC firmware version %d.%d, required %d.%d\n",
-			guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found,
-			guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted);
+	uc_fw->major_ver_found = css->guc_sw_version >> 16;
+	uc_fw->minor_ver_found = css->guc_sw_version & 0xFFFF;
+
+	if (uc_fw->major_ver_found != uc_fw->major_ver_wanted ||
+	    uc_fw->minor_ver_found < uc_fw->minor_ver_wanted) {
+		DRM_ERROR("Firmware version %d.%d, required %d.%d\n",
+			uc_fw->major_ver_found, uc_fw->minor_ver_found,
+			uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted);
 		err = -ENOEXEC;
 		goto fail;
 	}
 
 	DRM_DEBUG_DRIVER("firmware version %d.%d OK (minimum %d.%d)\n",
-			guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found,
-			guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted);
+			uc_fw->major_ver_found, uc_fw->minor_ver_found,
+			uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted);
 
 	mutex_lock(&dev->struct_mutex);
 	obj = i915_gem_object_create_from_data(dev, fw->data, fw->size);
@@ -641,31 +666,31 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw)
 		goto fail;
 	}
 
-	guc_fw->guc_fw_obj = obj;
-	guc_fw->guc_fw_size = fw->size;
+	uc_fw->uc_fw_obj = obj;
+	uc_fw->uc_fw_size = fw->size;
 
 	DRM_DEBUG_DRIVER("GuC fw fetch status SUCCESS, obj %p\n",
-			guc_fw->guc_fw_obj);
+			uc_fw->uc_fw_obj);
 
 	release_firmware(fw);
-	guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_SUCCESS;
+	uc_fw->fetch_status = UC_FIRMWARE_SUCCESS;
 	return;
 
 fail:
 	DRM_DEBUG_DRIVER("GuC fw fetch status FAIL; err %d, fw %p, obj %p\n",
-		err, fw, guc_fw->guc_fw_obj);
+		err, fw, uc_fw->uc_fw_obj);
 	DRM_ERROR("Failed to fetch GuC firmware from %s (error %d)\n",
-		  guc_fw->guc_fw_path, err);
+		  uc_fw->uc_fw_path, err);
 
 	mutex_lock(&dev->struct_mutex);
-	obj = guc_fw->guc_fw_obj;
+	obj = uc_fw->uc_fw_obj;
 	if (obj)
 		drm_gem_object_unreference(&obj->base);
-	guc_fw->guc_fw_obj = NULL;
+	uc_fw->uc_fw_obj = NULL;
 	mutex_unlock(&dev->struct_mutex);
 
 	release_firmware(fw);		/* OK even if fw is NULL */
-	guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_FAIL;
+	uc_fw->fetch_status = UC_FIRMWARE_FAIL;
 }
 
 /**
@@ -680,7 +705,7 @@ fail:
 void intel_guc_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
+	struct intel_uc_fw *guc_fw = &dev_priv->guc.guc_fw;
 	const char *fw_path;
 
 	/* A negative value means "use platform default" */
@@ -693,20 +718,20 @@ void intel_guc_init(struct drm_device *dev)
 		fw_path = NULL;
 	} else if (IS_SKYLAKE(dev)) {
 		fw_path = I915_SKL_GUC_UCODE;
-		guc_fw->guc_fw_major_wanted = 6;
-		guc_fw->guc_fw_minor_wanted = 1;
+		guc_fw->major_ver_wanted = 6;
+		guc_fw->minor_ver_wanted = 1;
 	} else if (IS_BROXTON(dev)) {
 		fw_path = I915_BXT_GUC_UCODE;
-		guc_fw->guc_fw_major_wanted = 8;
-		guc_fw->guc_fw_minor_wanted = 7;
+		guc_fw->major_ver_wanted = 8;
+		guc_fw->minor_ver_wanted = 7;
 	} else {
 		fw_path = "";	/* unknown device */
 	}
 
-	guc_fw->guc_dev = dev;
-	guc_fw->guc_fw_path = fw_path;
-	guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_NONE;
-	guc_fw->guc_fw_load_status = GUC_FIRMWARE_NONE;
+	guc_fw->uc_dev = dev;
+	guc_fw->uc_fw_path = fw_path;
+	guc_fw->fetch_status = UC_FIRMWARE_NONE;
+	guc_fw->load_status = UC_FIRMWARE_NONE;
 
 	/* Early (and silent) return if GuC loading is disabled */
 	if (!i915.enable_guc_loading)
@@ -716,9 +741,9 @@ void intel_guc_init(struct drm_device *dev)
 	if (*fw_path == '\0')
 		return;
 
-	guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_PENDING;
+	guc_fw->fetch_status = UC_FIRMWARE_PENDING;
 	DRM_DEBUG_DRIVER("GuC firmware pending, path %s\n", fw_path);
-	guc_fw_fetch(dev, guc_fw);
+	intel_uc_fw_fetch(dev, guc_fw);
 	/* status must now be FAIL or SUCCESS */
 }
 
@@ -729,17 +754,17 @@ void intel_guc_init(struct drm_device *dev)
 void intel_guc_fini(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
+	struct intel_uc_fw *guc_fw = &dev_priv->guc.guc_fw;
 
 	mutex_lock(&dev->struct_mutex);
 	direct_interrupts_to_host(dev_priv);
 	i915_guc_submission_disable(dev_priv);
 	i915_guc_submission_fini(dev_priv);
 
-	if (guc_fw->guc_fw_obj)
-		drm_gem_object_unreference(&guc_fw->guc_fw_obj->base);
-	guc_fw->guc_fw_obj = NULL;
+	if (guc_fw->uc_fw_obj)
+		drm_gem_object_unreference(&guc_fw->uc_fw_obj->base);
+	guc_fw->uc_fw_obj = NULL;
 	mutex_unlock(&dev->struct_mutex);
 
-	guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_NONE;
+	guc_fw->fetch_status = UC_FIRMWARE_NONE;
 }
-- 
1.9.1

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

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

* [PATCH 2/6] drm/i915/huc: Unified css_header struct for GuC and HuC
  2016-06-21 18:11 [PATCH 0/6] HuC Loading Patches Peter Antoine
  2016-06-21 18:11 ` [PATCH 1/6] drm/i915/guc: Make the GuC fw loading helper functions general Peter Antoine
@ 2016-06-21 18:11 ` Peter Antoine
  2016-06-28 14:32   ` Dave Gordon
  2016-06-21 18:11 ` [PATCH 3/6] drm/i915/huc: Add HuC fw loading support Peter Antoine
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 40+ messages in thread
From: Peter Antoine @ 2016-06-21 18:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: lawrence.t.li, sean.v.kelley, rodrigo.vivi

From: Alex Dai <yu.dai@intel.com>

HuC firmware css header has almost exactly same definition as GuC
firmware except for the sw_version. Also, add a new member fw_type
into intel_uc_fw to indicate what kind of fw it is. So, the loader
will pull right sw_version from header.

Signed-off-by: Alex Dai <yu.dai@intel.com>
Signed-off-by: Peter Antoine <peter.antoine@intel.com>
---
 drivers/gpu/drm/i915/intel_guc.h        |  4 ++++
 drivers/gpu/drm/i915/intel_guc_fwif.h   | 16 ++++++++++---
 drivers/gpu/drm/i915/intel_guc_loader.c | 42 +++++++++++++++++++++------------
 3 files changed, 44 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 836420b..0b4ed88 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -97,6 +97,9 @@ enum intel_uc_fw_status {
 	UC_FIRMWARE_SUCCESS
 };
 
+#define UC_FW_TYPE_GUC		0
+#define UC_FW_TYPE_HUC		1
+
 /*
  * This structure encapsulates all the data needed during the process
  * of fetching, caching, and loading the firmware image into the GuC.
@@ -114,6 +117,7 @@ struct intel_uc_fw {
 	uint16_t major_ver_found;
 	uint16_t minor_ver_found;
 
+	uint32_t fw_type;
 	uint32_t header_size;
 	uint32_t header_offset;
 	uint32_t rsa_size;
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h
index 944786d..a69ee36 100644
--- a/drivers/gpu/drm/i915/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
@@ -154,7 +154,7 @@
  * The GuC firmware layout looks like this:
  *
  *     +-------------------------------+
- *     |        guc_css_header         |
+ *     |         uc_css_header         |
  *     | contains major/minor version  |
  *     +-------------------------------+
  *     |             uCode             |
@@ -180,9 +180,16 @@
  * 3. Length info of each component can be found in header, in dwords.
  * 4. Modulus and exponent key are not required by driver. They may not appear
  * in fw. So driver will load a truncated firmware in this case.
+ *
+ * HuC firmware layout is same as GuC firmware.
+ *
+ * HuC firmware css header is different. However, the only difference is where
+ * the version information is saved. The uc_css_header is unified to support
+ * both. Driver should get HuC version from uc_css_header.huc_sw_version, while
+ * uc_css_header.guc_sw_version for GuC.
  */
 
-struct guc_css_header {
+struct uc_css_header {
 	uint32_t module_type;
 	/* header_size includes all non-uCode bits, including css_header, rsa
 	 * key, modulus key and exponent data. */
@@ -213,7 +220,10 @@ struct guc_css_header {
 
 	char username[8];
 	char buildnumber[12];
-	uint32_t device_id;
+	union {
+		uint32_t device_id;
+		uint32_t huc_sw_version;
+	};
 	uint32_t guc_sw_version;
 	uint32_t prod_preprod_fw;
 	uint32_t reserved[12];
diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
index ff054f5..70575bd 100644
--- a/drivers/gpu/drm/i915/intel_guc_loader.c
+++ b/drivers/gpu/drm/i915/intel_guc_loader.c
@@ -574,7 +574,7 @@ void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw)
 {
 	struct drm_i915_gem_object *obj;
 	const struct firmware *fw;
-	struct guc_css_header *css;
+	struct uc_css_header *css;
 	size_t size;
 	int err;
 
@@ -591,19 +591,19 @@ void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw)
 		uc_fw->uc_fw_path, fw);
 
 	/* Check the size of the blob before examining buffer contents */
-	if (fw->size < sizeof(struct guc_css_header)) {
+	if (fw->size < sizeof(struct uc_css_header)) {
 		DRM_ERROR("Firmware header is missing\n");
 		goto fail;
 	}
 
-	css = (struct guc_css_header *)fw->data;
+	css = (struct uc_css_header *)fw->data;
 
 	/* Firmware bits always start from header */
 	uc_fw->header_offset = 0;
 	uc_fw->header_size = (css->header_size_dw - css->modulus_size_dw -
 		css->key_size_dw - css->exponent_size_dw) * sizeof(u32);
 
-	if (uc_fw->header_size != sizeof(struct guc_css_header)) {
+	if (uc_fw->header_size != sizeof(struct uc_css_header)) {
 		DRM_ERROR("CSS header definition mismatch\n");
 		goto fail;
 	}
@@ -627,23 +627,35 @@ void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw)
 		goto fail;
 	}
 
-	/* Header and uCode will be loaded to WOPCM. Size of the two. */
-	size = uc_fw->header_size + uc_fw->ucode_size;
-
-	/* Top 32k of WOPCM is reserved (8K stack + 24k RC6 context). */
-	if (size > guc_wopcm_size(dev->dev_private)) {
-		DRM_ERROR("Firmware is too large to fit in WOPCM\n");
-		goto fail;
-	}
-
 	/*
 	 * The uC firmware image has the version number embedded at a well-known
 	 * offset within the firmware blob; note that major / minor version are
 	 * TWO bytes each (i.e. u16), although all pointers and offsets are defined
 	 * in terms of bytes (u8).
 	 */
-	uc_fw->major_ver_found = css->guc_sw_version >> 16;
-	uc_fw->minor_ver_found = css->guc_sw_version & 0xFFFF;
+	switch (uc_fw->fw_type) {
+	case UC_FW_TYPE_GUC:
+		/* Header and uCode will be loaded to WOPCM. Size of the two. */
+		size = uc_fw->header_size + uc_fw->ucode_size;
+
+		/* Top 32k of WOPCM is reserved (8K stack + 24k RC6 context). */
+		if (size > guc_wopcm_size(dev->dev_private)) {
+			DRM_ERROR("Firmware is too large to fit in WOPCM\n");
+			goto fail;
+		}
+
+		uc_fw->major_ver_found = css->guc_sw_version >> 16;
+		uc_fw->minor_ver_found = css->guc_sw_version & 0xFFFF;
+		break;
+	case UC_FW_TYPE_HUC:
+		uc_fw->major_ver_found = css->huc_sw_version >> 16;
+		uc_fw->minor_ver_found = css->huc_sw_version & 0xFFFF;
+		break;
+	default:
+		DRM_ERROR("Unknown firmware type %d\n", uc_fw->fw_type);
+		err = -ENOEXEC;
+		goto fail;
+	}
 
 	if (uc_fw->major_ver_found != uc_fw->major_ver_wanted ||
 	    uc_fw->minor_ver_found < uc_fw->minor_ver_wanted) {
-- 
1.9.1

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

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

* [PATCH 3/6] drm/i915/huc: Add HuC fw loading support
  2016-06-21 18:11 [PATCH 0/6] HuC Loading Patches Peter Antoine
  2016-06-21 18:11 ` [PATCH 1/6] drm/i915/guc: Make the GuC fw loading helper functions general Peter Antoine
  2016-06-21 18:11 ` [PATCH 2/6] drm/i915/huc: Unified css_header struct for GuC and HuC Peter Antoine
@ 2016-06-21 18:11 ` Peter Antoine
  2016-06-22  8:31   ` Daniel Vetter
  2016-06-28 14:54   ` Dave Gordon
  2016-06-21 18:11 ` [PATCH 4/6] drm/i915/huc: Add debugfs for HuC loading status check Peter Antoine
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 40+ messages in thread
From: Peter Antoine @ 2016-06-21 18:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: lawrence.t.li, sean.v.kelley, rodrigo.vivi

From: Alex Dai <yu.dai@intel.com>

The HuC loading process is similar to GuC. The intel_uc_fw_fetch()
is used for both cases.

HuC loading needs to be before GuC loading. The WOPCM setting must
be done early before loading any of them.

Signed-off-by: Alex Dai <yu.dai@intel.com>
Signed-off-by: Peter Antoine <peter.antoine@intel.com>
---
 drivers/gpu/drm/i915/Makefile           |   1 +
 drivers/gpu/drm/i915/i915_dma.c         |   3 +
 drivers/gpu/drm/i915/i915_drv.h         |   3 +
 drivers/gpu/drm/i915/i915_gem.c         |  13 +-
 drivers/gpu/drm/i915/i915_guc_reg.h     |   3 +
 drivers/gpu/drm/i915/intel_guc.h        |   1 +
 drivers/gpu/drm/i915/intel_guc_loader.c |  11 +-
 drivers/gpu/drm/i915/intel_huc.h        |  44 ++++++
 drivers/gpu/drm/i915/intel_huc_loader.c | 262 ++++++++++++++++++++++++++++++++
 9 files changed, 331 insertions(+), 10 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_huc.h
 create mode 100644 drivers/gpu/drm/i915/intel_huc_loader.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 276abf1..7384db0 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -44,6 +44,7 @@ i915-y += i915_cmd_parser.o \
 
 # general-purpose microcontroller (GuC) support
 i915-y += intel_guc_loader.o \
+	  intel_huc_loader.o \
 	  i915_guc_submission.o
 
 # autogenerated null render state
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index e28c0dd..a449a59 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -507,6 +507,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
 	 * working irqs for e.g. gmbus and dp aux transfers. */
 	intel_modeset_init(dev);
 
+	intel_huc_init(dev);
 	intel_guc_init(dev);
 
 	ret = i915_gem_init(dev);
@@ -532,6 +533,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
 cleanup_gem:
 	i915_gem_fini(dev);
 cleanup_irq:
+	intel_huc_fini(dev);
 	intel_guc_fini(dev);
 	drm_irq_uninstall(dev);
 	intel_teardown_gmbus(dev);
@@ -1563,6 +1565,7 @@ int i915_driver_unload(struct drm_device *dev)
 	/* Flush any outstanding unpin_work. */
 	flush_workqueue(dev_priv->wq);
 
+	intel_huc_fini(dev);
 	intel_guc_fini(dev);
 	i915_gem_fini(dev);
 	intel_fbc_cleanup_cfb(dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7c81757..8b88227 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -54,6 +54,7 @@
 #include "intel_bios.h"
 #include "intel_dpll_mgr.h"
 #include "intel_guc.h"
+#include "intel_huc.h"
 #include "intel_lrc.h"
 #include "intel_ringbuffer.h"
 
@@ -1749,6 +1750,7 @@ struct drm_i915_private {
 
 	struct intel_gvt gvt;
 
+	struct intel_huc huc;
 	struct intel_guc guc;
 
 	struct intel_csr csr;
@@ -2841,6 +2843,7 @@ struct drm_i915_cmd_table {
 #define HAS_GUC(dev)		(IS_GEN9(dev) && !IS_KABYLAKE(dev))
 #define HAS_GUC_UCODE(dev)	(HAS_GUC(dev))
 #define HAS_GUC_SCHED(dev)	(HAS_GUC(dev))
+#define HAS_HUC_UCODE(dev)	(HAS_GUC(dev))
 
 #define HAS_RESOURCE_STREAMER(dev) (IS_HASWELL(dev) || \
 				    INTEL_INFO(dev)->gen >= 8)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 6abd5e5..549dd3f 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -5143,9 +5143,16 @@ i915_gem_init_hw(struct drm_device *dev)
 	intel_mocs_init_l3cc_table(dev);
 
 	/* We can't enable contexts until all firmware is loaded */
-	ret = intel_guc_setup(dev);
-	if (ret)
-		goto out;
+	if (HAS_GUC(dev)) {
+		/* init WOPCM */
+		I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev));
+		I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE);
+
+		intel_huc_load(dev);
+		ret = intel_guc_setup(dev);
+		if (ret)
+			goto out;
+	}
 
 	/*
 	 * Increment the next seqno by 0x100 so we have a visible break
diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h b/drivers/gpu/drm/i915/i915_guc_reg.h
index cf5a65b..51533f1 100644
--- a/drivers/gpu/drm/i915/i915_guc_reg.h
+++ b/drivers/gpu/drm/i915/i915_guc_reg.h
@@ -61,9 +61,12 @@
 #define   DMA_ADDRESS_SPACE_GTT		  (8 << 16)
 #define DMA_COPY_SIZE			_MMIO(0xc310)
 #define DMA_CTRL			_MMIO(0xc314)
+#define   HUC_UKERNEL			  (1<<9)
 #define   UOS_MOVE			  (1<<4)
 #define   START_DMA			  (1<<0)
 #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)
 
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 0b4ed88..c4b92f3 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -160,6 +160,7 @@ extern const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status);
 extern int intel_guc_suspend(struct drm_device *dev);
 extern int intel_guc_resume(struct drm_device *dev);
 void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw);
+u32 guc_wopcm_size(struct drm_device *dev);
 
 /* i915_guc_submission.c */
 int i915_guc_submission_init(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
index 70575bd..c4a210d 100644
--- a/drivers/gpu/drm/i915/intel_guc_loader.c
+++ b/drivers/gpu/drm/i915/intel_guc_loader.c
@@ -270,7 +270,8 @@ static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv)
 	I915_WRITE(DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM);
 
 	/* Finally start the DMA */
-	I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(UOS_MOVE | START_DMA));
+	I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(UOS_MOVE | START_DMA) |
+			_MASKED_BIT_DISABLE(HUC_UKERNEL));
 
 	/*
 	 * Wait for the DMA to complete & the GuC to start up.
@@ -295,12 +296,12 @@ static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv)
 	return ret;
 }
 
-static u32 guc_wopcm_size(struct drm_i915_private *dev_priv)
+u32 guc_wopcm_size(struct drm_device *dev)
 {
 	u32 wopcm_size = GUC_WOPCM_TOP;
 
 	/* On BXT, the top of WOPCM is reserved for RC6 context */
-	if (IS_BROXTON(dev_priv))
+	if (IS_BROXTON(dev))
 		wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED;
 
 	return wopcm_size;
@@ -332,10 +333,6 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
 
 	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
 
-	/* init WOPCM */
-	I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev_priv));
-	I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE);
-
 	/* Enable MIA caching. GuC clock gating is disabled. */
 	I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE);
 
diff --git a/drivers/gpu/drm/i915/intel_huc.h b/drivers/gpu/drm/i915/intel_huc.h
new file mode 100644
index 0000000..946caa7
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_huc.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2014 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_HUC_H_
+#define _INTEL_HUC_H_
+
+#include "intel_guc.h"
+
+#define HUC_STATUS2		_MMIO(0xD3B0)
+#define   HUC_FW_VERIFIED	(1<<7)
+
+struct intel_huc {
+	/* Generic uC firmware management */
+	struct intel_uc_fw huc_fw;
+
+	/* HuC-specific additions */
+};
+
+extern void intel_huc_init(struct drm_device *dev);
+extern int intel_huc_load(struct drm_device *dev);
+extern void intel_huc_auth(struct drm_device *dev);
+extern void intel_huc_fini(struct drm_device *dev);
+
+#endif
diff --git a/drivers/gpu/drm/i915/intel_huc_loader.c b/drivers/gpu/drm/i915/intel_huc_loader.c
new file mode 100644
index 0000000..472fabe
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_huc_loader.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright © 2014 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 <linux/firmware.h>
+#include "i915_drv.h"
+#include "intel_huc.h"
+
+/**
+ * DOC: HuC Firmware
+ *
+ * Motivation:
+ * GEN9 introduces a new dedicated firmware for usage in media HEVC (High
+ * Efficiency Video Coding) operations. Userspace can use the firmware
+ * capabilities by adding HuC specific commands to batch buffers.
+ *
+ * Implementation:
+ * On supported platforms, i915's job is to load the firmware stored on the
+ * file system and assist with authentication. It is up to userspace to
+ * detect the presence of HuC support on a platform, on their own.
+ * For debugging, i915 provides a debugfs file, i915_huc_load_status_info
+ * which displays the firmware load status.
+ *
+ * The unified uC firmware loader is used. Firmware binary is fetched by the
+ * loader asynchronously from the driver init process. However, the actual
+ * loading to HW is deferred until GEM initialization is done. Be note that HuC
+ * firmware loading must be done before GuC loading.
+ */
+
+#define I915_SKL_HUC_UCODE "i915/skl_huc_ver1.bin"
+MODULE_FIRMWARE(I915_SKL_HUC_UCODE);
+
+/**
+ * intel_huc_load_ucode() - DMA's the firmware
+ * @dev: the drm device
+ *
+ * This function takes the gem object containing the firmware, sets up the DMA
+ * engine MMIO, triggers the DMA operation and waits for it to finish.
+ *
+ * Transfer the firmware image to RAM for execution by the microcontroller.
+ *
+ * Return: 0 on success, non-zero on failure
+ */
+
+static int huc_ucode_xfer(struct drm_i915_private *dev_priv)
+{
+	struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
+	unsigned long offset = 0;
+	u32 size;
+	int ret;
+
+	ret = i915_gem_object_set_to_gtt_domain(huc_fw->uc_fw_obj, false);
+	if (ret) {
+		DRM_DEBUG_DRIVER("set-domain failed %d\n", ret);
+		return ret;
+	}
+
+	ret = i915_gem_obj_ggtt_pin(huc_fw->uc_fw_obj, 0, 0);
+	if (ret) {
+		DRM_DEBUG_DRIVER("pin failed %d\n", ret);
+		return ret;
+	}
+
+	/* Invalidate GuC TLB to let GuC take the latest updates to GTT. */
+	I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);
+
+	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
+
+	/* Set the source address for the uCode */
+	offset = i915_gem_obj_ggtt_offset(huc_fw->uc_fw_obj) +
+			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);
+
+	/* Hardware doesn't look at destination address for HuC. Set it to 0,
+	 * but still program the correct address space.
+	 */
+	I915_WRITE(DMA_ADDR_1_LOW, 0);
+	I915_WRITE(DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM);
+
+	size = huc_fw->header_size + huc_fw->ucode_size;
+	I915_WRITE(DMA_COPY_SIZE, size);
+
+	/* Start the DMA */
+	I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(HUC_UKERNEL | START_DMA));
+
+	/* Wait for DMA to finish */
+	ret = wait_for_atomic((I915_READ(DMA_CTRL) & START_DMA) == 0, 50);
+
+	DRM_DEBUG_DRIVER("HuC DMA transfer wait over with ret %d\n", ret);
+
+	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
+
+	/*
+	 * We keep the object pages for reuse during resume. But we can unpin it
+	 * now that DMA has completed, so it doesn't continue to take up space.
+	 */
+	i915_gem_object_ggtt_unpin(huc_fw->uc_fw_obj);
+
+	return ret;
+}
+
+/**
+ * intel_huc_init() - initiate HuC firmware loading request
+ * @dev: the drm device
+ *
+ * Called early during driver load, but after GEM is initialised. The loading
+ * will continue only when driver explicitly specify firmware name and version.
+ * All other cases are considered as UC_FIRMWARE_NONE either because HW is not
+ * capable or driver yet support it. And there will be no error message for
+ * UC_FIRMWARE_NONE cases.
+ *
+ * The DMA-copying to HW is done later when intel_huc_ucode_load() is called.
+ */
+void intel_huc_init(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_huc *huc = &dev_priv->huc;
+	struct intel_uc_fw *huc_fw = &huc->huc_fw;
+	const char *fw_path = NULL;
+
+	huc_fw->uc_dev = dev;
+	huc_fw->uc_fw_path = NULL;
+	huc_fw->fetch_status = UC_FIRMWARE_NONE;
+	huc_fw->load_status = UC_FIRMWARE_NONE;
+	huc_fw->fw_type = UC_FW_TYPE_HUC;
+
+	if (!HAS_HUC_UCODE(dev))
+		return;
+
+	if (IS_SKYLAKE(dev)) {
+		fw_path = I915_SKL_HUC_UCODE;
+		huc_fw->major_ver_wanted = 1;
+		huc_fw->minor_ver_wanted = 5;
+	}
+
+	if (fw_path == NULL)
+		return;
+
+	huc_fw->uc_fw_path = fw_path;
+	huc_fw->fetch_status = UC_FIRMWARE_PENDING;
+
+	DRM_DEBUG_DRIVER("HuC firmware pending, path %s\n", fw_path);
+
+	intel_uc_fw_fetch(dev, huc_fw);
+}
+
+/**
+ * intel_huc_load() - load HuC uCode to device
+ * @dev: the drm device
+ *
+ * Called from gem_init_hw() during driver loading and also after a GPU reset.
+ * Be note that HuC loading must be done before GuC loading.
+ *
+ * The firmware image should have already been fetched into memory by the
+ * earlier call to intel_huc_ucode_init(), so here we need only check that
+ * is succeeded, and then transfer the image to the h/w.
+ *
+ * Return:	non-zero code on error
+ */
+int intel_huc_load(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
+	int err;
+
+	if (huc_fw->fetch_status == UC_FIRMWARE_NONE)
+		return 0;
+
+	DRM_DEBUG_DRIVER("%s fw status: fetch %s, load %s\n",
+		huc_fw->uc_fw_path,
+		intel_uc_fw_status_repr(huc_fw->fetch_status),
+		intel_uc_fw_status_repr(huc_fw->load_status));
+
+	if (huc_fw->fetch_status == UC_FIRMWARE_SUCCESS &&
+	    huc_fw->load_status == UC_FIRMWARE_FAIL)
+		return -ENOEXEC;
+
+	huc_fw->load_status = UC_FIRMWARE_PENDING;
+
+	switch (huc_fw->fetch_status) {
+	case UC_FIRMWARE_FAIL:
+		/* something went wrong :( */
+		err = -EIO;
+		goto fail;
+
+	case UC_FIRMWARE_NONE:
+	case UC_FIRMWARE_PENDING:
+	default:
+		/* "can't happen" */
+		WARN_ONCE(1, "HuC fw %s invalid fetch_status %s [%d]\n",
+			huc_fw->uc_fw_path,
+			intel_uc_fw_status_repr(huc_fw->fetch_status),
+			huc_fw->fetch_status);
+		err = -ENXIO;
+		goto fail;
+
+	case UC_FIRMWARE_SUCCESS:
+		break;
+	}
+
+	err = huc_ucode_xfer(dev_priv);
+	if (err)
+		goto fail;
+
+	huc_fw->load_status = UC_FIRMWARE_SUCCESS;
+
+	DRM_DEBUG_DRIVER("%s fw status: fetch %s, load %s\n",
+		huc_fw->uc_fw_path,
+		intel_uc_fw_status_repr(huc_fw->fetch_status),
+		intel_uc_fw_status_repr(huc_fw->load_status));
+
+	return 0;
+
+fail:
+	if (huc_fw->load_status == UC_FIRMWARE_PENDING)
+		huc_fw->load_status = UC_FIRMWARE_FAIL;
+
+	DRM_ERROR("Failed to complete HuC uCode load with ret %d\n", err);
+
+	return err;
+}
+
+/**
+ * intel_huc_fini() - clean up resources allocated for HuC
+ * @dev: the drm device
+ *
+ * Cleans up by releasing the huc firmware GEM obj.
+ */
+void intel_huc_fini(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
+
+	mutex_lock(&dev->struct_mutex);
+	if (huc_fw->uc_fw_obj)
+		drm_gem_object_unreference(&huc_fw->uc_fw_obj->base);
+	huc_fw->uc_fw_obj = NULL;
+	mutex_unlock(&dev->struct_mutex);
+
+	huc_fw->fetch_status = UC_FIRMWARE_NONE;
+}
-- 
1.9.1

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

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

* [PATCH 4/6] drm/i915/huc: Add debugfs for HuC loading status check
  2016-06-21 18:11 [PATCH 0/6] HuC Loading Patches Peter Antoine
                   ` (2 preceding siblings ...)
  2016-06-21 18:11 ` [PATCH 3/6] drm/i915/huc: Add HuC fw loading support Peter Antoine
@ 2016-06-21 18:11 ` Peter Antoine
  2016-06-23  8:47   ` Xiang, Haihao
  2016-06-28 14:57   ` Dave Gordon
  2016-06-21 18:11 ` [PATCH 5/6] drm/i915/huc: Support HuC authentication Peter Antoine
                   ` (2 subsequent siblings)
  6 siblings, 2 replies; 40+ messages in thread
From: Peter Antoine @ 2016-06-21 18:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: lawrence.t.li, sean.v.kelley, rodrigo.vivi

From: Alex Dai <yu.dai@intel.com>

Add debugfs entry for HuC loading status check.

Signed-off-by: Alex Dai <yu.dai@intel.com>
Signed-off-by: Peter Antoine <peter.antoine@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 69964c2..f5976f8 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2479,6 +2479,37 @@ static int i915_llc(struct seq_file *m, void *data)
 	return 0;
 }
 
+static int i915_huc_load_status_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = m->private;
+	struct drm_i915_private *dev_priv = node->minor->dev->dev_private;
+	struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
+
+	if (!HAS_HUC_UCODE(dev_priv->dev))
+		return 0;
+
+	seq_puts(m, "HuC firmware status:\n");
+	seq_printf(m, "\tpath: %s\n", huc_fw->uc_fw_path);
+	seq_printf(m, "\tfetch: %s\n",
+		intel_uc_fw_status_repr(huc_fw->fetch_status));
+	seq_printf(m, "\tload: %s\n",
+		intel_uc_fw_status_repr(huc_fw->load_status));
+	seq_printf(m, "\tversion wanted: %d.%d\n",
+		huc_fw->major_ver_wanted, huc_fw->minor_ver_wanted);
+	seq_printf(m, "\tversion found: %d.%d\n",
+		huc_fw->major_ver_found, huc_fw->minor_ver_found);
+	seq_printf(m, "\theader: offset is %d; size = %d\n",
+		huc_fw->header_offset, huc_fw->header_size);
+	seq_printf(m, "\tuCode: offset is %d; size = %d\n",
+		huc_fw->ucode_offset, huc_fw->ucode_size);
+	seq_printf(m, "\tRSA: offset is %d; size = %d\n",
+		huc_fw->rsa_offset, huc_fw->rsa_size);
+
+	seq_printf(m, "\nHuC status 0x%08x:\n", I915_READ(HUC_STATUS2));
+
+	return 0;
+}
+
 static int i915_guc_load_status_info(struct seq_file *m, void *data)
 {
 	struct drm_info_node *node = m->private;
@@ -5432,6 +5463,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
 	{"i915_guc_info", i915_guc_info, 0},
 	{"i915_guc_load_status", i915_guc_load_status_info, 0},
 	{"i915_guc_log_dump", i915_guc_log_dump, 0},
+	{"i915_huc_load_status", i915_huc_load_status_info, 0},
 	{"i915_frequency_info", i915_frequency_info, 0},
 	{"i915_hangcheck_info", i915_hangcheck_info, 0},
 	{"i915_drpc_info", i915_drpc_info, 0},
-- 
1.9.1

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

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

* [PATCH 5/6] drm/i915/huc: Support HuC authentication
  2016-06-21 18:11 [PATCH 0/6] HuC Loading Patches Peter Antoine
                   ` (3 preceding siblings ...)
  2016-06-21 18:11 ` [PATCH 4/6] drm/i915/huc: Add debugfs for HuC loading status check Peter Antoine
@ 2016-06-21 18:11 ` Peter Antoine
  2016-06-28 15:08   ` Dave Gordon
  2016-06-21 18:11 ` [PATCH 6/6] drm/i915/huc: Add BXT HuC Loading Support Peter Antoine
  2016-06-22 13:02 ` ✗ Ro.CI.BAT: warning for HuC Loading Patches Patchwork
  6 siblings, 1 reply; 40+ messages in thread
From: Peter Antoine @ 2016-06-21 18:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: sean.v.kelley, lawrence.t.li, rodrigo.vivi

The HuC authentication is done by host2guc call. The HuC RSA keys
are sent to GuC for authentication.

Signed-off-by: Alex Dai <yu.dai@intel.com>
Signed-off-by: Peter Antoine <peter.antoine@intel.com>
---
 drivers/gpu/drm/i915/i915_guc_submission.c | 65 ++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_guc_fwif.h      |  1 +
 drivers/gpu/drm/i915/intel_guc_loader.c    |  2 +
 drivers/gpu/drm/i915/intel_huc_loader.c    |  5 +++
 4 files changed, 73 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index bfb8400..41f3a42 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -25,6 +25,7 @@
 #include <linux/circ_buf.h>
 #include "i915_drv.h"
 #include "intel_guc.h"
+#include "intel_huc.h"
 
 /**
  * DOC: GuC-based command submission
@@ -1077,3 +1078,67 @@ int intel_guc_resume(struct drm_device *dev)
 
 	return host2guc_action(guc, data, ARRAY_SIZE(data));
 }
+
+/**
+ * intel_huc_auth() - authenticate ucode
+ * @dev: the drm device
+ *
+ * Triggers a HuC fw authentication request to the GuC via host-2-guc
+ * interface.
+ */
+void intel_huc_auth(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_guc *guc = &dev_priv->guc;
+	struct intel_huc *huc = &dev_priv->huc;
+	int ret;
+	u32 data[2];
+
+	/* Bypass the case where there is no HuC firmware */
+	if (huc->huc_fw.fetch_status == UC_FIRMWARE_NONE ||
+	    huc->huc_fw.load_status == UC_FIRMWARE_NONE)
+		return;
+
+	if (guc->guc_fw.load_status != UC_FIRMWARE_SUCCESS) {
+		DRM_ERROR("HuC: GuC fw wasn't loaded. Can't authenticate");
+		return;
+	}
+
+	if (huc->huc_fw.load_status != UC_FIRMWARE_SUCCESS) {
+		DRM_ERROR("HuC: fw wasn't loaded. Nothing to authenticate");
+		return;
+	}
+
+	ret = i915_gem_obj_ggtt_pin(huc->huc_fw.uc_fw_obj, 0, 0);
+	if (ret) {
+		DRM_ERROR("HuC: Pin failed");
+		return;
+	}
+
+	/* Invalidate GuC TLB to let GuC take the latest updates to GTT. */
+	I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);
+
+	/* Specify auth action and where public signature is. It's stored
+	 * at the beginning of the gem object, before the fw bits
+	 */
+	data[0] = HOST2GUC_ACTION_AUTHENTICATE_HUC;
+	data[1] = i915_gem_obj_ggtt_offset(huc->huc_fw.uc_fw_obj) +
+			huc->huc_fw.rsa_offset;
+
+	ret = host2guc_action(guc, data, ARRAY_SIZE(data));
+	if (ret) {
+		DRM_ERROR("HuC: GuC did not ack Auth request\n");
+		goto out;
+	}
+
+	/* Check authentication status, it should be done by now */
+	ret = wait_for_atomic(
+		(I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED) > 0, 50);
+	if (ret) {
+		DRM_ERROR("HuC: Authentication failed\n");
+		goto out;
+	}
+
+out:
+	i915_gem_object_ggtt_unpin(huc->huc_fw.uc_fw_obj);
+}
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h
index a69ee36..c5a6227 100644
--- a/drivers/gpu/drm/i915/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
@@ -437,6 +437,7 @@ enum host2guc_action {
 	HOST2GUC_ACTION_ENTER_S_STATE = 0x501,
 	HOST2GUC_ACTION_EXIT_S_STATE = 0x502,
 	HOST2GUC_ACTION_SLPC_REQUEST = 0x3003,
+	HOST2GUC_ACTION_AUTHENTICATE_HUC = 0x4000,
 	HOST2GUC_ACTION_LIMIT
 };
 
diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
index c4a210d..e876a23f 100644
--- a/drivers/gpu/drm/i915/intel_guc_loader.c
+++ b/drivers/gpu/drm/i915/intel_guc_loader.c
@@ -500,6 +500,8 @@ int intel_guc_setup(struct drm_device *dev)
 		intel_uc_fw_status_repr(guc_fw->fetch_status),
 		intel_uc_fw_status_repr(guc_fw->load_status));
 
+	intel_huc_auth(dev);
+
 	if (i915.enable_guc_submission) {
 		err = i915_guc_submission_enable(dev_priv);
 		if (err)
diff --git a/drivers/gpu/drm/i915/intel_huc_loader.c b/drivers/gpu/drm/i915/intel_huc_loader.c
index 472fabe..7205e9e 100644
--- a/drivers/gpu/drm/i915/intel_huc_loader.c
+++ b/drivers/gpu/drm/i915/intel_huc_loader.c
@@ -86,6 +86,11 @@ static int huc_ucode_xfer(struct drm_i915_private *dev_priv)
 	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
 	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
 
+	/* init WOPCM */
+	I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev_priv->dev));
+	I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE |
+			HUC_LOADING_AGENT_GUC);
+
 	/* Set the source address for the uCode */
 	offset = i915_gem_obj_ggtt_offset(huc_fw->uc_fw_obj) +
 			huc_fw->header_offset;
-- 
1.9.1

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

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

* [PATCH 6/6] drm/i915/huc: Add BXT HuC Loading Support
  2016-06-21 18:11 [PATCH 0/6] HuC Loading Patches Peter Antoine
                   ` (4 preceding siblings ...)
  2016-06-21 18:11 ` [PATCH 5/6] drm/i915/huc: Support HuC authentication Peter Antoine
@ 2016-06-21 18:11 ` Peter Antoine
  2016-06-21 18:26   ` Vivi, Rodrigo
  2016-06-28 15:20   ` Dave Gordon
  2016-06-22 13:02 ` ✗ Ro.CI.BAT: warning for HuC Loading Patches Patchwork
  6 siblings, 2 replies; 40+ messages in thread
From: Peter Antoine @ 2016-06-21 18:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: sean.v.kelley, lawrence.t.li, rodrigo.vivi

This patch adds the HuC Loading for the BXT.
Version 1.x of the HuC firmware.

Signed-off-by: Peter Antoine <peter.antoine@intel.com>
---
 drivers/gpu/drm/i915/i915_gem.c         | 13 +++----------
 drivers/gpu/drm/i915/intel_guc_loader.c | 29 +++++++++++++++++------------
 drivers/gpu/drm/i915/intel_huc_loader.c |  7 +++++++
 3 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 549dd3f..6abd5e5 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -5143,16 +5143,9 @@ i915_gem_init_hw(struct drm_device *dev)
 	intel_mocs_init_l3cc_table(dev);
 
 	/* We can't enable contexts until all firmware is loaded */
-	if (HAS_GUC(dev)) {
-		/* init WOPCM */
-		I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev));
-		I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE);
-
-		intel_huc_load(dev);
-		ret = intel_guc_setup(dev);
-		if (ret)
-			goto out;
-	}
+	ret = intel_guc_setup(dev);
+	if (ret)
+		goto out;
 
 	/*
 	 * Increment the next seqno by 0x100 so we have a visible break
diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
index e876a23f..289b5b6 100644
--- a/drivers/gpu/drm/i915/intel_guc_loader.c
+++ b/drivers/gpu/drm/i915/intel_guc_loader.c
@@ -82,6 +82,17 @@ const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status)
 	}
 };
 
+u32 guc_wopcm_size(struct drm_device *dev)
+{
+	u32 wopcm_size = GUC_WOPCM_TOP;
+
+	/* On BXT, the top of WOPCM is reserved for RC6 context */
+	if (IS_BROXTON(dev))
+		wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED;
+
+	return wopcm_size;
+}
+
 static void direct_interrupts_to_host(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
@@ -296,17 +307,6 @@ static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv)
 	return ret;
 }
 
-u32 guc_wopcm_size(struct drm_device *dev)
-{
-	u32 wopcm_size = GUC_WOPCM_TOP;
-
-	/* On BXT, the top of WOPCM is reserved for RC6 context */
-	if (IS_BROXTON(dev))
-		wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED;
-
-	return wopcm_size;
-}
-
 /*
  * Load the GuC firmware blob into the MinuteIA.
  */
@@ -333,6 +333,10 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
 
 	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
 
+	/* init WOPCM */
+	I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev));
+	I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE);
+
 	/* Enable MIA caching. GuC clock gating is disabled. */
 	I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE);
 
@@ -483,6 +487,7 @@ int intel_guc_setup(struct drm_device *dev)
 			goto fail;
 		}
 
+		intel_huc_load(dev);
 		err = guc_ucode_xfer(dev_priv);
 		if (!err)
 			break;
@@ -638,7 +643,7 @@ void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw)
 		size = uc_fw->header_size + uc_fw->ucode_size;
 
 		/* Top 32k of WOPCM is reserved (8K stack + 24k RC6 context). */
-		if (size > guc_wopcm_size(dev->dev_private)) {
+		if (size > guc_wopcm_size(dev)) {
 			DRM_ERROR("Firmware is too large to fit in WOPCM\n");
 			goto fail;
 		}
diff --git a/drivers/gpu/drm/i915/intel_huc_loader.c b/drivers/gpu/drm/i915/intel_huc_loader.c
index 7205e9e..7a43d4e 100644
--- a/drivers/gpu/drm/i915/intel_huc_loader.c
+++ b/drivers/gpu/drm/i915/intel_huc_loader.c
@@ -49,6 +49,9 @@
 #define I915_SKL_HUC_UCODE "i915/skl_huc_ver1.bin"
 MODULE_FIRMWARE(I915_SKL_HUC_UCODE);
 
+#define I915_BXT_HUC_UCODE "i915/bxt_huc_ver1.bin"
+MODULE_FIRMWARE(I915_BXT_HUC_UCODE);
+
 /**
  * intel_huc_load_ucode() - DMA's the firmware
  * @dev: the drm device
@@ -157,6 +160,10 @@ void intel_huc_init(struct drm_device *dev)
 		fw_path = I915_SKL_HUC_UCODE;
 		huc_fw->major_ver_wanted = 1;
 		huc_fw->minor_ver_wanted = 5;
+	} else if (IS_BROXTON(dev)) {
+		fw_path = I915_BXT_HUC_UCODE;
+		huc_fw->major_ver_wanted = 1;
+		huc_fw->minor_ver_wanted = 0;
 	}
 
 	if (fw_path == NULL)
-- 
1.9.1

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

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

* Re: [PATCH 6/6] drm/i915/huc: Add BXT HuC Loading Support
  2016-06-21 18:11 ` [PATCH 6/6] drm/i915/huc: Add BXT HuC Loading Support Peter Antoine
@ 2016-06-21 18:26   ` Vivi, Rodrigo
  2016-06-21 21:28     ` Antoine, Peter
  2016-06-28 15:20   ` Dave Gordon
  1 sibling, 1 reply; 40+ messages in thread
From: Vivi, Rodrigo @ 2016-06-21 18:26 UTC (permalink / raw)
  To: intel-gfx, Antoine, Peter; +Cc: Kelley, Sean V, Li, Lawrence T

Hi Peter,

On Tue, 2016-06-21 at 19:11 +0100, Peter Antoine wrote:
> This patch adds the HuC Loading for the BXT.
> Version 1.x of the HuC firmware.
> 
> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_gem.c         | 13 +++----------
>  drivers/gpu/drm/i915/intel_guc_loader.c | 29 +++++++++++++++++----
> --------
>  drivers/gpu/drm/i915/intel_huc_loader.c |  7 +++++++
>  3 files changed, 27 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_gem.c
> b/drivers/gpu/drm/i915/i915_gem.c
> index 549dd3f..6abd5e5 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -5143,16 +5143,9 @@ i915_gem_init_hw(struct drm_device *dev)
>  	intel_mocs_init_l3cc_table(dev);
>  
>  	/* We can't enable contexts until all firmware is loaded */
> -	if (HAS_GUC(dev)) {
> -		/* init WOPCM */
> -		I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev));
> -		I915_WRITE(DMA_GUC_WOPCM_OFFSET,
> GUC_WOPCM_OFFSET_VALUE);
> -
> -		intel_huc_load(dev);
> -		ret = intel_guc_setup(dev);
> -		if (ret)
> -			goto out;
> -	}
> +	ret = intel_guc_setup(dev);
> +	if (ret)
> +		goto out;
>  
>  	/*
>  	 * Increment the next seqno by 0x100 so we have a visible
> break
> diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c
> b/drivers/gpu/drm/i915/intel_guc_loader.c
> index e876a23f..289b5b6 100644
> --- a/drivers/gpu/drm/i915/intel_guc_loader.c
> +++ b/drivers/gpu/drm/i915/intel_guc_loader.c
> @@ -82,6 +82,17 @@ const char *intel_uc_fw_status_repr(enum
> intel_uc_fw_status status)
>  	}
>  };
>  
> +u32 guc_wopcm_size(struct drm_device *dev)
> +{
> +	u32 wopcm_size = GUC_WOPCM_TOP;
> +
> +	/* On BXT, the top of WOPCM is reserved for RC6 context */
> +	if (IS_BROXTON(dev))
> +		wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED;
> +
> +	return wopcm_size;
> +}
> +
>  static void direct_interrupts_to_host(struct drm_i915_private
> *dev_priv)
>  {
>  	struct intel_engine_cs *engine;
> @@ -296,17 +307,6 @@ static int guc_ucode_xfer_dma(struct
> drm_i915_private *dev_priv)
>  	return ret;
>  }
>  
> -u32 guc_wopcm_size(struct drm_device *dev)
> -{
> -	u32 wopcm_size = GUC_WOPCM_TOP;
> -
> -	/* On BXT, the top of WOPCM is reserved for RC6 context */
> -	if (IS_BROXTON(dev))
> -		wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED;
> -
> -	return wopcm_size;
> -}
> -
>  /*
>   * Load the GuC firmware blob into the MinuteIA.
>   */
> @@ -333,6 +333,10 @@ static int guc_ucode_xfer(struct
> drm_i915_private *dev_priv)
>  
>  	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
>  
> +	/* init WOPCM */
> +	I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev));
> +	I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE);
> +
>  	/* Enable MIA caching. GuC clock gating is disabled. */
>  	I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE);
>  
> @@ -483,6 +487,7 @@ int intel_guc_setup(struct drm_device *dev)
>  			goto fail;
>  		}
>  
> +		intel_huc_load(dev);
>  		err = guc_ucode_xfer(dev_priv);
>  		if (!err)
>  			break;
> @@ -638,7 +643,7 @@ void intel_uc_fw_fetch(struct drm_device *dev,
> struct intel_uc_fw *uc_fw)
>  		size = uc_fw->header_size + uc_fw->ucode_size;
>  
>  		/* Top 32k of WOPCM is reserved (8K stack + 24k RC6
> context). */
> -		if (size > guc_wopcm_size(dev->dev_private)) {
> +		if (size > guc_wopcm_size(dev)) {
>  			DRM_ERROR("Firmware is too large to fit in
> WOPCM\n");
>  			goto fail;
>  		}
> diff --git a/drivers/gpu/drm/i915/intel_huc_loader.c
> b/drivers/gpu/drm/i915/intel_huc_loader.c
> index 7205e9e..7a43d4e 100644
> --- a/drivers/gpu/drm/i915/intel_huc_loader.c
> +++ b/drivers/gpu/drm/i915/intel_huc_loader.c
> @@ -49,6 +49,9 @@
>  #define I915_SKL_HUC_UCODE "i915/skl_huc_ver1.bin"
>  MODULE_FIRMWARE(I915_SKL_HUC_UCODE);

We need to step away from symbolic links for all firmwares.

Specially with HuC that HuC team had never agreed with major_minor
where major increases if any change in API or ABI.

And also they have the major_minor_build number in the release like

intel/firmware/skl_huc_ver01_07_1398

So I believe we need to fix this first and then add the BXT in the
proper way without using any symbolic link.

>  
> +#define I915_BXT_HUC_UCODE "i915/bxt_huc_ver1.bin"
> +MODULE_FIRMWARE(I915_BXT_HUC_UCODE);

Also, where is this version? I believe I missed this release while I
was out. Could you please share with me?

Is it production and with all permissions to release at 01.org and
propagate to linux-firmware.git?

Thanks,
Rodrigo.

> +
>  /**
>   * intel_huc_load_ucode() - DMA's the firmware
>   * @dev: the drm device
> @@ -157,6 +160,10 @@ void intel_huc_init(struct drm_device *dev)
>  		fw_path = I915_SKL_HUC_UCODE;
>  		huc_fw->major_ver_wanted = 1;
>  		huc_fw->minor_ver_wanted = 5;
> +	} else if (IS_BROXTON(dev)) {
> +		fw_path = I915_BXT_HUC_UCODE;
> +		huc_fw->major_ver_wanted = 1;
> +		huc_fw->minor_ver_wanted = 0;
>  	}
>  
>  	if (fw_path == NULL)
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 6/6] drm/i915/huc: Add BXT HuC Loading Support
  2016-06-21 18:26   ` Vivi, Rodrigo
@ 2016-06-21 21:28     ` Antoine, Peter
  0 siblings, 0 replies; 40+ messages in thread
From: Antoine, Peter @ 2016-06-21 21:28 UTC (permalink / raw)
  To: Vivi, Rodrigo, intel-gfx; +Cc: Kelley, Sean V, Li, Lawrence T

Hi Rodrigo,

I tested with an old version that has been knocking about for ages. It is shipped on Android so I think it is production. I may be wrong there as Tom was handling the firmware release process and is not available to talk to.

I am being "ACT'ed"/"ACT'ioned"*, so am not sure when I'll stop having access to the firmware/hardware, so added the BXT patch so it was available to others, it has been tested on multiple platforms/kernels including being tested on media enabled platforms.

I have seen the skl huc version with the full version and build. I am not sure what the release version of the BXT HuC will be. It might be worth simply dropping the BXT patch (after review) so that when the correct firmware is released we have a tested/reviewed version of the code to base the changes on.

I think Chris Harris, is trying to organize the firmware releases/packaging, but the release process and structure is still up in the air a little. It might be worth contacting him directly to find out the  correct version and if there is a releasable version for BXT.

Peter

*still under review (the position and not just the correct verb to use :) ).

-----Original Message-----
From: Vivi, Rodrigo 
Sent: Tuesday, June 21, 2016 7:26 PM
To: intel-gfx@lists.freedesktop.org; Antoine, Peter <peter.antoine@intel.com>
Cc: Prigent, Christophe <christophe.prigent@intel.com>; Kelley, Sean V <sean.v.kelley@intel.com>; Gordon, David S <david.s.gordon@intel.com>; Li, Lawrence T <lawrence.t.li@intel.com>
Subject: Re: [PATCH 6/6] drm/i915/huc: Add BXT HuC Loading Support

Hi Peter,

On Tue, 2016-06-21 at 19:11 +0100, Peter Antoine wrote:
> This patch adds the HuC Loading for the BXT.
> Version 1.x of the HuC firmware.
> 
> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_gem.c         | 13 +++----------
>  drivers/gpu/drm/i915/intel_guc_loader.c | 29 +++++++++++++++++----
> --------
>  drivers/gpu/drm/i915/intel_huc_loader.c |  7 +++++++
>  3 files changed, 27 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_gem.c 
> b/drivers/gpu/drm/i915/i915_gem.c index 549dd3f..6abd5e5 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -5143,16 +5143,9 @@ i915_gem_init_hw(struct drm_device *dev)
>  	intel_mocs_init_l3cc_table(dev);
>  
>  	/* We can't enable contexts until all firmware is loaded */
> -	if (HAS_GUC(dev)) {
> -		/* init WOPCM */
> -		I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev));
> -		I915_WRITE(DMA_GUC_WOPCM_OFFSET,
> GUC_WOPCM_OFFSET_VALUE);
> -
> -		intel_huc_load(dev);
> -		ret = intel_guc_setup(dev);
> -		if (ret)
> -			goto out;
> -	}
> +	ret = intel_guc_setup(dev);
> +	if (ret)
> +		goto out;
>  
>  	/*
>  	 * Increment the next seqno by 0x100 so we have a visible break diff 
> --git a/drivers/gpu/drm/i915/intel_guc_loader.c
> b/drivers/gpu/drm/i915/intel_guc_loader.c
> index e876a23f..289b5b6 100644
> --- a/drivers/gpu/drm/i915/intel_guc_loader.c
> +++ b/drivers/gpu/drm/i915/intel_guc_loader.c
> @@ -82,6 +82,17 @@ const char *intel_uc_fw_status_repr(enum 
> intel_uc_fw_status status)
>  	}
>  };
>  
> +u32 guc_wopcm_size(struct drm_device *dev) {
> +	u32 wopcm_size = GUC_WOPCM_TOP;
> +
> +	/* On BXT, the top of WOPCM is reserved for RC6 context */
> +	if (IS_BROXTON(dev))
> +		wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED;
> +
> +	return wopcm_size;
> +}
> +
>  static void direct_interrupts_to_host(struct drm_i915_private
> *dev_priv)
>  {
>  	struct intel_engine_cs *engine;
> @@ -296,17 +307,6 @@ static int guc_ucode_xfer_dma(struct 
> drm_i915_private *dev_priv)
>  	return ret;
>  }
>  
> -u32 guc_wopcm_size(struct drm_device *dev) -{
> -	u32 wopcm_size = GUC_WOPCM_TOP;
> -
> -	/* On BXT, the top of WOPCM is reserved for RC6 context */
> -	if (IS_BROXTON(dev))
> -		wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED;
> -
> -	return wopcm_size;
> -}
> -
>  /*
>   * Load the GuC firmware blob into the MinuteIA.
>   */
> @@ -333,6 +333,10 @@ static int guc_ucode_xfer(struct drm_i915_private 
> *dev_priv)
>  
>  	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
>  
> +	/* init WOPCM */
> +	I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev));
> +	I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE);
> +
>  	/* Enable MIA caching. GuC clock gating is disabled. */
>  	I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE);
>  
> @@ -483,6 +487,7 @@ int intel_guc_setup(struct drm_device *dev)
>  			goto fail;
>  		}
>  
> +		intel_huc_load(dev);
>  		err = guc_ucode_xfer(dev_priv);
>  		if (!err)
>  			break;
> @@ -638,7 +643,7 @@ void intel_uc_fw_fetch(struct drm_device *dev, 
> struct intel_uc_fw *uc_fw)
>  		size = uc_fw->header_size + uc_fw->ucode_size;
>  
>  		/* Top 32k of WOPCM is reserved (8K stack + 24k RC6 context). */
> -		if (size > guc_wopcm_size(dev->dev_private)) {
> +		if (size > guc_wopcm_size(dev)) {
>  			DRM_ERROR("Firmware is too large to fit in WOPCM\n");
>  			goto fail;
>  		}
> diff --git a/drivers/gpu/drm/i915/intel_huc_loader.c
> b/drivers/gpu/drm/i915/intel_huc_loader.c
> index 7205e9e..7a43d4e 100644
> --- a/drivers/gpu/drm/i915/intel_huc_loader.c
> +++ b/drivers/gpu/drm/i915/intel_huc_loader.c
> @@ -49,6 +49,9 @@
>  #define I915_SKL_HUC_UCODE "i915/skl_huc_ver1.bin"
>  MODULE_FIRMWARE(I915_SKL_HUC_UCODE);

We need to step away from symbolic links for all firmwares.

Specially with HuC that HuC team had never agreed with major_minor where major increases if any change in API or ABI.

And also they have the major_minor_build number in the release like

intel/firmware/skl_huc_ver01_07_1398

So I believe we need to fix this first and then add the BXT in the proper way without using any symbolic link.

>  
> +#define I915_BXT_HUC_UCODE "i915/bxt_huc_ver1.bin"
> +MODULE_FIRMWARE(I915_BXT_HUC_UCODE);

Also, where is this version? I believe I missed this release while I was out. Could you please share with me?

Is it production and with all permissions to release at 01.org and propagate to linux-firmware.git?

Thanks,
Rodrigo.

> +
>  /**
>   * intel_huc_load_ucode() - DMA's the firmware
>   * @dev: the drm device
> @@ -157,6 +160,10 @@ void intel_huc_init(struct drm_device *dev)
>  		fw_path = I915_SKL_HUC_UCODE;
>  		huc_fw->major_ver_wanted = 1;
>  		huc_fw->minor_ver_wanted = 5;
> +	} else if (IS_BROXTON(dev)) {
> +		fw_path = I915_BXT_HUC_UCODE;
> +		huc_fw->major_ver_wanted = 1;
> +		huc_fw->minor_ver_wanted = 0;
>  	}
>  
>  	if (fw_path == NULL)
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/6] drm/i915/huc: Add HuC fw loading support
  2016-06-21 18:11 ` [PATCH 3/6] drm/i915/huc: Add HuC fw loading support Peter Antoine
@ 2016-06-22  8:31   ` Daniel Vetter
  2016-06-23 10:14     ` Dave Gordon
  2016-06-28 14:54   ` Dave Gordon
  1 sibling, 1 reply; 40+ messages in thread
From: Daniel Vetter @ 2016-06-22  8:31 UTC (permalink / raw)
  To: Peter Antoine; +Cc: sean.v.kelley, intel-gfx, lawrence.t.li, rodrigo.vivi

On Tue, Jun 21, 2016 at 07:11:22PM +0100, Peter Antoine wrote:
> From: Alex Dai <yu.dai@intel.com>
> 
> The HuC loading process is similar to GuC. The intel_uc_fw_fetch()
> is used for both cases.
> 
> HuC loading needs to be before GuC loading. The WOPCM setting must
> be done early before loading any of them.
> 
> Signed-off-by: Alex Dai <yu.dai@intel.com>
> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
> ---
>  drivers/gpu/drm/i915/Makefile           |   1 +
>  drivers/gpu/drm/i915/i915_dma.c         |   3 +
>  drivers/gpu/drm/i915/i915_drv.h         |   3 +
>  drivers/gpu/drm/i915/i915_gem.c         |  13 +-
>  drivers/gpu/drm/i915/i915_guc_reg.h     |   3 +
>  drivers/gpu/drm/i915/intel_guc.h        |   1 +
>  drivers/gpu/drm/i915/intel_guc_loader.c |  11 +-
>  drivers/gpu/drm/i915/intel_huc.h        |  44 ++++++
>  drivers/gpu/drm/i915/intel_huc_loader.c | 262 ++++++++++++++++++++++++++++++++
>  9 files changed, 331 insertions(+), 10 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/intel_huc.h
>  create mode 100644 drivers/gpu/drm/i915/intel_huc_loader.c
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 276abf1..7384db0 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -44,6 +44,7 @@ i915-y += i915_cmd_parser.o \
>  
>  # general-purpose microcontroller (GuC) support
>  i915-y += intel_guc_loader.o \
> +	  intel_huc_loader.o \
>  	  i915_guc_submission.o
>  
>  # autogenerated null render state
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index e28c0dd..a449a59 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -507,6 +507,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
>  	 * working irqs for e.g. gmbus and dp aux transfers. */
>  	intel_modeset_init(dev);
>  
> +	intel_huc_init(dev);
>  	intel_guc_init(dev);
>  
>  	ret = i915_gem_init(dev);
> @@ -532,6 +533,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
>  cleanup_gem:
>  	i915_gem_fini(dev);
>  cleanup_irq:
> +	intel_huc_fini(dev);
>  	intel_guc_fini(dev);
>  	drm_irq_uninstall(dev);
>  	intel_teardown_gmbus(dev);
> @@ -1563,6 +1565,7 @@ int i915_driver_unload(struct drm_device *dev)
>  	/* Flush any outstanding unpin_work. */
>  	flush_workqueue(dev_priv->wq);
>  
> +	intel_huc_fini(dev);
>  	intel_guc_fini(dev);
>  	i915_gem_fini(dev);
>  	intel_fbc_cleanup_cfb(dev_priv);
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 7c81757..8b88227 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -54,6 +54,7 @@
>  #include "intel_bios.h"
>  #include "intel_dpll_mgr.h"
>  #include "intel_guc.h"
> +#include "intel_huc.h"
>  #include "intel_lrc.h"
>  #include "intel_ringbuffer.h"
>  
> @@ -1749,6 +1750,7 @@ struct drm_i915_private {
>  
>  	struct intel_gvt gvt;
>  
> +	struct intel_huc huc;
>  	struct intel_guc guc;
>  
>  	struct intel_csr csr;
> @@ -2841,6 +2843,7 @@ struct drm_i915_cmd_table {
>  #define HAS_GUC(dev)		(IS_GEN9(dev) && !IS_KABYLAKE(dev))
>  #define HAS_GUC_UCODE(dev)	(HAS_GUC(dev))
>  #define HAS_GUC_SCHED(dev)	(HAS_GUC(dev))
> +#define HAS_HUC_UCODE(dev)	(HAS_GUC(dev))
>  
>  #define HAS_RESOURCE_STREAMER(dev) (IS_HASWELL(dev) || \
>  				    INTEL_INFO(dev)->gen >= 8)
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 6abd5e5..549dd3f 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -5143,9 +5143,16 @@ i915_gem_init_hw(struct drm_device *dev)
>  	intel_mocs_init_l3cc_table(dev);
>  
>  	/* We can't enable contexts until all firmware is loaded */
> -	ret = intel_guc_setup(dev);
> -	if (ret)
> -		goto out;
> +	if (HAS_GUC(dev)) {
> +		/* init WOPCM */
> +		I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev));
> +		I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE);
> +
> +		intel_huc_load(dev);
> +		ret = intel_guc_setup(dev);
> +		if (ret)
> +			goto out;
> +	}
>  
>  	/*
>  	 * Increment the next seqno by 0x100 so we have a visible break
> diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h b/drivers/gpu/drm/i915/i915_guc_reg.h
> index cf5a65b..51533f1 100644
> --- a/drivers/gpu/drm/i915/i915_guc_reg.h
> +++ b/drivers/gpu/drm/i915/i915_guc_reg.h
> @@ -61,9 +61,12 @@
>  #define   DMA_ADDRESS_SPACE_GTT		  (8 << 16)
>  #define DMA_COPY_SIZE			_MMIO(0xc310)
>  #define DMA_CTRL			_MMIO(0xc314)
> +#define   HUC_UKERNEL			  (1<<9)
>  #define   UOS_MOVE			  (1<<4)
>  #define   START_DMA			  (1<<0)
>  #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)
>  
> diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
> index 0b4ed88..c4b92f3 100644
> --- a/drivers/gpu/drm/i915/intel_guc.h
> +++ b/drivers/gpu/drm/i915/intel_guc.h
> @@ -160,6 +160,7 @@ extern const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status);
>  extern int intel_guc_suspend(struct drm_device *dev);
>  extern int intel_guc_resume(struct drm_device *dev);
>  void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw);
> +u32 guc_wopcm_size(struct drm_device *dev);
>  
>  /* i915_guc_submission.c */
>  int i915_guc_submission_init(struct drm_i915_private *dev_priv);
> diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
> index 70575bd..c4a210d 100644
> --- a/drivers/gpu/drm/i915/intel_guc_loader.c
> +++ b/drivers/gpu/drm/i915/intel_guc_loader.c
> @@ -270,7 +270,8 @@ static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv)
>  	I915_WRITE(DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM);
>  
>  	/* Finally start the DMA */
> -	I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(UOS_MOVE | START_DMA));
> +	I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(UOS_MOVE | START_DMA) |
> +			_MASKED_BIT_DISABLE(HUC_UKERNEL));
>  
>  	/*
>  	 * Wait for the DMA to complete & the GuC to start up.
> @@ -295,12 +296,12 @@ static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv)
>  	return ret;
>  }
>  
> -static u32 guc_wopcm_size(struct drm_i915_private *dev_priv)
> +u32 guc_wopcm_size(struct drm_device *dev)
>  {
>  	u32 wopcm_size = GUC_WOPCM_TOP;
>  
>  	/* On BXT, the top of WOPCM is reserved for RC6 context */
> -	if (IS_BROXTON(dev_priv))
> +	if (IS_BROXTON(dev))
>  		wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED;
>  
>  	return wopcm_size;
> @@ -332,10 +333,6 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
>  
>  	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
>  
> -	/* init WOPCM */
> -	I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev_priv));
> -	I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE);
> -
>  	/* Enable MIA caching. GuC clock gating is disabled. */
>  	I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE);
>  
> diff --git a/drivers/gpu/drm/i915/intel_huc.h b/drivers/gpu/drm/i915/intel_huc.h
> new file mode 100644
> index 0000000..946caa7
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_huc.h
> @@ -0,0 +1,44 @@
> +/*
> + * Copyright © 2014 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_HUC_H_
> +#define _INTEL_HUC_H_
> +
> +#include "intel_guc.h"
> +
> +#define HUC_STATUS2		_MMIO(0xD3B0)
> +#define   HUC_FW_VERIFIED	(1<<7)
> +
> +struct intel_huc {
> +	/* Generic uC firmware management */
> +	struct intel_uc_fw huc_fw;
> +
> +	/* HuC-specific additions */
> +};
> +
> +extern void intel_huc_init(struct drm_device *dev);
> +extern int intel_huc_load(struct drm_device *dev);
> +extern void intel_huc_auth(struct drm_device *dev);
> +extern void intel_huc_fini(struct drm_device *dev);
> +
> +#endif
> diff --git a/drivers/gpu/drm/i915/intel_huc_loader.c b/drivers/gpu/drm/i915/intel_huc_loader.c
> new file mode 100644
> index 0000000..472fabe
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_huc_loader.c
> @@ -0,0 +1,262 @@
> +/*
> + * Copyright © 2014 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 <linux/firmware.h>
> +#include "i915_drv.h"
> +#include "intel_huc.h"
> +
> +/**
> + * DOC: HuC Firmware
> + *
> + * Motivation:
> + * GEN9 introduces a new dedicated firmware for usage in media HEVC (High
> + * Efficiency Video Coding) operations. Userspace can use the firmware
> + * capabilities by adding HuC specific commands to batch buffers.
> + *
> + * Implementation:
> + * On supported platforms, i915's job is to load the firmware stored on the
> + * file system and assist with authentication. It is up to userspace to
> + * detect the presence of HuC support on a platform, on their own.
> + * For debugging, i915 provides a debugfs file, i915_huc_load_status_info
> + * which displays the firmware load status.
> + *
> + * The unified uC firmware loader is used. Firmware binary is fetched by the
> + * loader asynchronously from the driver init process. However, the actual
> + * loading to HW is deferred until GEM initialization is done. Be note that HuC
> + * firmware loading must be done before GuC loading.
> + */
> +
> +#define I915_SKL_HUC_UCODE "i915/skl_huc_ver1.bin"
> +MODULE_FIRMWARE(I915_SKL_HUC_UCODE);
> +
> +/**
> + * intel_huc_load_ucode() - DMA's the firmware
> + * @dev: the drm device
> + *
> + * This function takes the gem object containing the firmware, sets up the DMA
> + * engine MMIO, triggers the DMA operation and waits for it to finish.
> + *
> + * Transfer the firmware image to RAM for execution by the microcontroller.
> + *
> + * Return: 0 on success, non-zero on failure
> + */
> +
> +static int huc_ucode_xfer(struct drm_i915_private *dev_priv)
> +{
> +	struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
> +	unsigned long offset = 0;
> +	u32 size;
> +	int ret;
> +
> +	ret = i915_gem_object_set_to_gtt_domain(huc_fw->uc_fw_obj, false);
> +	if (ret) {
> +		DRM_DEBUG_DRIVER("set-domain failed %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = i915_gem_obj_ggtt_pin(huc_fw->uc_fw_obj, 0, 0);
> +	if (ret) {
> +		DRM_DEBUG_DRIVER("pin failed %d\n", ret);
> +		return ret;
> +	}
> +
> +	/* Invalidate GuC TLB to let GuC take the latest updates to GTT. */
> +	I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);
> +
> +	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
> +	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
> +
> +	/* Set the source address for the uCode */
> +	offset = i915_gem_obj_ggtt_offset(huc_fw->uc_fw_obj) +
> +			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);
> +
> +	/* Hardware doesn't look at destination address for HuC. Set it to 0,
> +	 * but still program the correct address space.
> +	 */
> +	I915_WRITE(DMA_ADDR_1_LOW, 0);
> +	I915_WRITE(DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM);
> +
> +	size = huc_fw->header_size + huc_fw->ucode_size;
> +	I915_WRITE(DMA_COPY_SIZE, size);
> +
> +	/* Start the DMA */
> +	I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(HUC_UKERNEL | START_DMA));
> +
> +	/* Wait for DMA to finish */
> +	ret = wait_for_atomic((I915_READ(DMA_CTRL) & START_DMA) == 0, 50);
> +
> +	DRM_DEBUG_DRIVER("HuC DMA transfer wait over with ret %d\n", ret);
> +
> +	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
> +
> +	/*
> +	 * We keep the object pages for reuse during resume. But we can unpin it
> +	 * now that DMA has completed, so it doesn't continue to take up space.
> +	 */
> +	i915_gem_object_ggtt_unpin(huc_fw->uc_fw_obj);
> +
> +	return ret;
> +}
> +
> +/**
> + * intel_huc_init() - initiate HuC firmware loading request
> + * @dev: the drm device
> + *
> + * Called early during driver load, but after GEM is initialised. The loading
> + * will continue only when driver explicitly specify firmware name and version.
> + * All other cases are considered as UC_FIRMWARE_NONE either because HW is not
> + * capable or driver yet support it. And there will be no error message for
> + * UC_FIRMWARE_NONE cases.
> + *
> + * The DMA-copying to HW is done later when intel_huc_ucode_load() is called.
> + */
> +void intel_huc_init(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_huc *huc = &dev_priv->huc;
> +	struct intel_uc_fw *huc_fw = &huc->huc_fw;
> +	const char *fw_path = NULL;
> +
> +	huc_fw->uc_dev = dev;
> +	huc_fw->uc_fw_path = NULL;
> +	huc_fw->fetch_status = UC_FIRMWARE_NONE;
> +	huc_fw->load_status = UC_FIRMWARE_NONE;
> +	huc_fw->fw_type = UC_FW_TYPE_HUC;
> +
> +	if (!HAS_HUC_UCODE(dev))
> +		return;
> +
> +	if (IS_SKYLAKE(dev)) {
> +		fw_path = I915_SKL_HUC_UCODE;
> +		huc_fw->major_ver_wanted = 1;
> +		huc_fw->minor_ver_wanted = 5;
> +	}
> +
> +	if (fw_path == NULL)
> +		return;
> +
> +	huc_fw->uc_fw_path = fw_path;
> +	huc_fw->fetch_status = UC_FIRMWARE_PENDING;
> +
> +	DRM_DEBUG_DRIVER("HuC firmware pending, path %s\n", fw_path);
> +
> +	intel_uc_fw_fetch(dev, huc_fw);
> +}
> +
> +/**
> + * intel_huc_load() - load HuC uCode to device
> + * @dev: the drm device
> + *
> + * Called from gem_init_hw() during driver loading and also after a GPU reset.
> + * Be note that HuC loading must be done before GuC loading.
> + *
> + * The firmware image should have already been fetched into memory by the
> + * earlier call to intel_huc_ucode_init(), so here we need only check that
> + * is succeeded, and then transfer the image to the h/w.
> + *
> + * Return:	non-zero code on error
> + */
> +int intel_huc_load(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
> +	int err;
> +
> +	if (huc_fw->fetch_status == UC_FIRMWARE_NONE)
> +		return 0;
> +
> +	DRM_DEBUG_DRIVER("%s fw status: fetch %s, load %s\n",
> +		huc_fw->uc_fw_path,
> +		intel_uc_fw_status_repr(huc_fw->fetch_status),
> +		intel_uc_fw_status_repr(huc_fw->load_status));
> +
> +	if (huc_fw->fetch_status == UC_FIRMWARE_SUCCESS &&
> +	    huc_fw->load_status == UC_FIRMWARE_FAIL)
> +		return -ENOEXEC;
> +
> +	huc_fw->load_status = UC_FIRMWARE_PENDING;
> +
> +	switch (huc_fw->fetch_status) {
> +	case UC_FIRMWARE_FAIL:
> +		/* something went wrong :( */
> +		err = -EIO;
> +		goto fail;
> +
> +	case UC_FIRMWARE_NONE:
> +	case UC_FIRMWARE_PENDING:
> +	default:
> +		/* "can't happen" */
> +		WARN_ONCE(1, "HuC fw %s invalid fetch_status %s [%d]\n",
> +			huc_fw->uc_fw_path,
> +			intel_uc_fw_status_repr(huc_fw->fetch_status),
> +			huc_fw->fetch_status);
> +		err = -ENXIO;
> +		goto fail;
> +
> +	case UC_FIRMWARE_SUCCESS:
> +		break;
> +	}

Can we please remove all that indirection through fetch_status? This
really shouldn't be that complicated that you need pages of code to
generate/decode status. I know it's copypaste from guc, but I didn't like
it there, and I definitely don't want 2 copies of this. Please simplify
both places.

The correct fix is to give the uc_fw_fetch function an error code, and rip
out all that cargo culted status handling. All of it.
-Daniel

> +
> +	err = huc_ucode_xfer(dev_priv);
> +	if (err)
> +		goto fail;
> +
> +	huc_fw->load_status = UC_FIRMWARE_SUCCESS;
> +
> +	DRM_DEBUG_DRIVER("%s fw status: fetch %s, load %s\n",
> +		huc_fw->uc_fw_path,
> +		intel_uc_fw_status_repr(huc_fw->fetch_status),
> +		intel_uc_fw_status_repr(huc_fw->load_status));
> +
> +	return 0;
> +
> +fail:
> +	if (huc_fw->load_status == UC_FIRMWARE_PENDING)
> +		huc_fw->load_status = UC_FIRMWARE_FAIL;
> +
> +	DRM_ERROR("Failed to complete HuC uCode load with ret %d\n", err);
> +
> +	return err;
> +}
> +
> +/**
> + * intel_huc_fini() - clean up resources allocated for HuC
> + * @dev: the drm device
> + *
> + * Cleans up by releasing the huc firmware GEM obj.
> + */
> +void intel_huc_fini(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
> +
> +	mutex_lock(&dev->struct_mutex);
> +	if (huc_fw->uc_fw_obj)
> +		drm_gem_object_unreference(&huc_fw->uc_fw_obj->base);
> +	huc_fw->uc_fw_obj = NULL;
> +	mutex_unlock(&dev->struct_mutex);
> +
> +	huc_fw->fetch_status = UC_FIRMWARE_NONE;
> +}
> -- 
> 1.9.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* ✗ Ro.CI.BAT: warning for HuC Loading Patches
  2016-06-21 18:11 [PATCH 0/6] HuC Loading Patches Peter Antoine
                   ` (5 preceding siblings ...)
  2016-06-21 18:11 ` [PATCH 6/6] drm/i915/huc: Add BXT HuC Loading Support Peter Antoine
@ 2016-06-22 13:02 ` Patchwork
  6 siblings, 0 replies; 40+ messages in thread
From: Patchwork @ 2016-06-22 13:02 UTC (permalink / raw)
  To: Peter Antoine; +Cc: intel-gfx

== Series Details ==

Series: HuC Loading Patches
URL   : https://patchwork.freedesktop.org/series/9011/
State : warning

== Summary ==

Series 9011v1 HuC Loading Patches
http://patchwork.freedesktop.org/api/1.0/series/9011/revisions/1/mbox

Test drv_hangman:
        Subgroup error-state-basic:
                pass       -> DMESG-WARN (fi-skl-i5-6260u)
                pass       -> DMESG-WARN (fi-skl-i7-6700k)
Test drv_module_reload_basic:
                pass       -> DMESG-WARN (fi-skl-i5-6260u)
                pass       -> DMESG-WARN (fi-skl-i7-6700k)
Test gem_exec_suspend:
        Subgroup basic-s3:
                pass       -> DMESG-WARN (fi-skl-i5-6260u)
                pass       -> DMESG-WARN (fi-skl-i7-6700k)
Test gem_ringfill:
        Subgroup basic-default-hang:
                pass       -> DMESG-WARN (fi-skl-i5-6260u)
                pass       -> DMESG-WARN (fi-skl-i7-6700k)
Test kms_pipe_crc_basic:
        Subgroup hang-read-crc-pipe-a:
                pass       -> DMESG-WARN (fi-skl-i5-6260u)
                pass       -> DMESG-WARN (fi-skl-i7-6700k)
        Subgroup hang-read-crc-pipe-b:
                pass       -> DMESG-WARN (fi-skl-i5-6260u)
                pass       -> DMESG-WARN (fi-skl-i7-6700k)
        Subgroup hang-read-crc-pipe-c:
                pass       -> DMESG-WARN (fi-skl-i5-6260u)
                pass       -> DMESG-WARN (fi-skl-i7-6700k)
        Subgroup read-crc-pipe-b:
                skip       -> PASS       (fi-skl-i5-6260u)
        Subgroup suspend-read-crc-pipe-a:
                pass       -> DMESG-WARN (fi-skl-i5-6260u)
                pass       -> DMESG-WARN (fi-skl-i7-6700k)
        Subgroup suspend-read-crc-pipe-b:
                dmesg-warn -> SKIP       (ro-bdw-i7-5557U)
                dmesg-warn -> SKIP       (ro-bdw-i5-5250u)
                pass       -> DMESG-WARN (fi-skl-i5-6260u)
                pass       -> DMESG-WARN (fi-skl-i7-6700k)
        Subgroup suspend-read-crc-pipe-c:
                skip       -> DMESG-WARN (ro-bdw-i5-5250u)
                pass       -> SKIP       (fi-skl-i5-6260u)
                pass       -> DMESG-WARN (fi-skl-i7-6700k)

fi-hsw-i7-4770k  total:226  pass:194  dwarn:0   dfail:0   fail:1   skip:31 
fi-skl-i5-6260u  total:226  pass:192  dwarn:9   dfail:0   fail:1   skip:24 
fi-skl-i7-6700k  total:226  pass:178  dwarn:10  dfail:0   fail:1   skip:37 
ro-bdw-i5-5250u  total:226  pass:197  dwarn:2   dfail:0   fail:1   skip:26 
ro-bdw-i7-5557U  total:226  pass:198  dwarn:0   dfail:0   fail:1   skip:27 
ro-bdw-i7-5600u  total:226  pass:185  dwarn:0   dfail:0   fail:1   skip:40 
ro-bsw-n3050     total:226  pass:172  dwarn:0   dfail:0   fail:3   skip:51 
ro-byt-n2820     total:226  pass:173  dwarn:0   dfail:0   fail:4   skip:49 
ro-hsw-i3-4010u  total:226  pass:190  dwarn:0   dfail:0   fail:1   skip:35 
ro-hsw-i7-4770r  total:226  pass:190  dwarn:0   dfail:0   fail:1   skip:35 
ro-ilk-i7-620lm  total:226  pass:150  dwarn:0   dfail:0   fail:2   skip:74 
ro-ilk1-i5-650   total:221  pass:150  dwarn:0   dfail:0   fail:2   skip:69 
ro-ivb-i7-3770   total:226  pass:181  dwarn:0   dfail:0   fail:1   skip:44 
ro-ivb2-i7-3770  total:226  pass:185  dwarn:0   dfail:0   fail:1   skip:40 
ro-skl3-i5-6260u total:226  pass:201  dwarn:1   dfail:0   fail:1   skip:23 
ro-snb-i7-2620M  total:226  pass:174  dwarn:0   dfail:0   fail:2   skip:50 

Results at /archive/results/CI_IGT_test/RO_Patchwork_1266/

f1f5a05 drm-intel-nightly: 2016y-06m-22d-10h-45m-32s UTC integration manifest
0d4242a drm/i915/huc: Add BXT HuC Loading Support
631e5fe drm/i915/huc: Support HuC authentication
34ba604 drm/i915/huc: Add debugfs for HuC loading status check
fff271c drm/i915/huc: Add HuC fw loading support
6f2a5b7 drm/i915/huc: Unified css_header struct for GuC and HuC
6e9ab54 drm/i915/guc: Make the GuC fw loading helper functions general

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

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

* Re: [PATCH 4/6] drm/i915/huc: Add debugfs for HuC loading status check
  2016-06-21 18:11 ` [PATCH 4/6] drm/i915/huc: Add debugfs for HuC loading status check Peter Antoine
@ 2016-06-23  8:47   ` Xiang, Haihao
  2016-06-23  9:51     ` Peter Antoine
  2016-06-23 10:01     ` Peter Antoine
  2016-06-28 14:57   ` Dave Gordon
  1 sibling, 2 replies; 40+ messages in thread
From: Xiang, Haihao @ 2016-06-23  8:47 UTC (permalink / raw)
  To: intel-gfx, Antoine, Peter; +Cc: Kelley, Sean V, Li, Lawrence T, Vivi, Rodrigo


Hi Peter,

Besides debugfs, could you add a IOCTL to check HuC loading status?
Userspace media driver needs to advertise the features based on HuC to
user.

Thanks
Haihao


> From: Alex Dai <yu.dai@intel.com>
> 
> Add debugfs entry for HuC loading status check.
> 
> Signed-off-by: Alex Dai <yu.dai@intel.com>
> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c | 32
> ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
> b/drivers/gpu/drm/i915/i915_debugfs.c
> index 69964c2..f5976f8 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -2479,6 +2479,37 @@ static int i915_llc(struct seq_file *m, void
> *data)
>  	return 0;
>  }
>  
> +static int i915_huc_load_status_info(struct seq_file *m, void *data)
> +{
> +	struct drm_info_node *node = m->private;
> +	struct drm_i915_private *dev_priv = node->minor->dev-
> >dev_private;
> +	struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
> +
> +	if (!HAS_HUC_UCODE(dev_priv->dev))
> +		return 0;
> +
> +	seq_puts(m, "HuC firmware status:\n");
> +	seq_printf(m, "\tpath: %s\n", huc_fw->uc_fw_path);
> +	seq_printf(m, "\tfetch: %s\n",
> +		intel_uc_fw_status_repr(huc_fw->fetch_status));
> +	seq_printf(m, "\tload: %s\n",
> +		intel_uc_fw_status_repr(huc_fw->load_status));
> +	seq_printf(m, "\tversion wanted: %d.%d\n",
> +		huc_fw->major_ver_wanted, huc_fw->minor_ver_wanted);
> +	seq_printf(m, "\tversion found: %d.%d\n",
> +		huc_fw->major_ver_found, huc_fw->minor_ver_found);
> +	seq_printf(m, "\theader: offset is %d; size = %d\n",
> +		huc_fw->header_offset, huc_fw->header_size);
> +	seq_printf(m, "\tuCode: offset is %d; size = %d\n",
> +		huc_fw->ucode_offset, huc_fw->ucode_size);
> +	seq_printf(m, "\tRSA: offset is %d; size = %d\n",
> +		huc_fw->rsa_offset, huc_fw->rsa_size);
> +
> +	seq_printf(m, "\nHuC status 0x%08x:\n",
> I915_READ(HUC_STATUS2));
> +
> +	return 0;
> +}
> +
>  static int i915_guc_load_status_info(struct seq_file *m, void *data)
>  {
>  	struct drm_info_node *node = m->private;
> @@ -5432,6 +5463,7 @@ static const struct drm_info_list
> i915_debugfs_list[] = {
>  	{"i915_guc_info", i915_guc_info, 0},
>  	{"i915_guc_load_status", i915_guc_load_status_info, 0},
>  	{"i915_guc_log_dump", i915_guc_log_dump, 0},
> +	{"i915_huc_load_status", i915_huc_load_status_info, 0},
>  	{"i915_frequency_info", i915_frequency_info, 0},
>  	{"i915_hangcheck_info", i915_hangcheck_info, 0},
>  	{"i915_drpc_info", i915_drpc_info, 0},
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 4/6] drm/i915/huc: Add debugfs for HuC loading status check
  2016-06-23  8:47   ` Xiang, Haihao
@ 2016-06-23  9:51     ` Peter Antoine
  2016-06-23 10:01     ` Peter Antoine
  1 sibling, 0 replies; 40+ messages in thread
From: Peter Antoine @ 2016-06-23  9:51 UTC (permalink / raw)
  To: Xiang, Haihao; +Cc: Kelley, Sean V, intel-gfx, Li, Lawrence T, Vivi, Rodrigo

[-- Attachment #1: Type: TEXT/PLAIN, Size: 3088 bytes --]



On Thu, 23 Jun 2016, Xiang, Haihao wrote:

>
> Hi Peter,
>
> Besides debugfs, could you add a IOCTL to check HuC loading status?
> Userspace media driver needs to advertise the features based on HuC to
> user.
>
> Thanks
> Haihao
>
>
>> From: Alex Dai <yu.dai@intel.com>
>>
>> Add debugfs entry for HuC loading status check.
>>
>> Signed-off-by: Alex Dai <yu.dai@intel.com>
>> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
>> ---
>>  drivers/gpu/drm/i915/i915_debugfs.c | 32
>> ++++++++++++++++++++++++++++++++
>>  1 file changed, 32 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
>> b/drivers/gpu/drm/i915/i915_debugfs.c
>> index 69964c2..f5976f8 100644
>> --- a/drivers/gpu/drm/i915/i915_debugfs.c
>> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
>> @@ -2479,6 +2479,37 @@ static int i915_llc(struct seq_file *m, void
>> *data)
>>  	return 0;
>>  }
>>  
>> +static int i915_huc_load_status_info(struct seq_file *m, void *data)
>> +{
>> +	struct drm_info_node *node = m->private;
>> +	struct drm_i915_private *dev_priv = node->minor->dev-
>>> dev_private;
>> +	struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
>> +
>> +	if (!HAS_HUC_UCODE(dev_priv->dev))
>> +		return 0;
>> +
>> +	seq_puts(m, "HuC firmware status:\n");
>> +	seq_printf(m, "\tpath: %s\n", huc_fw->uc_fw_path);
>> +	seq_printf(m, "\tfetch: %s\n",
>> +		intel_uc_fw_status_repr(huc_fw->fetch_status));
>> +	seq_printf(m, "\tload: %s\n",
>> +		intel_uc_fw_status_repr(huc_fw->load_status));
>> +	seq_printf(m, "\tversion wanted: %d.%d\n",
>> +		huc_fw->major_ver_wanted, huc_fw->minor_ver_wanted);
>> +	seq_printf(m, "\tversion found: %d.%d\n",
>> +		huc_fw->major_ver_found, huc_fw->minor_ver_found);
>> +	seq_printf(m, "\theader: offset is %d; size = %d\n",
>> +		huc_fw->header_offset, huc_fw->header_size);
>> +	seq_printf(m, "\tuCode: offset is %d; size = %d\n",
>> +		huc_fw->ucode_offset, huc_fw->ucode_size);
>> +	seq_printf(m, "\tRSA: offset is %d; size = %d\n",
>> +		huc_fw->rsa_offset, huc_fw->rsa_size);
>> +
>> +	seq_printf(m, "\nHuC status 0x%08x:\n",
>> I915_READ(HUC_STATUS2));
>> +
>> +	return 0;
>> +}
>> +
>>  static int i915_guc_load_status_info(struct seq_file *m, void *data)
>>  {
>>  	struct drm_info_node *node = m->private;
>> @@ -5432,6 +5463,7 @@ static const struct drm_info_list
>> i915_debugfs_list[] = {
>>  	{"i915_guc_info", i915_guc_info, 0},
>>  	{"i915_guc_load_status", i915_guc_load_status_info, 0},
>>  	{"i915_guc_log_dump", i915_guc_log_dump, 0},
>> +	{"i915_huc_load_status", i915_huc_load_status_info, 0},
>>  	{"i915_frequency_info", i915_frequency_info, 0},
>>  	{"i915_hangcheck_info", i915_hangcheck_info, 0},
>>  	{"i915_drpc_info", i915_drpc_info, 0},

--
    Peter Antoine (Android Graphics Driver Software Engineer)
    ---------------------------------------------------------------------
    Intel Corporation (UK) Limited
    Registered No. 1134945 (England)
    Registered Office: Pipers Way, Swindon SN3 1RJ
    VAT No: 860 2173 47

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

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

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

* Re: [PATCH 4/6] drm/i915/huc: Add debugfs for HuC loading status check
  2016-06-23  8:47   ` Xiang, Haihao
  2016-06-23  9:51     ` Peter Antoine
@ 2016-06-23 10:01     ` Peter Antoine
  2016-06-23 10:48       ` Michel Thierry
  1 sibling, 1 reply; 40+ messages in thread
From: Peter Antoine @ 2016-06-23 10:01 UTC (permalink / raw)
  To: Xiang, Haihao, daniel.vetter
  Cc: Kelley, Sean V, intel-gfx, Li, Lawrence T, Vivi, Rodrigo

[-- Attachment #1: Type: TEXT/PLAIN, Size: 3226 bytes --]

Daniel,

Is this suggestion acceptable? I don't want to waste time and effort 
writing code that is not going to be accepted?

Peter.

On Thu, 23 Jun 2016, Xiang, Haihao wrote:

>
> Hi Peter,
>
> Besides debugfs, could you add a IOCTL to check HuC loading status?
> Userspace media driver needs to advertise the features based on HuC to
> user.
>
> Thanks
> Haihao
>
>
>> From: Alex Dai <yu.dai@intel.com>
>>
>> Add debugfs entry for HuC loading status check.
>>
>> Signed-off-by: Alex Dai <yu.dai@intel.com>
>> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
>> ---
>>  drivers/gpu/drm/i915/i915_debugfs.c | 32
>> ++++++++++++++++++++++++++++++++
>>  1 file changed, 32 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
>> b/drivers/gpu/drm/i915/i915_debugfs.c
>> index 69964c2..f5976f8 100644
>> --- a/drivers/gpu/drm/i915/i915_debugfs.c
>> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
>> @@ -2479,6 +2479,37 @@ static int i915_llc(struct seq_file *m, void
>> *data)
>>  	return 0;
>>  }
>>  
>> +static int i915_huc_load_status_info(struct seq_file *m, void *data)
>> +{
>> +	struct drm_info_node *node = m->private;
>> +	struct drm_i915_private *dev_priv = node->minor->dev-
>>> dev_private;
>> +	struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
>> +
>> +	if (!HAS_HUC_UCODE(dev_priv->dev))
>> +		return 0;
>> +
>> +	seq_puts(m, "HuC firmware status:\n");
>> +	seq_printf(m, "\tpath: %s\n", huc_fw->uc_fw_path);
>> +	seq_printf(m, "\tfetch: %s\n",
>> +		intel_uc_fw_status_repr(huc_fw->fetch_status));
>> +	seq_printf(m, "\tload: %s\n",
>> +		intel_uc_fw_status_repr(huc_fw->load_status));
>> +	seq_printf(m, "\tversion wanted: %d.%d\n",
>> +		huc_fw->major_ver_wanted, huc_fw->minor_ver_wanted);
>> +	seq_printf(m, "\tversion found: %d.%d\n",
>> +		huc_fw->major_ver_found, huc_fw->minor_ver_found);
>> +	seq_printf(m, "\theader: offset is %d; size = %d\n",
>> +		huc_fw->header_offset, huc_fw->header_size);
>> +	seq_printf(m, "\tuCode: offset is %d; size = %d\n",
>> +		huc_fw->ucode_offset, huc_fw->ucode_size);
>> +	seq_printf(m, "\tRSA: offset is %d; size = %d\n",
>> +		huc_fw->rsa_offset, huc_fw->rsa_size);
>> +
>> +	seq_printf(m, "\nHuC status 0x%08x:\n",
>> I915_READ(HUC_STATUS2));
>> +
>> +	return 0;
>> +}
>> +
>>  static int i915_guc_load_status_info(struct seq_file *m, void *data)
>>  {
>>  	struct drm_info_node *node = m->private;
>> @@ -5432,6 +5463,7 @@ static const struct drm_info_list
>> i915_debugfs_list[] = {
>>  	{"i915_guc_info", i915_guc_info, 0},
>>  	{"i915_guc_load_status", i915_guc_load_status_info, 0},
>>  	{"i915_guc_log_dump", i915_guc_log_dump, 0},
>> +	{"i915_huc_load_status", i915_huc_load_status_info, 0},
>>  	{"i915_frequency_info", i915_frequency_info, 0},
>>  	{"i915_hangcheck_info", i915_hangcheck_info, 0},
>>  	{"i915_drpc_info", i915_drpc_info, 0},

--
    Peter Antoine (Android Graphics Driver Software Engineer)
    ---------------------------------------------------------------------
    Intel Corporation (UK) Limited
    Registered No. 1134945 (England)
    Registered Office: Pipers Way, Swindon SN3 1RJ
    VAT No: 860 2173 47

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

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

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

* Re: [PATCH 3/6] drm/i915/huc: Add HuC fw loading support
  2016-06-22  8:31   ` Daniel Vetter
@ 2016-06-23 10:14     ` Dave Gordon
  2016-06-23 13:52       ` Peter Antoine
  0 siblings, 1 reply; 40+ messages in thread
From: Dave Gordon @ 2016-06-23 10:14 UTC (permalink / raw)
  To: Daniel Vetter, Peter Antoine
  Cc: sean.v.kelley, intel-gfx, lawrence.t.li, rodrigo.vivi

On 22/06/16 09:31, Daniel Vetter wrote:
> On Tue, Jun 21, 2016 at 07:11:22PM +0100, Peter Antoine wrote:
>> From: Alex Dai <yu.dai@intel.com>
>>
>> The HuC loading process is similar to GuC. The intel_uc_fw_fetch()
>> is used for both cases.
>>
>> HuC loading needs to be before GuC loading. The WOPCM setting must
>> be done early before loading any of them.
>>
>> Signed-off-by: Alex Dai <yu.dai@intel.com>
>> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
>> ---
>>   drivers/gpu/drm/i915/Makefile           |   1 +
>>   drivers/gpu/drm/i915/i915_dma.c         |   3 +
>>   drivers/gpu/drm/i915/i915_drv.h         |   3 +
>>   drivers/gpu/drm/i915/i915_gem.c         |  13 +-
>>   drivers/gpu/drm/i915/i915_guc_reg.h     |   3 +
>>   drivers/gpu/drm/i915/intel_guc.h        |   1 +
>>   drivers/gpu/drm/i915/intel_guc_loader.c |  11 +-
>>   drivers/gpu/drm/i915/intel_huc.h        |  44 ++++++
>>   drivers/gpu/drm/i915/intel_huc_loader.c | 262 ++++++++++++++++++++++++++++++++
>>   9 files changed, 331 insertions(+), 10 deletions(-)
>>   create mode 100644 drivers/gpu/drm/i915/intel_huc.h
>>   create mode 100644 drivers/gpu/drm/i915/intel_huc_loader.c
>>
>> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
>> index 276abf1..7384db0 100644
>> --- a/drivers/gpu/drm/i915/Makefile
>> +++ b/drivers/gpu/drm/i915/Makefile
>> @@ -44,6 +44,7 @@ i915-y += i915_cmd_parser.o \
>>
>>   # general-purpose microcontroller (GuC) support
>>   i915-y += intel_guc_loader.o \
>> +	  intel_huc_loader.o \
>>   	  i915_guc_submission.o
>>
>>   # autogenerated null render state
>> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
>> index e28c0dd..a449a59 100644
>> --- a/drivers/gpu/drm/i915/i915_dma.c
>> +++ b/drivers/gpu/drm/i915/i915_dma.c
>> @@ -507,6 +507,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
>>   	 * working irqs for e.g. gmbus and dp aux transfers. */
>>   	intel_modeset_init(dev);
>>
>> +	intel_huc_init(dev);
>>   	intel_guc_init(dev);
>>
>>   	ret = i915_gem_init(dev);
>> @@ -532,6 +533,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
>>   cleanup_gem:
>>   	i915_gem_fini(dev);
>>   cleanup_irq:
>> +	intel_huc_fini(dev);
>>   	intel_guc_fini(dev);
>>   	drm_irq_uninstall(dev);
>>   	intel_teardown_gmbus(dev);
>> @@ -1563,6 +1565,7 @@ int i915_driver_unload(struct drm_device *dev)
>>   	/* Flush any outstanding unpin_work. */
>>   	flush_workqueue(dev_priv->wq);
>>
>> +	intel_huc_fini(dev);
>>   	intel_guc_fini(dev);
>>   	i915_gem_fini(dev);
>>   	intel_fbc_cleanup_cfb(dev_priv);
>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>> index 7c81757..8b88227 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.h
>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>> @@ -54,6 +54,7 @@
>>   #include "intel_bios.h"
>>   #include "intel_dpll_mgr.h"
>>   #include "intel_guc.h"
>> +#include "intel_huc.h"
>>   #include "intel_lrc.h"
>>   #include "intel_ringbuffer.h"
>>
>> @@ -1749,6 +1750,7 @@ struct drm_i915_private {
>>
>>   	struct intel_gvt gvt;
>>
>> +	struct intel_huc huc;
>>   	struct intel_guc guc;
>>
>>   	struct intel_csr csr;
>> @@ -2841,6 +2843,7 @@ struct drm_i915_cmd_table {
>>   #define HAS_GUC(dev)		(IS_GEN9(dev) && !IS_KABYLAKE(dev))
>>   #define HAS_GUC_UCODE(dev)	(HAS_GUC(dev))
>>   #define HAS_GUC_SCHED(dev)	(HAS_GUC(dev))
>> +#define HAS_HUC_UCODE(dev)	(HAS_GUC(dev))
>>
>>   #define HAS_RESOURCE_STREAMER(dev) (IS_HASWELL(dev) || \
>>   				    INTEL_INFO(dev)->gen >= 8)
>> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
>> index 6abd5e5..549dd3f 100644
>> --- a/drivers/gpu/drm/i915/i915_gem.c
>> +++ b/drivers/gpu/drm/i915/i915_gem.c
>> @@ -5143,9 +5143,16 @@ i915_gem_init_hw(struct drm_device *dev)
>>   	intel_mocs_init_l3cc_table(dev);
>>
>>   	/* We can't enable contexts until all firmware is loaded */
>> -	ret = intel_guc_setup(dev);
>> -	if (ret)
>> -		goto out;
>> +	if (HAS_GUC(dev)) {
>> +		/* init WOPCM */
>> +		I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev));
>> +		I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE);
>> +
>> +		intel_huc_load(dev);
>> +		ret = intel_guc_setup(dev);
>> +		if (ret)
>> +			goto out;
>> +	}
>>
>>   	/*
>>   	 * Increment the next seqno by 0x100 so we have a visible break
>> diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h b/drivers/gpu/drm/i915/i915_guc_reg.h
>> index cf5a65b..51533f1 100644
>> --- a/drivers/gpu/drm/i915/i915_guc_reg.h
>> +++ b/drivers/gpu/drm/i915/i915_guc_reg.h
>> @@ -61,9 +61,12 @@
>>   #define   DMA_ADDRESS_SPACE_GTT		  (8 << 16)
>>   #define DMA_COPY_SIZE			_MMIO(0xc310)
>>   #define DMA_CTRL			_MMIO(0xc314)
>> +#define   HUC_UKERNEL			  (1<<9)
>>   #define   UOS_MOVE			  (1<<4)
>>   #define   START_DMA			  (1<<0)
>>   #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)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
>> index 0b4ed88..c4b92f3 100644
>> --- a/drivers/gpu/drm/i915/intel_guc.h
>> +++ b/drivers/gpu/drm/i915/intel_guc.h
>> @@ -160,6 +160,7 @@ extern const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status);
>>   extern int intel_guc_suspend(struct drm_device *dev);
>>   extern int intel_guc_resume(struct drm_device *dev);
>>   void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw);
>> +u32 guc_wopcm_size(struct drm_device *dev);
>>
>>   /* i915_guc_submission.c */
>>   int i915_guc_submission_init(struct drm_i915_private *dev_priv);
>> diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
>> index 70575bd..c4a210d 100644
>> --- a/drivers/gpu/drm/i915/intel_guc_loader.c
>> +++ b/drivers/gpu/drm/i915/intel_guc_loader.c
>> @@ -270,7 +270,8 @@ static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv)
>>   	I915_WRITE(DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM);
>>
>>   	/* Finally start the DMA */
>> -	I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(UOS_MOVE | START_DMA));
>> +	I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(UOS_MOVE | START_DMA) |
>> +			_MASKED_BIT_DISABLE(HUC_UKERNEL));
>>
>>   	/*
>>   	 * Wait for the DMA to complete & the GuC to start up.
>> @@ -295,12 +296,12 @@ static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv)
>>   	return ret;
>>   }
>>
>> -static u32 guc_wopcm_size(struct drm_i915_private *dev_priv)
>> +u32 guc_wopcm_size(struct drm_device *dev)
>>   {
>>   	u32 wopcm_size = GUC_WOPCM_TOP;
>>
>>   	/* On BXT, the top of WOPCM is reserved for RC6 context */
>> -	if (IS_BROXTON(dev_priv))
>> +	if (IS_BROXTON(dev))
>>   		wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED;
>>
>>   	return wopcm_size;
>> @@ -332,10 +333,6 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
>>
>>   	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
>>
>> -	/* init WOPCM */
>> -	I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev_priv));
>> -	I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE);
>> -
>>   	/* Enable MIA caching. GuC clock gating is disabled. */
>>   	I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE);
>>
>> diff --git a/drivers/gpu/drm/i915/intel_huc.h b/drivers/gpu/drm/i915/intel_huc.h
>> new file mode 100644
>> index 0000000..946caa7
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/intel_huc.h
>> @@ -0,0 +1,44 @@
>> +/*
>> + * Copyright © 2014 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_HUC_H_
>> +#define _INTEL_HUC_H_
>> +
>> +#include "intel_guc.h"
>> +
>> +#define HUC_STATUS2		_MMIO(0xD3B0)
>> +#define   HUC_FW_VERIFIED	(1<<7)
>> +
>> +struct intel_huc {
>> +	/* Generic uC firmware management */
>> +	struct intel_uc_fw huc_fw;
>> +
>> +	/* HuC-specific additions */
>> +};
>> +
>> +extern void intel_huc_init(struct drm_device *dev);
>> +extern int intel_huc_load(struct drm_device *dev);
>> +extern void intel_huc_auth(struct drm_device *dev);
>> +extern void intel_huc_fini(struct drm_device *dev);
>> +
>> +#endif
>> diff --git a/drivers/gpu/drm/i915/intel_huc_loader.c b/drivers/gpu/drm/i915/intel_huc_loader.c
>> new file mode 100644
>> index 0000000..472fabe
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/intel_huc_loader.c
>> @@ -0,0 +1,262 @@
>> +/*
>> + * Copyright © 2014 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 <linux/firmware.h>
>> +#include "i915_drv.h"
>> +#include "intel_huc.h"
>> +
>> +/**
>> + * DOC: HuC Firmware
>> + *
>> + * Motivation:
>> + * GEN9 introduces a new dedicated firmware for usage in media HEVC (High
>> + * Efficiency Video Coding) operations. Userspace can use the firmware
>> + * capabilities by adding HuC specific commands to batch buffers.
>> + *
>> + * Implementation:
>> + * On supported platforms, i915's job is to load the firmware stored on the
>> + * file system and assist with authentication. It is up to userspace to
>> + * detect the presence of HuC support on a platform, on their own.
>> + * For debugging, i915 provides a debugfs file, i915_huc_load_status_info
>> + * which displays the firmware load status.
>> + *
>> + * The unified uC firmware loader is used. Firmware binary is fetched by the
>> + * loader asynchronously from the driver init process. However, the actual
>> + * loading to HW is deferred until GEM initialization is done. Be note that HuC
>> + * firmware loading must be done before GuC loading.
>> + */
>> +
>> +#define I915_SKL_HUC_UCODE "i915/skl_huc_ver1.bin"
>> +MODULE_FIRMWARE(I915_SKL_HUC_UCODE);
>> +
>> +/**
>> + * intel_huc_load_ucode() - DMA's the firmware
>> + * @dev: the drm device
>> + *
>> + * This function takes the gem object containing the firmware, sets up the DMA
>> + * engine MMIO, triggers the DMA operation and waits for it to finish.
>> + *
>> + * Transfer the firmware image to RAM for execution by the microcontroller.
>> + *
>> + * Return: 0 on success, non-zero on failure
>> + */
>> +
>> +static int huc_ucode_xfer(struct drm_i915_private *dev_priv)
>> +{
>> +	struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
>> +	unsigned long offset = 0;
>> +	u32 size;
>> +	int ret;
>> +
>> +	ret = i915_gem_object_set_to_gtt_domain(huc_fw->uc_fw_obj, false);
>> +	if (ret) {
>> +		DRM_DEBUG_DRIVER("set-domain failed %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	ret = i915_gem_obj_ggtt_pin(huc_fw->uc_fw_obj, 0, 0);
>> +	if (ret) {
>> +		DRM_DEBUG_DRIVER("pin failed %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	/* Invalidate GuC TLB to let GuC take the latest updates to GTT. */
>> +	I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);
>> +
>> +	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
>> +	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
>> +
>> +	/* Set the source address for the uCode */
>> +	offset = i915_gem_obj_ggtt_offset(huc_fw->uc_fw_obj) +
>> +			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);
>> +
>> +	/* Hardware doesn't look at destination address for HuC. Set it to 0,
>> +	 * but still program the correct address space.
>> +	 */
>> +	I915_WRITE(DMA_ADDR_1_LOW, 0);
>> +	I915_WRITE(DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM);
>> +
>> +	size = huc_fw->header_size + huc_fw->ucode_size;
>> +	I915_WRITE(DMA_COPY_SIZE, size);
>> +
>> +	/* Start the DMA */
>> +	I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(HUC_UKERNEL | START_DMA));
>> +
>> +	/* Wait for DMA to finish */
>> +	ret = wait_for_atomic((I915_READ(DMA_CTRL) & START_DMA) == 0, 50);
>> +
>> +	DRM_DEBUG_DRIVER("HuC DMA transfer wait over with ret %d\n", ret);
>> +
>> +	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
>> +
>> +	/*
>> +	 * We keep the object pages for reuse during resume. But we can unpin it
>> +	 * now that DMA has completed, so it doesn't continue to take up space.
>> +	 */
>> +	i915_gem_object_ggtt_unpin(huc_fw->uc_fw_obj);
>> +
>> +	return ret;
>> +}
>> +
>> +/**
>> + * intel_huc_init() - initiate HuC firmware loading request
>> + * @dev: the drm device
>> + *
>> + * Called early during driver load, but after GEM is initialised. The loading
>> + * will continue only when driver explicitly specify firmware name and version.
>> + * All other cases are considered as UC_FIRMWARE_NONE either because HW is not
>> + * capable or driver yet support it. And there will be no error message for
>> + * UC_FIRMWARE_NONE cases.
>> + *
>> + * The DMA-copying to HW is done later when intel_huc_ucode_load() is called.
>> + */
>> +void intel_huc_init(struct drm_device *dev)
>> +{
>> +	struct drm_i915_private *dev_priv = dev->dev_private;
>> +	struct intel_huc *huc = &dev_priv->huc;
>> +	struct intel_uc_fw *huc_fw = &huc->huc_fw;
>> +	const char *fw_path = NULL;
>> +
>> +	huc_fw->uc_dev = dev;
>> +	huc_fw->uc_fw_path = NULL;
>> +	huc_fw->fetch_status = UC_FIRMWARE_NONE;
>> +	huc_fw->load_status = UC_FIRMWARE_NONE;
>> +	huc_fw->fw_type = UC_FW_TYPE_HUC;
>> +
>> +	if (!HAS_HUC_UCODE(dev))
>> +		return;
>> +
>> +	if (IS_SKYLAKE(dev)) {
>> +		fw_path = I915_SKL_HUC_UCODE;
>> +		huc_fw->major_ver_wanted = 1;
>> +		huc_fw->minor_ver_wanted = 5;
>> +	}
>> +
>> +	if (fw_path == NULL)
>> +		return;
>> +
>> +	huc_fw->uc_fw_path = fw_path;
>> +	huc_fw->fetch_status = UC_FIRMWARE_PENDING;
>> +
>> +	DRM_DEBUG_DRIVER("HuC firmware pending, path %s\n", fw_path);
>> +
>> +	intel_uc_fw_fetch(dev, huc_fw);
>> +}
>> +
>> +/**
>> + * intel_huc_load() - load HuC uCode to device
>> + * @dev: the drm device
>> + *
>> + * Called from gem_init_hw() during driver loading and also after a GPU reset.
>> + * Be note that HuC loading must be done before GuC loading.
>> + *
>> + * The firmware image should have already been fetched into memory by the
>> + * earlier call to intel_huc_ucode_init(), so here we need only check that
>> + * is succeeded, and then transfer the image to the h/w.
>> + *
>> + * Return:	non-zero code on error
>> + */
>> +int intel_huc_load(struct drm_device *dev)
>> +{
>> +	struct drm_i915_private *dev_priv = dev->dev_private;
>> +	struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
>> +	int err;
>> +
>> +	if (huc_fw->fetch_status == UC_FIRMWARE_NONE)
>> +		return 0;
>> +
>> +	DRM_DEBUG_DRIVER("%s fw status: fetch %s, load %s\n",
>> +		huc_fw->uc_fw_path,
>> +		intel_uc_fw_status_repr(huc_fw->fetch_status),
>> +		intel_uc_fw_status_repr(huc_fw->load_status));
>> +
>> +	if (huc_fw->fetch_status == UC_FIRMWARE_SUCCESS &&
>> +	    huc_fw->load_status == UC_FIRMWARE_FAIL)
>> +		return -ENOEXEC;
>> +
>> +	huc_fw->load_status = UC_FIRMWARE_PENDING;
>> +
>> +	switch (huc_fw->fetch_status) {
>> +	case UC_FIRMWARE_FAIL:
>> +		/* something went wrong :( */
>> +		err = -EIO;
>> +		goto fail;
>> +
>> +	case UC_FIRMWARE_NONE:
>> +	case UC_FIRMWARE_PENDING:
>> +	default:
>> +		/* "can't happen" */
>> +		WARN_ONCE(1, "HuC fw %s invalid fetch_status %s [%d]\n",
>> +			huc_fw->uc_fw_path,
>> +			intel_uc_fw_status_repr(huc_fw->fetch_status),
>> +			huc_fw->fetch_status);
>> +		err = -ENXIO;
>> +		goto fail;
>> +
>> +	case UC_FIRMWARE_SUCCESS:
>> +		break;
>> +	}
>
> Can we please remove all that indirection through fetch_status? This
> really shouldn't be that complicated that you need pages of code to
> generate/decode status. I know it's copypaste from guc, but I didn't like
> it there, and I definitely don't want 2 copies of this. Please simplify
> both places.
>
> The correct fix is to give the uc_fw_fetch function an error code, and rip
> out all that cargo culted status handling. All of it.
> -Daniel

No, the *correct* fix is to unify all the firmware loaders we have.
There should just be ONE piece of code that can be used to fetch and 
load ANy firmware into ANY auxiliary microcontroller. NOT one per 
microcontroller, all different -- that way lies madness.

We already had a unified loader for the HuC and GuC a year ago, but IIRC 
the party line then was "just make it (GuC) specific, then copypaste it 
for the second uC, and when we've got three versions we'll have learnt 
how we really want a unified loader to behave."

Well. here's the copypaste, and we already have a different loader for 
the DMC/CSR, so it must be time for (re-)unification.

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

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

* Re: [PATCH 4/6] drm/i915/huc: Add debugfs for HuC loading status check
  2016-06-23 10:01     ` Peter Antoine
@ 2016-06-23 10:48       ` Michel Thierry
  2016-06-23 22:04         ` Kelley, Sean V
  0 siblings, 1 reply; 40+ messages in thread
From: Michel Thierry @ 2016-06-23 10:48 UTC (permalink / raw)
  To: Peter Antoine, Xiang, Haihao, daniel.vetter
  Cc: Kelley, Sean V, intel-gfx, Li, Lawrence T, Vivi, Rodrigo

On 6/23/2016 11:01 AM, Peter Antoine wrote:
> Daniel,
>
> Is this suggestion acceptable? I don't want to waste time and effort
> writing code that is not going to be accepted?
>
> Peter.
>

Reuse I915_GETPARAM and do more-less what Chris did for i915.enable_gvt? [1]


[1] 
https://cgit.freedesktop.org/drm-intel/commit/?id=7822492fd21a44eeb3568082b0ab915df7388061

> On Thu, 23 Jun 2016, Xiang, Haihao wrote:
>
>>
>> Hi Peter,
>>
>> Besides debugfs, could you add a IOCTL to check HuC loading status?
>> Userspace media driver needs to advertise the features based on HuC to
>> user.
>>
>> Thanks
>> Haihao
>>
>>
>>> From: Alex Dai <yu.dai@intel.com>
>>>
>>> Add debugfs entry for HuC loading status check.
>>>
>>> Signed-off-by: Alex Dai <yu.dai@intel.com>
>>> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
>>> ---
>>>  drivers/gpu/drm/i915/i915_debugfs.c | 32
>>> ++++++++++++++++++++++++++++++++
>>>  1 file changed, 32 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
>>> b/drivers/gpu/drm/i915/i915_debugfs.c
>>> index 69964c2..f5976f8 100644
>>> --- a/drivers/gpu/drm/i915/i915_debugfs.c
>>> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
>>> @@ -2479,6 +2479,37 @@ static int i915_llc(struct seq_file *m, void
>>> *data)
>>>      return 0;
>>>  }
>>>
>>> +static int i915_huc_load_status_info(struct seq_file *m, void *data)
>>> +{
>>> +    struct drm_info_node *node = m->private;
>>> +    struct drm_i915_private *dev_priv = node->minor->dev-
>>>> dev_private;
>>> +    struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
>>> +
>>> +    if (!HAS_HUC_UCODE(dev_priv->dev))
>>> +            return 0;
>>> +
>>> +    seq_puts(m, "HuC firmware status:\n");
>>> +    seq_printf(m, "\tpath: %s\n", huc_fw->uc_fw_path);
>>> +    seq_printf(m, "\tfetch: %s\n",
>>> +            intel_uc_fw_status_repr(huc_fw->fetch_status));
>>> +    seq_printf(m, "\tload: %s\n",
>>> +            intel_uc_fw_status_repr(huc_fw->load_status));
>>> +    seq_printf(m, "\tversion wanted: %d.%d\n",
>>> +            huc_fw->major_ver_wanted, huc_fw->minor_ver_wanted);
>>> +    seq_printf(m, "\tversion found: %d.%d\n",
>>> +            huc_fw->major_ver_found, huc_fw->minor_ver_found);
>>> +    seq_printf(m, "\theader: offset is %d; size = %d\n",
>>> +            huc_fw->header_offset, huc_fw->header_size);
>>> +    seq_printf(m, "\tuCode: offset is %d; size = %d\n",
>>> +            huc_fw->ucode_offset, huc_fw->ucode_size);
>>> +    seq_printf(m, "\tRSA: offset is %d; size = %d\n",
>>> +            huc_fw->rsa_offset, huc_fw->rsa_size);
>>> +
>>> +    seq_printf(m, "\nHuC status 0x%08x:\n",
>>> I915_READ(HUC_STATUS2));
>>> +
>>> +    return 0;
>>> +}
>>> +
>>>  static int i915_guc_load_status_info(struct seq_file *m, void *data)
>>>  {
>>>      struct drm_info_node *node = m->private;
>>> @@ -5432,6 +5463,7 @@ static const struct drm_info_list
>>> i915_debugfs_list[] = {
>>>      {"i915_guc_info", i915_guc_info, 0},
>>>      {"i915_guc_load_status", i915_guc_load_status_info, 0},
>>>      {"i915_guc_log_dump", i915_guc_log_dump, 0},
>>> +    {"i915_huc_load_status", i915_huc_load_status_info, 0},
>>>      {"i915_frequency_info", i915_frequency_info, 0},
>>>      {"i915_hangcheck_info", i915_hangcheck_info, 0},
>>>      {"i915_drpc_info", i915_drpc_info, 0},
>
> --
>     Peter Antoine (Android Graphics Driver Software Engineer)
>     ---------------------------------------------------------------------
>     Intel Corporation (UK) Limited
>     Registered No. 1134945 (England)
>     Registered Office: Pipers Way, Swindon SN3 1RJ
>     VAT No: 860 2173 47
>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/6] drm/i915/huc: Add HuC fw loading support
  2016-06-23 10:14     ` Dave Gordon
@ 2016-06-23 13:52       ` Peter Antoine
  2016-07-13 12:48         ` Daniel Vetter
  0 siblings, 1 reply; 40+ messages in thread
From: Peter Antoine @ 2016-06-23 13:52 UTC (permalink / raw)
  To: Dave Gordon; +Cc: sean.v.kelley, intel-gfx, lawrence.t.li, rodrigo.vivi

[-- Attachment #1: Type: TEXT/PLAIN, Size: 21101 bytes --]

On Thu, 23 Jun 2016, Dave Gordon wrote:

> On 22/06/16 09:31, Daniel Vetter wrote:
>> On Tue, Jun 21, 2016 at 07:11:22PM +0100, Peter Antoine wrote:
>>> From: Alex Dai <yu.dai@intel.com>
>>> 
>>> The HuC loading process is similar to GuC. The intel_uc_fw_fetch()
>>> is used for both cases.
>>> 
>>> HuC loading needs to be before GuC loading. The WOPCM setting must
>>> be done early before loading any of them.
>>> 
>>> Signed-off-by: Alex Dai <yu.dai@intel.com>
>>> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
>>> ---
>>>   drivers/gpu/drm/i915/Makefile           |   1 +
>>>   drivers/gpu/drm/i915/i915_dma.c         |   3 +
>>>   drivers/gpu/drm/i915/i915_drv.h         |   3 +
>>>   drivers/gpu/drm/i915/i915_gem.c         |  13 +-
>>>   drivers/gpu/drm/i915/i915_guc_reg.h     |   3 +
>>>   drivers/gpu/drm/i915/intel_guc.h        |   1 +
>>>   drivers/gpu/drm/i915/intel_guc_loader.c |  11 +-
>>>   drivers/gpu/drm/i915/intel_huc.h        |  44 ++++++
>>>   drivers/gpu/drm/i915/intel_huc_loader.c | 262 
>>> ++++++++++++++++++++++++++++++++
>>>   9 files changed, 331 insertions(+), 10 deletions(-)
>>>   create mode 100644 drivers/gpu/drm/i915/intel_huc.h
>>>   create mode 100644 drivers/gpu/drm/i915/intel_huc_loader.c
>>> 
>>> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
>>> index 276abf1..7384db0 100644
>>> --- a/drivers/gpu/drm/i915/Makefile
>>> +++ b/drivers/gpu/drm/i915/Makefile
>>> @@ -44,6 +44,7 @@ i915-y += i915_cmd_parser.o \
>>>
>>>   # general-purpose microcontroller (GuC) support
>>>   i915-y += intel_guc_loader.o \
>>> +	  intel_huc_loader.o \
>>>   	  i915_guc_submission.o
>>>
>>>   # autogenerated null render state
>>> diff --git a/drivers/gpu/drm/i915/i915_dma.c 
>>> b/drivers/gpu/drm/i915/i915_dma.c
>>> index e28c0dd..a449a59 100644
>>> --- a/drivers/gpu/drm/i915/i915_dma.c
>>> +++ b/drivers/gpu/drm/i915/i915_dma.c
>>> @@ -507,6 +507,7 @@ static int i915_load_modeset_init(struct drm_device 
>>> *dev)
>>>   	 * working irqs for e.g. gmbus and dp aux transfers. */
>>>   	intel_modeset_init(dev);
>>> 
>>> +	intel_huc_init(dev);
>>>   	intel_guc_init(dev);
>>>
>>>   	ret = i915_gem_init(dev);
>>> @@ -532,6 +533,7 @@ static int i915_load_modeset_init(struct drm_device 
>>> *dev)
>>>   cleanup_gem:
>>>   	i915_gem_fini(dev);
>>>   cleanup_irq:
>>> +	intel_huc_fini(dev);
>>>   	intel_guc_fini(dev);
>>>   	drm_irq_uninstall(dev);
>>>   	intel_teardown_gmbus(dev);
>>> @@ -1563,6 +1565,7 @@ int i915_driver_unload(struct drm_device *dev)
>>>   	/* Flush any outstanding unpin_work. */
>>>   	flush_workqueue(dev_priv->wq);
>>> 
>>> +	intel_huc_fini(dev);
>>>   	intel_guc_fini(dev);
>>>   	i915_gem_fini(dev);
>>>   	intel_fbc_cleanup_cfb(dev_priv);
>>> diff --git a/drivers/gpu/drm/i915/i915_drv.h 
>>> b/drivers/gpu/drm/i915/i915_drv.h
>>> index 7c81757..8b88227 100644
>>> --- a/drivers/gpu/drm/i915/i915_drv.h
>>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>>> @@ -54,6 +54,7 @@
>>>   #include "intel_bios.h"
>>>   #include "intel_dpll_mgr.h"
>>>   #include "intel_guc.h"
>>> +#include "intel_huc.h"
>>>   #include "intel_lrc.h"
>>>   #include "intel_ringbuffer.h"
>>> 
>>> @@ -1749,6 +1750,7 @@ struct drm_i915_private {
>>>
>>>   	struct intel_gvt gvt;
>>> 
>>> +	struct intel_huc huc;
>>>   	struct intel_guc guc;
>>>
>>>   	struct intel_csr csr;
>>> @@ -2841,6 +2843,7 @@ struct drm_i915_cmd_table {
>>>   #define HAS_GUC(dev)		(IS_GEN9(dev) && !IS_KABYLAKE(dev))
>>>   #define HAS_GUC_UCODE(dev)	(HAS_GUC(dev))
>>>   #define HAS_GUC_SCHED(dev)	(HAS_GUC(dev))
>>> +#define HAS_HUC_UCODE(dev)	(HAS_GUC(dev))
>>>
>>>   #define HAS_RESOURCE_STREAMER(dev) (IS_HASWELL(dev) || \
>>>   				    INTEL_INFO(dev)->gen >= 8)
>>> diff --git a/drivers/gpu/drm/i915/i915_gem.c 
>>> b/drivers/gpu/drm/i915/i915_gem.c
>>> index 6abd5e5..549dd3f 100644
>>> --- a/drivers/gpu/drm/i915/i915_gem.c
>>> +++ b/drivers/gpu/drm/i915/i915_gem.c
>>> @@ -5143,9 +5143,16 @@ i915_gem_init_hw(struct drm_device *dev)
>>>   	intel_mocs_init_l3cc_table(dev);
>>>
>>>   	/* We can't enable contexts until all firmware is loaded */
>>> -	ret = intel_guc_setup(dev);
>>> -	if (ret)
>>> -		goto out;
>>> +	if (HAS_GUC(dev)) {
>>> +		/* init WOPCM */
>>> +		I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev));
>>> +		I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE);
>>> +
>>> +		intel_huc_load(dev);
>>> +		ret = intel_guc_setup(dev);
>>> +		if (ret)
>>> +			goto out;
>>> +	}
>>>
>>>   	/*
>>>   	 * Increment the next seqno by 0x100 so we have a visible break
>>> diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h 
>>> b/drivers/gpu/drm/i915/i915_guc_reg.h
>>> index cf5a65b..51533f1 100644
>>> --- a/drivers/gpu/drm/i915/i915_guc_reg.h
>>> +++ b/drivers/gpu/drm/i915/i915_guc_reg.h
>>> @@ -61,9 +61,12 @@
>>>   #define   DMA_ADDRESS_SPACE_GTT		  (8 << 16)
>>>   #define DMA_COPY_SIZE			_MMIO(0xc310)
>>>   #define DMA_CTRL			_MMIO(0xc314)
>>> +#define   HUC_UKERNEL			  (1<<9)
>>>   #define   UOS_MOVE			  (1<<4)
>>>   #define   START_DMA			  (1<<0)
>>>   #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)
>>> 
>>> diff --git a/drivers/gpu/drm/i915/intel_guc.h 
>>> b/drivers/gpu/drm/i915/intel_guc.h
>>> index 0b4ed88..c4b92f3 100644
>>> --- a/drivers/gpu/drm/i915/intel_guc.h
>>> +++ b/drivers/gpu/drm/i915/intel_guc.h
>>> @@ -160,6 +160,7 @@ extern const char *intel_uc_fw_status_repr(enum 
>>> intel_uc_fw_status status);
>>>   extern int intel_guc_suspend(struct drm_device *dev);
>>>   extern int intel_guc_resume(struct drm_device *dev);
>>>   void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw 
>>> *uc_fw);
>>> +u32 guc_wopcm_size(struct drm_device *dev);
>>>
>>>   /* i915_guc_submission.c */
>>>   int i915_guc_submission_init(struct drm_i915_private *dev_priv);
>>> diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c 
>>> b/drivers/gpu/drm/i915/intel_guc_loader.c
>>> index 70575bd..c4a210d 100644
>>> --- a/drivers/gpu/drm/i915/intel_guc_loader.c
>>> +++ b/drivers/gpu/drm/i915/intel_guc_loader.c
>>> @@ -270,7 +270,8 @@ static int guc_ucode_xfer_dma(struct drm_i915_private 
>>> *dev_priv)
>>>   	I915_WRITE(DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM);
>>>
>>>   	/* Finally start the DMA */
>>> -	I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(UOS_MOVE | START_DMA));
>>> +	I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(UOS_MOVE | START_DMA) |
>>> +			_MASKED_BIT_DISABLE(HUC_UKERNEL));
>>>
>>>   	/*
>>>   	 * Wait for the DMA to complete & the GuC to start up.
>>> @@ -295,12 +296,12 @@ static int guc_ucode_xfer_dma(struct 
>>> drm_i915_private *dev_priv)
>>>   	return ret;
>>>   }
>>> 
>>> -static u32 guc_wopcm_size(struct drm_i915_private *dev_priv)
>>> +u32 guc_wopcm_size(struct drm_device *dev)
>>>   {
>>>   	u32 wopcm_size = GUC_WOPCM_TOP;
>>>
>>>   	/* On BXT, the top of WOPCM is reserved for RC6 context */
>>> -	if (IS_BROXTON(dev_priv))
>>> +	if (IS_BROXTON(dev))
>>>   		wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED;
>>>
>>>   	return wopcm_size;
>>> @@ -332,10 +333,6 @@ static int guc_ucode_xfer(struct drm_i915_private 
>>> *dev_priv)
>>>
>>>   	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
>>> 
>>> -	/* init WOPCM */
>>> -	I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev_priv));
>>> -	I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE);
>>> -
>>>   	/* Enable MIA caching. GuC clock gating is disabled. */
>>>   	I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE);
>>> 
>>> diff --git a/drivers/gpu/drm/i915/intel_huc.h 
>>> b/drivers/gpu/drm/i915/intel_huc.h
>>> new file mode 100644
>>> index 0000000..946caa7
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/i915/intel_huc.h
>>> @@ -0,0 +1,44 @@
>>> +/*
>>> + * Copyright © 2014 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_HUC_H_
>>> +#define _INTEL_HUC_H_
>>> +
>>> +#include "intel_guc.h"
>>> +
>>> +#define HUC_STATUS2		_MMIO(0xD3B0)
>>> +#define   HUC_FW_VERIFIED	(1<<7)
>>> +
>>> +struct intel_huc {
>>> +	/* Generic uC firmware management */
>>> +	struct intel_uc_fw huc_fw;
>>> +
>>> +	/* HuC-specific additions */
>>> +};
>>> +
>>> +extern void intel_huc_init(struct drm_device *dev);
>>> +extern int intel_huc_load(struct drm_device *dev);
>>> +extern void intel_huc_auth(struct drm_device *dev);
>>> +extern void intel_huc_fini(struct drm_device *dev);
>>> +
>>> +#endif
>>> diff --git a/drivers/gpu/drm/i915/intel_huc_loader.c 
>>> b/drivers/gpu/drm/i915/intel_huc_loader.c
>>> new file mode 100644
>>> index 0000000..472fabe
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/i915/intel_huc_loader.c
>>> @@ -0,0 +1,262 @@
>>> +/*
>>> + * Copyright © 2014 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 <linux/firmware.h>
>>> +#include "i915_drv.h"
>>> +#include "intel_huc.h"
>>> +
>>> +/**
>>> + * DOC: HuC Firmware
>>> + *
>>> + * Motivation:
>>> + * GEN9 introduces a new dedicated firmware for usage in media HEVC (High
>>> + * Efficiency Video Coding) operations. Userspace can use the firmware
>>> + * capabilities by adding HuC specific commands to batch buffers.
>>> + *
>>> + * Implementation:
>>> + * On supported platforms, i915's job is to load the firmware stored on 
>>> the
>>> + * file system and assist with authentication. It is up to userspace to
>>> + * detect the presence of HuC support on a platform, on their own.
>>> + * For debugging, i915 provides a debugfs file, i915_huc_load_status_info
>>> + * which displays the firmware load status.
>>> + *
>>> + * The unified uC firmware loader is used. Firmware binary is fetched by 
>>> the
>>> + * loader asynchronously from the driver init process. However, the 
>>> actual
>>> + * loading to HW is deferred until GEM initialization is done. Be note 
>>> that HuC
>>> + * firmware loading must be done before GuC loading.
>>> + */
>>> +
>>> +#define I915_SKL_HUC_UCODE "i915/skl_huc_ver1.bin"
>>> +MODULE_FIRMWARE(I915_SKL_HUC_UCODE);
>>> +
>>> +/**
>>> + * intel_huc_load_ucode() - DMA's the firmware
>>> + * @dev: the drm device
>>> + *
>>> + * This function takes the gem object containing the firmware, sets up 
>>> the DMA
>>> + * engine MMIO, triggers the DMA operation and waits for it to finish.
>>> + *
>>> + * Transfer the firmware image to RAM for execution by the 
>>> microcontroller.
>>> + *
>>> + * Return: 0 on success, non-zero on failure
>>> + */
>>> +
>>> +static int huc_ucode_xfer(struct drm_i915_private *dev_priv)
>>> +{
>>> +	struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
>>> +	unsigned long offset = 0;
>>> +	u32 size;
>>> +	int ret;
>>> +
>>> +	ret = i915_gem_object_set_to_gtt_domain(huc_fw->uc_fw_obj, false);
>>> +	if (ret) {
>>> +		DRM_DEBUG_DRIVER("set-domain failed %d\n", ret);
>>> +		return ret;
>>> +	}
>>> +
>>> +	ret = i915_gem_obj_ggtt_pin(huc_fw->uc_fw_obj, 0, 0);
>>> +	if (ret) {
>>> +		DRM_DEBUG_DRIVER("pin failed %d\n", ret);
>>> +		return ret;
>>> +	}
>>> +
>>> +	/* Invalidate GuC TLB to let GuC take the latest updates to GTT. */
>>> +	I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);
>>> +
>>> +	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
>>> +	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
>>> +
>>> +	/* Set the source address for the uCode */
>>> +	offset = i915_gem_obj_ggtt_offset(huc_fw->uc_fw_obj) +
>>> +			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);
>>> +
>>> +	/* Hardware doesn't look at destination address for HuC. Set it to 0,
>>> +	 * but still program the correct address space.
>>> +	 */
>>> +	I915_WRITE(DMA_ADDR_1_LOW, 0);
>>> +	I915_WRITE(DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM);
>>> +
>>> +	size = huc_fw->header_size + huc_fw->ucode_size;
>>> +	I915_WRITE(DMA_COPY_SIZE, size);
>>> +
>>> +	/* Start the DMA */
>>> +	I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(HUC_UKERNEL | START_DMA));
>>> +
>>> +	/* Wait for DMA to finish */
>>> +	ret = wait_for_atomic((I915_READ(DMA_CTRL) & START_DMA) == 0, 50);
>>> +
>>> +	DRM_DEBUG_DRIVER("HuC DMA transfer wait over with ret %d\n", ret);
>>> +
>>> +	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
>>> +
>>> +	/*
>>> +	 * We keep the object pages for reuse during resume. But we can unpin 
>>> it
>>> +	 * now that DMA has completed, so it doesn't continue to take up 
>>> space.
>>> +	 */
>>> +	i915_gem_object_ggtt_unpin(huc_fw->uc_fw_obj);
>>> +
>>> +	return ret;
>>> +}
>>> +
>>> +/**
>>> + * intel_huc_init() - initiate HuC firmware loading request
>>> + * @dev: the drm device
>>> + *
>>> + * Called early during driver load, but after GEM is initialised. The 
>>> loading
>>> + * will continue only when driver explicitly specify firmware name and 
>>> version.
>>> + * All other cases are considered as UC_FIRMWARE_NONE either because HW 
>>> is not
>>> + * capable or driver yet support it. And there will be no error message 
>>> for
>>> + * UC_FIRMWARE_NONE cases.
>>> + *
>>> + * The DMA-copying to HW is done later when intel_huc_ucode_load() is 
>>> called.
>>> + */
>>> +void intel_huc_init(struct drm_device *dev)
>>> +{
>>> +	struct drm_i915_private *dev_priv = dev->dev_private;
>>> +	struct intel_huc *huc = &dev_priv->huc;
>>> +	struct intel_uc_fw *huc_fw = &huc->huc_fw;
>>> +	const char *fw_path = NULL;
>>> +
>>> +	huc_fw->uc_dev = dev;
>>> +	huc_fw->uc_fw_path = NULL;
>>> +	huc_fw->fetch_status = UC_FIRMWARE_NONE;
>>> +	huc_fw->load_status = UC_FIRMWARE_NONE;
>>> +	huc_fw->fw_type = UC_FW_TYPE_HUC;
>>> +
>>> +	if (!HAS_HUC_UCODE(dev))
>>> +		return;
>>> +
>>> +	if (IS_SKYLAKE(dev)) {
>>> +		fw_path = I915_SKL_HUC_UCODE;
>>> +		huc_fw->major_ver_wanted = 1;
>>> +		huc_fw->minor_ver_wanted = 5;
>>> +	}
>>> +
>>> +	if (fw_path == NULL)
>>> +		return;
>>> +
>>> +	huc_fw->uc_fw_path = fw_path;
>>> +	huc_fw->fetch_status = UC_FIRMWARE_PENDING;
>>> +
>>> +	DRM_DEBUG_DRIVER("HuC firmware pending, path %s\n", fw_path);
>>> +
>>> +	intel_uc_fw_fetch(dev, huc_fw);
>>> +}
>>> +
>>> +/**
>>> + * intel_huc_load() - load HuC uCode to device
>>> + * @dev: the drm device
>>> + *
>>> + * Called from gem_init_hw() during driver loading and also after a GPU 
>>> reset.
>>> + * Be note that HuC loading must be done before GuC loading.
>>> + *
>>> + * The firmware image should have already been fetched into memory by the
>>> + * earlier call to intel_huc_ucode_init(), so here we need only check 
>>> that
>>> + * is succeeded, and then transfer the image to the h/w.
>>> + *
>>> + * Return:	non-zero code on error
>>> + */
>>> +int intel_huc_load(struct drm_device *dev)
>>> +{
>>> +	struct drm_i915_private *dev_priv = dev->dev_private;
>>> +	struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
>>> +	int err;
>>> +
>>> +	if (huc_fw->fetch_status == UC_FIRMWARE_NONE)
>>> +		return 0;
>>> +
>>> +	DRM_DEBUG_DRIVER("%s fw status: fetch %s, load %s\n",
>>> +		huc_fw->uc_fw_path,
>>> +		intel_uc_fw_status_repr(huc_fw->fetch_status),
>>> +		intel_uc_fw_status_repr(huc_fw->load_status));
>>> +
>>> +	if (huc_fw->fetch_status == UC_FIRMWARE_SUCCESS &&
>>> +	    huc_fw->load_status == UC_FIRMWARE_FAIL)
>>> +		return -ENOEXEC;
>>> +
>>> +	huc_fw->load_status = UC_FIRMWARE_PENDING;
>>> +
>>> +	switch (huc_fw->fetch_status) {
>>> +	case UC_FIRMWARE_FAIL:
>>> +		/* something went wrong :( */
>>> +		err = -EIO;
>>> +		goto fail;
>>> +
>>> +	case UC_FIRMWARE_NONE:
>>> +	case UC_FIRMWARE_PENDING:
>>> +	default:
>>> +		/* "can't happen" */
>>> +		WARN_ONCE(1, "HuC fw %s invalid fetch_status %s [%d]\n",
>>> +			huc_fw->uc_fw_path,
>>> +			intel_uc_fw_status_repr(huc_fw->fetch_status),
>>> +			huc_fw->fetch_status);
>>> +		err = -ENXIO;
>>> +		goto fail;
>>> +
>>> +	case UC_FIRMWARE_SUCCESS:
>>> +		break;
>>> +	}
>> 
>> Can we please remove all that indirection through fetch_status? This
>> really shouldn't be that complicated that you need pages of code to
>> generate/decode status. I know it's copypaste from guc, but I didn't like
>> it there, and I definitely don't want 2 copies of this. Please simplify
>> both places.
>> 
>> The correct fix is to give the uc_fw_fetch function an error code, and rip
>> out all that cargo culted status handling. All of it.
>> -Daniel
>
> No, the *correct* fix is to unify all the firmware loaders we have.
> There should just be ONE piece of code that can be used to fetch and load ANy 
> firmware into ANY auxiliary microcontroller. NOT one per microcontroller, all 
> different -- that way lies madness.
>
> We already had a unified loader for the HuC and GuC a year ago, but IIRC the 
> party line then was "just make it (GuC) specific, then copypaste it for the 
> second uC, and when we've got three versions we'll have learnt how we really 
> want a unified loader to behave."
>
> Well. here's the copypaste, and we already have a different loader for the 
> DMC/CSR, so it must be time for (re-)unification.
>
> .Dave.
>

Just to add, if you uc_fw_fetch() has an error code you will still have to 
remember the state of the fetch or at each reset/resume/etc... or you will 
have to try the firmware load again and that can take a long time. So the 
state will have to be re-instated.

Seeing this code was written with the given goals and were written in the 
same vane as code that was deemed acceptable, it seems weird at this late 
stage to change the design goals.

Note: this is the third time that these patches have been posted and were 
only rejected (as far as I know) due to no open-source user. Which there 
is now, and is why I have reposted these patches.

Peter.

https://patchwork.freedesktop.org/series/9011/  22/6/2016
https://patchwork.freedesktop.org/series/3188/  9/2/2016
https://patchwork.freedesktop.org/series/2355/  11/1/2016

--
    Peter Antoine (Android Graphics Driver Software Engineer)
    ---------------------------------------------------------------------
    Intel Corporation (UK) Limited
    Registered No. 1134945 (England)
    Registered Office: Pipers Way, Swindon SN3 1RJ
    VAT No: 860 2173 47

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

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

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

* Re: [PATCH 4/6] drm/i915/huc: Add debugfs for HuC loading status check
  2016-06-23 10:48       ` Michel Thierry
@ 2016-06-23 22:04         ` Kelley, Sean V
  2016-07-13  8:13           ` Xiang, Haihao
  0 siblings, 1 reply; 40+ messages in thread
From: Kelley, Sean V @ 2016-06-23 22:04 UTC (permalink / raw)
  To: Thierry, Michel, Antoine, Peter, Xiang, Haihao, daniel.vetter
  Cc: intel-gfx, Li, Lawrence T, Vivi, Rodrigo



> -----Original Message-----
> From: Thierry, Michel
> Sent: Thursday, June 23, 2016 3:48 AM
> To: Antoine, Peter <peter.antoine@intel.com>; Xiang, Haihao
> <haihao.xiang@intel.com>; daniel.vetter@ffwll.ch
> Cc: Kelley, Sean V <sean.v.kelley@intel.com>; intel-
> gfx@lists.freedesktop.org; Li, Lawrence T <lawrence.t.li@intel.com>; Vivi,
> Rodrigo <rodrigo.vivi@intel.com>
> Subject: Re: [Intel-gfx] [PATCH 4/6] drm/i915/huc: Add debugfs for HuC
> loading status check
> 
> On 6/23/2016 11:01 AM, Peter Antoine wrote:
> > Daniel,
> >
> > Is this suggestion acceptable? I don't want to waste time and effort
> > writing code that is not going to be accepted?
> >
> > Peter.
> >
> 
> Reuse I915_GETPARAM and do more-less what Chris did for
> i915.enable_gvt? [1]
> 
> 
> [1]
> https://cgit.freedesktop.org/drm-
> intel/commit/?id=7822492fd21a44eeb3568082b0ab915df7388061

Something along those lines would work for me with our media UMD.

Thanks,

Sean

> 
> > On Thu, 23 Jun 2016, Xiang, Haihao wrote:
> >
> >>
> >> Hi Peter,
> >>
> >> Besides debugfs, could you add a IOCTL to check HuC loading status?
> >> Userspace media driver needs to advertise the features based on HuC
> >> to user.
> >>
> >> Thanks
> >> Haihao
> >>
> >>
> >>> From: Alex Dai <yu.dai@intel.com>
> >>>
> >>> Add debugfs entry for HuC loading status check.
> >>>
> >>> Signed-off-by: Alex Dai <yu.dai@intel.com>
> >>> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
> >>> ---
> >>>  drivers/gpu/drm/i915/i915_debugfs.c | 32
> >>> ++++++++++++++++++++++++++++++++
> >>>  1 file changed, 32 insertions(+)
> >>>
> >>> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
> >>> b/drivers/gpu/drm/i915/i915_debugfs.c
> >>> index 69964c2..f5976f8 100644
> >>> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> >>> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> >>> @@ -2479,6 +2479,37 @@ static int i915_llc(struct seq_file *m, void
> >>> *data)
> >>>      return 0;
> >>>  }
> >>>
> >>> +static int i915_huc_load_status_info(struct seq_file *m, void
> >>> +*data) {
> >>> +    struct drm_info_node *node = m->private;
> >>> +    struct drm_i915_private *dev_priv = node->minor->dev-
> >>>> dev_private;
> >>> +    struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
> >>> +
> >>> +    if (!HAS_HUC_UCODE(dev_priv->dev))
> >>> +            return 0;
> >>> +
> >>> +    seq_puts(m, "HuC firmware status:\n");
> >>> +    seq_printf(m, "\tpath: %s\n", huc_fw->uc_fw_path);
> >>> +    seq_printf(m, "\tfetch: %s\n",
> >>> +            intel_uc_fw_status_repr(huc_fw->fetch_status));
> >>> +    seq_printf(m, "\tload: %s\n",
> >>> +            intel_uc_fw_status_repr(huc_fw->load_status));
> >>> +    seq_printf(m, "\tversion wanted: %d.%d\n",
> >>> +            huc_fw->major_ver_wanted, huc_fw->minor_ver_wanted);
> >>> +    seq_printf(m, "\tversion found: %d.%d\n",
> >>> +            huc_fw->major_ver_found, huc_fw->minor_ver_found);
> >>> +    seq_printf(m, "\theader: offset is %d; size = %d\n",
> >>> +            huc_fw->header_offset, huc_fw->header_size);
> >>> +    seq_printf(m, "\tuCode: offset is %d; size = %d\n",
> >>> +            huc_fw->ucode_offset, huc_fw->ucode_size);
> >>> +    seq_printf(m, "\tRSA: offset is %d; size = %d\n",
> >>> +            huc_fw->rsa_offset, huc_fw->rsa_size);
> >>> +
> >>> +    seq_printf(m, "\nHuC status 0x%08x:\n",
> >>> I915_READ(HUC_STATUS2));
> >>> +
> >>> +    return 0;
> >>> +}
> >>> +
> >>>  static int i915_guc_load_status_info(struct seq_file *m, void
> >>> *data)  {
> >>>      struct drm_info_node *node = m->private; @@ -5432,6 +5463,7 @@
> >>> static const struct drm_info_list i915_debugfs_list[] = {
> >>>      {"i915_guc_info", i915_guc_info, 0},
> >>>      {"i915_guc_load_status", i915_guc_load_status_info, 0},
> >>>      {"i915_guc_log_dump", i915_guc_log_dump, 0},
> >>> +    {"i915_huc_load_status", i915_huc_load_status_info, 0},
> >>>      {"i915_frequency_info", i915_frequency_info, 0},
> >>>      {"i915_hangcheck_info", i915_hangcheck_info, 0},
> >>>      {"i915_drpc_info", i915_drpc_info, 0},
> >
> > --
> >     Peter Antoine (Android Graphics Driver Software Engineer)
> >     ---------------------------------------------------------------------
> >     Intel Corporation (UK) Limited
> >     Registered No. 1134945 (England)
> >     Registered Office: Pipers Way, Swindon SN3 1RJ
> >     VAT No: 860 2173 47
> >
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 1/6] drm/i915/guc: Make the GuC fw loading helper functions general
  2016-06-21 18:11 ` [PATCH 1/6] drm/i915/guc: Make the GuC fw loading helper functions general Peter Antoine
@ 2016-06-28 14:24   ` Dave Gordon
  0 siblings, 0 replies; 40+ messages in thread
From: Dave Gordon @ 2016-06-28 14:24 UTC (permalink / raw)
  To: Peter Antoine, intel-gfx; +Cc: sean.v.kelley, lawrence.t.li, rodrigo.vivi

On 21/06/16 19:11, Peter Antoine wrote:
> Rename some of the GuC fw loading code to make them more general. We
> will utilize them for HuC loading as well.
>      s/intel_guc_fw/intel_uc_fw/g
>      s/GUC_FIRMWARE/UC_FIRMWARE/g
>
> Struct intel_guc_fw is renamed to intel_uc_fw. Prefix of tts members,
> such as 'guc' or 'guc_fw' either is renamed to 'uc' or removed for
> same purpose.
>
> Signed-off-by: Alex Dai <yu.dai@intel.com>
> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
> ---
>   drivers/gpu/drm/i915/i915_debugfs.c        |  12 +-
>   drivers/gpu/drm/i915/i915_guc_submission.c |   4 +-
>   drivers/gpu/drm/i915/intel_guc.h           |  39 ++---
>   drivers/gpu/drm/i915/intel_guc_loader.c    | 221 ++++++++++++++++-------------
>   4 files changed, 151 insertions(+), 125 deletions(-)

The renaming is fine, but this patch also includes other changes 
(flagged below) which constitute a regression. It looks like it's based 
on (and is reinstating code from) Alex's original patch
- 33a732f drm/i915: GuC-specific firmware loader
thus reverting some of the changes in the more recent
+ fce91f2 drm/i915/guc: add enable_guc_loading parameter

I suggest the purely mechanical search-and-replace should be done in a 
first preliminary patch, and then any remaining changes should be 
carefully examined to see whether they are still wanted -- I suspect 
they aren't.

> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 7d63af0..69964c2 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -2483,7 +2483,7 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data)
>   {
>   	struct drm_info_node *node = m->private;
>   	struct drm_i915_private *dev_priv = node->minor->dev->dev_private;
> -	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
> +	struct intel_uc_fw *guc_fw = &dev_priv->guc.guc_fw;
>   	u32 tmp, i;
>
>   	if (!HAS_GUC_UCODE(dev_priv))
> @@ -2491,15 +2491,15 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data)
>
>   	seq_printf(m, "GuC firmware status:\n");
>   	seq_printf(m, "\tpath: %s\n",
> -		guc_fw->guc_fw_path);
> +		guc_fw->uc_fw_path);
>   	seq_printf(m, "\tfetch: %s\n",
> -		intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status));
> +		intel_uc_fw_status_repr(guc_fw->fetch_status));
>   	seq_printf(m, "\tload: %s\n",
> -		intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
> +		intel_uc_fw_status_repr(guc_fw->load_status));
>   	seq_printf(m, "\tversion wanted: %d.%d\n",
> -		guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted);
> +		guc_fw->major_ver_wanted, guc_fw->minor_ver_wanted);
>   	seq_printf(m, "\tversion found: %d.%d\n",
> -		guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found);
> +		guc_fw->major_ver_found, guc_fw->minor_ver_found);
>   	seq_printf(m, "\theader: offset is %d; size = %d\n",
>   		guc_fw->header_offset, guc_fw->header_size);
>   	seq_printf(m, "\tuCode: offset is %d; size = %d\n",
> diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
> index 01c7cdf..bfb8400 100644
> --- a/drivers/gpu/drm/i915/i915_guc_submission.c
> +++ b/drivers/gpu/drm/i915/i915_guc_submission.c
> @@ -1039,7 +1039,7 @@ int intel_guc_suspend(struct drm_device *dev)
>   	struct i915_gem_context *ctx;
>   	u32 data[3];
>
> -	if (guc->guc_fw.guc_fw_load_status != GUC_FIRMWARE_SUCCESS)
> +	if (guc->guc_fw.load_status != UC_FIRMWARE_SUCCESS)
>   		return 0;
>
>   	ctx = dev_priv->kernel_context;
> @@ -1065,7 +1065,7 @@ int intel_guc_resume(struct drm_device *dev)
>   	struct i915_gem_context *ctx;
>   	u32 data[3];
>
> -	if (guc->guc_fw.guc_fw_load_status != GUC_FIRMWARE_SUCCESS)
> +	if (guc->guc_fw.load_status != UC_FIRMWARE_SUCCESS)
>   		return 0;
>
>   	ctx = dev_priv->kernel_context;
> diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
> index 3e3e743..836420b 100644
> --- a/drivers/gpu/drm/i915/intel_guc.h
> +++ b/drivers/gpu/drm/i915/intel_guc.h
> @@ -90,29 +90,29 @@ struct i915_guc_client {
>   	uint64_t submissions[I915_NUM_ENGINES];
>   };
>
> -enum intel_guc_fw_status {
> -	GUC_FIRMWARE_FAIL = -1,
> -	GUC_FIRMWARE_NONE = 0,
> -	GUC_FIRMWARE_PENDING,
> -	GUC_FIRMWARE_SUCCESS
> +enum intel_uc_fw_status {
> +	UC_FIRMWARE_FAIL = -1,
> +	UC_FIRMWARE_NONE = 0,
> +	UC_FIRMWARE_PENDING,
> +	UC_FIRMWARE_SUCCESS
>   };
>
>   /*
>    * This structure encapsulates all the data needed during the process
>    * of fetching, caching, and loading the firmware image into the GuC.
>    */
> -struct intel_guc_fw {
> -	struct drm_device *		guc_dev;
> -	const char *			guc_fw_path;
> -	size_t				guc_fw_size;
> -	struct drm_i915_gem_object *	guc_fw_obj;
> -	enum intel_guc_fw_status	guc_fw_fetch_status;
> -	enum intel_guc_fw_status	guc_fw_load_status;
> -
> -	uint16_t			guc_fw_major_wanted;
> -	uint16_t			guc_fw_minor_wanted;
> -	uint16_t			guc_fw_major_found;
> -	uint16_t			guc_fw_minor_found;
> +struct intel_uc_fw {
> +	struct drm_device *uc_dev;
> +	const char *uc_fw_path;
> +	size_t uc_fw_size;
> +	struct drm_i915_gem_object *uc_fw_obj;
> +	enum intel_uc_fw_status fetch_status;
> +	enum intel_uc_fw_status	load_status;
> +
> +	uint16_t major_ver_wanted;
> +	uint16_t minor_ver_wanted;
> +	uint16_t major_ver_found;
> +	uint16_t minor_ver_found;
>
>   	uint32_t header_size;
>   	uint32_t header_offset;
> @@ -123,7 +123,7 @@ struct intel_guc_fw {
>   };
>
>   struct intel_guc {
> -	struct intel_guc_fw guc_fw;
> +	struct intel_uc_fw guc_fw;
>   	uint32_t log_flags;
>   	struct drm_i915_gem_object *log_obj;
>
> @@ -152,9 +152,10 @@ struct intel_guc {
>   extern void intel_guc_init(struct drm_device *dev);
>   extern int intel_guc_setup(struct drm_device *dev);
>   extern void intel_guc_fini(struct drm_device *dev);
> -extern const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status);
> +extern const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status);
>   extern int intel_guc_suspend(struct drm_device *dev);
>   extern int intel_guc_resume(struct drm_device *dev);
> +void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw);
>
>   /* i915_guc_submission.c */
>   int i915_guc_submission_init(struct drm_i915_private *dev_priv);
> diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
> index 8fe96a2..ff054f5 100644
> --- a/drivers/gpu/drm/i915/intel_guc_loader.c
> +++ b/drivers/gpu/drm/i915/intel_guc_loader.c
> @@ -66,16 +66,16 @@ MODULE_FIRMWARE(I915_SKL_GUC_UCODE);
>   MODULE_FIRMWARE(I915_BXT_GUC_UCODE);
>
>   /* User-friendly representation of an enum */
> -const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status)
> +const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status)
>   {
>   	switch (status) {
> -	case GUC_FIRMWARE_FAIL:
> +	case UC_FIRMWARE_FAIL:
>   		return "FAIL";
> -	case GUC_FIRMWARE_NONE:
> +	case UC_FIRMWARE_NONE:
>   		return "NONE";
> -	case GUC_FIRMWARE_PENDING:
> +	case UC_FIRMWARE_PENDING:
>   		return "PENDING";
> -	case GUC_FIRMWARE_SUCCESS:
> +	case UC_FIRMWARE_SUCCESS:
>   		return "SUCCESS";
>   	default:
>   		return "UNKNOWN!";
> @@ -238,8 +238,8 @@ static inline bool guc_ucode_response(struct drm_i915_private *dev_priv,
>    */
>   static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv)
>   {
> -	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
> -	struct drm_i915_gem_object *fw_obj = guc_fw->guc_fw_obj;
> +	struct intel_uc_fw *guc_fw = &dev_priv->guc.guc_fw;
> +	struct drm_i915_gem_object *fw_obj = guc_fw->uc_fw_obj;
>   	unsigned long offset;
>   	struct sg_table *sg = fw_obj->pages;
>   	u32 status, rsa[UOS_RSA_SCRATCH_MAX_COUNT];
> @@ -311,17 +311,17 @@ static u32 guc_wopcm_size(struct drm_i915_private *dev_priv)
>    */
>   static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
>   {
> -	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
> +	struct intel_uc_fw *guc_fw = &dev_priv->guc.guc_fw;
>   	struct drm_device *dev = dev_priv->dev;
>   	int ret;
>
> -	ret = i915_gem_object_set_to_gtt_domain(guc_fw->guc_fw_obj, false);
> +	ret = i915_gem_object_set_to_gtt_domain(guc_fw->uc_fw_obj, false);
>   	if (ret) {
>   		DRM_DEBUG_DRIVER("set-domain failed %d\n", ret);
>   		return ret;
>   	}
>
> -	ret = i915_gem_obj_ggtt_pin(guc_fw->guc_fw_obj, 0, 0);
> +	ret = i915_gem_obj_ggtt_pin(guc_fw->uc_fw_obj, 0, 0);
>   	if (ret) {
>   		DRM_DEBUG_DRIVER("pin failed %d\n", ret);
>   		return ret;
> @@ -373,7 +373,7 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
>   	 * We keep the object pages for reuse during resume. But we can unpin it
>   	 * now that DMA has completed, so it doesn't continue to take up space.
>   	 */
> -	i915_gem_object_ggtt_unpin(guc_fw->guc_fw_obj);
> +	i915_gem_object_ggtt_unpin(guc_fw->uc_fw_obj);
>
>   	return ret;
>   }
> @@ -412,46 +412,58 @@ static int i915_reset_guc(struct drm_i915_private *dev_priv)
>   int intel_guc_setup(struct drm_device *dev)

This section is the bit that looks like it's based on an old version of 
this function ...

>   {
>   	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
> -	const char *fw_path = guc_fw->guc_fw_path;
> -	int retries, ret, err;
> -
> -	DRM_DEBUG_DRIVER("GuC fw status: path %s, fetch %s, load %s\n",
> -		fw_path,
> -		intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status),
> -		intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
> -
> -	/* Loading forbidden, or no firmware to load? */
> -	if (!i915.enable_guc_loading) {
> -		err = 0;
> -		goto fail;
> -	} else if (fw_path == NULL) {
> -		/* Device is known to have no uCode (e.g. no GuC) */
> -		err = -ENXIO;
> -		goto fail;
> -	} else if (*fw_path == '\0') {
> -		/* Device has a GuC but we don't know what f/w to load? */
> -		DRM_INFO("No GuC firmware known for this platform\n");
> -		err = -ENODEV;
> -		goto fail;
> -	}
> +	struct intel_uc_fw *guc_fw = &dev_priv->guc.guc_fw;
> +	int retries, ret, err = 0;
> +
> +	if (!i915.enable_guc_loading)
> +		return 0;
> +
> +	DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n",
> +		intel_uc_fw_status_repr(guc_fw->fetch_status),
> +		intel_uc_fw_status_repr(guc_fw->load_status));
> +
> +	direct_interrupts_to_host(dev_priv);
> +
> +	if (guc_fw->fetch_status == UC_FIRMWARE_NONE)
> +		return 0;
> +
> +	if (guc_fw->fetch_status == UC_FIRMWARE_SUCCESS &&
> +	    guc_fw->load_status == UC_FIRMWARE_FAIL)
> +		return -ENOEXEC;
>
> -	/* Fetch failed, or already fetched but failed to load? */
> -	if (guc_fw->guc_fw_fetch_status != GUC_FIRMWARE_SUCCESS) {
> +	guc_fw->load_status = UC_FIRMWARE_PENDING;
> +
> +	DRM_DEBUG_DRIVER("GuC fw fetch status %s\n",
> +		intel_uc_fw_status_repr(guc_fw->fetch_status));
> +
> +	switch (guc_fw->fetch_status) {
> +	case UC_FIRMWARE_FAIL:
> +		/* something went wrong :( */
>   		err = -EIO;
>   		goto fail;
> -	} else if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_FAIL) {
> -		err = -ENOEXEC;
> +
> +	case UC_FIRMWARE_NONE:
> +	case UC_FIRMWARE_PENDING:
> +	default:
> +		/* "can't happen" */
> +		WARN_ONCE(1, "GuC fw %s invalid guc_fw_fetch_status %s [%d]\n",
> +			guc_fw->uc_fw_path,
> +			intel_uc_fw_status_repr(guc_fw->fetch_status),
> +			guc_fw->fetch_status);
> +		err = -ENXIO;
>   		goto fail;
> +
> +	case UC_FIRMWARE_SUCCESS:
> +		break;
>   	}

After this we're mostly back to search-and-replace, I think.

.Dave.

>   	direct_interrupts_to_host(dev_priv);
>
> -	guc_fw->guc_fw_load_status = GUC_FIRMWARE_PENDING;
> +	guc_fw->load_status = UC_FIRMWARE_PENDING;
>
>   	DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n",
> -		intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status),
> -		intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
> +		intel_uc_fw_status_repr(guc_fw->fetch_status),
> +		intel_uc_fw_status_repr(guc_fw->load_status));
>
>   	err = i915_guc_submission_init(dev_priv);
>   	if (err)
> @@ -485,11 +497,11 @@ int intel_guc_setup(struct drm_device *dev)
>   			 "retry %d more time(s)\n", err, retries);
>   	}
>
> -	guc_fw->guc_fw_load_status = GUC_FIRMWARE_SUCCESS;
> +	guc_fw->load_status = UC_FIRMWARE_SUCCESS;
>
>   	DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n",
> -		intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status),
> -		intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
> +		intel_uc_fw_status_repr(guc_fw->fetch_status),
> +		intel_uc_fw_status_repr(guc_fw->load_status));
>
>   	if (i915.enable_guc_submission) {
>   		err = i915_guc_submission_enable(dev_priv);
> @@ -501,8 +513,8 @@ int intel_guc_setup(struct drm_device *dev)
>   	return 0;
>
>   fail:
> -	if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_PENDING)
> -		guc_fw->guc_fw_load_status = GUC_FIRMWARE_FAIL;
> +	if (guc_fw->load_status == UC_FIRMWARE_PENDING)
> +		guc_fw->load_status = UC_FIRMWARE_FAIL;
>
>   	direct_interrupts_to_host(dev_priv);
>   	i915_guc_submission_disable(dev_priv);
> @@ -535,7 +547,7 @@ fail:
>   		DRM_ERROR("GuC firmware load failed: %d\n", err);
>
>   	if (i915.enable_guc_submission) {
> -		if (fw_path == NULL)
> +		if (guc_fw->uc_fw_path == NULL)
>   			DRM_INFO("GuC submission without firmware not supported\n");
>   		if (ret == 0)
>   			DRM_INFO("Falling back from GuC submission to execlist mode\n");
> @@ -547,7 +559,18 @@ fail:
>   	return ret;
>   }
>
> -static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw)
> +/**
> + * intel_uc_fw_fetch() - fetch fw blob and save it to internal obj
> + * @dev:	drm device
> + * @uc_fw:	the intel_uc_fw to be setup
> + *
> + * The caller should have setup fw path and fw version required. This function
> + * first fetch the fw blob from file system. If succeed, it will do some basic
> + * check based on css header information. At last, a GEM obj is created and
> + * filled with the fw data. This obj will be loaded to HW at later stage of
> + * driver init process.
> + */
> +void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw)
>   {
>   	struct drm_i915_gem_object *obj;
>   	const struct firmware *fw;
> @@ -555,17 +578,17 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw)
>   	size_t size;
>   	int err;
>
> -	DRM_DEBUG_DRIVER("before requesting firmware: GuC fw fetch status %s\n",
> -		intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status));
> +	DRM_DEBUG_DRIVER("before requesting firmware: uC fw fetch status %s\n",
> +		intel_uc_fw_status_repr(uc_fw->fetch_status));
>
> -	err = request_firmware(&fw, guc_fw->guc_fw_path, &dev->pdev->dev);
> +	err = request_firmware(&fw, uc_fw->uc_fw_path, &dev->pdev->dev);
>   	if (err)
>   		goto fail;
>   	if (!fw)
>   		goto fail;
>
> -	DRM_DEBUG_DRIVER("fetch GuC fw from %s succeeded, fw %p\n",
> -		guc_fw->guc_fw_path, fw);
> +	DRM_DEBUG_DRIVER("fetch uC fw from %s succeeded, fw %p\n",
> +		uc_fw->uc_fw_path, fw);
>
>   	/* Check the size of the blob before examining buffer contents */
>   	if (fw->size < sizeof(struct guc_css_header)) {
> @@ -576,62 +599,64 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw)
>   	css = (struct guc_css_header *)fw->data;
>
>   	/* Firmware bits always start from header */
> -	guc_fw->header_offset = 0;
> -	guc_fw->header_size = (css->header_size_dw - css->modulus_size_dw -
> +	uc_fw->header_offset = 0;
> +	uc_fw->header_size = (css->header_size_dw - css->modulus_size_dw -
>   		css->key_size_dw - css->exponent_size_dw) * sizeof(u32);
>
> -	if (guc_fw->header_size != sizeof(struct guc_css_header)) {
> +	if (uc_fw->header_size != sizeof(struct guc_css_header)) {
>   		DRM_ERROR("CSS header definition mismatch\n");
>   		goto fail;
>   	}
>
>   	/* then, uCode */
> -	guc_fw->ucode_offset = guc_fw->header_offset + guc_fw->header_size;
> -	guc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32);
> +	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);
>
>   	/* now RSA */
>   	if (css->key_size_dw != UOS_RSA_SCRATCH_MAX_COUNT) {
>   		DRM_ERROR("RSA key size is bad\n");
>   		goto fail;
>   	}
> -	guc_fw->rsa_offset = guc_fw->ucode_offset + guc_fw->ucode_size;
> -	guc_fw->rsa_size = css->key_size_dw * sizeof(u32);
> +	uc_fw->rsa_offset = uc_fw->ucode_offset + uc_fw->ucode_size;
> +	uc_fw->rsa_size = css->key_size_dw * sizeof(u32);
>
>   	/* At least, it should have header, uCode and RSA. Size of all three. */
> -	size = guc_fw->header_size + guc_fw->ucode_size + guc_fw->rsa_size;
> +	size = uc_fw->header_size + uc_fw->ucode_size + uc_fw->rsa_size;
>   	if (fw->size < size) {
>   		DRM_ERROR("Missing firmware components\n");
>   		goto fail;
>   	}
>
>   	/* Header and uCode will be loaded to WOPCM. Size of the two. */
> -	size = guc_fw->header_size + guc_fw->ucode_size;
> +	size = uc_fw->header_size + uc_fw->ucode_size;
> +
> +	/* Top 32k of WOPCM is reserved (8K stack + 24k RC6 context). */
>   	if (size > guc_wopcm_size(dev->dev_private)) {
>   		DRM_ERROR("Firmware is too large to fit in WOPCM\n");
>   		goto fail;
>   	}
>
>   	/*
> -	 * The GuC firmware image has the version number embedded at a well-known
> +	 * The uC firmware image has the version number embedded at a well-known
>   	 * offset within the firmware blob; note that major / minor version are
>   	 * TWO bytes each (i.e. u16), although all pointers and offsets are defined
>   	 * in terms of bytes (u8).
>   	 */
> -	guc_fw->guc_fw_major_found = css->guc_sw_version >> 16;
> -	guc_fw->guc_fw_minor_found = css->guc_sw_version & 0xFFFF;
> -
> -	if (guc_fw->guc_fw_major_found != guc_fw->guc_fw_major_wanted ||
> -	    guc_fw->guc_fw_minor_found < guc_fw->guc_fw_minor_wanted) {
> -		DRM_ERROR("GuC firmware version %d.%d, required %d.%d\n",
> -			guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found,
> -			guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted);
> +	uc_fw->major_ver_found = css->guc_sw_version >> 16;
> +	uc_fw->minor_ver_found = css->guc_sw_version & 0xFFFF;
> +
> +	if (uc_fw->major_ver_found != uc_fw->major_ver_wanted ||
> +	    uc_fw->minor_ver_found < uc_fw->minor_ver_wanted) {
> +		DRM_ERROR("Firmware version %d.%d, required %d.%d\n",
> +			uc_fw->major_ver_found, uc_fw->minor_ver_found,
> +			uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted);
>   		err = -ENOEXEC;
>   		goto fail;
>   	}
>
>   	DRM_DEBUG_DRIVER("firmware version %d.%d OK (minimum %d.%d)\n",
> -			guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found,
> -			guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted);
> +			uc_fw->major_ver_found, uc_fw->minor_ver_found,
> +			uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted);
>
>   	mutex_lock(&dev->struct_mutex);
>   	obj = i915_gem_object_create_from_data(dev, fw->data, fw->size);
> @@ -641,31 +666,31 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw)
>   		goto fail;
>   	}
>
> -	guc_fw->guc_fw_obj = obj;
> -	guc_fw->guc_fw_size = fw->size;
> +	uc_fw->uc_fw_obj = obj;
> +	uc_fw->uc_fw_size = fw->size;
>
>   	DRM_DEBUG_DRIVER("GuC fw fetch status SUCCESS, obj %p\n",
> -			guc_fw->guc_fw_obj);
> +			uc_fw->uc_fw_obj);
>
>   	release_firmware(fw);
> -	guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_SUCCESS;
> +	uc_fw->fetch_status = UC_FIRMWARE_SUCCESS;
>   	return;
>
>   fail:
>   	DRM_DEBUG_DRIVER("GuC fw fetch status FAIL; err %d, fw %p, obj %p\n",
> -		err, fw, guc_fw->guc_fw_obj);
> +		err, fw, uc_fw->uc_fw_obj);
>   	DRM_ERROR("Failed to fetch GuC firmware from %s (error %d)\n",
> -		  guc_fw->guc_fw_path, err);
> +		  uc_fw->uc_fw_path, err);
>
>   	mutex_lock(&dev->struct_mutex);
> -	obj = guc_fw->guc_fw_obj;
> +	obj = uc_fw->uc_fw_obj;
>   	if (obj)
>   		drm_gem_object_unreference(&obj->base);
> -	guc_fw->guc_fw_obj = NULL;
> +	uc_fw->uc_fw_obj = NULL;
>   	mutex_unlock(&dev->struct_mutex);
>
>   	release_firmware(fw);		/* OK even if fw is NULL */
> -	guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_FAIL;
> +	uc_fw->fetch_status = UC_FIRMWARE_FAIL;
>   }
>
>   /**
> @@ -680,7 +705,7 @@ fail:
>   void intel_guc_init(struct drm_device *dev)
>   {
>   	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
> +	struct intel_uc_fw *guc_fw = &dev_priv->guc.guc_fw;
>   	const char *fw_path;
>
>   	/* A negative value means "use platform default" */
> @@ -693,20 +718,20 @@ void intel_guc_init(struct drm_device *dev)
>   		fw_path = NULL;
>   	} else if (IS_SKYLAKE(dev)) {
>   		fw_path = I915_SKL_GUC_UCODE;
> -		guc_fw->guc_fw_major_wanted = 6;
> -		guc_fw->guc_fw_minor_wanted = 1;
> +		guc_fw->major_ver_wanted = 6;
> +		guc_fw->minor_ver_wanted = 1;
>   	} else if (IS_BROXTON(dev)) {
>   		fw_path = I915_BXT_GUC_UCODE;
> -		guc_fw->guc_fw_major_wanted = 8;
> -		guc_fw->guc_fw_minor_wanted = 7;
> +		guc_fw->major_ver_wanted = 8;
> +		guc_fw->minor_ver_wanted = 7;
>   	} else {
>   		fw_path = "";	/* unknown device */
>   	}
>
> -	guc_fw->guc_dev = dev;
> -	guc_fw->guc_fw_path = fw_path;
> -	guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_NONE;
> -	guc_fw->guc_fw_load_status = GUC_FIRMWARE_NONE;
> +	guc_fw->uc_dev = dev;
> +	guc_fw->uc_fw_path = fw_path;
> +	guc_fw->fetch_status = UC_FIRMWARE_NONE;
> +	guc_fw->load_status = UC_FIRMWARE_NONE;
>
>   	/* Early (and silent) return if GuC loading is disabled */
>   	if (!i915.enable_guc_loading)
> @@ -716,9 +741,9 @@ void intel_guc_init(struct drm_device *dev)
>   	if (*fw_path == '\0')
>   		return;
>
> -	guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_PENDING;
> +	guc_fw->fetch_status = UC_FIRMWARE_PENDING;
>   	DRM_DEBUG_DRIVER("GuC firmware pending, path %s\n", fw_path);
> -	guc_fw_fetch(dev, guc_fw);
> +	intel_uc_fw_fetch(dev, guc_fw);
>   	/* status must now be FAIL or SUCCESS */
>   }
>
> @@ -729,17 +754,17 @@ void intel_guc_init(struct drm_device *dev)
>   void intel_guc_fini(struct drm_device *dev)
>   {
>   	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
> +	struct intel_uc_fw *guc_fw = &dev_priv->guc.guc_fw;
>
>   	mutex_lock(&dev->struct_mutex);
>   	direct_interrupts_to_host(dev_priv);
>   	i915_guc_submission_disable(dev_priv);
>   	i915_guc_submission_fini(dev_priv);
>
> -	if (guc_fw->guc_fw_obj)
> -		drm_gem_object_unreference(&guc_fw->guc_fw_obj->base);
> -	guc_fw->guc_fw_obj = NULL;
> +	if (guc_fw->uc_fw_obj)
> +		drm_gem_object_unreference(&guc_fw->uc_fw_obj->base);
> +	guc_fw->uc_fw_obj = NULL;
>   	mutex_unlock(&dev->struct_mutex);
>
> -	guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_NONE;
> +	guc_fw->fetch_status = UC_FIRMWARE_NONE;
>   }
>

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

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

* Re: [PATCH 2/6] drm/i915/huc: Unified css_header struct for GuC and HuC
  2016-06-21 18:11 ` [PATCH 2/6] drm/i915/huc: Unified css_header struct for GuC and HuC Peter Antoine
@ 2016-06-28 14:32   ` Dave Gordon
  2016-06-30 10:39     ` Antoine, Peter
  0 siblings, 1 reply; 40+ messages in thread
From: Dave Gordon @ 2016-06-28 14:32 UTC (permalink / raw)
  To: Peter Antoine, intel-gfx; +Cc: sean.v.kelley, lawrence.t.li, rodrigo.vivi

On 21/06/16 19:11, Peter Antoine wrote:
> From: Alex Dai <yu.dai@intel.com>
>
> HuC firmware css header has almost exactly same definition as GuC
> firmware except for the sw_version. Also, add a new member fw_type
> into intel_uc_fw to indicate what kind of fw it is. So, the loader
> will pull right sw_version from header.
>
> Signed-off-by: Alex Dai <yu.dai@intel.com>
> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
> ---
>   drivers/gpu/drm/i915/intel_guc.h        |  4 ++++
>   drivers/gpu/drm/i915/intel_guc_fwif.h   | 16 ++++++++++---
>   drivers/gpu/drm/i915/intel_guc_loader.c | 42 +++++++++++++++++++++------------
>   3 files changed, 44 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
> index 836420b..0b4ed88 100644
> --- a/drivers/gpu/drm/i915/intel_guc.h
> +++ b/drivers/gpu/drm/i915/intel_guc.h
> @@ -97,6 +97,9 @@ enum intel_uc_fw_status {
>   	UC_FIRMWARE_SUCCESS
>   };
>
> +#define UC_FW_TYPE_GUC		0
> +#define UC_FW_TYPE_HUC		1
> +
>   /*
>    * This structure encapsulates all the data needed during the process
>    * of fetching, caching, and loading the firmware image into the GuC.
> @@ -114,6 +117,7 @@ struct intel_uc_fw {
>   	uint16_t major_ver_found;
>   	uint16_t minor_ver_found;
>
> +	uint32_t fw_type;
>   	uint32_t header_size;
>   	uint32_t header_offset;
>   	uint32_t rsa_size;
> diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h
> index 944786d..a69ee36 100644
> --- a/drivers/gpu/drm/i915/intel_guc_fwif.h
> +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
> @@ -154,7 +154,7 @@
>    * The GuC firmware layout looks like this:
>    *
>    *     +-------------------------------+
> - *     |        guc_css_header         |
> + *     |         uc_css_header         |
>    *     | contains major/minor version  |
>    *     +-------------------------------+
>    *     |             uCode             |
> @@ -180,9 +180,16 @@
>    * 3. Length info of each component can be found in header, in dwords.
>    * 4. Modulus and exponent key are not required by driver. They may not appear
>    * in fw. So driver will load a truncated firmware in this case.
> + *
> + * HuC firmware layout is same as GuC firmware.
> + *
> + * HuC firmware css header is different. However, the only difference is where
> + * the version information is saved. The uc_css_header is unified to support
> + * both. Driver should get HuC version from uc_css_header.huc_sw_version, while
> + * uc_css_header.guc_sw_version for GuC.
>    */
>
> -struct guc_css_header {
> +struct uc_css_header {

This name change could have been part of the previous global 
search-and-replace.

>   	uint32_t module_type;
>   	/* header_size includes all non-uCode bits, including css_header, rsa
>   	 * key, modulus key and exponent data. */
> @@ -213,7 +220,10 @@ struct guc_css_header {
>
>   	char username[8];
>   	char buildnumber[12];
> -	uint32_t device_id;
> +	union {
> +		uint32_t device_id;
> +		uint32_t huc_sw_version;
> +	};
>   	uint32_t guc_sw_version;
>   	uint32_t prod_preprod_fw;
>   	uint32_t reserved[12];

This can't really be right; the HuC f/w header doesn't contain a 
guc_sw_version! So the union must be more like:

	union {
		struct {
			uint32_t device_id;
			uint32_t guc_sw_version;
			uint32_t prod_preprod_fw;
		} guc_data;
		struct {
			uint32_t huc_sw_version;
			uint32_t prod_preprod_fw;
			uint32_t dummy;
		} huc_data;
	};
    	uint32_t reserved[12];

... or something - I don't know what the actual layout is here.

Otherwise generally OK.

.Dave.

> diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
> index ff054f5..70575bd 100644
> --- a/drivers/gpu/drm/i915/intel_guc_loader.c
> +++ b/drivers/gpu/drm/i915/intel_guc_loader.c
> @@ -574,7 +574,7 @@ void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw)
>   {
>   	struct drm_i915_gem_object *obj;
>   	const struct firmware *fw;
> -	struct guc_css_header *css;
> +	struct uc_css_header *css;
>   	size_t size;
>   	int err;
>
> @@ -591,19 +591,19 @@ void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw)
>   		uc_fw->uc_fw_path, fw);
>
>   	/* Check the size of the blob before examining buffer contents */
> -	if (fw->size < sizeof(struct guc_css_header)) {
> +	if (fw->size < sizeof(struct uc_css_header)) {
>   		DRM_ERROR("Firmware header is missing\n");
>   		goto fail;
>   	}
>
> -	css = (struct guc_css_header *)fw->data;
> +	css = (struct uc_css_header *)fw->data;
>
>   	/* Firmware bits always start from header */
>   	uc_fw->header_offset = 0;
>   	uc_fw->header_size = (css->header_size_dw - css->modulus_size_dw -
>   		css->key_size_dw - css->exponent_size_dw) * sizeof(u32);
>
> -	if (uc_fw->header_size != sizeof(struct guc_css_header)) {
> +	if (uc_fw->header_size != sizeof(struct uc_css_header)) {
>   		DRM_ERROR("CSS header definition mismatch\n");
>   		goto fail;
>   	}
> @@ -627,23 +627,35 @@ void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw)
>   		goto fail;
>   	}
>
> -	/* Header and uCode will be loaded to WOPCM. Size of the two. */
> -	size = uc_fw->header_size + uc_fw->ucode_size;
> -
> -	/* Top 32k of WOPCM is reserved (8K stack + 24k RC6 context). */
> -	if (size > guc_wopcm_size(dev->dev_private)) {
> -		DRM_ERROR("Firmware is too large to fit in WOPCM\n");
> -		goto fail;
> -	}
> -
>   	/*
>   	 * The uC firmware image has the version number embedded at a well-known
>   	 * offset within the firmware blob; note that major / minor version are
>   	 * TWO bytes each (i.e. u16), although all pointers and offsets are defined
>   	 * in terms of bytes (u8).
>   	 */
> -	uc_fw->major_ver_found = css->guc_sw_version >> 16;
> -	uc_fw->minor_ver_found = css->guc_sw_version & 0xFFFF;
> +	switch (uc_fw->fw_type) {
> +	case UC_FW_TYPE_GUC:
> +		/* Header and uCode will be loaded to WOPCM. Size of the two. */
> +		size = uc_fw->header_size + uc_fw->ucode_size;
> +
> +		/* Top 32k of WOPCM is reserved (8K stack + 24k RC6 context). */
> +		if (size > guc_wopcm_size(dev->dev_private)) {
> +			DRM_ERROR("Firmware is too large to fit in WOPCM\n");
> +			goto fail;
> +		}
> +
> +		uc_fw->major_ver_found = css->guc_sw_version >> 16;
> +		uc_fw->minor_ver_found = css->guc_sw_version & 0xFFFF;
> +		break;
> +	case UC_FW_TYPE_HUC:
> +		uc_fw->major_ver_found = css->huc_sw_version >> 16;
> +		uc_fw->minor_ver_found = css->huc_sw_version & 0xFFFF;
> +		break;
> +	default:
> +		DRM_ERROR("Unknown firmware type %d\n", uc_fw->fw_type);
> +		err = -ENOEXEC;
> +		goto fail;
> +	}
>
>   	if (uc_fw->major_ver_found != uc_fw->major_ver_wanted ||
>   	    uc_fw->minor_ver_found < uc_fw->minor_ver_wanted) {
>

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

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

* Re: [PATCH 3/6] drm/i915/huc: Add HuC fw loading support
  2016-06-21 18:11 ` [PATCH 3/6] drm/i915/huc: Add HuC fw loading support Peter Antoine
  2016-06-22  8:31   ` Daniel Vetter
@ 2016-06-28 14:54   ` Dave Gordon
  2016-06-28 15:45     ` Dave Gordon
  1 sibling, 1 reply; 40+ messages in thread
From: Dave Gordon @ 2016-06-28 14:54 UTC (permalink / raw)
  To: Peter Antoine, intel-gfx; +Cc: sean.v.kelley, lawrence.t.li, rodrigo.vivi

On 21/06/16 19:11, Peter Antoine wrote:
> From: Alex Dai <yu.dai@intel.com>
>
> The HuC loading process is similar to GuC. The intel_uc_fw_fetch()
> is used for both cases.
>
> HuC loading needs to be before GuC loading. The WOPCM setting must
> be done early before loading any of them.
>
> Signed-off-by: Alex Dai <yu.dai@intel.com>
> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
> ---
>   drivers/gpu/drm/i915/Makefile           |   1 +
>   drivers/gpu/drm/i915/i915_dma.c         |   3 +
>   drivers/gpu/drm/i915/i915_drv.h         |   3 +
>   drivers/gpu/drm/i915/i915_gem.c         |  13 +-
>   drivers/gpu/drm/i915/i915_guc_reg.h     |   3 +
>   drivers/gpu/drm/i915/intel_guc.h        |   1 +
>   drivers/gpu/drm/i915/intel_guc_loader.c |  11 +-
>   drivers/gpu/drm/i915/intel_huc.h        |  44 ++++++
>   drivers/gpu/drm/i915/intel_huc_loader.c | 262 ++++++++++++++++++++++++++++++++
>   9 files changed, 331 insertions(+), 10 deletions(-)
>   create mode 100644 drivers/gpu/drm/i915/intel_huc.h
>   create mode 100644 drivers/gpu/drm/i915/intel_huc_loader.c
>
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 276abf1..7384db0 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -44,6 +44,7 @@ i915-y += i915_cmd_parser.o \
>
>   # general-purpose microcontroller (GuC) support
>   i915-y += intel_guc_loader.o \
> +	  intel_huc_loader.o \
>   	  i915_guc_submission.o
>
>   # autogenerated null render state
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index e28c0dd..a449a59 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -507,6 +507,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
>   	 * working irqs for e.g. gmbus and dp aux transfers. */
>   	intel_modeset_init(dev);
>
> +	intel_huc_init(dev);
>   	intel_guc_init(dev);
>
>   	ret = i915_gem_init(dev);
> @@ -532,6 +533,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
>   cleanup_gem:
>   	i915_gem_fini(dev);
>   cleanup_irq:
> +	intel_huc_fini(dev);
>   	intel_guc_fini(dev);
>   	drm_irq_uninstall(dev);
>   	intel_teardown_gmbus(dev);
> @@ -1563,6 +1565,7 @@ int i915_driver_unload(struct drm_device *dev)
>   	/* Flush any outstanding unpin_work. */
>   	flush_workqueue(dev_priv->wq);
>
> +	intel_huc_fini(dev);
>   	intel_guc_fini(dev);
>   	i915_gem_fini(dev);
>   	intel_fbc_cleanup_cfb(dev_priv);
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 7c81757..8b88227 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -54,6 +54,7 @@
>   #include "intel_bios.h"
>   #include "intel_dpll_mgr.h"
>   #include "intel_guc.h"
> +#include "intel_huc.h"
>   #include "intel_lrc.h"
>   #include "intel_ringbuffer.h"
>
> @@ -1749,6 +1750,7 @@ struct drm_i915_private {
>
>   	struct intel_gvt gvt;
>
> +	struct intel_huc huc;
>   	struct intel_guc guc;
>
>   	struct intel_csr csr;
> @@ -2841,6 +2843,7 @@ struct drm_i915_cmd_table {
>   #define HAS_GUC(dev)		(IS_GEN9(dev) && !IS_KABYLAKE(dev))
>   #define HAS_GUC_UCODE(dev)	(HAS_GUC(dev))
>   #define HAS_GUC_SCHED(dev)	(HAS_GUC(dev))
> +#define HAS_HUC_UCODE(dev)	(HAS_GUC(dev))
>
>   #define HAS_RESOURCE_STREAMER(dev) (IS_HASWELL(dev) || \
>   				    INTEL_INFO(dev)->gen >= 8)
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 6abd5e5..549dd3f 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -5143,9 +5143,16 @@ i915_gem_init_hw(struct drm_device *dev)
>   	intel_mocs_init_l3cc_table(dev);
>
>   	/* We can't enable contexts until all firmware is loaded */
> -	ret = intel_guc_setup(dev);
> -	if (ret)
> -		goto out;
> +	if (HAS_GUC(dev)) {
> +		/* init WOPCM */
> +		I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev));
> +		I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE);
> +
> +		intel_huc_load(dev);
> +		ret = intel_guc_setup(dev);
> +		if (ret)
> +			goto out;
> +	}

No -- the call to intel_guc_setup() at least should not be inside the 
HAS_GUC() clause. It needs to be called anyway, to ensure execlist mode 
is set up correctly if GuC mode is not supported.

See e556f7c16 drm/i915/guc: fix GuC loading/submission check

>   	/*
>   	 * Increment the next seqno by 0x100 so we have a visible break
> diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h b/drivers/gpu/drm/i915/i915_guc_reg.h
> index cf5a65b..51533f1 100644
> --- a/drivers/gpu/drm/i915/i915_guc_reg.h
> +++ b/drivers/gpu/drm/i915/i915_guc_reg.h
> @@ -61,9 +61,12 @@
>   #define   DMA_ADDRESS_SPACE_GTT		  (8 << 16)
>   #define DMA_COPY_SIZE			_MMIO(0xc310)
>   #define DMA_CTRL			_MMIO(0xc314)
> +#define   HUC_UKERNEL			  (1<<9)
>   #define   UOS_MOVE			  (1<<4)
>   #define   START_DMA			  (1<<0)
>   #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)
>
> diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
> index 0b4ed88..c4b92f3 100644
> --- a/drivers/gpu/drm/i915/intel_guc.h
> +++ b/drivers/gpu/drm/i915/intel_guc.h
> @@ -160,6 +160,7 @@ extern const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status);
>   extern int intel_guc_suspend(struct drm_device *dev);
>   extern int intel_guc_resume(struct drm_device *dev);
>   void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw);
> +u32 guc_wopcm_size(struct drm_device *dev);
>
>   /* i915_guc_submission.c */
>   int i915_guc_submission_init(struct drm_i915_private *dev_priv);
> diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
> index 70575bd..c4a210d 100644
> --- a/drivers/gpu/drm/i915/intel_guc_loader.c
> +++ b/drivers/gpu/drm/i915/intel_guc_loader.c
> @@ -270,7 +270,8 @@ static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv)
>   	I915_WRITE(DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM);
>
>   	/* Finally start the DMA */
> -	I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(UOS_MOVE | START_DMA));
> +	I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(UOS_MOVE | START_DMA) |
> +			_MASKED_BIT_DISABLE(HUC_UKERNEL));
>
>   	/*
>   	 * Wait for the DMA to complete & the GuC to start up.
> @@ -295,12 +296,12 @@ static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv)
>   	return ret;
>   }
>
> -static u32 guc_wopcm_size(struct drm_i915_private *dev_priv)
> +u32 guc_wopcm_size(struct drm_device *dev)
>   {
>   	u32 wopcm_size = GUC_WOPCM_TOP;
>
>   	/* On BXT, the top of WOPCM is reserved for RC6 context */
> -	if (IS_BROXTON(dev_priv))
> +	if (IS_BROXTON(dev))

No -- dev_priv is preferred.

>   		wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED;
>
>   	return wopcm_size;
> @@ -332,10 +333,6 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
>
>   	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
>
> -	/* init WOPCM */
> -	I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev_priv));
> -	I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE);
> -
>   	/* Enable MIA caching. GuC clock gating is disabled. */
>   	I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE);
>
> diff --git a/drivers/gpu/drm/i915/intel_huc.h b/drivers/gpu/drm/i915/intel_huc.h
> new file mode 100644
> index 0000000..946caa7
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_huc.h
> @@ -0,0 +1,44 @@
> +/*
> + * Copyright © 2014 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_HUC_H_
> +#define _INTEL_HUC_H_
> +
> +#include "intel_guc.h"
> +
> +#define HUC_STATUS2		_MMIO(0xD3B0)
> +#define   HUC_FW_VERIFIED	(1<<7)
> +
> +struct intel_huc {
> +	/* Generic uC firmware management */
> +	struct intel_uc_fw huc_fw;
> +
> +	/* HuC-specific additions */
> +};
> +
> +extern void intel_huc_init(struct drm_device *dev);
> +extern int intel_huc_load(struct drm_device *dev);
> +extern void intel_huc_auth(struct drm_device *dev);
> +extern void intel_huc_fini(struct drm_device *dev);
> +
> +#endif
> diff --git a/drivers/gpu/drm/i915/intel_huc_loader.c b/drivers/gpu/drm/i915/intel_huc_loader.c
> new file mode 100644
> index 0000000..472fabe
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_huc_loader.c
> @@ -0,0 +1,262 @@
> +/*
> + * Copyright © 2014 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 <linux/firmware.h>
> +#include "i915_drv.h"
> +#include "intel_huc.h"
> +
> +/**
> + * DOC: HuC Firmware
> + *
> + * Motivation:
> + * GEN9 introduces a new dedicated firmware for usage in media HEVC (High
> + * Efficiency Video Coding) operations. Userspace can use the firmware
> + * capabilities by adding HuC specific commands to batch buffers.
> + *
> + * Implementation:
> + * On supported platforms, i915's job is to load the firmware stored on the
> + * file system and assist with authentication. It is up to userspace to
> + * detect the presence of HuC support on a platform, on their own.
> + * For debugging, i915 provides a debugfs file, i915_huc_load_status_info
> + * which displays the firmware load status.
> + *
> + * The unified uC firmware loader is used. Firmware binary is fetched by the
> + * loader asynchronously from the driver init process. However, the actual
> + * loading to HW is deferred until GEM initialization is done. Be note that HuC
> + * firmware loading must be done before GuC loading.
> + */
> +
> +#define I915_SKL_HUC_UCODE "i915/skl_huc_ver1.bin"
> +MODULE_FIRMWARE(I915_SKL_HUC_UCODE);
> +
> +/**
> + * intel_huc_load_ucode() - DMA's the firmware
> + * @dev: the drm device
> + *
> + * This function takes the gem object containing the firmware, sets up the DMA
> + * engine MMIO, triggers the DMA operation and waits for it to finish.
> + *
> + * Transfer the firmware image to RAM for execution by the microcontroller.
> + *
> + * Return: 0 on success, non-zero on failure
> + */
> +
> +static int huc_ucode_xfer(struct drm_i915_private *dev_priv)
> +{
> +	struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
> +	unsigned long offset = 0;
> +	u32 size;
> +	int ret;
> +
> +	ret = i915_gem_object_set_to_gtt_domain(huc_fw->uc_fw_obj, false);
> +	if (ret) {
> +		DRM_DEBUG_DRIVER("set-domain failed %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = i915_gem_obj_ggtt_pin(huc_fw->uc_fw_obj, 0, 0);
> +	if (ret) {
> +		DRM_DEBUG_DRIVER("pin failed %d\n", ret);
> +		return ret;
> +	}
> +
> +	/* Invalidate GuC TLB to let GuC take the latest updates to GTT. */
> +	I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);
> +
> +	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
> +	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
> +
> +	/* Set the source address for the uCode */
> +	offset = i915_gem_obj_ggtt_offset(huc_fw->uc_fw_obj) +
> +			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);
> +
> +	/* Hardware doesn't look at destination address for HuC. Set it to 0,
> +	 * but still program the correct address space.
> +	 */
> +	I915_WRITE(DMA_ADDR_1_LOW, 0);
> +	I915_WRITE(DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM);
> +
> +	size = huc_fw->header_size + huc_fw->ucode_size;
> +	I915_WRITE(DMA_COPY_SIZE, size);
> +
> +	/* Start the DMA */
> +	I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(HUC_UKERNEL | START_DMA));
> +
> +	/* Wait for DMA to finish */
> +	ret = wait_for_atomic((I915_READ(DMA_CTRL) & START_DMA) == 0, 50);
> +
> +	DRM_DEBUG_DRIVER("HuC DMA transfer wait over with ret %d\n", ret);
> +
> +	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
> +
> +	/*
> +	 * We keep the object pages for reuse during resume. But we can unpin it
> +	 * now that DMA has completed, so it doesn't continue to take up space.
> +	 */
> +	i915_gem_object_ggtt_unpin(huc_fw->uc_fw_obj);
> +
> +	return ret;
> +}
> +
> +/**
> + * intel_huc_init() - initiate HuC firmware loading request
> + * @dev: the drm device
> + *
> + * Called early during driver load, but after GEM is initialised. The loading
> + * will continue only when driver explicitly specify firmware name and version.
> + * All other cases are considered as UC_FIRMWARE_NONE either because HW is not
> + * capable or driver yet support it. And there will be no error message for
> + * UC_FIRMWARE_NONE cases.
> + *
> + * The DMA-copying to HW is done later when intel_huc_ucode_load() is called.
> + */
> +void intel_huc_init(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_huc *huc = &dev_priv->huc;
> +	struct intel_uc_fw *huc_fw = &huc->huc_fw;
> +	const char *fw_path = NULL;
> +
> +	huc_fw->uc_dev = dev;
> +	huc_fw->uc_fw_path = NULL;
> +	huc_fw->fetch_status = UC_FIRMWARE_NONE;
> +	huc_fw->load_status = UC_FIRMWARE_NONE;
> +	huc_fw->fw_type = UC_FW_TYPE_HUC;
> +
> +	if (!HAS_HUC_UCODE(dev))

dev_priv is preferred for all such macros

> +		return;
> +
> +	if (IS_SKYLAKE(dev)) {

and again.

The rest looks OK.

.Dave.

> +		fw_path = I915_SKL_HUC_UCODE;
> +		huc_fw->major_ver_wanted = 1;
> +		huc_fw->minor_ver_wanted = 5;
> +	}
> +
> +	if (fw_path == NULL)
> +		return;
> +
> +	huc_fw->uc_fw_path = fw_path;
> +	huc_fw->fetch_status = UC_FIRMWARE_PENDING;
> +
> +	DRM_DEBUG_DRIVER("HuC firmware pending, path %s\n", fw_path);
> +
> +	intel_uc_fw_fetch(dev, huc_fw);
> +}
> +
> +/**
> + * intel_huc_load() - load HuC uCode to device
> + * @dev: the drm device
> + *
> + * Called from gem_init_hw() during driver loading and also after a GPU reset.
> + * Be note that HuC loading must be done before GuC loading.
> + *
> + * The firmware image should have already been fetched into memory by the
> + * earlier call to intel_huc_ucode_init(), so here we need only check that
> + * is succeeded, and then transfer the image to the h/w.
> + *
> + * Return:	non-zero code on error
> + */
> +int intel_huc_load(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
> +	int err;
> +
> +	if (huc_fw->fetch_status == UC_FIRMWARE_NONE)
> +		return 0;
> +
> +	DRM_DEBUG_DRIVER("%s fw status: fetch %s, load %s\n",
> +		huc_fw->uc_fw_path,
> +		intel_uc_fw_status_repr(huc_fw->fetch_status),
> +		intel_uc_fw_status_repr(huc_fw->load_status));
> +
> +	if (huc_fw->fetch_status == UC_FIRMWARE_SUCCESS &&
> +	    huc_fw->load_status == UC_FIRMWARE_FAIL)
> +		return -ENOEXEC;
> +
> +	huc_fw->load_status = UC_FIRMWARE_PENDING;
> +
> +	switch (huc_fw->fetch_status) {
> +	case UC_FIRMWARE_FAIL:
> +		/* something went wrong :( */
> +		err = -EIO;
> +		goto fail;
> +
> +	case UC_FIRMWARE_NONE:
> +	case UC_FIRMWARE_PENDING:
> +	default:
> +		/* "can't happen" */
> +		WARN_ONCE(1, "HuC fw %s invalid fetch_status %s [%d]\n",
> +			huc_fw->uc_fw_path,
> +			intel_uc_fw_status_repr(huc_fw->fetch_status),
> +			huc_fw->fetch_status);
> +		err = -ENXIO;
> +		goto fail;
> +
> +	case UC_FIRMWARE_SUCCESS:
> +		break;
> +	}
> +
> +	err = huc_ucode_xfer(dev_priv);
> +	if (err)
> +		goto fail;
> +
> +	huc_fw->load_status = UC_FIRMWARE_SUCCESS;
> +
> +	DRM_DEBUG_DRIVER("%s fw status: fetch %s, load %s\n",
> +		huc_fw->uc_fw_path,
> +		intel_uc_fw_status_repr(huc_fw->fetch_status),
> +		intel_uc_fw_status_repr(huc_fw->load_status));
> +
> +	return 0;
> +
> +fail:
> +	if (huc_fw->load_status == UC_FIRMWARE_PENDING)
> +		huc_fw->load_status = UC_FIRMWARE_FAIL;
> +
> +	DRM_ERROR("Failed to complete HuC uCode load with ret %d\n", err);
> +
> +	return err;
> +}
> +
> +/**
> + * intel_huc_fini() - clean up resources allocated for HuC
> + * @dev: the drm device
> + *
> + * Cleans up by releasing the huc firmware GEM obj.
> + */
> +void intel_huc_fini(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
> +
> +	mutex_lock(&dev->struct_mutex);
> +	if (huc_fw->uc_fw_obj)
> +		drm_gem_object_unreference(&huc_fw->uc_fw_obj->base);
> +	huc_fw->uc_fw_obj = NULL;
> +	mutex_unlock(&dev->struct_mutex);
> +
> +	huc_fw->fetch_status = UC_FIRMWARE_NONE;
> +}
>

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

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

* Re: [PATCH 4/6] drm/i915/huc: Add debugfs for HuC loading status check
  2016-06-21 18:11 ` [PATCH 4/6] drm/i915/huc: Add debugfs for HuC loading status check Peter Antoine
  2016-06-23  8:47   ` Xiang, Haihao
@ 2016-06-28 14:57   ` Dave Gordon
  1 sibling, 0 replies; 40+ messages in thread
From: Dave Gordon @ 2016-06-28 14:57 UTC (permalink / raw)
  To: Peter Antoine, intel-gfx; +Cc: sean.v.kelley, lawrence.t.li, rodrigo.vivi

On 21/06/16 19:11, Peter Antoine wrote:
> From: Alex Dai <yu.dai@intel.com>
>
> Add debugfs entry for HuC loading status check.
>
> Signed-off-by: Alex Dai <yu.dai@intel.com>
> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
> ---
>   drivers/gpu/drm/i915/i915_debugfs.c | 32 ++++++++++++++++++++++++++++++++
>   1 file changed, 32 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 69964c2..f5976f8 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -2479,6 +2479,37 @@ static int i915_llc(struct seq_file *m, void *data)
>   	return 0;
>   }
>
> +static int i915_huc_load_status_info(struct seq_file *m, void *data)
> +{
> +	struct drm_info_node *node = m->private;
> +	struct drm_i915_private *dev_priv = node->minor->dev->dev_private;
> +	struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
> +
> +	if (!HAS_HUC_UCODE(dev_priv->dev))
> +		return 0;
> +
> +	seq_puts(m, "HuC firmware status:\n");
> +	seq_printf(m, "\tpath: %s\n", huc_fw->uc_fw_path);
> +	seq_printf(m, "\tfetch: %s\n",
> +		intel_uc_fw_status_repr(huc_fw->fetch_status));
> +	seq_printf(m, "\tload: %s\n",
> +		intel_uc_fw_status_repr(huc_fw->load_status));
> +	seq_printf(m, "\tversion wanted: %d.%d\n",
> +		huc_fw->major_ver_wanted, huc_fw->minor_ver_wanted);
> +	seq_printf(m, "\tversion found: %d.%d\n",
> +		huc_fw->major_ver_found, huc_fw->minor_ver_found);
> +	seq_printf(m, "\theader: offset is %d; size = %d\n",
> +		huc_fw->header_offset, huc_fw->header_size);
> +	seq_printf(m, "\tuCode: offset is %d; size = %d\n",
> +		huc_fw->ucode_offset, huc_fw->ucode_size);
> +	seq_printf(m, "\tRSA: offset is %d; size = %d\n",
> +		huc_fw->rsa_offset, huc_fw->rsa_size);
> +
> +	seq_printf(m, "\nHuC status 0x%08x:\n", I915_READ(HUC_STATUS2));
> +
> +	return 0;
> +}
> +
>   static int i915_guc_load_status_info(struct seq_file *m, void *data)
>   {
>   	struct drm_info_node *node = m->private;
> @@ -5432,6 +5463,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
>   	{"i915_guc_info", i915_guc_info, 0},
>   	{"i915_guc_load_status", i915_guc_load_status_info, 0},
>   	{"i915_guc_log_dump", i915_guc_log_dump, 0},
> +	{"i915_huc_load_status", i915_huc_load_status_info, 0},
>   	{"i915_frequency_info", i915_frequency_info, 0},
>   	{"i915_hangcheck_info", i915_hangcheck_info, 0},
>   	{"i915_drpc_info", i915_drpc_info, 0},
>

This is OK, although it should probably be unified with the GuC load 
status function (i.e. two trivial wrappers round a common printing 
function). But we can do that later, so:

Reviewed-by: Dave Gordon <david.s.gordon@intel.com>

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

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

* Re: [PATCH 5/6] drm/i915/huc: Support HuC authentication
  2016-06-21 18:11 ` [PATCH 5/6] drm/i915/huc: Support HuC authentication Peter Antoine
@ 2016-06-28 15:08   ` Dave Gordon
  2016-06-30 10:42     ` Antoine, Peter
  0 siblings, 1 reply; 40+ messages in thread
From: Dave Gordon @ 2016-06-28 15:08 UTC (permalink / raw)
  To: Peter Antoine, intel-gfx; +Cc: sean.v.kelley, lawrence.t.li, rodrigo.vivi

On 21/06/16 19:11, Peter Antoine wrote:
> The HuC authentication is done by host2guc call. The HuC RSA keys
> are sent to GuC for authentication.
>
> Signed-off-by: Alex Dai <yu.dai@intel.com>
> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
> ---
>   drivers/gpu/drm/i915/i915_guc_submission.c | 65 ++++++++++++++++++++++++++++++
>   drivers/gpu/drm/i915/intel_guc_fwif.h      |  1 +
>   drivers/gpu/drm/i915/intel_guc_loader.c    |  2 +
>   drivers/gpu/drm/i915/intel_huc_loader.c    |  5 +++
>   4 files changed, 73 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
> index bfb8400..41f3a42 100644
> --- a/drivers/gpu/drm/i915/i915_guc_submission.c
> +++ b/drivers/gpu/drm/i915/i915_guc_submission.c
> @@ -25,6 +25,7 @@
>   #include <linux/circ_buf.h>
>   #include "i915_drv.h"
>   #include "intel_guc.h"
> +#include "intel_huc.h"
>
>   /**
>    * DOC: GuC-based command submission
> @@ -1077,3 +1078,67 @@ int intel_guc_resume(struct drm_device *dev)
>
>   	return host2guc_action(guc, data, ARRAY_SIZE(data));
>   }
> +
> +/**
> + * intel_huc_auth() - authenticate ucode
> + * @dev: the drm device
> + *
> + * Triggers a HuC fw authentication request to the GuC via host-2-guc
> + * interface.
> + */
> +void intel_huc_auth(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_guc *guc = &dev_priv->guc;
> +	struct intel_huc *huc = &dev_priv->huc;
> +	int ret;
> +	u32 data[2];
> +
> +	/* Bypass the case where there is no HuC firmware */
> +	if (huc->huc_fw.fetch_status == UC_FIRMWARE_NONE ||
> +	    huc->huc_fw.load_status == UC_FIRMWARE_NONE)
> +		return;
> +
> +	if (guc->guc_fw.load_status != UC_FIRMWARE_SUCCESS) {
> +		DRM_ERROR("HuC: GuC fw wasn't loaded. Can't authenticate");
> +		return;
> +	}
> +
> +	if (huc->huc_fw.load_status != UC_FIRMWARE_SUCCESS) {
> +		DRM_ERROR("HuC: fw wasn't loaded. Nothing to authenticate");
> +		return;
> +	}
> +
> +	ret = i915_gem_obj_ggtt_pin(huc->huc_fw.uc_fw_obj, 0, 0);
> +	if (ret) {
> +		DRM_ERROR("HuC: Pin failed");
> +		return;
> +	}
> +
> +	/* Invalidate GuC TLB to let GuC take the latest updates to GTT. */
> +	I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);
> +
> +	/* Specify auth action and where public signature is. It's stored
> +	 * at the beginning of the gem object, before the fw bits
> +	 */
> +	data[0] = HOST2GUC_ACTION_AUTHENTICATE_HUC;
> +	data[1] = i915_gem_obj_ggtt_offset(huc->huc_fw.uc_fw_obj) +
> +			huc->huc_fw.rsa_offset;
> +
> +	ret = host2guc_action(guc, data, ARRAY_SIZE(data));
> +	if (ret) {
> +		DRM_ERROR("HuC: GuC did not ack Auth request\n");
> +		goto out;
> +	}
> +
> +	/* Check authentication status, it should be done by now */
> +	ret = wait_for_atomic(
> +		(I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED) > 0, 50);
> +	if (ret) {
> +		DRM_ERROR("HuC: Authentication failed\n");
> +		goto out;
> +	}
> +
> +out:
> +	i915_gem_object_ggtt_unpin(huc->huc_fw.uc_fw_obj);
> +}
> diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h
> index a69ee36..c5a6227 100644
> --- a/drivers/gpu/drm/i915/intel_guc_fwif.h
> +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
> @@ -437,6 +437,7 @@ enum host2guc_action {
>   	HOST2GUC_ACTION_ENTER_S_STATE = 0x501,
>   	HOST2GUC_ACTION_EXIT_S_STATE = 0x502,
>   	HOST2GUC_ACTION_SLPC_REQUEST = 0x3003,
> +	HOST2GUC_ACTION_AUTHENTICATE_HUC = 0x4000,
>   	HOST2GUC_ACTION_LIMIT
>   };
>
> diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
> index c4a210d..e876a23f 100644
> --- a/drivers/gpu/drm/i915/intel_guc_loader.c
> +++ b/drivers/gpu/drm/i915/intel_guc_loader.c
> @@ -500,6 +500,8 @@ int intel_guc_setup(struct drm_device *dev)
>   		intel_uc_fw_status_repr(guc_fw->fetch_status),
>   		intel_uc_fw_status_repr(guc_fw->load_status));
>
> +	intel_huc_auth(dev);
> +
>   	if (i915.enable_guc_submission) {
>   		err = i915_guc_submission_enable(dev_priv);
>   		if (err)
> diff --git a/drivers/gpu/drm/i915/intel_huc_loader.c b/drivers/gpu/drm/i915/intel_huc_loader.c
> index 472fabe..7205e9e 100644
> --- a/drivers/gpu/drm/i915/intel_huc_loader.c
> +++ b/drivers/gpu/drm/i915/intel_huc_loader.c
> @@ -86,6 +86,11 @@ static int huc_ucode_xfer(struct drm_i915_private *dev_priv)
>   	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
>   	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
>
> +	/* init WOPCM */
> +	I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev_priv->dev));

Didn't we already do this somewhere else, in one of the earlier patches?

Otherwise looks OK.

.Dave.

> +	I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE |
> +			HUC_LOADING_AGENT_GUC);
> +
>   	/* Set the source address for the uCode */
>   	offset = i915_gem_obj_ggtt_offset(huc_fw->uc_fw_obj) +
>   			huc_fw->header_offset;

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

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

* Re: [PATCH 6/6] drm/i915/huc: Add BXT HuC Loading Support
  2016-06-21 18:11 ` [PATCH 6/6] drm/i915/huc: Add BXT HuC Loading Support Peter Antoine
  2016-06-21 18:26   ` Vivi, Rodrigo
@ 2016-06-28 15:20   ` Dave Gordon
  1 sibling, 0 replies; 40+ messages in thread
From: Dave Gordon @ 2016-06-28 15:20 UTC (permalink / raw)
  To: Peter Antoine, intel-gfx; +Cc: sean.v.kelley, lawrence.t.li, rodrigo.vivi

On 21/06/16 19:11, Peter Antoine wrote:
> This patch adds the HuC Loading for the BXT.
> Version 1.x of the HuC firmware.
>
> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
> ---
>   drivers/gpu/drm/i915/i915_gem.c         | 13 +++----------
>   drivers/gpu/drm/i915/intel_guc_loader.c | 29 +++++++++++++++++------------
>   drivers/gpu/drm/i915/intel_huc_loader.c |  7 +++++++
>   3 files changed, 27 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 549dd3f..6abd5e5 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -5143,16 +5143,9 @@ i915_gem_init_hw(struct drm_device *dev)
>   	intel_mocs_init_l3cc_table(dev);
>
>   	/* We can't enable contexts until all firmware is loaded */
> -	if (HAS_GUC(dev)) {
> -		/* init WOPCM */
> -		I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev));
> -		I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE);
> -
> -		intel_huc_load(dev);
> -		ret = intel_guc_setup(dev);
> -		if (ret)
> -			goto out;
> -	}
> +	ret = intel_guc_setup(dev);
> +	if (ret)
> +		goto out;

This reverts one of the earlier changes that I objected to!
Please squash them together so it isn't changed and then changed back.

>   	/*
>   	 * Increment the next seqno by 0x100 so we have a visible break
> diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
> index e876a23f..289b5b6 100644
> --- a/drivers/gpu/drm/i915/intel_guc_loader.c
> +++ b/drivers/gpu/drm/i915/intel_guc_loader.c
> @@ -82,6 +82,17 @@ const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status)
>   	}
>   };
>
> +u32 guc_wopcm_size(struct drm_device *dev)
> +{
> +	u32 wopcm_size = GUC_WOPCM_TOP;
> +
> +	/* On BXT, the top of WOPCM is reserved for RC6 context */
> +	if (IS_BROXTON(dev))
> +		wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED;
> +
> +	return wopcm_size;
> +}
> +
>   static void direct_interrupts_to_host(struct drm_i915_private *dev_priv)
>   {
>   	struct intel_engine_cs *engine;
> @@ -296,17 +307,6 @@ static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv)
>   	return ret;
>   }
>
> -u32 guc_wopcm_size(struct drm_device *dev)
> -{
> -	u32 wopcm_size = GUC_WOPCM_TOP;
> -
> -	/* On BXT, the top of WOPCM is reserved for RC6 context */
> -	if (IS_BROXTON(dev))
> -		wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED;
> -
> -	return wopcm_size;
> -}
> -

This is just being moved around? Does it need to be?

>   /*
>    * Load the GuC firmware blob into the MinuteIA.
>    */
> @@ -333,6 +333,10 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
>
>   	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
>
> +	/* init WOPCM */
> +	I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev));
> +	I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE);
> +

Is this being moved around (again?)
I think we should end up with GUC_WOPCM_SIZE being set just once.

>   	/* Enable MIA caching. GuC clock gating is disabled. */
>   	I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE);
>
> @@ -483,6 +487,7 @@ int intel_guc_setup(struct drm_device *dev)
>   			goto fail;
>   		}
>
> +		intel_huc_load(dev);
>   		err = guc_ucode_xfer(dev_priv);
>   		if (!err)
>   			break;
> @@ -638,7 +643,7 @@ void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw)
>   		size = uc_fw->header_size + uc_fw->ucode_size;
>
>   		/* Top 32k of WOPCM is reserved (8K stack + 24k RC6 context). */
> -		if (size > guc_wopcm_size(dev->dev_private)) {
> +		if (size > guc_wopcm_size(dev)) {
>   			DRM_ERROR("Firmware is too large to fit in WOPCM\n");
>   			goto fail;
>   		}
> diff --git a/drivers/gpu/drm/i915/intel_huc_loader.c b/drivers/gpu/drm/i915/intel_huc_loader.c
> index 7205e9e..7a43d4e 100644
> --- a/drivers/gpu/drm/i915/intel_huc_loader.c
> +++ b/drivers/gpu/drm/i915/intel_huc_loader.c
> @@ -49,6 +49,9 @@
>   #define I915_SKL_HUC_UCODE "i915/skl_huc_ver1.bin"
>   MODULE_FIRMWARE(I915_SKL_HUC_UCODE);
>
> +#define I915_BXT_HUC_UCODE "i915/bxt_huc_ver1.bin"
> +MODULE_FIRMWARE(I915_BXT_HUC_UCODE);
> +
>   /**
>    * intel_huc_load_ucode() - DMA's the firmware
>    * @dev: the drm device
> @@ -157,6 +160,10 @@ void intel_huc_init(struct drm_device *dev)
>   		fw_path = I915_SKL_HUC_UCODE;
>   		huc_fw->major_ver_wanted = 1;
>   		huc_fw->minor_ver_wanted = 5;
> +	} else if (IS_BROXTON(dev)) {
> +		fw_path = I915_BXT_HUC_UCODE;
> +		huc_fw->major_ver_wanted = 1;
> +		huc_fw->minor_ver_wanted = 0;
>   	}
>
>   	if (fw_path == NULL)

Overall: I think the general functionality is OK, but there are a few 
specific points that need to be fixed (unless they already are, by a 
later patch). In addition, the series need to be reorganised so that we 
don't have the same lines of code repeatedly shuffled from one place to 
another, or a change made and then reverted.

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

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

* Re: [PATCH 3/6] drm/i915/huc: Add HuC fw loading support
  2016-06-28 14:54   ` Dave Gordon
@ 2016-06-28 15:45     ` Dave Gordon
  2016-06-28 23:03       ` Rodrigo Vivi
  0 siblings, 1 reply; 40+ messages in thread
From: Dave Gordon @ 2016-06-28 15:45 UTC (permalink / raw)
  To: Peter Antoine, intel-gfx; +Cc: sean.v.kelley, lawrence.t.li, rodrigo.vivi

On 28/06/16 15:54, Dave Gordon wrote:
> On 21/06/16 19:11, Peter Antoine wrote:
>> From: Alex Dai <yu.dai@intel.com>
>>
>> The HuC loading process is similar to GuC. The intel_uc_fw_fetch()
>> is used for both cases.
>>
>> HuC loading needs to be before GuC loading. The WOPCM setting must
>> be done early before loading any of them.
>>
>> Signed-off-by: Alex Dai <yu.dai@intel.com>
>> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
>> ---
>>   drivers/gpu/drm/i915/Makefile           |   1 +
>>   drivers/gpu/drm/i915/i915_dma.c         |   3 +

... and one more thing: i915_dma.c has been deleted.
The code this touches is now in i915_drv.c

.Dave.

>>   drivers/gpu/drm/i915/i915_drv.h         |   3 +
>>   drivers/gpu/drm/i915/i915_gem.c         |  13 +-
>>   drivers/gpu/drm/i915/i915_guc_reg.h     |   3 +
>>   drivers/gpu/drm/i915/intel_guc.h        |   1 +
>>   drivers/gpu/drm/i915/intel_guc_loader.c |  11 +-
>>   drivers/gpu/drm/i915/intel_huc.h        |  44 ++++++
>>   drivers/gpu/drm/i915/intel_huc_loader.c | 262

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

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

* Re: [PATCH 3/6] drm/i915/huc: Add HuC fw loading support
  2016-06-28 15:45     ` Dave Gordon
@ 2016-06-28 23:03       ` Rodrigo Vivi
  2016-06-29 14:31         ` Dave Gordon
  0 siblings, 1 reply; 40+ messages in thread
From: Rodrigo Vivi @ 2016-06-28 23:03 UTC (permalink / raw)
  To: Dave Gordon; +Cc: lawrence.t.li, sean.v.kelley, intel-gfx, Vivi, Rodrigo

I don't believe we need to be that extreme here.

Daniel asked a cleaner version, but we don't need to block the huc on
a full rework of an unified fw loader.

On Tue, Jun 28, 2016 at 8:45 AM, Dave Gordon <david.s.gordon@intel.com> wrote:
> On 28/06/16 15:54, Dave Gordon wrote:
>>
>> On 21/06/16 19:11, Peter Antoine wrote:
>>>
>>> From: Alex Dai <yu.dai@intel.com>
>>>
>>> The HuC loading process is similar to GuC. The intel_uc_fw_fetch()
>>> is used for both cases.
>>>
>>> HuC loading needs to be before GuC loading. The WOPCM setting must
>>> be done early before loading any of them.
>>>
>>> Signed-off-by: Alex Dai <yu.dai@intel.com>
>>> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
>>> ---
>>>   drivers/gpu/drm/i915/Makefile           |   1 +
>>>   drivers/gpu/drm/i915/i915_dma.c         |   3 +
>
>
> ... and one more thing: i915_dma.c has been deleted.
> The code this touches is now in i915_drv.c
>
> .Dave.
>
>>>   drivers/gpu/drm/i915/i915_drv.h         |   3 +
>>>   drivers/gpu/drm/i915/i915_gem.c         |  13 +-
>>>   drivers/gpu/drm/i915/i915_guc_reg.h     |   3 +
>>>   drivers/gpu/drm/i915/intel_guc.h        |   1 +
>>>   drivers/gpu/drm/i915/intel_guc_loader.c |  11 +-
>>>   drivers/gpu/drm/i915/intel_huc.h        |  44 ++++++
>>>   drivers/gpu/drm/i915/intel_huc_loader.c | 262
>
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/6] drm/i915/huc: Add HuC fw loading support
  2016-06-28 23:03       ` Rodrigo Vivi
@ 2016-06-29 14:31         ` Dave Gordon
  2016-06-29 17:59           ` Rodrigo Vivi
  0 siblings, 1 reply; 40+ messages in thread
From: Dave Gordon @ 2016-06-29 14:31 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: lawrence.t.li, sean.v.kelley, intel-gfx, Vivi, Rodrigo

On 29/06/16 00:03, Rodrigo Vivi wrote:
> I don't believe we need to be that extreme here.
>
> Daniel asked a cleaner version, but we don't need to block the huc on
> a full rework of an unified fw loader.

Oh, I agree, we should take this "mostly" as-is and then reunify them after.

.Dave.

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

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

* Re: [PATCH 3/6] drm/i915/huc: Add HuC fw loading support
  2016-06-29 14:31         ` Dave Gordon
@ 2016-06-29 17:59           ` Rodrigo Vivi
  2016-07-05 14:41             ` Dave Gordon
  0 siblings, 1 reply; 40+ messages in thread
From: Rodrigo Vivi @ 2016-06-29 17:59 UTC (permalink / raw)
  To: Dave Gordon; +Cc: lawrence.t.li, sean.v.kelley, intel-gfx, Vivi, Rodrigo

But the merge on hug/guc loading is just the minor thing Daniel asked.

The major request is to stop using the fetch_status, but errnos
instead. so, maybe one extra patch that simplifies this right now
before this series would be the ideal so we could speed up the merge
and maybe later to the unified firmware loading solution.



On Wed, Jun 29, 2016 at 7:31 AM, Dave Gordon <david.s.gordon@intel.com> wrote:
> On 29/06/16 00:03, Rodrigo Vivi wrote:
>>
>> I don't believe we need to be that extreme here.
>>
>> Daniel asked a cleaner version, but we don't need to block the huc on
>> a full rework of an unified fw loader.
>
>
> Oh, I agree, we should take this "mostly" as-is and then reunify them after.
>
> .Dave.
>



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 2/6] drm/i915/huc: Unified css_header struct for GuC and HuC
  2016-06-28 14:32   ` Dave Gordon
@ 2016-06-30 10:39     ` Antoine, Peter
  0 siblings, 0 replies; 40+ messages in thread
From: Antoine, Peter @ 2016-06-30 10:39 UTC (permalink / raw)
  To: Gordon, David S, intel-gfx; +Cc: Kelley, Sean V, Li, Lawrence T, Vivi, Rodrigo



-----Original Message-----
From: Gordon, David S 
Sent: Tuesday, June 28, 2016 3:33 PM
To: Antoine, Peter <peter.antoine@intel.com>; intel-gfx@lists.freedesktop.org
Cc: Prigent, Christophe <christophe.prigent@intel.com>; Kelley, Sean V <sean.v.kelley@intel.com>; Li, Lawrence T <lawrence.t.li@intel.com>; Vivi, Rodrigo <rodrigo.vivi@intel.com>; Dai, Yu <yu.dai@intel.com>
Subject: Re: [PATCH 2/6] drm/i915/huc: Unified css_header struct for GuC and HuC

On 21/06/16 19:11, Peter Antoine wrote:
> From: Alex Dai <yu.dai@intel.com>
>
> HuC firmware css header has almost exactly same definition as GuC 
> firmware except for the sw_version. Also, add a new member fw_type 
> into intel_uc_fw to indicate what kind of fw it is. So, the loader 
> will pull right sw_version from header.
>
> Signed-off-by: Alex Dai <yu.dai@intel.com>
> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
> ---
>   drivers/gpu/drm/i915/intel_guc.h        |  4 ++++
>   drivers/gpu/drm/i915/intel_guc_fwif.h   | 16 ++++++++++---
>   drivers/gpu/drm/i915/intel_guc_loader.c | 42 +++++++++++++++++++++------------
>   3 files changed, 44 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_guc.h 
> b/drivers/gpu/drm/i915/intel_guc.h
> index 836420b..0b4ed88 100644
> --- a/drivers/gpu/drm/i915/intel_guc.h
> +++ b/drivers/gpu/drm/i915/intel_guc.h
> @@ -97,6 +97,9 @@ enum intel_uc_fw_status {
>   	UC_FIRMWARE_SUCCESS
>   };
>
> +#define UC_FW_TYPE_GUC		0
> +#define UC_FW_TYPE_HUC		1
> +
>   /*
>    * This structure encapsulates all the data needed during the process
>    * of fetching, caching, and loading the firmware image into the GuC.
> @@ -114,6 +117,7 @@ struct intel_uc_fw {
>   	uint16_t major_ver_found;
>   	uint16_t minor_ver_found;
>
> +	uint32_t fw_type;
>   	uint32_t header_size;
>   	uint32_t header_offset;
>   	uint32_t rsa_size;
> diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h 
> b/drivers/gpu/drm/i915/intel_guc_fwif.h
> index 944786d..a69ee36 100644
> --- a/drivers/gpu/drm/i915/intel_guc_fwif.h
> +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
> @@ -154,7 +154,7 @@
>    * The GuC firmware layout looks like this:
>    *
>    *     +-------------------------------+
> - *     |        guc_css_header         |
> + *     |         uc_css_header         |
>    *     | contains major/minor version  |
>    *     +-------------------------------+
>    *     |             uCode             |
> @@ -180,9 +180,16 @@
>    * 3. Length info of each component can be found in header, in dwords.
>    * 4. Modulus and exponent key are not required by driver. They may not appear
>    * in fw. So driver will load a truncated firmware in this case.
> + *
> + * HuC firmware layout is same as GuC firmware.
> + *
> + * HuC firmware css header is different. However, the only difference 
> + is where
> + * the version information is saved. The uc_css_header is unified to 
> + support
> + * both. Driver should get HuC version from 
> + uc_css_header.huc_sw_version, while
> + * uc_css_header.guc_sw_version for GuC.
>    */
>
> -struct guc_css_header {
> +struct uc_css_header {

This name change could have been part of the previous global search-and-replace.

>   	uint32_t module_type;
>   	/* header_size includes all non-uCode bits, including css_header, rsa
>   	 * key, modulus key and exponent data. */ @@ -213,7 +220,10 @@ 
> struct guc_css_header {
>
>   	char username[8];
>   	char buildnumber[12];
> -	uint32_t device_id;
> +	union {
> +		uint32_t device_id;
> +		uint32_t huc_sw_version;
> +	};
>   	uint32_t guc_sw_version;
>   	uint32_t prod_preprod_fw;
>   	uint32_t reserved[12];

This can't really be right; the HuC f/w header doesn't contain a guc_sw_version! So the union must be more like:

	union {
		struct {
			uint32_t device_id;
			uint32_t guc_sw_version;
			uint32_t prod_preprod_fw;
		} guc_data;
		struct {
			uint32_t huc_sw_version;
			uint32_t prod_preprod_fw;
			uint32_t dummy;
		} huc_data;
	};
    	uint32_t reserved[12];

... or something - I don't know what the actual layout is here.

Otherwise generally OK.

.Dave.

Not really, It's not wrong. It just could be clearer. But adding other structs just muddies the water.
I think Alex's code is easier to read (and correct). Guc_sw_version is simply not used on the huc it is a bad design by the firmware designers not to use a fix format for all fw but just make the word we need a union is simplest.  

Probably could change it to:
Union {
	Struct {
  		Uint32_t device_id;
		Unit32_t guc_sw_version;
	};
	Struct {
		Uint32_t huc_sw_version;
		Uint32_t filler;
	};
} 
Just looking at the code. But I am going to leave it alone unless there is real objection to it.
Peter.

> diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c 
> b/drivers/gpu/drm/i915/intel_guc_loader.c
> index ff054f5..70575bd 100644
> --- a/drivers/gpu/drm/i915/intel_guc_loader.c
> +++ b/drivers/gpu/drm/i915/intel_guc_loader.c
> @@ -574,7 +574,7 @@ void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw)
>   {
>   	struct drm_i915_gem_object *obj;
>   	const struct firmware *fw;
> -	struct guc_css_header *css;
> +	struct uc_css_header *css;
>   	size_t size;
>   	int err;
>
> @@ -591,19 +591,19 @@ void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw)
>   		uc_fw->uc_fw_path, fw);
>
>   	/* Check the size of the blob before examining buffer contents */
> -	if (fw->size < sizeof(struct guc_css_header)) {
> +	if (fw->size < sizeof(struct uc_css_header)) {
>   		DRM_ERROR("Firmware header is missing\n");
>   		goto fail;
>   	}
>
> -	css = (struct guc_css_header *)fw->data;
> +	css = (struct uc_css_header *)fw->data;
>
>   	/* Firmware bits always start from header */
>   	uc_fw->header_offset = 0;
>   	uc_fw->header_size = (css->header_size_dw - css->modulus_size_dw -
>   		css->key_size_dw - css->exponent_size_dw) * sizeof(u32);
>
> -	if (uc_fw->header_size != sizeof(struct guc_css_header)) {
> +	if (uc_fw->header_size != sizeof(struct uc_css_header)) {
>   		DRM_ERROR("CSS header definition mismatch\n");
>   		goto fail;
>   	}
> @@ -627,23 +627,35 @@ void intel_uc_fw_fetch(struct drm_device *dev, struct intel_uc_fw *uc_fw)
>   		goto fail;
>   	}
>
> -	/* Header and uCode will be loaded to WOPCM. Size of the two. */
> -	size = uc_fw->header_size + uc_fw->ucode_size;
> -
> -	/* Top 32k of WOPCM is reserved (8K stack + 24k RC6 context). */
> -	if (size > guc_wopcm_size(dev->dev_private)) {
> -		DRM_ERROR("Firmware is too large to fit in WOPCM\n");
> -		goto fail;
> -	}
> -
>   	/*
>   	 * The uC firmware image has the version number embedded at a well-known
>   	 * offset within the firmware blob; note that major / minor version are
>   	 * TWO bytes each (i.e. u16), although all pointers and offsets are defined
>   	 * in terms of bytes (u8).
>   	 */
> -	uc_fw->major_ver_found = css->guc_sw_version >> 16;
> -	uc_fw->minor_ver_found = css->guc_sw_version & 0xFFFF;
> +	switch (uc_fw->fw_type) {
> +	case UC_FW_TYPE_GUC:
> +		/* Header and uCode will be loaded to WOPCM. Size of the two. */
> +		size = uc_fw->header_size + uc_fw->ucode_size;
> +
> +		/* Top 32k of WOPCM is reserved (8K stack + 24k RC6 context). */
> +		if (size > guc_wopcm_size(dev->dev_private)) {
> +			DRM_ERROR("Firmware is too large to fit in WOPCM\n");
> +			goto fail;
> +		}
> +
> +		uc_fw->major_ver_found = css->guc_sw_version >> 16;
> +		uc_fw->minor_ver_found = css->guc_sw_version & 0xFFFF;
> +		break;
> +	case UC_FW_TYPE_HUC:
> +		uc_fw->major_ver_found = css->huc_sw_version >> 16;
> +		uc_fw->minor_ver_found = css->huc_sw_version & 0xFFFF;
> +		break;
> +	default:
> +		DRM_ERROR("Unknown firmware type %d\n", uc_fw->fw_type);
> +		err = -ENOEXEC;
> +		goto fail;
> +	}
>
>   	if (uc_fw->major_ver_found != uc_fw->major_ver_wanted ||
>   	    uc_fw->minor_ver_found < uc_fw->minor_ver_wanted) {
>

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

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

* Re: [PATCH 5/6] drm/i915/huc: Support HuC authentication
  2016-06-28 15:08   ` Dave Gordon
@ 2016-06-30 10:42     ` Antoine, Peter
  0 siblings, 0 replies; 40+ messages in thread
From: Antoine, Peter @ 2016-06-30 10:42 UTC (permalink / raw)
  To: Gordon, David S, intel-gfx; +Cc: Kelley, Sean V, Li, Lawrence T, Vivi, Rodrigo



-----Original Message-----
From: Gordon, David S 
Sent: Tuesday, June 28, 2016 4:08 PM
To: Antoine, Peter <peter.antoine@intel.com>; intel-gfx@lists.freedesktop.org
Cc: Prigent, Christophe <christophe.prigent@intel.com>; Kelley, Sean V <sean.v.kelley@intel.com>; Li, Lawrence T <lawrence.t.li@intel.com>; Vivi, Rodrigo <rodrigo.vivi@intel.com>; Dai, Yu <yu.dai@intel.com>
Subject: Re: [PATCH 5/6] drm/i915/huc: Support HuC authentication

On 21/06/16 19:11, Peter Antoine wrote:
> The HuC authentication is done by host2guc call. The HuC RSA keys are 
> sent to GuC for authentication.
>
> Signed-off-by: Alex Dai <yu.dai@intel.com>
> Signed-off-by: Peter Antoine <peter.antoine@intel.com>
> ---
>   drivers/gpu/drm/i915/i915_guc_submission.c | 65 ++++++++++++++++++++++++++++++
>   drivers/gpu/drm/i915/intel_guc_fwif.h      |  1 +
>   drivers/gpu/drm/i915/intel_guc_loader.c    |  2 +
>   drivers/gpu/drm/i915/intel_huc_loader.c    |  5 +++
>   4 files changed, 73 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c 
> b/drivers/gpu/drm/i915/i915_guc_submission.c
> index bfb8400..41f3a42 100644
> --- a/drivers/gpu/drm/i915/i915_guc_submission.c
> +++ b/drivers/gpu/drm/i915/i915_guc_submission.c
> @@ -25,6 +25,7 @@
>   #include <linux/circ_buf.h>
>   #include "i915_drv.h"
>   #include "intel_guc.h"
> +#include "intel_huc.h"
>
>   /**
>    * DOC: GuC-based command submission @@ -1077,3 +1078,67 @@ int 
> intel_guc_resume(struct drm_device *dev)
>
>   	return host2guc_action(guc, data, ARRAY_SIZE(data));
>   }
> +
> +/**
> + * intel_huc_auth() - authenticate ucode
> + * @dev: the drm device
> + *
> + * Triggers a HuC fw authentication request to the GuC via host-2-guc
> + * interface.
> + */
> +void intel_huc_auth(struct drm_device *dev) {
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_guc *guc = &dev_priv->guc;
> +	struct intel_huc *huc = &dev_priv->huc;
> +	int ret;
> +	u32 data[2];
> +
> +	/* Bypass the case where there is no HuC firmware */
> +	if (huc->huc_fw.fetch_status == UC_FIRMWARE_NONE ||
> +	    huc->huc_fw.load_status == UC_FIRMWARE_NONE)
> +		return;
> +
> +	if (guc->guc_fw.load_status != UC_FIRMWARE_SUCCESS) {
> +		DRM_ERROR("HuC: GuC fw wasn't loaded. Can't authenticate");
> +		return;
> +	}
> +
> +	if (huc->huc_fw.load_status != UC_FIRMWARE_SUCCESS) {
> +		DRM_ERROR("HuC: fw wasn't loaded. Nothing to authenticate");
> +		return;
> +	}
> +
> +	ret = i915_gem_obj_ggtt_pin(huc->huc_fw.uc_fw_obj, 0, 0);
> +	if (ret) {
> +		DRM_ERROR("HuC: Pin failed");
> +		return;
> +	}
> +
> +	/* Invalidate GuC TLB to let GuC take the latest updates to GTT. */
> +	I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);
> +
> +	/* Specify auth action and where public signature is. It's stored
> +	 * at the beginning of the gem object, before the fw bits
> +	 */
> +	data[0] = HOST2GUC_ACTION_AUTHENTICATE_HUC;
> +	data[1] = i915_gem_obj_ggtt_offset(huc->huc_fw.uc_fw_obj) +
> +			huc->huc_fw.rsa_offset;
> +
> +	ret = host2guc_action(guc, data, ARRAY_SIZE(data));
> +	if (ret) {
> +		DRM_ERROR("HuC: GuC did not ack Auth request\n");
> +		goto out;
> +	}
> +
> +	/* Check authentication status, it should be done by now */
> +	ret = wait_for_atomic(
> +		(I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED) > 0, 50);
> +	if (ret) {
> +		DRM_ERROR("HuC: Authentication failed\n");
> +		goto out;
> +	}
> +
> +out:
> +	i915_gem_object_ggtt_unpin(huc->huc_fw.uc_fw_obj);
> +}
> diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h 
> b/drivers/gpu/drm/i915/intel_guc_fwif.h
> index a69ee36..c5a6227 100644
> --- a/drivers/gpu/drm/i915/intel_guc_fwif.h
> +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
> @@ -437,6 +437,7 @@ enum host2guc_action {
>   	HOST2GUC_ACTION_ENTER_S_STATE = 0x501,
>   	HOST2GUC_ACTION_EXIT_S_STATE = 0x502,
>   	HOST2GUC_ACTION_SLPC_REQUEST = 0x3003,
> +	HOST2GUC_ACTION_AUTHENTICATE_HUC = 0x4000,
>   	HOST2GUC_ACTION_LIMIT
>   };
>
> diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c 
> b/drivers/gpu/drm/i915/intel_guc_loader.c
> index c4a210d..e876a23f 100644
> --- a/drivers/gpu/drm/i915/intel_guc_loader.c
> +++ b/drivers/gpu/drm/i915/intel_guc_loader.c
> @@ -500,6 +500,8 @@ int intel_guc_setup(struct drm_device *dev)
>   		intel_uc_fw_status_repr(guc_fw->fetch_status),
>   		intel_uc_fw_status_repr(guc_fw->load_status));
>
> +	intel_huc_auth(dev);
> +
>   	if (i915.enable_guc_submission) {
>   		err = i915_guc_submission_enable(dev_priv);
>   		if (err)
> diff --git a/drivers/gpu/drm/i915/intel_huc_loader.c 
> b/drivers/gpu/drm/i915/intel_huc_loader.c
> index 472fabe..7205e9e 100644
> --- a/drivers/gpu/drm/i915/intel_huc_loader.c
> +++ b/drivers/gpu/drm/i915/intel_huc_loader.c
> @@ -86,6 +86,11 @@ static int huc_ucode_xfer(struct drm_i915_private *dev_priv)
>   	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
>   	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
>
> +	/* init WOPCM */
> +	I915_WRITE(GUC_WOPCM_SIZE, guc_wopcm_size(dev_priv->dev));

Didn't we already do this somewhere else, in one of the earlier patches?

Otherwise looks OK.

.Dave.

In the GuC loader it also sets this up. But, as we are using a shared function to get the size and the registers is write once, if the HuC is not supported (or there is no firmware) that wont get called but this will. It (I think) makes the code more robust and with the retry and reset code, it is called in the required functions and does not need conditionals around it.

> +	I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE |
> +			HUC_LOADING_AGENT_GUC);
> +
>   	/* Set the source address for the uCode */
>   	offset = i915_gem_obj_ggtt_offset(huc_fw->uc_fw_obj) +
>   			huc_fw->header_offset;

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

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

* Re: [PATCH 3/6] drm/i915/huc: Add HuC fw loading support
  2016-06-29 17:59           ` Rodrigo Vivi
@ 2016-07-05 14:41             ` Dave Gordon
  0 siblings, 0 replies; 40+ messages in thread
From: Dave Gordon @ 2016-07-05 14:41 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: lawrence.t.li, sean.v.kelley, intel-gfx, Vivi, Rodrigo

On 29/06/16 18:59, Rodrigo Vivi wrote:
>> On Wed, Jun 29, 2016 at 7:31 AM, Dave Gordon <david.s.gordon@intel.com> wrote:
>>> On 29/06/16 00:03, Rodrigo Vivi wrote:
>>>>
>>>> I don't believe we need to be that extreme here.
>>>>
>>>> Daniel asked a cleaner version, but we don't need to block the huc on
>>>> a full rework of an unified fw loader.
>>>
>>>
>>> Oh, I agree, we should take this "mostly" as-is and then reunify them after.
>>>
>>> .Dave.
>
> But the merge on hug/guc loading is just the minor thing Daniel asked.
>
> The major request is to stop using the fetch_status, but errnos
> instead.

That's not going to happen. It's written as a state machine for good 
reason, because the various elements (fetch/load/reload) get called at 
different (and rather arbitrary) points in the driver load sequence, and 
they need to maintain state from one stage to another, not rely on the 
caller(s) to interpret errnos to determine what the next callback should be.

Unless you (or Daniel) just mean change the details of the encoding i.e. 
how that state is represented? We could do that, but I don't think it 
would be useful to reuse unrelated errnos rather than have our own 
precise and specific enumeration of the state of the loading process.

.Dave.

> so, maybe one extra patch that simplifies this right now
> before this series would be the ideal so we could speed up the merge
> and maybe later to the unified firmware loading solution.

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

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

* Re: [PATCH 4/6] drm/i915/huc: Add debugfs for HuC loading status check
  2016-06-23 22:04         ` Kelley, Sean V
@ 2016-07-13  8:13           ` Xiang, Haihao
  0 siblings, 0 replies; 40+ messages in thread
From: Xiang, Haihao @ 2016-07-13  8:13 UTC (permalink / raw)
  To: Thierry, Michel, Kelley, Sean V, Antoine, Peter, daniel.vetter
  Cc: intel-gfx, Li, Lawrence T, Vivi, Rodrigo


Hi Peter,

Could you provide the interface for UMD driver to detect HuC FW loading
status in your new patch set? A normal user doesn't have permission to
read files in debugfs. Reusing I915_GETPARAM is fine for me.

Thanks
Haihao


> 
> > -----Original Message-----
> > From: Thierry, Michel
> > Sent: Thursday, June 23, 2016 3:48 AM
> > To: Antoine, Peter <peter.antoine@intel.com>; Xiang, Haihao
> > <haihao.xiang@intel.com>; daniel.vetter@ffwll.ch
> > Cc: Kelley, Sean V <sean.v.kelley@intel.com>; intel-
> > gfx@lists.freedesktop.org; Li, Lawrence T <lawrence.t.li@intel.com>
> > ; Vivi,
> > Rodrigo <rodrigo.vivi@intel.com>
> > Subject: Re: [Intel-gfx] [PATCH 4/6] drm/i915/huc: Add debugfs for
> > HuC
> > loading status check
> > 
> > On 6/23/2016 11:01 AM, Peter Antoine wrote:
> > > Daniel,
> > > 
> > > Is this suggestion acceptable? I don't want to waste time and
> > > effort
> > > writing code that is not going to be accepted?
> > > 
> > > Peter.
> > > 
> > 
> > Reuse I915_GETPARAM and do more-less what Chris did for
> > i915.enable_gvt? [1]
> > 
> > 
> > [1]
> > https://cgit.freedesktop.org/drm-
> > intel/commit/?id=7822492fd21a44eeb3568082b0ab915df7388061
> 
> Something along those lines would work for me with our media UMD.
> 
> Thanks,
> 
> Sean
> 
> > 
> > > On Thu, 23 Jun 2016, Xiang, Haihao wrote:
> > > 
> > > > 
> > > > Hi Peter,
> > > > 
> > > > Besides debugfs, could you add a IOCTL to check HuC loading
> > > > status?
> > > > Userspace media driver needs to advertise the features based on
> > > > HuC
> > > > to user.
> > > > 
> > > > Thanks
> > > > Haihao
> > > > 
> > > > 
> > > > > From: Alex Dai <yu.dai@intel.com>
> > > > > 
> > > > > Add debugfs entry for HuC loading status check.
> > > > > 
> > > > > Signed-off-by: Alex Dai <yu.dai@intel.com>
> > > > > Signed-off-by: Peter Antoine <peter.antoine@intel.com>
> > > > > ---
> > > > >  drivers/gpu/drm/i915/i915_debugfs.c | 32
> > > > > ++++++++++++++++++++++++++++++++
> > > > >  1 file changed, 32 insertions(+)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
> > > > > b/drivers/gpu/drm/i915/i915_debugfs.c
> > > > > index 69964c2..f5976f8 100644
> > > > > --- a/drivers/gpu/drm/i915/i915_debugfs.c
> > > > > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> > > > > @@ -2479,6 +2479,37 @@ static int i915_llc(struct seq_file
> > > > > *m, void
> > > > > *data)
> > > > >      return 0;
> > > > >  }
> > > > > 
> > > > > +static int i915_huc_load_status_info(struct seq_file *m,
> > > > > void
> > > > > +*data) {
> > > > > +    struct drm_info_node *node = m->private;
> > > > > +    struct drm_i915_private *dev_priv = node->minor->dev-
> > > > > > dev_private;
> > > > > +    struct intel_uc_fw *huc_fw = &dev_priv->huc.huc_fw;
> > > > > +
> > > > > +    if (!HAS_HUC_UCODE(dev_priv->dev))
> > > > > +            return 0;
> > > > > +
> > > > > +    seq_puts(m, "HuC firmware status:\n");
> > > > > +    seq_printf(m, "\tpath: %s\n", huc_fw->uc_fw_path);
> > > > > +    seq_printf(m, "\tfetch: %s\n",
> > > > > +            intel_uc_fw_status_repr(huc_fw->fetch_status));
> > > > > +    seq_printf(m, "\tload: %s\n",
> > > > > +            intel_uc_fw_status_repr(huc_fw->load_status));
> > > > > +    seq_printf(m, "\tversion wanted: %d.%d\n",
> > > > > +            huc_fw->major_ver_wanted, huc_fw-
> > > > > >minor_ver_wanted);
> > > > > +    seq_printf(m, "\tversion found: %d.%d\n",
> > > > > +            huc_fw->major_ver_found, huc_fw-
> > > > > >minor_ver_found);
> > > > > +    seq_printf(m, "\theader: offset is %d; size = %d\n",
> > > > > +            huc_fw->header_offset, huc_fw->header_size);
> > > > > +    seq_printf(m, "\tuCode: offset is %d; size = %d\n",
> > > > > +            huc_fw->ucode_offset, huc_fw->ucode_size);
> > > > > +    seq_printf(m, "\tRSA: offset is %d; size = %d\n",
> > > > > +            huc_fw->rsa_offset, huc_fw->rsa_size);
> > > > > +
> > > > > +    seq_printf(m, "\nHuC status 0x%08x:\n",
> > > > > I915_READ(HUC_STATUS2));
> > > > > +
> > > > > +    return 0;
> > > > > +}
> > > > > +
> > > > >  static int i915_guc_load_status_info(struct seq_file *m,
> > > > > void
> > > > > *data)  {
> > > > >      struct drm_info_node *node = m->private; @@ -5432,6
> > > > > +5463,7 @@
> > > > > static const struct drm_info_list i915_debugfs_list[] = {
> > > > >      {"i915_guc_info", i915_guc_info, 0},
> > > > >      {"i915_guc_load_status", i915_guc_load_status_info, 0},
> > > > >      {"i915_guc_log_dump", i915_guc_log_dump, 0},
> > > > > +    {"i915_huc_load_status", i915_huc_load_status_info, 0},
> > > > >      {"i915_frequency_info", i915_frequency_info, 0},
> > > > >      {"i915_hangcheck_info", i915_hangcheck_info, 0},
> > > > >      {"i915_drpc_info", i915_drpc_info, 0},
> > > 
> > > --
> > >     Peter Antoine (Android Graphics Driver Software Engineer)
> > >     -------------------------------------------------------------
> > > --------
> > >     Intel Corporation (UK) Limited
> > >     Registered No. 1134945 (England)
> > >     Registered Office: Pipers Way, Swindon SN3 1RJ
> > >     VAT No: 860 2173 47
> > > 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/6] drm/i915/huc: Add HuC fw loading support
  2016-06-23 13:52       ` Peter Antoine
@ 2016-07-13 12:48         ` Daniel Vetter
  2016-07-13 14:52           ` Peter Antoine
  2016-07-14 14:08           ` Dave Gordon
  0 siblings, 2 replies; 40+ messages in thread
From: Daniel Vetter @ 2016-07-13 12:48 UTC (permalink / raw)
  To: Peter Antoine; +Cc: lawrence.t.li, sean.v.kelley, intel-gfx, rodrigo.vivi

On Thu, Jun 23, 2016 at 02:52:41PM +0100, Peter Antoine wrote:
> On Thu, 23 Jun 2016, Dave Gordon wrote:
> > On 22/06/16 09:31, Daniel Vetter wrote:
> > No, the *correct* fix is to unify all the firmware loaders we have.
> > There should just be ONE piece of code that can be used to fetch and
> > load ANy firmware into ANY auxiliary microcontroller. NOT one per
> > microcontroller, all different -- that way lies madness.
> > 
> > We already had a unified loader for the HuC and GuC a year ago, but IIRC
> > the party line then was "just make it (GuC) specific, then copypaste it
> > for the second uC, and when we've got three versions we'll have learnt
> > how we really want a unified loader to behave."
> > 
> > Well. here's the copypaste, and we already have a different loader for
> > the DMC/CSR, so it must be time for (re-)unification.
> > 
> > .Dave.
> > 
> 
> Just to add, if you uc_fw_fetch() has an error code you will still have to
> remember the state of the fetch or at each reset/resume/etc... or you will
> have to try the firmware load again and that can take a long time. So the
> state will have to be re-instated.
> 
> Seeing this code was written with the given goals and were written in the
> same vane as code that was deemed acceptable, it seems weird at this late
> stage to change the design goals.
> 
> Note: this is the third time that these patches have been posted and were
> only rejected (as far as I know) due to no open-source user. Which there is
> now, and is why I have reposted these patches.

I never liked the guc firmware code, but figure for one copy it's not
worth fighting over. Adding more copies (or perpetuating the design by
making it generic) isn't what I'm looking for. Firmware loading shouldn't
be that complicated, really.

The unified firmware loader is called request_firmware. If that's not good
enough, pls fix the core function, not paper code over in i915. In that
regard DMC/CSR is unified, everything else isn't yet.

Iirc the big issue is delayed firmware loading for built-in i915 and fw
only available later on. This is an open issue in request_firmware() since
years, and there's various patches floating around. If the problem is that
Greg KH doesn't consider those patches, I can help with that. But not
pushing the core fix forward isn't acceptable imo. Once that fix is landed
we can treat request_firmware as reliable (it might take a while, hence
must be run in an async work like DMC loading), with no need to ever retry
anything. If fw loading fails we can just mark the entire render part of
the gpu as dead by injecting the equivalent of a non-recoverable hang
(async setup) or failing engine init with -EIO (if this is still
synchronous, which I don't expect really).

If there's another reason for this complexity, please explain since I'd
like to understand why we need this.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/6] drm/i915/huc: Add HuC fw loading support
  2016-07-13 12:48         ` Daniel Vetter
@ 2016-07-13 14:52           ` Peter Antoine
  2016-07-14 14:16             ` Daniel Vetter
  2016-07-14 14:08           ` Dave Gordon
  1 sibling, 1 reply; 40+ messages in thread
From: Peter Antoine @ 2016-07-13 14:52 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx, rodrigo.vivi, lawrence.t.li, sean.v.kelley

On Wed, 13 Jul 2016, Daniel Vetter wrote:

> On Thu, Jun 23, 2016 at 02:52:41PM +0100, Peter Antoine wrote:
>> On Thu, 23 Jun 2016, Dave Gordon wrote:
>>> On 22/06/16 09:31, Daniel Vetter wrote:
>>> No, the *correct* fix is to unify all the firmware loaders we have.
>>> There should just be ONE piece of code that can be used to fetch and
>>> load ANy firmware into ANY auxiliary microcontroller. NOT one per
>>> microcontroller, all different -- that way lies madness.
>>>
>>> We already had a unified loader for the HuC and GuC a year ago, but IIRC
>>> the party line then was "just make it (GuC) specific, then copypaste it
>>> for the second uC, and when we've got three versions we'll have learnt
>>> how we really want a unified loader to behave."
>>>
>>> Well. here's the copypaste, and we already have a different loader for
>>> the DMC/CSR, so it must be time for (re-)unification.
>>>
>>> .Dave.
>>>
>>
>> Just to add, if you uc_fw_fetch() has an error code you will still have to
>> remember the state of the fetch or at each reset/resume/etc... or you will
>> have to try the firmware load again and that can take a long time. So the
>> state will have to be re-instated.
>>
>> Seeing this code was written with the given goals and were written in the
>> same vane as code that was deemed acceptable, it seems weird at this late
>> stage to change the design goals.
>>
>> Note: this is the third time that these patches have been posted and were
>> only rejected (as far as I know) due to no open-source user. Which there is
>> now, and is why I have reposted these patches.
>
> I never liked the guc firmware code, but figure for one copy it's not
> worth fighting over. Adding more copies (or perpetuating the design by
> making it generic) isn't what I'm looking for. Firmware loading shouldn't
> be that complicated, really.
>
> The unified firmware loader is called request_firmware. If that's not good
> enough, pls fix the core function, not paper code over in i915. In that
> regard DMC/CSR is unified, everything else isn't yet.
>
> Iirc the big issue is delayed firmware loading for built-in i915 and fw
> only available later on. This is an open issue in request_firmware() since
> years, and there's various patches floating around. If the problem is that
> Greg KH doesn't consider those patches, I can help with that. But not
> pushing the core fix forward isn't acceptable imo. Once that fix is landed
> we can treat request_firmware as reliable (it might take a while, hence
> must be run in an async work like DMC loading), with no need to ever retry
> anything. If fw loading fails we can just mark the entire render part of
> the gpu as dead by injecting the equivalent of a non-recoverable hang
> (async setup) or failing engine init with -EIO (if this is still
> synchronous, which I don't expect really).
>
> If there's another reason for this complexity, please explain since I'd
> like to understand why we need this.
> -Daniel
>

I was not involved at the start and I am porting code that others have 
written, but as far as I understand this, you requested that the code be 
duplicated. See Dave's comment above as he was involved.

The code uses request_firmware() to handle the load of the firmware into 
memory and the rest of this code manages the loading of that memory into 
the HuC's SRAM. This needs extra setup that should not really go into the 
generic firmware loader (one loader for uIA's make sense as this will 
futureproof the code). Also the SRAM is write-once memory and needs to 
be handled correctly. Also, the GuC needs to verify the HuC some this 
becomes a little be more fun.

Also, again you are ignoring the point that not having firmware is not 
fatal. We remember the state of the load as this is required to save time 
when we come out of reset to not waste time trying to reload the firmware, 
if it has failed already. They are other mechinums to do this, but they 
will always need some form of history.

Also, if request_firmware() is broken why has this not been fixed? If it 
has been broken for "years" why and how do you expect to to be fixed now? If 
the "not pushing the core fix is not acceptable" why has that not been done?

Peter.

--
    Peter Antoine (Android Graphics Driver Software Engineer)
    ---------------------------------------------------------------------
    Intel Corporation (UK) Limited
    Registered No. 1134945 (England)
    Registered Office: Pipers Way, Swindon SN3 1RJ
    VAT No: 860 2173 47
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/6] drm/i915/huc: Add HuC fw loading support
  2016-07-13 12:48         ` Daniel Vetter
  2016-07-13 14:52           ` Peter Antoine
@ 2016-07-14 14:08           ` Dave Gordon
  2016-07-14 14:26             ` Daniel Vetter
  1 sibling, 1 reply; 40+ messages in thread
From: Dave Gordon @ 2016-07-14 14:08 UTC (permalink / raw)
  To: Daniel Vetter, Peter Antoine
  Cc: sean.v.kelley, intel-gfx, lawrence.t.li, rodrigo.vivi

On 13/07/16 13:48, Daniel Vetter wrote:
> On Thu, Jun 23, 2016 at 02:52:41PM +0100, Peter Antoine wrote:
>> On Thu, 23 Jun 2016, Dave Gordon wrote:
>>> On 22/06/16 09:31, Daniel Vetter wrote:
>>> No, the *correct* fix is to unify all the firmware loaders we have.
>>> There should just be ONE piece of code that can be used to fetch and
>>> load ANy firmware into ANY auxiliary microcontroller. NOT one per
>>> microcontroller, all different -- that way lies madness.
>>>
>>> We already had a unified loader for the HuC and GuC a year ago, but IIRC
>>> the party line then was "just make it (GuC) specific, then copypaste it
>>> for the second uC, and when we've got three versions we'll have learnt
>>> how we really want a unified loader to behave."
>>>
>>> Well. here's the copypaste, and we already have a different loader for
>>> the DMC/CSR, so it must be time for (re-)unification.
>>>
>>> .Dave.
>>
>> Just to add, if you uc_fw_fetch() has an error code you will still have to
>> remember the state of the fetch or at each reset/resume/etc... or you will
>> have to try the firmware load again and that can take a long time. So the
>> state will have to be re-instated.
>>
>> Seeing this code was written with the given goals and were written in the
>> same vane as code that was deemed acceptable, it seems weird at this late
>> stage to change the design goals.
>>
>> Note: this is the third time that these patches have been posted and were
>> only rejected (as far as I know) due to no open-source user. Which there is
>> now, and is why I have reposted these patches.
>
> I never liked the guc firmware code, but figure for one copy it's not
> worth fighting over. Adding more copies (or perpetuating the design by
> making it generic) isn't what I'm looking for.

*You* asked for more copies, back when we proposed a single unified 
solution last year. We already had a *single* GuC+HuC loader which could 
also have been extended to support the DMC as well, but at the time you 
wanted a GuC-specific version -- and by implication, a separate HuC 
loader -- *in addition to* the DMC loader.

 > Firmware loading shouldn't be that complicated, really.

Maybe it shouldn't be, and maybe it isn't -- you may not be seeing how 
simple this code actually is. Fetch firmware, validate it, save it in a 
GEM object; later, DMA it to the h/w; at each stage keep track of status 
so we know what has been done and what is still to do (or redo, during 
reset).

Any complications are because the h/w (e.g. write-once memory) makes 
them necessary, or artefacts of the GEM object system, or because of the 
driver's byzantine sequence of operations during 
load/reset/suspend/resume/unload.

> The unified firmware loader is called request_firmware. If that's not good
> enough, pls fix the core function, not paper code over in i915.

That's exactly the function we call. Then we have to validate and save 
the blob. And remember that we've done so.

> In that regard DMC/CSR is unified, everything else isn't yet.

Unified with what? Maybe the "DMC" is unified with the "CSR" -- which 
AFAIK are the same thing -- and the software just randomly uses both 
names to maximise confusion?

	if (HAS_CSR(dev)) {
		struct intel_csr *csr = &dev_priv->csr;

		err_printf(m, "DMC loaded: %s\n",
			   yesno(csr->dmc_payload != NULL));
		err_printf(m, "DMC fw version: %d.%d\n",
			   CSR_VERSION_MAJOR(csr->version),
			   CSR_VERSION_MINOR(csr->version));
	}
...
	if (!IS_GEN9(dev_priv)) {
		DRM_ERROR("No CSR support available for this platform\n");
		return;
	}
	if (!dev_priv->csr.dmc_payload) {
		DRM_ERROR("Tried to program CSR with empty payload\n");
		return;
	}

And according to the comments in intel_csr.c -- but not the code --

/*
  * Firmware loading status will be one of the below states:
  * FW_UNINITIALIZED, FW_LOADED, FW_FAILED.
  *
  * Once the firmware is written into the registers status will
  * be moved from FW_UNINITIALIZED to FW_LOADED and for any
  * erroneous condition status will be moved to FW_FAILED.
  */

So I don't think you should hold this code up as a masterpiece of 
"unified" design -- which in any case you argued against last year, when 
we presented a unified loader. Specifically, you said, "In my experience 
trying to extract common code at all costs is harmful way too often."

Also, the approach taken in the DMC loader -- which appears to have been 
copypasted from a /very early/ version of the GuC loader, before I fixed 
the async-load problems -- just wouldn't work for the HuC/GuC, where the 
kernel needs to know when the firmware load has been completed so that 
it can start sending work to the GuC. The DMC loader only works because 
it doesn't actually matter when (or if) it's loaded. It would be 
*completely wrong* to load the HuC/Guc that way.

> Iirc the big issue is delayed firmware loading for built-in i915 and fw
> only available later on. This is an open issue in request_firmware() since
> years, and there's various patches floating around. If the problem is that
> Greg KH doesn't consider those patches, I can help with that. But not
> pushing the core fix forward isn't acceptable imo.

We're not addressing that issue at all here, for Linux we expect the 
firmware will be in the ramdisk so it's available immediately. Android 
has an issue with that, but we already have solutions there.

> Once that fix is landed
> we can treat request_firmware as reliable (it might take a while, hence
> must be run in an async work like DMC loading), with no need to ever retry
> anything.

No, it *can't* run "in an async work like DMC loading" -- that was 
exactly what was wrong with the original GuC loader before I got 
involved. The firmware was delivered to the GuC h/w asynchronously, 
*after* the kernel had already started sending work to the engines. That 
was utterly bogus!

*This* version is fully synchronous; the kernel calls for the firmware 
using request_firmware() (and waits until it's succeeded or failed), and 
later asks for the firmware to be loaded into the GuC (again, waiting 
until it has succeeded or failed).

> If fw loading fails we can just mark the entire render part of
> the gpu as dead by injecting the equivalent of a non-recoverable hang
> (async setup) or failing engine init with -EIO (if this is still
> synchronous, which I don't expect really).

Which is just what we do. This patchset is essentially just adding HuC 
loading to the existing GuC loading process, reusing as much as possible 
of the same code.

> If there's another reason for this complexity, please explain since I'd
> like to understand why we need this.
> -Daniel

Less complexity than you think.

   531  1698 14255 drivers/gpu/drm/i915/intel_csr.c
   751  2757 22889 drivers/gpu/drm/i915/intel_guc_loader.c

Much the same size, to within a (binary) order-of-magnitude. Obviously 
the GuC code *necessarily* does more because the f/w interfaces are much 
more complex (ctx pool, ADS, etc); but those are not optional. And the 
GuC code has to deal with reloading after RC6 or GPU reset, which AFAICT 
the DMC doesn't.

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

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

* Re: [PATCH 3/6] drm/i915/huc: Add HuC fw loading support
  2016-07-13 14:52           ` Peter Antoine
@ 2016-07-14 14:16             ` Daniel Vetter
  2016-07-14 14:39               ` Dave Gordon
  2016-07-14 14:43               ` Peter Antoine
  0 siblings, 2 replies; 40+ messages in thread
From: Daniel Vetter @ 2016-07-14 14:16 UTC (permalink / raw)
  To: Peter Antoine; +Cc: lawrence.t.li, sean.v.kelley, intel-gfx, rodrigo.vivi

On Wed, Jul 13, 2016 at 03:52:39PM +0100, Peter Antoine wrote:
> On Wed, 13 Jul 2016, Daniel Vetter wrote:
> 
> > On Thu, Jun 23, 2016 at 02:52:41PM +0100, Peter Antoine wrote:
> > > On Thu, 23 Jun 2016, Dave Gordon wrote:
> > > > On 22/06/16 09:31, Daniel Vetter wrote:
> > > > No, the *correct* fix is to unify all the firmware loaders we have.
> > > > There should just be ONE piece of code that can be used to fetch and
> > > > load ANy firmware into ANY auxiliary microcontroller. NOT one per
> > > > microcontroller, all different -- that way lies madness.
> > > > 
> > > > We already had a unified loader for the HuC and GuC a year ago, but IIRC
> > > > the party line then was "just make it (GuC) specific, then copypaste it
> > > > for the second uC, and when we've got three versions we'll have learnt
> > > > how we really want a unified loader to behave."
> > > > 
> > > > Well. here's the copypaste, and we already have a different loader for
> > > > the DMC/CSR, so it must be time for (re-)unification.
> > > > 
> > > > .Dave.
> > > > 
> > > 
> > > Just to add, if you uc_fw_fetch() has an error code you will still have to
> > > remember the state of the fetch or at each reset/resume/etc... or you will
> > > have to try the firmware load again and that can take a long time. So the
> > > state will have to be re-instated.
> > > 
> > > Seeing this code was written with the given goals and were written in the
> > > same vane as code that was deemed acceptable, it seems weird at this late
> > > stage to change the design goals.
> > > 
> > > Note: this is the third time that these patches have been posted and were
> > > only rejected (as far as I know) due to no open-source user. Which there is
> > > now, and is why I have reposted these patches.
> > 
> > I never liked the guc firmware code, but figure for one copy it's not
> > worth fighting over. Adding more copies (or perpetuating the design by
> > making it generic) isn't what I'm looking for. Firmware loading shouldn't
> > be that complicated, really.
> > 
> > The unified firmware loader is called request_firmware. If that's not good
> > enough, pls fix the core function, not paper code over in i915. In that
> > regard DMC/CSR is unified, everything else isn't yet.
> > 
> > Iirc the big issue is delayed firmware loading for built-in i915 and fw
> > only available later on. This is an open issue in request_firmware() since
> > years, and there's various patches floating around. If the problem is that
> > Greg KH doesn't consider those patches, I can help with that. But not
> > pushing the core fix forward isn't acceptable imo. Once that fix is landed
> > we can treat request_firmware as reliable (it might take a while, hence
> > must be run in an async work like DMC loading), with no need to ever retry
> > anything. If fw loading fails we can just mark the entire render part of
> > the gpu as dead by injecting the equivalent of a non-recoverable hang
> > (async setup) or failing engine init with -EIO (if this is still
> > synchronous, which I don't expect really).
> > 
> > If there's another reason for this complexity, please explain since I'd
> > like to understand why we need this.
> > -Daniel
> > 
> 
> I was not involved at the start and I am porting code that others have
> written, but as far as I understand this, you requested that the code be
> duplicated. See Dave's comment above as he was involved.
> 
> The code uses request_firmware() to handle the load of the firmware into
> memory and the rest of this code manages the loading of that memory into the
> HuC's SRAM. This needs extra setup that should not really go into the
> generic firmware loader (one loader for uIA's make sense as this will
> futureproof the code). Also the SRAM is write-once memory and needs to be
> handled correctly. Also, the GuC needs to verify the HuC some this becomes a
> little be more fun.
> 
> Also, again you are ignoring the point that not having firmware is not
> fatal. We remember the state of the load as this is required to save time
> when we come out of reset to not waste time trying to reload the firmware,
> if it has failed already. They are other mechinums to do this, but they will
> always need some form of history.
> 
> Also, if request_firmware() is broken why has this not been fixed? If it has
> been broken for "years" why and how do you expect to to be fixed now? If the
> "not pushing the core fix is not acceptable" why has that not been done?

Apparently because I'm a too nice maintainer and allowed half-solutions to
get landed, under the expecations that people would indeed follow up and
fix things.

And yes, you care, you fix it, is how this works, whether you like it or
not.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/6] drm/i915/huc: Add HuC fw loading support
  2016-07-14 14:08           ` Dave Gordon
@ 2016-07-14 14:26             ` Daniel Vetter
  2016-07-15  7:33               ` Dave Gordon
  0 siblings, 1 reply; 40+ messages in thread
From: Daniel Vetter @ 2016-07-14 14:26 UTC (permalink / raw)
  To: Dave Gordon; +Cc: sean.v.kelley, lawrence.t.li, intel-gfx, rodrigo.vivi

On Thu, Jul 14, 2016 at 03:08:41PM +0100, Dave Gordon wrote:
> On 13/07/16 13:48, Daniel Vetter wrote:
> > On Thu, Jun 23, 2016 at 02:52:41PM +0100, Peter Antoine wrote:
> > > On Thu, 23 Jun 2016, Dave Gordon wrote:
> > > > On 22/06/16 09:31, Daniel Vetter wrote:
> > > > No, the *correct* fix is to unify all the firmware loaders we have.
> > > > There should just be ONE piece of code that can be used to fetch and
> > > > load ANy firmware into ANY auxiliary microcontroller. NOT one per
> > > > microcontroller, all different -- that way lies madness.
> > > > 
> > > > We already had a unified loader for the HuC and GuC a year ago, but IIRC
> > > > the party line then was "just make it (GuC) specific, then copypaste it
> > > > for the second uC, and when we've got three versions we'll have learnt
> > > > how we really want a unified loader to behave."
> > > > 
> > > > Well. here's the copypaste, and we already have a different loader for
> > > > the DMC/CSR, so it must be time for (re-)unification.
> > > > 
> > > > .Dave.
> > > 
> > > Just to add, if you uc_fw_fetch() has an error code you will still have to
> > > remember the state of the fetch or at each reset/resume/etc... or you will
> > > have to try the firmware load again and that can take a long time. So the
> > > state will have to be re-instated.
> > > 
> > > Seeing this code was written with the given goals and were written in the
> > > same vane as code that was deemed acceptable, it seems weird at this late
> > > stage to change the design goals.
> > > 
> > > Note: this is the third time that these patches have been posted and were
> > > only rejected (as far as I know) due to no open-source user. Which there is
> > > now, and is why I have reposted these patches.
> > 
> > I never liked the guc firmware code, but figure for one copy it's not
> > worth fighting over. Adding more copies (or perpetuating the design by
> > making it generic) isn't what I'm looking for.
> 
> *You* asked for more copies, back when we proposed a single unified solution
> last year. We already had a *single* GuC+HuC loader which could also have
> been extended to support the DMC as well, but at the time you wanted a
> GuC-specific version -- and by implication, a separate HuC loader -- *in
> addition to* the DMC loader.
> 
> > Firmware loading shouldn't be that complicated, really.
> 
> Maybe it shouldn't be, and maybe it isn't -- you may not be seeing how
> simple this code actually is. Fetch firmware, validate it, save it in a GEM
> object; later, DMA it to the h/w; at each stage keep track of status so we
> know what has been done and what is still to do (or redo, during reset).
> 
> Any complications are because the h/w (e.g. write-once memory) makes them
> necessary, or artefacts of the GEM object system, or because of the driver's
> byzantine sequence of operations during load/reset/suspend/resume/unload.
> 
> > The unified firmware loader is called request_firmware. If that's not good
> > enough, pls fix the core function, not paper code over in i915.
> 
> That's exactly the function we call. Then we have to validate and save the
> blob. And remember that we've done so.
> 
> > In that regard DMC/CSR is unified, everything else isn't yet.
> 
> Unified with what? Maybe the "DMC" is unified with the "CSR" -- which AFAIK
> are the same thing -- and the software just randomly uses both names to
> maximise confusion?
> 
> 	if (HAS_CSR(dev)) {
> 		struct intel_csr *csr = &dev_priv->csr;
> 
> 		err_printf(m, "DMC loaded: %s\n",
> 			   yesno(csr->dmc_payload != NULL));
> 		err_printf(m, "DMC fw version: %d.%d\n",
> 			   CSR_VERSION_MAJOR(csr->version),
> 			   CSR_VERSION_MINOR(csr->version));
> 	}
> ...
> 	if (!IS_GEN9(dev_priv)) {
> 		DRM_ERROR("No CSR support available for this platform\n");
> 		return;
> 	}
> 	if (!dev_priv->csr.dmc_payload) {
> 		DRM_ERROR("Tried to program CSR with empty payload\n");
> 		return;
> 	}
> 
> And according to the comments in intel_csr.c -- but not the code --
> 
> /*
>  * Firmware loading status will be one of the below states:
>  * FW_UNINITIALIZED, FW_LOADED, FW_FAILED.
>  *
>  * Once the firmware is written into the registers status will
>  * be moved from FW_UNINITIALIZED to FW_LOADED and for any
>  * erroneous condition status will be moved to FW_FAILED.
>  */
> 
> So I don't think you should hold this code up as a masterpiece of "unified"
> design -- which in any case you argued against last year, when we presented
> a unified loader. Specifically, you said, "In my experience trying to
> extract common code at all costs is harmful way too often."
> 
> Also, the approach taken in the DMC loader -- which appears to have been
> copypasted from a /very early/ version of the GuC loader, before I fixed the
> async-load problems -- just wouldn't work for the HuC/GuC, where the kernel
> needs to know when the firmware load has been completed so that it can start
> sending work to the GuC. The DMC loader only works because it doesn't
> actually matter when (or if) it's loaded. It would be *completely wrong* to
> load the HuC/Guc that way.
> 
> > Iirc the big issue is delayed firmware loading for built-in i915 and fw
> > only available later on. This is an open issue in request_firmware() since
> > years, and there's various patches floating around. If the problem is that
> > Greg KH doesn't consider those patches, I can help with that. But not
> > pushing the core fix forward isn't acceptable imo.
> 
> We're not addressing that issue at all here, for Linux we expect the
> firmware will be in the ramdisk so it's available immediately. Android has
> an issue with that, but we already have solutions there.

Cros has the same issue, and it just cropped up again because Google is
unhappy that this is still not fixed in upstream. This is by no means
android specific at all, no reason to have a hack for it only in android.

> > Once that fix is landed
> > we can treat request_firmware as reliable (it might take a while, hence
> > must be run in an async work like DMC loading), with no need to ever retry
> > anything.
> 
> No, it *can't* run "in an async work like DMC loading" -- that was exactly
> what was wrong with the original GuC loader before I got involved. The
> firmware was delivered to the GuC h/w asynchronously, *after* the kernel had
> already started sending work to the engines. That was utterly bogus!
> 
> *This* version is fully synchronous; the kernel calls for the firmware using
> request_firmware() (and waits until it's succeeded or failed), and later
> asks for the firmware to be loaded into the GuC (again, waiting until it has
> succeeded or failed).

You need to appropriately sync with async work at the right point. For dmc
that's done using rpm/power domain refcounts, it's not nonexisting (since
indeed just running stuff async would fall over). For GuC/HuC we need some
way to synchronize elsewhere, like flush_work in execbuf.

And if the firmware failed to load after flush_work(), then we can
reliable fail execbuf with EIO (like in any other case when the hw is
considered too dead too be useful). And if flush_work is too expensive,
we can create a nice completion, where the fastpath is lockless. I still
don't see why a big state machinery is needed for this at all.

And if this version is fully synchrnous, why does it even need such a
complicated status handling? Fall over with -EIO really should do be
enough.

> > If fw loading fails we can just mark the entire render part of
> > the gpu as dead by injecting the equivalent of a non-recoverable hang
> > (async setup) or failing engine init with -EIO (if this is still
> > synchronous, which I don't expect really).
> 
> Which is just what we do. This patchset is essentially just adding HuC
> loading to the existing GuC loading process, reusing as much as possible of
> the same code.
> 
> > If there's another reason for this complexity, please explain since I'd
> > like to understand why we need this.
> > -Daniel
> 
> Less complexity than you think.
> 
>   531  1698 14255 drivers/gpu/drm/i915/intel_csr.c
>   751  2757 22889 drivers/gpu/drm/i915/intel_guc_loader.c
> 
> Much the same size, to within a (binary) order-of-magnitude. Obviously the
> GuC code *necessarily* does more because the f/w interfaces are much more
> complex (ctx pool, ADS, etc); but those are not optional. And the GuC code
> has to deal with reloading after RC6 or GPU reset, which AFAICT the DMC
> doesn't.

I'm not against code size, but against the status matrix. I nuked it from
intel_csr.c, I want it gone from the guc/huc loader too. It imo serves no
point.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/6] drm/i915/huc: Add HuC fw loading support
  2016-07-14 14:16             ` Daniel Vetter
@ 2016-07-14 14:39               ` Dave Gordon
  2016-07-14 14:43               ` Peter Antoine
  1 sibling, 0 replies; 40+ messages in thread
From: Dave Gordon @ 2016-07-14 14:39 UTC (permalink / raw)
  To: Daniel Vetter, Peter Antoine
  Cc: sean.v.kelley, intel-gfx, lawrence.t.li, rodrigo.vivi

On 14/07/16 15:16, Daniel Vetter wrote:
> On Wed, Jul 13, 2016 at 03:52:39PM +0100, Peter Antoine wrote:
>> On Wed, 13 Jul 2016, Daniel Vetter wrote:
>>
>>> On Thu, Jun 23, 2016 at 02:52:41PM +0100, Peter Antoine wrote:
>>>> On Thu, 23 Jun 2016, Dave Gordon wrote:
>>>>> On 22/06/16 09:31, Daniel Vetter wrote:
>>>>> No, the *correct* fix is to unify all the firmware loaders we have.
>>>>> There should just be ONE piece of code that can be used to fetch and
>>>>> load ANy firmware into ANY auxiliary microcontroller. NOT one per
>>>>> microcontroller, all different -- that way lies madness.
>>>>>
>>>>> We already had a unified loader for the HuC and GuC a year ago, but IIRC
>>>>> the party line then was "just make it (GuC) specific, then copypaste it
>>>>> for the second uC, and when we've got three versions we'll have learnt
>>>>> how we really want a unified loader to behave."
>>>>>
>>>>> Well. here's the copypaste, and we already have a different loader for
>>>>> the DMC/CSR, so it must be time for (re-)unification.
>>>>>
>>>>> .Dave.
>>>>
>>>> Just to add, if you uc_fw_fetch() has an error code you will still have to
>>>> remember the state of the fetch or at each reset/resume/etc... or you will
>>>> have to try the firmware load again and that can take a long time. So the
>>>> state will have to be re-instated.
>>>>
>>>> Seeing this code was written with the given goals and were written in the
>>>> same vane as code that was deemed acceptable, it seems weird at this late
>>>> stage to change the design goals.
>>>>
>>>> Note: this is the third time that these patches have been posted and were
>>>> only rejected (as far as I know) due to no open-source user. Which there is
>>>> now, and is why I have reposted these patches.
>>>
>>> I never liked the guc firmware code, but figure for one copy it's not
>>> worth fighting over. Adding more copies (or perpetuating the design by
>>> making it generic) isn't what I'm looking for. Firmware loading shouldn't
>>> be that complicated, really.
>>>
>>> The unified firmware loader is called request_firmware. If that's not good
>>> enough, pls fix the core function, not paper code over in i915. In that
>>> regard DMC/CSR is unified, everything else isn't yet.
>>>
>>> Iirc the big issue is delayed firmware loading for built-in i915 and fw
>>> only available later on. This is an open issue in request_firmware() since
>>> years, and there's various patches floating around. If the problem is that
>>> Greg KH doesn't consider those patches, I can help with that. But not
>>> pushing the core fix forward isn't acceptable imo. Once that fix is landed
>>> we can treat request_firmware as reliable (it might take a while, hence
>>> must be run in an async work like DMC loading), with no need to ever retry
>>> anything. If fw loading fails we can just mark the entire render part of
>>> the gpu as dead by injecting the equivalent of a non-recoverable hang
>>> (async setup) or failing engine init with -EIO (if this is still
>>> synchronous, which I don't expect really).
>>>
>>> If there's another reason for this complexity, please explain since I'd
>>> like to understand why we need this.
>>> -Daniel
>>
>> I was not involved at the start and I am porting code that others have
>> written, but as far as I understand this, you requested that the code be
>> duplicated. See Dave's comment above as he was involved.
>>
>> The code uses request_firmware() to handle the load of the firmware into
>> memory and the rest of this code manages the loading of that memory into the
>> HuC's SRAM. This needs extra setup that should not really go into the
>> generic firmware loader (one loader for uIA's make sense as this will
>> futureproof the code). Also the SRAM is write-once memory and needs to be
>> handled correctly. Also, the GuC needs to verify the HuC some this becomes a
>> little be more fun.
>>
>> Also, again you are ignoring the point that not having firmware is not
>> fatal. We remember the state of the load as this is required to save time
>> when we come out of reset to not waste time trying to reload the firmware,
>> if it has failed already. They are other mechinums to do this, but they will
>> always need some form of history.
>>
>> Also, if request_firmware() is broken why has this not been fixed? If it has
>> been broken for "years" why and how do you expect to to be fixed now? If the
>> "not pushing the core fix is not acceptable" why has that not been done?
>
> Apparently because I'm a too nice maintainer and allowed half-solutions to
> get landed, under the expecations that people would indeed follow up and
> fix things.
>
> And yes, you care, you fix it, is how this works, whether you like it or
> not.
> -Daniel

AFAIK request_firmware() is *not* broken. It does what it says i.e. 
fetches a blob from the internal bucket or from the filesystem; and 
fails if it's not found. So it doesn't need fixing.

What's broken (from the Android POV) is i915 needing to do too much too 
early i.e. before all filesystems are mounted. The answer to *that* is 
to defer *all* engine initialisation until (much) later; but that's 
nothing at all to do with Peter's patches here.

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

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

* Re: [PATCH 3/6] drm/i915/huc: Add HuC fw loading support
  2016-07-14 14:16             ` Daniel Vetter
  2016-07-14 14:39               ` Dave Gordon
@ 2016-07-14 14:43               ` Peter Antoine
  1 sibling, 0 replies; 40+ messages in thread
From: Peter Antoine @ 2016-07-14 14:43 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx, rodrigo.vivi, lawrence.t.li, sean.v.kelley

On Thu, 14 Jul 2016, Daniel Vetter wrote:

> On Wed, Jul 13, 2016 at 03:52:39PM +0100, Peter Antoine wrote:
>> On Wed, 13 Jul 2016, Daniel Vetter wrote:
>>
>>> On Thu, Jun 23, 2016 at 02:52:41PM +0100, Peter Antoine wrote:
>>>> On Thu, 23 Jun 2016, Dave Gordon wrote:
>>>>> On 22/06/16 09:31, Daniel Vetter wrote:
>>>>> No, the *correct* fix is to unify all the firmware loaders we have.
>>>>> There should just be ONE piece of code that can be used to fetch and
>>>>> load ANy firmware into ANY auxiliary microcontroller. NOT one per
>>>>> microcontroller, all different -- that way lies madness.
>>>>>
>>>>> We already had a unified loader for the HuC and GuC a year ago, but IIRC
>>>>> the party line then was "just make it (GuC) specific, then copypaste it
>>>>> for the second uC, and when we've got three versions we'll have learnt
>>>>> how we really want a unified loader to behave."
>>>>>
>>>>> Well. here's the copypaste, and we already have a different loader for
>>>>> the DMC/CSR, so it must be time for (re-)unification.
>>>>>
>>>>> .Dave.
>>>>>
>>>>
>>>> Just to add, if you uc_fw_fetch() has an error code you will still have to
>>>> remember the state of the fetch or at each reset/resume/etc... or you will
>>>> have to try the firmware load again and that can take a long time. So the
>>>> state will have to be re-instated.
>>>>
>>>> Seeing this code was written with the given goals and were written in the
>>>> same vane as code that was deemed acceptable, it seems weird at this late
>>>> stage to change the design goals.
>>>>
>>>> Note: this is the third time that these patches have been posted and were
>>>> only rejected (as far as I know) due to no open-source user. Which there is
>>>> now, and is why I have reposted these patches.
>>>
>>> I never liked the guc firmware code, but figure for one copy it's not
>>> worth fighting over. Adding more copies (or perpetuating the design by
>>> making it generic) isn't what I'm looking for. Firmware loading shouldn't
>>> be that complicated, really.
>>>
>>> The unified firmware loader is called request_firmware. If that's not good
>>> enough, pls fix the core function, not paper code over in i915. In that
>>> regard DMC/CSR is unified, everything else isn't yet.
>>>
>>> Iirc the big issue is delayed firmware loading for built-in i915 and fw
>>> only available later on. This is an open issue in request_firmware() since
>>> years, and there's various patches floating around. If the problem is that
>>> Greg KH doesn't consider those patches, I can help with that. But not
>>> pushing the core fix forward isn't acceptable imo. Once that fix is landed
>>> we can treat request_firmware as reliable (it might take a while, hence
>>> must be run in an async work like DMC loading), with no need to ever retry
>>> anything. If fw loading fails we can just mark the entire render part of
>>> the gpu as dead by injecting the equivalent of a non-recoverable hang
>>> (async setup) or failing engine init with -EIO (if this is still
>>> synchronous, which I don't expect really).
>>>
>>> If there's another reason for this complexity, please explain since I'd
>>> like to understand why we need this.
>>> -Daniel
>>>
>>
>> I was not involved at the start and I am porting code that others have
>> written, but as far as I understand this, you requested that the code be
>> duplicated. See Dave's comment above as he was involved.
>>
>> The code uses request_firmware() to handle the load of the firmware into
>> memory and the rest of this code manages the loading of that memory into the
>> HuC's SRAM. This needs extra setup that should not really go into the
>> generic firmware loader (one loader for uIA's make sense as this will
>> futureproof the code). Also the SRAM is write-once memory and needs to be
>> handled correctly. Also, the GuC needs to verify the HuC some this becomes a
>> little be more fun.
>>
>> Also, again you are ignoring the point that not having firmware is not
>> fatal. We remember the state of the load as this is required to save time
>> when we come out of reset to not waste time trying to reload the firmware,
>> if it has failed already. They are other mechinums to do this, but they will
>> always need some form of history.
>>
>> Also, if request_firmware() is broken why has this not been fixed? If it has
>> been broken for "years" why and how do you expect to to be fixed now? If the
>> "not pushing the core fix is not acceptable" why has that not been done?
>
> Apparently because I'm a too nice maintainer and allowed half-solutions to
> get landed, under the expecations that people would indeed follow up and
> fix things.
>
> And yes, you care, you fix it, is how this works, whether you like it or
> not.
> -Daniel
>
Daniel,

I won't have to time to do this. So I'll leave the HuC/GuC rewrite for 
you to find someone else to take them on as this is likely to take more 
time than I will be employed by Intel.

Peter.


--
    Peter Antoine (Android Graphics Driver Software Engineer)
    ---------------------------------------------------------------------
    Intel Corporation (UK) Limited
    Registered No. 1134945 (England)
    Registered Office: Pipers Way, Swindon SN3 1RJ
    VAT No: 860 2173 47
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/6] drm/i915/huc: Add HuC fw loading support
  2016-07-14 14:26             ` Daniel Vetter
@ 2016-07-15  7:33               ` Dave Gordon
  0 siblings, 0 replies; 40+ messages in thread
From: Dave Gordon @ 2016-07-15  7:33 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: lawrence.t.li, sean.v.kelley, intel-gfx, rodrigo.vivi

On 14/07/16 15:26, Daniel Vetter wrote:
> On Thu, Jul 14, 2016 at 03:08:41PM +0100, Dave Gordon wrote:
>> On 13/07/16 13:48, Daniel Vetter wrote:
>>> On Thu, Jun 23, 2016 at 02:52:41PM +0100, Peter Antoine wrote:
>>>> On Thu, 23 Jun 2016, Dave Gordon wrote:
>>>>> On 22/06/16 09:31, Daniel Vetter wrote:
>>>>> No, the *correct* fix is to unify all the firmware loaders we have.
>>>>> There should just be ONE piece of code that can be used to fetch and
>>>>> load ANy firmware into ANY auxiliary microcontroller. NOT one per
>>>>> microcontroller, all different -- that way lies madness.
>>>>>
>>>>> We already had a unified loader for the HuC and GuC a year ago, but IIRC
>>>>> the party line then was "just make it (GuC) specific, then copypaste it
>>>>> for the second uC, and when we've got three versions we'll have learnt
>>>>> how we really want a unified loader to behave."
>>>>>
>>>>> Well. here's the copypaste, and we already have a different loader for
>>>>> the DMC/CSR, so it must be time for (re-)unification.
>>>>>
>>>>> .Dave.
>>>>
>>>> Just to add, if you uc_fw_fetch() has an error code you will still have to
>>>> remember the state of the fetch or at each reset/resume/etc... or you will
>>>> have to try the firmware load again and that can take a long time. So the
>>>> state will have to be re-instated.
>>>>
>>>> Seeing this code was written with the given goals and were written in the
>>>> same vane as code that was deemed acceptable, it seems weird at this late
>>>> stage to change the design goals.
>>>>
>>>> Note: this is the third time that these patches have been posted and were
>>>> only rejected (as far as I know) due to no open-source user. Which there is
>>>> now, and is why I have reposted these patches.
>>>
>>> I never liked the guc firmware code, but figure for one copy it's not
>>> worth fighting over. Adding more copies (or perpetuating the design by
>>> making it generic) isn't what I'm looking for.
>>
>> *You* asked for more copies, back when we proposed a single unified solution
>> last year. We already had a *single* GuC+HuC loader which could also have
>> been extended to support the DMC as well, but at the time you wanted a
>> GuC-specific version -- and by implication, a separate HuC loader -- *in
>> addition to* the DMC loader.
>>
>>> Firmware loading shouldn't be that complicated, really.
>>
>> Maybe it shouldn't be, and maybe it isn't -- you may not be seeing how
>> simple this code actually is. Fetch firmware, validate it, save it in a GEM
>> object; later, DMA it to the h/w; at each stage keep track of status so we
>> know what has been done and what is still to do (or redo, during reset).
>>
>> Any complications are because the h/w (e.g. write-once memory) makes them
>> necessary, or artefacts of the GEM object system, or because of the driver's
>> byzantine sequence of operations during load/reset/suspend/resume/unload.
>>
>>> The unified firmware loader is called request_firmware. If that's not good
>>> enough, pls fix the core function, not paper code over in i915.
>>
>> That's exactly the function we call. Then we have to validate and save the
>> blob. And remember that we've done so.
>>
>>> In that regard DMC/CSR is unified, everything else isn't yet.
>>
>> Unified with what? Maybe the "DMC" is unified with the "CSR" -- which AFAIK
>> are the same thing -- and the software just randomly uses both names to
>> maximise confusion?
>>
>> 	if (HAS_CSR(dev)) {
>> 		struct intel_csr *csr = &dev_priv->csr;
>>
>> 		err_printf(m, "DMC loaded: %s\n",
>> 			   yesno(csr->dmc_payload != NULL));
>> 		err_printf(m, "DMC fw version: %d.%d\n",
>> 			   CSR_VERSION_MAJOR(csr->version),
>> 			   CSR_VERSION_MINOR(csr->version));
>> 	}
>> ...
>> 	if (!IS_GEN9(dev_priv)) {
>> 		DRM_ERROR("No CSR support available for this platform\n");
>> 		return;
>> 	}
>> 	if (!dev_priv->csr.dmc_payload) {
>> 		DRM_ERROR("Tried to program CSR with empty payload\n");
>> 		return;
>> 	}
>>
>> And according to the comments in intel_csr.c -- but not the code --
>>
>> /*
>>   * Firmware loading status will be one of the below states:
>>   * FW_UNINITIALIZED, FW_LOADED, FW_FAILED.
>>   *
>>   * Once the firmware is written into the registers status will
>>   * be moved from FW_UNINITIALIZED to FW_LOADED and for any
>>   * erroneous condition status will be moved to FW_FAILED.
>>   */
>>
>> So I don't think you should hold this code up as a masterpiece of "unified"
>> design -- which in any case you argued against last year, when we presented
>> a unified loader. Specifically, you said, "In my experience trying to
>> extract common code at all costs is harmful way too often."
>>
>> Also, the approach taken in the DMC loader -- which appears to have been
>> copypasted from a /very early/ version of the GuC loader, before I fixed the
>> async-load problems -- just wouldn't work for the HuC/GuC, where the kernel
>> needs to know when the firmware load has been completed so that it can start
>> sending work to the GuC. The DMC loader only works because it doesn't
>> actually matter when (or if) it's loaded. It would be *completely wrong* to
>> load the HuC/Guc that way.
>>
>>> Iirc the big issue is delayed firmware loading for built-in i915 and fw
>>> only available later on. This is an open issue in request_firmware() since
>>> years, and there's various patches floating around. If the problem is that
>>> Greg KH doesn't consider those patches, I can help with that. But not
>>> pushing the core fix forward isn't acceptable imo.
>>
>> We're not addressing that issue at all here, for Linux we expect the
>> firmware will be in the ramdisk so it's available immediately. Android has
>> an issue with that, but we already have solutions there.
>
> Cros has the same issue, and it just cropped up again because Google is
> unhappy that this is still not fixed in upstream. This is by no means
> android specific at all, no reason to have a hack for it only in android.

Then you can take, or adapt, the patch we use in Android. It's very 
simple -- we defer as much engine initialisation as possible until first 
open. But that's nothing to do with this patchset.

>>> Once that fix is landed
>>> we can treat request_firmware as reliable (it might take a while, hence
>>> must be run in an async work like DMC loading), with no need to ever retry
>>> anything.
>>
>> No, it *can't* run "in an async work like DMC loading" -- that was exactly
>> what was wrong with the original GuC loader before I got involved. The
>> firmware was delivered to the GuC h/w asynchronously, *after* the kernel had
>> already started sending work to the engines. That was utterly bogus!
>>
>> *This* version is fully synchronous; the kernel calls for the firmware using
>> request_firmware() (and waits until it's succeeded or failed), and later
>> asks for the firmware to be loaded into the GuC (again, waiting until it has
>> succeeded or failed).
>
> You need to appropriately sync with async work at the right point. For dmc
> that's done using rpm/power domain refcounts, it's not nonexisting (since
> indeed just running stuff async would fall over).

Actually the DMC load synchronisation *is* nonexistent. Mainline code 
*cannot tell* whether the DMC firmware has been loaded (unless there's 
some way to ask the DMC itself). It *cannot* (for example) stall until 
the load completes, because all it can tell is that there's a nonzero 
refcount on a power domain, not who holds it or why. That's *OK* for the 
DMC because the driver doesn't /need/ to know; it doesn't talk to the 
DMC firmware anyway. But for the GuC/HuC, we need to know.

> For GuC/HuC we need some way to synchronize elsewhere, like flush_work
> in execbuf.
>
> And if the firmware failed to load after flush_work(), then we can
> reliable fail execbuf with EIO (like in any other case when the hw is
> considered too dead too be useful). And if flush_work is too expensive,
> we can create a nice completion, where the fastpath is lockless. I still
> don't see why a big state machinery is needed for this at all.

The completion approach is *exactly* what we used in the original 
unified loader design with asynchronous fetch-ahead and correctly 
synchronised loading, and *you* objected to it, even though it was 
already coded for the GuC+HuC and could easily have been used for the 
DMC as well.

> And if this version is fully synchrnous, why does it even need such a
> complicated status handling? Fall over with -EIO really should do be
> enough.

It's NOT complicated, and it IS necessary.

A state machine with only FOUR states and FIVE transitions 
(NONE->PENDING->[SUCCESS|FAIL]->NONE) is hardly complicated!

And its NECESSARY because the each of the fetch-from-filesystem and 
push-into-WOPCM operations are separate phases, and we want to do the 
first just once -- especially as, in this synchronous scheme, it may 
delay driver initialisation if we have to wait for the user helper. And 
(unlike the DMC) the GuC and HuC have to be DMA-REloaded at various 
points (RC6, resume, reset, etC). So OF COURSE we have to pass status 
from the fetch to the DMAloader, and we have to remember whether each 
stage has not yet started, is in progress, has been successful, or has 
already failed. You could move the GuC state out into the general i915 
data and have the /callers/ of the GuC-related functions hold and 
interpret it, but that would make the code far less modular.

>>> If fw loading fails we can just mark the entire render part of
>>> the gpu as dead by injecting the equivalent of a non-recoverable hang
>>> (async setup) or failing engine init with -EIO (if this is still
>>> synchronous, which I don't expect really).
>>
>> Which is just what we do. This patchset is essentially just adding HuC
>> loading to the existing GuC loading process, reusing as much as possible of
>> the same code.
>>
>>> If there's another reason for this complexity, please explain since I'd
>>> like to understand why we need this.
>>> -Daniel
>>
>> Less complexity than you think.
>>
>>    531  1698 14255 drivers/gpu/drm/i915/intel_csr.c
>>    751  2757 22889 drivers/gpu/drm/i915/intel_guc_loader.c
>>
>> Much the same size, to within a (binary) order-of-magnitude. Obviously the
>> GuC code *necessarily* does more because the f/w interfaces are much more
>> complex (ctx pool, ADS, etc); but those are not optional. And the GuC code
>> has to deal with reloading after RC6 or GPU reset, which AFAICT the DMC
>> doesn't.
>
> I'm not against code size, but against the status matrix. I nuked it from
> intel_csr.c, I want it gone from the guc/huc loader too. It imo serves no
> point.
> -Daniel

There's no "matrix", just the simplest possible linear sequence.
There are FIVE, count'em, FIVE assignments to guc_fw_fetch_status in the 
code, representing exactly those transitions mentioned above
(NONE->PENDING->[SUCCESS|FAIL]->NONE).

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

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

end of thread, other threads:[~2016-07-15  7:33 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-21 18:11 [PATCH 0/6] HuC Loading Patches Peter Antoine
2016-06-21 18:11 ` [PATCH 1/6] drm/i915/guc: Make the GuC fw loading helper functions general Peter Antoine
2016-06-28 14:24   ` Dave Gordon
2016-06-21 18:11 ` [PATCH 2/6] drm/i915/huc: Unified css_header struct for GuC and HuC Peter Antoine
2016-06-28 14:32   ` Dave Gordon
2016-06-30 10:39     ` Antoine, Peter
2016-06-21 18:11 ` [PATCH 3/6] drm/i915/huc: Add HuC fw loading support Peter Antoine
2016-06-22  8:31   ` Daniel Vetter
2016-06-23 10:14     ` Dave Gordon
2016-06-23 13:52       ` Peter Antoine
2016-07-13 12:48         ` Daniel Vetter
2016-07-13 14:52           ` Peter Antoine
2016-07-14 14:16             ` Daniel Vetter
2016-07-14 14:39               ` Dave Gordon
2016-07-14 14:43               ` Peter Antoine
2016-07-14 14:08           ` Dave Gordon
2016-07-14 14:26             ` Daniel Vetter
2016-07-15  7:33               ` Dave Gordon
2016-06-28 14:54   ` Dave Gordon
2016-06-28 15:45     ` Dave Gordon
2016-06-28 23:03       ` Rodrigo Vivi
2016-06-29 14:31         ` Dave Gordon
2016-06-29 17:59           ` Rodrigo Vivi
2016-07-05 14:41             ` Dave Gordon
2016-06-21 18:11 ` [PATCH 4/6] drm/i915/huc: Add debugfs for HuC loading status check Peter Antoine
2016-06-23  8:47   ` Xiang, Haihao
2016-06-23  9:51     ` Peter Antoine
2016-06-23 10:01     ` Peter Antoine
2016-06-23 10:48       ` Michel Thierry
2016-06-23 22:04         ` Kelley, Sean V
2016-07-13  8:13           ` Xiang, Haihao
2016-06-28 14:57   ` Dave Gordon
2016-06-21 18:11 ` [PATCH 5/6] drm/i915/huc: Support HuC authentication Peter Antoine
2016-06-28 15:08   ` Dave Gordon
2016-06-30 10:42     ` Antoine, Peter
2016-06-21 18:11 ` [PATCH 6/6] drm/i915/huc: Add BXT HuC Loading Support Peter Antoine
2016-06-21 18:26   ` Vivi, Rodrigo
2016-06-21 21:28     ` Antoine, Peter
2016-06-28 15:20   ` Dave Gordon
2016-06-22 13:02 ` ✗ Ro.CI.BAT: warning for HuC Loading Patches Patchwork

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.